From ca386ec364d8c3812ab108731dbf7aae97ab46a3 Mon Sep 17 00:00:00 2001 From: Refaktor Date: Tue, 26 Mar 2024 13:03:07 +0100 Subject: [PATCH] Xmlgen (#167) * added save\current\secure and .enc cont cli command, fixed few bugs * improvements to spreadsheet, support for raw values, tests don't pass * spreadsheet constructor accepts lists for values too, \word for pipeword option, factor-of renamed to multiple-of, tests and examples updated, securesave improved * improved support for xword and exword (xml like tags, dec, to-word, xmlgen example --- env/object.go | 4 +-- evaldo/builtins.go | 67 ++++++++++++++++++++++++++++++++++++++++ examples/xmlgen/try1.rye | 38 +++++++++++++++++++++++ loader/loader.go | 6 ++-- 4 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 examples/xmlgen/try1.rye diff --git a/env/object.go b/env/object.go index e640f6c6..812a8d1a 100644 --- a/env/object.go +++ b/env/object.go @@ -771,7 +771,7 @@ func (i Xword) Inspect(e Idxs) string { } func (b Xword) Print(e Idxs) string { - return e.GetWord(b.Index) + return "<" + e.GetWord(b.Index) + ">" } func (i Xword) Trace(msg string) { @@ -820,7 +820,7 @@ func (i EXword) Inspect(e Idxs) string { } func (b EXword) Print(e Idxs) string { - return e.GetWord(b.Index) + return "" } func (i EXword) Trace(msg string) { diff --git a/evaldo/builtins.go b/evaldo/builtins.go index 2f0314ac..0466a660 100644 --- a/evaldo/builtins.go +++ b/evaldo/builtins.go @@ -343,6 +343,18 @@ var builtins = map[string]*env.Builtin{ return *env.NewWord(idx) case env.Word: return *env.NewWord(str.Index) + case env.Xword: + return *env.NewWord(str.Index) + case env.EXword: + return *env.NewWord(str.Index) + case env.Tagword: + return *env.NewWord(str.Index) + case env.Setword: + return *env.NewWord(str.Index) + case env.LSetword: + return *env.NewWord(str.Index) + case env.Getword: + return *env.NewWord(str.Index) default: return MakeArgError(ps, 1, []env.Type{env.StringType, env.WordType}, "to-word") } @@ -622,6 +634,31 @@ var builtins = map[string]*env.Builtin{ }, }, + "dec!": { // *** + Argsn: 1, + Doc: "Searches for a word and increments it's integer value in-place.", + Pure: false, + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch arg := arg0.(type) { + case env.Word: + intval, found, ctx := ps.Ctx.Get2(arg.Index) + if found { + switch iintval := intval.(type) { + case env.Integer: + ctx.Set(arg.Index, *env.NewInteger(iintval.Value - 1)) + return *env.NewInteger(1 + iintval.Value) + default: + return MakeBuiltinError(ps, "Value in word is not integer.", "inc!") + } + } + return MakeBuiltinError(ps, "Word not found in context.", "inc!") + + default: + return MakeArgError(ps, 1, []env.Type{env.WordType}, "inc!") + } + }, + }, + "change!": { // *** Argsn: 2, Doc: "Searches for a word and changes it's value in-place. If value changes returns true otherwise false", @@ -2886,6 +2923,7 @@ var builtins = map[string]*env.Builtin{ acc := arg1 ser := ps.Ser ps.Ser = bloc.Series + ps.Res = arg1 for i := 0; int64(i) < cond.Value; i++ { ps = EvalBlockInj(ps, acc, true) if ps.ErrorFlag { @@ -3117,6 +3155,35 @@ var builtins = map[string]*env.Builtin{ }, }, + "for-all": { // ** + Argsn: 2, + Doc: "Accepts a block of values and a block of code, does the code for each of the values, injecting them.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch block := arg0.(type) { + case env.Block: + switch code := arg1.(type) { + case env.Block: + ser := ps.Ser + ps.Ser = code.Series + for i := 0; i < block.Series.Len(); i++ { + ps = EvalBlockInj(ps, block, true) + if ps.ErrorFlag { + return ps.Res + } + block.Series.Next() + ps.Ser.Reset() + } + ps.Ser = ser + return ps.Res + default: + return MakeArgError(ps, 2, []env.Type{env.BlockType}, "for") + } + default: + return MakeArgError(ps, 1, []env.Type{env.BlockType}, "for") + } + }, + }, + // Higher order functions "purge": { // TODO ... doesn't fully work diff --git a/examples/xmlgen/try1.rye b/examples/xmlgen/try1.rye new file mode 100644 index 00000000..29fea518 --- /dev/null +++ b/examples/xmlgen/try1.rye @@ -0,0 +1,38 @@ + +private { + + prn\depth: fn { t d } { prn produce d "" { + " " } , prn t } + is-not: fn { a b } { a = b |not } + ; enter-console "asdasd" + + proc: fnc { val blk depth current } current-ctx { + sleep 1000 + for-all blk { :bk + switch type? tok: peek bk { + xword { print "" , prn\depth tok depth , proc val next bk inc depth tok } ; todo -- maybe make it recursive so you know current word + exword { print tok , depth: depth - 1 , tok .to-word = to-word current \not \if { print "Error" } , return 1 } + block { with val tok \type? .is-not 'function \if { .prn } } + string { prn\depth join { "" } depth } + } + } + } + fnc { val blk } current-ctx { proc val blk 0 'no } +} :xmlgen + +xml-template: { + +
+ ( name ) +
+ ( .fullname ) + "Surname next" + ( -> "surname" ) + +} + +do { fullname: fn1 { -> "name" :n , -> "surname" :s , n + " " + s } } +do { input "Enter author's name:" :name , does { } } + +xmlgen dict { "name" "Jim" "surname" "Metelko" } xml-template + diff --git a/loader/loader.go b/loader/loader.go index 59623d36..13acc319 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -397,7 +397,7 @@ func newParser() *Parser { // TODO -- add string eaddress path url time BLOCK <- "{" SPACES SERIES* "}" BBLOCK <- "[" SPACES SERIES* "]" GROUP <- "(" SPACES SERIES* ")" - SERIES <- (GROUP / COMMENT / URI / EMAIL / STRING / DECIMAL / NUMBER / COMMA / SETWORD / LSETWORD / ONECHARPIPE / PIPEWORD / XWORD / OPWORD / TAGWORD / EXWORD / CPATH / FPATH / KINDWORD / GENWORD / GETWORD / WORD / VOID / BLOCK / GROUP / BBLOCK / ARGBLOCK ) SPACES + SERIES <- (GROUP / COMMENT / URI / EMAIL / STRING / DECIMAL / NUMBER / COMMA / SETWORD / LSETWORD / ONECHARPIPE / PIPEWORD / EXWORD / XWORD / OPWORD / TAGWORD / CPATH / FPATH / KINDWORD / GENWORD / GETWORD / WORD / VOID / BLOCK / GROUP / BBLOCK / ARGBLOCK ) SPACES ARGBLOCK <- "{" WORD ":" WORD "}" WORD <- LETTER LETTERORNUM* / NORMOPWORDS GENWORD <- "~" UCLETTER LCLETTERORNUM* @@ -409,7 +409,7 @@ func newParser() *Parser { // TODO -- add string eaddress path url time OPWORD <- "." LETTER LETTERORNUM* / "." NORMOPWORDS / OPARROWS / ONECHARWORDS / "[*" LETTERORNUM* TAGWORD <- "'" LETTER LETTERORNUM* KINDWORD <- "~(" LETTER LETTERORNUM* ")~"? - XWORD <- "<" LETTER LETTERORNUM* ">"? + XWORD <- "<" LETTER LETTERORNUMNOX* " "? XPARAMS* ">" EXWORD <- ""? STRING <- ('"' STRINGCHAR* '"') / ("$" STRINGCHAR1* "$") SPACES <- SPACE+ @@ -424,6 +424,8 @@ func newParser() *Parser { // TODO -- add string eaddress path url time OPARROWS <- "<<" / "<~" / "<-" / ">=" / "<=" LETTER <- < [a-zA-Z^(` + "`" + `] > LETTERORNUM <- < [a-zA-Z0-9-?=.\\!_+<>\]*()] > + LETTERORNUMNOX <- < [a-zA-Z0-9-?=.\\!_+\]*()] > + XPARAMS <- < !">" . > URIPATH <- < [a-zA-Z0-9-?&=.,:@/\\!_> ()] > UCLETTER <- < [A-Z] > LCLETTERORNUM <- < [a-z0-9] >