summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lang/golang/go.go56
-rw-r--r--parser/kind.go52
-rw-r--r--parser/node.go2
-rw-r--r--parser/parse_test.go17
-rw-r--r--vm0/vm.go42
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{
diff --git a/vm0/vm.go b/vm0/vm.go
index 4c726ed..3e589ed 100644
--- a/vm0/vm.go
+++ b/vm0/vm.go
@@ -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