VM and compiler update (#63)

* renamed test folders and fixed bug where wrong jump labels would be exectuted for rewrite.

* Added support for Osize (len(string)) and factored out the array tests

* Added current instruction number to VM prompt if program is loaded.

* added support for unary expressions.

* updated README of and sorted the help commands

* updated readme of the compiler

* bumped version -> 0.39.0
This commit is contained in:
Anthony De Meulemeester 2018-04-04 21:41:19 +02:00 committed by GitHub
parent 83e467e527
commit 941bd7e728
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 475 additions and 292 deletions

View file

@ -380,15 +380,16 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
case *ast.CallExpr:
var (
f *funcScope
ok bool
numArgs = len(n.Args)
f *funcScope
ok bool
numArgs = len(n.Args)
isBuiltin = isBuiltin(n.Fun)
)
switch fun := n.Fun.(type) {
case *ast.Ident:
f, ok = c.funcs[fun.Name]
if !ok && !isBuiltin(n.Fun) {
if !ok && !isBuiltin {
log.Fatalf("could not resolve function %s", fun.Name)
}
case *ast.SelectorExpr:
@ -410,12 +411,15 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
for _, arg := range n.Args {
ast.Walk(c, arg)
}
if numArgs == 2 {
emitOpcode(c.prog, vm.Oswap)
}
if numArgs == 3 {
emitInt(c.prog, 2)
emitOpcode(c.prog, vm.Oxswap)
// Do not swap for builtin functions.
if !isBuiltin {
if numArgs == 2 {
emitOpcode(c.prog, vm.Oswap)
}
if numArgs == 3 {
emitInt(c.prog, 2)
emitOpcode(c.prog, vm.Oxswap)
}
}
// c# compiler adds a NOP (0x61) before every function call. Dont think its relevant
@ -424,7 +428,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
emitOpcode(c.prog, vm.Onop)
// Check builtin first to avoid nil pointer on funcScope!
if isBuiltin(n.Fun) {
if isBuiltin {
// Use the ident to check, builtins are not in func scopes.
// We can be sure builtins are of type *ast.Ident.
c.convertBuiltin(n.Fun.(*ast.Ident).Name, n)
@ -456,7 +460,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
return nil
case *ast.UnaryExpr:
// TODO(@anthdm)
ast.Walk(c, n.X)
c.convertToken(n.Op)
return nil
case *ast.IncDecStmt:
ast.Walk(c, n.X)
@ -528,9 +534,15 @@ func (c *codegen) convertSyscall(name string) {
func (c *codegen) convertBuiltin(name string, expr *ast.CallExpr) {
switch name {
case "len":
emitOpcode(c.prog, vm.Oarraysize)
arg := expr.Args[0]
typ := c.typeInfo.Types[arg].Type
if isStringType(typ) {
emitOpcode(c.prog, vm.Osize)
} else {
emitOpcode(c.prog, vm.Oarraysize)
}
case "append":
log.Fatal("builtin (append) not yet implemented.")
emitOpcode(c.prog, vm.Oappend)
}
}
@ -621,6 +633,8 @@ func (c *codegen) convertToken(tok token.Token) {
emitOpcode(c.prog, vm.Odec)
case token.INC:
emitOpcode(c.prog, vm.Oinc)
case token.NOT:
emitOpcode(c.prog, vm.Onot)
default:
log.Fatalf("compiler could not convert token: %s", tok)
}
@ -702,7 +716,7 @@ func (c *codegen) writeJumps() {
switch vm.Opcode(op) {
case vm.Ojmp, vm.Ojmpifnot, vm.Ojmpif, vm.Ocall:
index := int16(binary.LittleEndian.Uint16(b[j : j+2]))
if int(index) > len(c.l) {
if int(index) > len(c.l) || int(index) < 0 {
continue
}
offset := uint16(c.l[index] - i)