From f326b05a6d3dda2d68875f52e2c2c0192f3d1a32 Mon Sep 17 00:00:00 2001 From: refaktor Date: Wed, 8 May 2024 03:12:15 +0200 Subject: [PATCH] adding support for modwords and lmodwords , also partially opcpaths and pipecpaths --- env/env.go | 17 +++++++-- env/idxs.go | 4 +++ env/object.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ evaldo/evaldo.go | 19 +++++++++- loader/loader.go | 24 ++++++++++++- main.go | 4 +-- 6 files changed, 156 insertions(+), 6 deletions(-) diff --git a/env/env.go b/env/env.go index a7706d45..68f79f53 100755 --- a/env/env.go +++ b/env/env.go @@ -243,8 +243,21 @@ func (e *RyeCtx) Get2(word int) (Object, bool, *RyeCtx) { } func (e *RyeCtx) Set(word int, val Object) Object { - e.state[word] = val - return val + if _, exists := e.state[word]; exists { + return NewError("Can't set already set word, try using modword") + } else { + e.state[word] = val + return val + } +} + +func (e *RyeCtx) Mod(word int, val Object) Object { + if _, exists := e.state[word]; exists { + e.state[word] = val + return val + } else { + return NewError("Can't mod an unset word, try using setword") + } } type ProgramState struct { diff --git a/env/idxs.go b/env/idxs.go index 71bacacb..04b58e69 100755 --- a/env/idxs.go +++ b/env/idxs.go @@ -48,6 +48,10 @@ var NativeTypes = [...]string{ // Todo change to BuiltinTypes "SpreadsheetRowType", "Decimal", "Vector", + "OpCPath", + "PipeCPath", + "Modword", + "LModword", } func (e *Idxs) IndexWord(w string) int { diff --git a/env/object.go b/env/object.go index 9c3bfb12..88e340ba 100644 --- a/env/object.go +++ b/env/object.go @@ -48,6 +48,10 @@ const ( SpreadsheetRowType Type = 33 DecimalType Type = 34 VectorType Type = 35 + OpCPathType Type = 36 + PipeCPathType Type = 37 + ModwordType Type = 38 + LModwordType Type = 39 ) // after adding new type here, also add string to idxs.go @@ -601,6 +605,96 @@ func (i LSetword) Dump(e Idxs) string { return ":" + e.GetWord(i.Index) } +// +// MODWORD +// + +type Modword struct { + Index int +} + +func NewModword(index int) *Modword { + nat := Modword{index} + return &nat +} + +func (i Modword) Type() Type { + return ModwordType +} + +func (i Modword) Inspect(e Idxs) string { + return "[Modword: " + e.GetWord(i.Index) + "]" +} + +func (b Modword) Print(e Idxs) string { + return e.GetWord(b.Index) + ":" +} + +func (i Modword) Trace(msg string) { + fmt.Print(msg + "(Modword): ") + fmt.Println(i.Index) +} + +func (i Modword) GetKind() int { + return int(ModwordType) +} + +func (i Modword) Equal(o Object) bool { + if i.Type() != o.Type() { + return false + } + return i.Index == o.(Modword).Index +} + +func (i Modword) Dump(e Idxs) string { + return e.GetWord(i.Index) + ":" +} + +// +// LMODWORD +// + +type LModword struct { + Index int +} + +func NewLModword(index int) *LModword { + nat := LModword{index} + return &nat +} + +func (i LModword) Type() Type { + return LModwordType +} + +func (i LModword) Inspect(e Idxs) string { + return "[LModword: " + e.GetWord(i.Index) + "]" +} + +func (b LModword) Print(e Idxs) string { + return ":" + e.GetWord(b.Index) +} + +func (i LModword) Trace(msg string) { + fmt.Print(msg + "(lModword): ") + fmt.Println(i.Index) +} + +func (i LModword) GetKind() int { + return int(LModwordType) +} + +func (i LModword) Equal(o Object) bool { + if i.Type() != o.Type() { + return false + } + return i.Index == o.(LModword).Index +} + +func (i LModword) Dump(e Idxs) string { + return ":" + e.GetWord(i.Index) +} + // // OPWORD // diff --git a/evaldo/evaldo.go b/evaldo/evaldo.go index b90ba709..8009eb51 100644 --- a/evaldo/evaldo.go +++ b/evaldo/evaldo.go @@ -329,6 +329,8 @@ func EvalExpressionConcrete(ps *env.ProgramState) *env.ProgramState { return EvalGenword(ps, object.(env.Genword), nil, false) case env.SetwordType: return EvalSetword(ps, object.(env.Setword)) + case env.ModwordType: + return EvalModword(ps, object.(env.Modword)) case env.GetwordType: return EvalGetword(ps, object.(env.Getword), nil, false) case env.CommaType: @@ -495,7 +497,22 @@ func EvalSetword(ps *env.ProgramState, word env.Setword) *env.ProgramState { // es1 := EvalExpression(es) ps1, _ := EvalExpressionInj(ps, nil, false) idx := word.Index - ps1.Ctx.Set(idx, ps1.Res) + ps1.Res = ps1.Ctx.Set(idx, ps1.Res) + if ps1.Res.Type() == env.ErrorType { + ps1.ErrorFlag = true + } + return ps1 +} + +// evaluates expression to the right and sets the result of it to a word in current context +func EvalModword(ps *env.ProgramState, word env.Modword) *env.ProgramState { + // es1 := EvalExpression(es) + ps1, _ := EvalExpressionInj(ps, nil, false) + idx := word.Index + ps1.Res = ps1.Ctx.Mod(idx, ps1.Res) + if ps1.Res.Type() == env.ErrorType { + ps1.ErrorFlag = true + } return ps1 } diff --git a/loader/loader.go b/loader/loader.go index b1a5479e..7ff4b8eb 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -305,6 +305,20 @@ func parseLSetword(v *Values, d Any) (Any, error) { return *env.NewLSetword(idx), nil } +func parseModword(v *Values, d Any) (Any, error) { + //fmt.Println("SETWORD:" + v.Token()) + word := v.Token() + idx := wordIndex.IndexWord(word[:len(word)-2]) + return *env.NewModword(idx), nil +} + +func parseLModword(v *Values, d Any) (Any, error) { + //fmt.Println("SETWORD:" + v.Token()) + word := v.Token() + idx := wordIndex.IndexWord(word[2:]) + return *env.NewLModword(idx), nil +} + func parseOpword(v *Values, d Any) (Any, error) { //fmt.Println("OPWORD:" + v.Token()) word := v.Token() @@ -404,12 +418,14 @@ 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 / EXWORD / XWORD / OPWORD / TAGWORD / CPATH / FPATH / KINDWORD / GENWORD / GETWORD / WORD / VOID / BLOCK / GROUP / BBLOCK / ARGBLOCK ) SPACES + SERIES <- (GROUP / COMMENT / URI / EMAIL / STRING / DECIMAL / NUMBER / COMMA / MODWORD / SETWORD / LMODWORD / LSETWORD / ONECHARPIPE / PIPECPATH / PIPEWORD / EXWORD / XWORD / OPCPATH / OPWORD / TAGWORD / CPATH / FPATH / KINDWORD / GENWORD / GETWORD / WORD / VOID / BLOCK / GROUP / BBLOCK / ARGBLOCK ) SPACES ARGBLOCK <- "{" WORD ":" WORD "}" WORD <- LETTER LETTERORNUM* / NORMOPWORDS GENWORD <- "~" UCLETTER LCLETTERORNUM* SETWORD <- LETTER LETTERORNUM* ":" + MODWORD <- LETTER LETTERORNUM* "::" LSETWORD <- ":" LETTER LETTERORNUM* + LMODWORD <- "::" LETTER LETTERORNUM* GETWORD <- "?" LETTER LETTERORNUM* PIPEWORD <- "\\" LETTER LETTERORNUM* / "|" LETTER LETTERORNUM* / PIPEARROWS / "|" NORMOPWORDS ONECHARPIPE <- "|" ONECHARWORDS @@ -425,6 +441,8 @@ func newParser() *Parser { // TODO -- add string eaddress path url time EMAILPART <- < ([a-zA-Z0-9._]+) > FPATH <- "%" URIPATH* CPATH <- WORD ( "/" WORD )+ + OPCPATH <- "." WORD ( "/" WORD )+ + PIPECPATH <- "\\" WORD ( "/" WORD )+ ONECHARWORDS <- < [<>*+-=/] > NORMOPWORDS <- < ("_"[<>*+-=/]) > PIPEARROWS <- ">>" / "~>" / "->" @@ -462,6 +480,8 @@ func newParser() *Parser { // TODO -- add string eaddress path url time g["VOID"].Action = parseVoid g["SETWORD"].Action = parseSetword g["LSETWORD"].Action = parseLSetword + g["MODWORD"].Action = parseModword + g["LMODWORD"].Action = parseLModword g["OPWORD"].Action = parseOpword g["PIPEWORD"].Action = parsePipeword g["ONECHARPIPE"].Action = parseOnecharpipe @@ -478,6 +498,8 @@ func newParser() *Parser { // TODO -- add string eaddress path url time g["URI"].Action = parseUri g["FPATH"].Action = parseFpath g["CPATH"].Action = parseCPath + g["OPCPATH"].Action = parseCPath + g["PIPECPATH"].Action = parseCPath g["COMMENT"].Action = parseComment /* g["SERIES"].Action = func(v *Values, d Any) (Any, error) { return v, nil diff --git a/main.go b/main.go index 08f33e31..b9fb1565 100644 --- a/main.go +++ b/main.go @@ -571,11 +571,11 @@ func main_cgi_file(file string, sig bool) { } func main_rye_repl(_ io.Reader, _ io.Writer, subc bool, here bool) { - input := " 123 " // "name: \"Rye\" version: \"0.011 alpha\"" + input := " " // "name: \"Rye\" version: \"0.011 alpha\"" // userHomeDir, _ := os.UserHomeDir() // profile_path := filepath.Join(userHomeDir, ".rye-profile") - fmt.Println("Welcome to Rye console. Use ls for current or lsp or lsp\\ \"prin\" to list parent context.") + fmt.Println("Welcome to Rye console. Use ls to list current or lsp and lsp\\ \"prin\" to list parent contexts.") //if _, err := os.Stat(profile_path); err == nil { //content, err := os.ReadFile(profile_path)