summaryrefslogtreecommitdiff
path: root/parser/compiler.go
diff options
context:
space:
mode:
Diffstat (limited to 'parser/compiler.go')
-rw-r--r--parser/compiler.go89
1 files changed, 55 insertions, 34 deletions
diff --git a/parser/compiler.go b/parser/compiler.go
index e821c90..501fb25 100644
--- a/parser/compiler.go
+++ b/parser/compiler.go
@@ -4,7 +4,9 @@ import (
"fmt"
"log"
"os"
+ "path"
"reflect"
+ "runtime"
"strconv"
"github.com/mvertes/parscan/lang"
@@ -45,8 +47,10 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
fixList := Tokens{} // list of tokens to fix after we gathered all necessary information
stack := []*symbol{} // for symbolic evaluation, type checking, etc
- emit := func(pos int, op vm.Op, arg ...int) {
- c.Code = append(c.Code, vm.Instruction{Pos: vm.Pos(pos), Op: op, Arg: arg})
+ emit := func(t scanner.Token, op vm.Op, arg ...int) {
+ _, file, line, _ := runtime.Caller(1)
+ fmt.Fprintf(os.Stderr, "%s:%d: %v emit %v %v\n", path.Base(file), line, t, op, arg)
+ c.Code = append(c.Code, vm.Instruction{Pos: vm.Pos(t.Pos), Op: op, Arg: arg})
}
push := func(s *symbol) { stack = append(stack, s) }
pop := func() *symbol { l := len(stack) - 1; s := stack[l]; stack = stack[:l]; return s }
@@ -59,7 +63,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
return err
}
push(&symbol{kind: symConst, value: vm.ValueOf(n), typ: vm.TypeOf(0)})
- emit(t.Pos, vm.Push, n)
+ emit(t, vm.Push, n)
case lang.String:
s := t.Block()
@@ -71,49 +75,49 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
c.strings[s] = i
}
push(&symbol{kind: symConst, value: v})
- emit(t.Pos, vm.Dup, i)
+ emit(t, vm.Dup, i)
case lang.Add:
push(&symbol{typ: arithmeticOpType(pop(), pop())})
- emit(t.Pos, vm.Add)
+ emit(t, vm.Add)
case lang.Mul:
push(&symbol{typ: arithmeticOpType(pop(), pop())})
- emit(t.Pos, vm.Mul)
+ emit(t, vm.Mul)
case lang.Sub:
push(&symbol{typ: arithmeticOpType(pop(), pop())})
- emit(t.Pos, vm.Sub)
+ emit(t, vm.Sub)
case lang.Minus:
- emit(t.Pos, vm.Push, 0)
- emit(t.Pos, vm.Sub)
+ emit(t, vm.Push, 0)
+ emit(t, vm.Sub)
case lang.Not:
- emit(t.Pos, vm.Not)
+ emit(t, vm.Not)
case lang.Plus:
// Unary '+' is idempotent. Nothing to do.
case lang.Addr:
push(&symbol{typ: vm.PointerTo(pop().typ)})
- emit(t.Pos, vm.Addr)
+ emit(t, vm.Addr)
case lang.Deref:
push(&symbol{typ: pop().typ.Elem()})
- emit(t.Pos, vm.Deref)
+ emit(t, vm.Deref)
case lang.Index:
push(&symbol{typ: pop().typ.Elem()})
- emit(t.Pos, vm.Index)
+ emit(t, vm.Index)
case lang.Greater:
push(&symbol{typ: booleanOpType(pop(), pop())})
- emit(t.Pos, vm.Greater)
+ emit(t, vm.Greater)
case lang.Less:
push(&symbol{typ: booleanOpType(pop(), pop())})
- emit(t.Pos, vm.Lower)
+ emit(t, vm.Lower)
case lang.Call:
s := pop()
@@ -123,7 +127,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
for i := 0; i < typ.Rtype.NumOut(); i++ {
push(&symbol{typ: typ.Out(i)})
}
- emit(t.Pos, vm.Call)
+ emit(t, vm.Call)
break
}
push(s)
@@ -135,13 +139,29 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
for i := 0; i < rtyp.NumOut(); i++ {
push(&symbol{typ: &vm.Type{Rtype: rtyp.Out(i)}})
}
- emit(t.Pos, vm.CallX, t.Beg)
+ emit(t, vm.CallX, t.Beg)
case lang.Composite:
log.Println("COMPOSITE")
+ /*
+ d := pop()
+ switch d.typ.Rtype.Kind() {
+ case reflect.Struct:
+ // nf := d.typ.Rtype.NumField()
+ // emit(t.Pos, vm.New, d.index, c.typeSym(d.typ).index)
+ emit(t, vm.Field, 0)
+ emit(t, vm.Vassign)
+ emit(t, vm.Fdup, 2)
+ emit(t, vm.Field, 1)
+ emit(t, vm.Vassign)
+ emit(t, vm.Pop, 1)
+ // emit(t, vm.Fdup, 2)
+ // Assume an element list with no keys, one per struct field in order
+ }
+ */
case lang.Grow:
- emit(t.Pos, vm.Grow, t.Beg)
+ emit(t, vm.Grow, t.Beg)
case lang.Define:
// TODO: support assignment to local, composite objects.
@@ -155,12 +175,12 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
v := vm.NewValue(typ)
c.addSym(l, st.Str, v, symVar, typ, false)
c.Data = append(c.Data, v)
- emit(st.Pos, vm.Assign, l)
+ emit(t, vm.Assign, l)
case lang.Assign:
st := tokens[i-1]
if st.Tok == lang.Period || st.Tok == lang.Index {
- emit(t.Pos, vm.Vassign)
+ emit(t, vm.Vassign)
break
}
s, ok := c.symbols[st.Str]
@@ -178,25 +198,25 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
}
if s.local {
if !s.used {
- emit(st.Pos, vm.New, s.index, c.typeSym(s.typ).index)
+ emit(st, vm.New, s.index, c.typeSym(s.typ).index)
s.used = true
}
- emit(st.Pos, vm.Fassign, s.index)
+ emit(st, vm.Fassign, s.index)
break
}
if s.index == unsetAddr {
s.index = len(c.Data)
c.Data = append(c.Data, s.value)
}
- emit(st.Pos, vm.Assign, s.index)
+ emit(st, vm.Assign, s.index)
case lang.Equal:
push(&symbol{typ: booleanOpType(pop(), pop())})
- emit(t.Pos, vm.Equal)
+ emit(t, vm.Equal)
case lang.EqualSet:
push(&symbol{typ: booleanOpType(pop(), pop())})
- emit(t.Pos, vm.EqualSet)
+ emit(t, vm.EqualSet)
case lang.Ident:
if i < len(tokens)-1 {
@@ -214,13 +234,14 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
break
}
if s.local {
- emit(t.Pos, vm.Fdup, s.index)
+ emit(t, vm.Fdup, s.index)
} else {
if s.index == unsetAddr {
s.index = len(c.Data)
c.Data = append(c.Data, s.value)
}
- emit(t.Pos, vm.Dup, s.index)
+ log.Println(t, ": emit(", t.Pos, vm.Dup, s.index, ")")
+ emit(t, vm.Dup, s.index)
}
case lang.Label:
@@ -248,7 +269,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
} else {
i = int(s.value.Data.Int()) - len(c.Code)
}
- emit(t.Pos, vm.JumpFalse, i)
+ emit(t, vm.JumpFalse, i)
case lang.JumpSetFalse:
var i int
@@ -259,7 +280,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
} else {
i = int(s.value.Data.Int()) - len(c.Code)
}
- emit(t.Pos, vm.JumpSetFalse, i)
+ emit(t, vm.JumpSetFalse, i)
case lang.JumpSetTrue:
var i int
@@ -270,7 +291,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
} else {
i = int(s.value.Data.Int()) - len(c.Code)
}
- emit(t.Pos, vm.JumpSetTrue, i)
+ emit(t, vm.JumpSetTrue, i)
case lang.Goto:
var i int
@@ -280,7 +301,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
} else {
i = int(s.value.Data.Int()) - len(c.Code)
}
- emit(t.Pos, vm.Jump, i)
+ emit(t, vm.Jump, i)
case lang.Period:
s := pop()
@@ -306,17 +327,17 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
sym = c.symbols[name]
}
push(sym)
- emit(t.Pos, vm.Dup, l)
+ emit(t, vm.Dup, l)
default:
if f, ok := s.typ.Rtype.FieldByName(t.Str[1:]); ok {
- emit(t.Pos, vm.Field, f.Index...)
+ emit(t, vm.Field, f.Index...)
break
}
return fmt.Errorf("field or method not found: %s", t.Str[1:])
}
case lang.Return:
- emit(t.Pos, vm.Return, t.Beg, t.End)
+ emit(t, vm.Return, t.Beg, t.End)
default:
return fmt.Errorf("Codegen: unsupported token %v", t)