summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lang/token.go1
-rw-r--r--parser/type.go52
-rw-r--r--vm/vm.go4
3 files changed, 25 insertions, 32 deletions
diff --git a/lang/token.go b/lang/token.go
index 95a1be5..af2fc26 100644
--- a/lang/token.go
+++ b/lang/token.go
@@ -105,6 +105,7 @@ const (
// Internal virtual machine tokens (no corresponding keyword)
Call
CallX
+ Grow
Label
JumpFalse
JumpSetFalse
diff --git a/parser/type.go b/parser/type.go
index 7d7d3ed..00aedc8 100644
--- a/parser/type.go
+++ b/parser/type.go
@@ -96,21 +96,7 @@ func (p *Parser) parseParamTypes(in Tokens, flag typeFlag) (types []reflect.Type
}
// Type was ommitted, apply the previous one from the right.
types = append([]reflect.Type{types[0]}, types...)
- zv := reflect.New(types[0]).Elem().Interface()
- switch flag {
- case parseTypeIn:
- p.addSym(-i-2, param, zv, symVar, types[0], true)
- case parseTypeOut:
- p.addSym(p.framelen[p.funcScope], param, zv, symVar, types[0], true)
- p.framelen[p.funcScope]++
- case parseTypeVar:
- if local {
- p.addSym(p.framelen[p.funcScope], param, zv, symVar, types[0], local)
- p.framelen[p.funcScope]++
- } else {
- p.addSym(unsetAddr, param, zv, symVar, types[0], local)
- }
- }
+ p.addSymVar(i, param, types[0], flag, local)
vars = append(vars, param)
continue
}
@@ -120,23 +106,7 @@ func (p *Parser) parseParamTypes(in Tokens, flag typeFlag) (types []reflect.Type
return nil, nil, err
}
if param != "" {
- zv := reflect.New(typ).Elem().Interface()
- switch flag {
- case parseTypeIn:
- p.addSym(-i-2, param, zv, symVar, typ, true)
- case parseTypeOut:
- p.addSym(p.framelen[p.funcScope], param, zv, symVar, typ, true)
- p.framelen[p.funcScope]++
- case parseTypeVar:
- if local {
- p.addSym(p.framelen[p.funcScope], param, zv, symVar, typ, local)
- p.framelen[p.funcScope]++
- } else {
- p.addSym(unsetAddr, param, zv, symVar, typ, local)
- }
- }
- } else if flag == parseTypeOut {
- p.framelen[p.funcScope]++
+ p.addSymVar(i, param, typ, flag, local)
}
types = append([]reflect.Type{typ}, types...)
vars = append(vars, param)
@@ -144,6 +114,24 @@ func (p *Parser) parseParamTypes(in Tokens, flag typeFlag) (types []reflect.Type
return types, vars, err
}
+func (p *Parser) addSymVar(index int, name string, typ reflect.Type, flag typeFlag, local bool) {
+ zv := reflect.New(typ).Elem().Interface()
+ switch flag {
+ case parseTypeIn:
+ p.addSym(-index-2, name, zv, symVar, typ, true)
+ case parseTypeOut:
+ p.addSym(p.framelen[p.funcScope], name, zv, symVar, typ, true)
+ p.framelen[p.funcScope]++
+ case parseTypeVar:
+ if !local {
+ p.addSym(unsetAddr, name, zv, symVar, typ, local)
+ break
+ }
+ p.addSym(p.framelen[p.funcScope], name, zv, symVar, typ, local)
+ p.framelen[p.funcScope]++
+ }
+}
+
// hasFirstParam returns true if the first token of a list is a parameter name.
func (p *Parser) hasFirstParam(in Tokens) bool {
if in[0].Id != lang.Ident {
diff --git a/vm/vm.go b/vm/vm.go
index 6f2df12..ba1f97e 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -25,6 +25,7 @@ const (
EqualSet // n1 n2 -- n1 cond ; cond = n1 == n2
Exit // -- ;
Greater // n1 n2 -- cond; cond = n1 > n2
+ Grow // -- ; sp += $1
Jump // -- ; ip += $1
JumpTrue // cond -- ; if cond { ip += $1 }
JumpFalse // cond -- ; if cond { ip += $1 }
@@ -54,6 +55,7 @@ var strop = [...]string{ // for VM tracing.
Fassign: "Fassign",
Fdup: "Fdup",
Greater: "Greater",
+ Grow: "Grow",
Jump: "Jump",
JumpTrue: "JumpTrue",
JumpFalse: "JumpFalse",
@@ -202,6 +204,8 @@ func (m *Machine) Run() (err error) {
mem = mem[:sp-int(op[2])]
case Push:
mem = append(mem, int(op[2]))
+ case Grow:
+ mem = append(mem, make([]any, op[2])...)
case Return:
ip = mem[fp-2].(int)
ofp := fp