diff options
| -rw-r--r-- | lang/golang/go.go | 56 | ||||
| -rw-r--r-- | parser/kind.go | 52 | ||||
| -rw-r--r-- | parser/node.go | 2 | ||||
| -rw-r--r-- | parser/parse_test.go | 17 | ||||
| -rw-r--r-- | vm0/vm.go | 42 |
5 files changed, 94 insertions, 75 deletions
diff --git a/lang/golang/go.go b/lang/golang/go.go index cc13a24..49b12d8 100644 --- a/lang/golang/go.go +++ b/lang/golang/go.go @@ -45,46 +45,26 @@ var GoScanner = &scanner.Scanner{ }, } -const ( - Undefined = parser.Kind(iota) - FuncDecl - CallExpr - IfStmt - StmtBloc - ReturnStmt - Ident - StringLit - NumberLit - ParBloc - DotOp - MulOp - AddOp - SubOp - AssignOp - DefOp - InfOp -) - var GoParser = &parser.Parser{ Scanner: GoScanner, Spec: map[string]parser.NodeSpec{ - ".": {DotOp, parser.Call, 3}, - "*": {MulOp, 0, 4}, - "+": {AddOp, 0, 5}, - "-": {SubOp, 0, 5}, - "<": {InfOp, 0, 6}, - ":=": {DefOp, 0, 7}, - "=": {AssignOp, 0, 7}, - "#call": {CallExpr, 0, 0}, - "#id": {Ident, 0, 0}, - "#num": {NumberLit, 0, 0}, - "if": {IfStmt, parser.Stmt | parser.ExprSep, 0}, - "func": {FuncDecl, parser.Decl | parser.Call, 0}, - "return": {ReturnStmt, parser.Stmt, 0}, - "{..}": {StmtBloc, parser.ExprSep, 0}, - "{": {StmtBloc, parser.ExprSep, 0}, // FIXME: redundant with above - "(..)": {ParBloc, parser.Call, 0}, - "(": {ParBloc, parser.Call, 0}, // FIXME: redundant with above - `".."`: {StringLit, 0, 0}, + ".": {parser.DotOp, parser.Call, 3}, + "*": {parser.MulOp, 0, 4}, + "+": {parser.AddOp, 0, 5}, + "-": {parser.SubOp, 0, 5}, + "<": {parser.InfOp, 0, 6}, + ":=": {parser.DefOp, 0, 7}, + "=": {parser.AssignOp, 0, 7}, + "#call": {parser.CallExpr, 0, 0}, + "#id": {parser.Ident, 0, 0}, + "#num": {parser.NumberLit, 0, 0}, + "if": {parser.IfStmt, parser.Stmt | parser.ExprSep, 0}, + "func": {parser.FuncDecl, parser.Decl | parser.Call, 0}, + "return": {parser.ReturnStmt, parser.Stmt, 0}, + "{..}": {parser.StmtBloc, parser.ExprSep, 0}, + "{": {parser.StmtBloc, parser.ExprSep, 0}, // FIXME: redundant with above + "(..)": {parser.ParBloc, parser.Call, 0}, + "(": {parser.ParBloc, parser.Call, 0}, // FIXME: redundant with above + `".."`: {parser.StringLit, 0, 0}, }, } diff --git a/parser/kind.go b/parser/kind.go new file mode 100644 index 0000000..d570358 --- /dev/null +++ b/parser/kind.go @@ -0,0 +1,52 @@ +package parser + +import "fmt" + +type Kind int + +const ( + Undefined = Kind(iota) + FuncDecl + CallExpr + IfStmt + StmtBloc + ReturnStmt + Ident + StringLit + NumberLit + ParBloc + DotOp + MulOp + AddOp + SubOp + AssignOp + DefOp + InfOp +) + +var kindString = [...]string{ + Undefined: "Undefined", + FuncDecl: "FuncDecl", + CallExpr: "CallExpr", + IfStmt: "IfStmt", + StmtBloc: "StmtBloc", + ReturnStmt: "ReturnStmt", + Ident: "Ident", + StringLit: "StringLit", + NumberLit: "NumberLit", + ParBloc: "ParBloc", + DotOp: "DotOp", + MulOp: "MulOp", + AddOp: "AddOP", + SubOp: "SubOp", + AssignOp: "AssignOp", + DefOp: "DefOp", + InfOp: "InfOp", +} + +func (k Kind) String() string { + if int(k) < 0 || int(k) > len(kindString) { + return fmt.Sprintf("unknown kind %d", k) + } + return kindString[k] +} diff --git a/parser/node.go b/parser/node.go index 6ebc2a7..f81285a 100644 --- a/parser/node.go +++ b/parser/node.go @@ -2,8 +2,6 @@ package parser import "github.com/gnolang/parscan/scanner" -type Kind int - type Node struct { Child []*Node // sub-tree nodes scanner.Token // token at origin of the node diff --git a/parser/parse_test.go b/parser/parse_test.go index dc363cb..3bf6955 100644 --- a/parser/parse_test.go +++ b/parser/parse_test.go @@ -47,23 +47,6 @@ var GoScanner = &scanner.Scanner{ }, } -const ( - Undefined = Kind(iota) - FuncDecl - CallExpr - IfStmt - StmtBloc - ReturnStmt - ParBloc - MulOp - AddOp - SubOp - DotOp - AssignOp - DefOp - InfOp -) - var GoParser = &Parser{ Scanner: GoScanner, Spec: map[string]NodeSpec{ @@ -2,10 +2,8 @@ package vm0 import ( "fmt" - "strconv" "strings" - "github.com/gnolang/parscan/lang/golang" "github.com/gnolang/parscan/parser" ) @@ -37,14 +35,14 @@ func (i *Interp) Eval(src string) (r []any, err error) { } // Run implements a stack based virtual machine which directly walks the AST. -func (i *Interp) Run(node *parser.Node, scope string) ([]any, error) { +func (i *Interp) Run(node *parser.Node, scope string) (res []any, err error) { stop := false node.Walk2(nil, 0, func(n, a *parser.Node, k int) (ok bool) { // Node pre-order processing. switch n.Kind { - case golang.StmtBloc: - if a != nil && a.Kind == golang.IfStmt { + case parser.StmtBloc: + if a != nil && a.Kind == parser.IfStmt { // Control-flow in 'if' sub-tree if k == 1 { // 'if' first body branch, evaluated when condition is true. @@ -56,7 +54,7 @@ func (i *Interp) Run(node *parser.Node, scope string) ([]any, error) { // 'else' body branch, evaluated when condition is false. return !i.pop().(bool) } - case golang.FuncDecl: + case parser.FuncDecl: i.declareFunc(n, scope) return false } @@ -68,33 +66,41 @@ func (i *Interp) Run(node *parser.Node, scope string) ([]any, error) { } l := len(i.stack) switch n.Kind { - case golang.NumberLit: - num, _ := strconv.Atoi(n.Content()) // TODO(marc): compute num value at scanning. - i.push(num) - case golang.StringLit: + case parser.NumberLit: + switch v := n.Value().(type) { + case int64: + i.push(int(v)) + case error: + err = v + return false + default: + err = fmt.Errorf("type not supported: %T\n", v) + return false + } + case parser.StringLit: i.push(n.Block()) - case golang.InfOp: + case parser.InfOp: i.stack[l-2] = i.stack[l-2].(int) < i.stack[l-1].(int) i.stack = i.stack[:l-1] - case golang.AddOp: + case parser.AddOp: i.stack[l-2] = i.stack[l-2].(int) + i.stack[l-1].(int) i.stack = i.stack[:l-1] - case golang.SubOp: + case parser.SubOp: i.stack[l-2] = i.stack[l-2].(int) - i.stack[l-1].(int) i.stack = i.stack[:l-1] - case golang.MulOp: + case parser.MulOp: i.stack[l-2] = i.stack[l-2].(int) * i.stack[l-1].(int) i.stack = i.stack[:l-1] - case golang.AssignOp, golang.DefOp: + case parser.AssignOp, parser.DefOp: i.stack[i.stack[l-2].(int)] = i.stack[l-1] i.stack = i.stack[:l-2] - case golang.ReturnStmt: + case parser.ReturnStmt: stop = true return false - case golang.CallExpr: + case parser.CallExpr: i.push(len(n.Child[1].Child)) // number of arguments to call i.callFunc(n) - case golang.Ident: + case parser.Ident: name := n.Content() v, sc, ok := i.getSym(name, scope) fp := i.fp |
