diff options
| author | Marc Vertes <mvertes@free.fr> | 2023-11-10 23:00:20 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2023-11-10 23:00:20 +0100 |
| commit | 1977ce7c976cbbd5bd0de1d479a0abe269e62f3d (patch) | |
| tree | d0252db9117692c698af53e44e6b0d3f447a0eb1 | |
| parent | bec71a19e7d7cd0847d1cfa6ef2110d7301fcdd1 (diff) | |
vm: add Grow instruction to increase stack
| -rw-r--r-- | lang/token.go | 1 | ||||
| -rw-r--r-- | parser/type.go | 52 | ||||
| -rw-r--r-- | vm/vm.go | 4 |
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 { @@ -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 |
