Use frames

This commit is contained in:
Marc Vertes
2018-02-02 18:34:07 +01:00
parent 2f1e444aab
commit bf9ac2df4c
4 changed files with 45 additions and 57 deletions

6
gi.go
View File

@@ -9,8 +9,10 @@ func main() {
package main
func main() {
for a := 0; a < 10000; a++ {
if (a & 0x8ff) == 0x800 {
//for a := 0; a < 10000; a++ {
for a := 0; a < 20000000; a++ {
//if (a & 0x8ff) == 0x800 {
if (a & 0x8ffff) == 0x80000 {
println(a)
}
}

View File

@@ -10,7 +10,7 @@ import (
// TODO: remove coupling with go/ast and go/token. This should be handled only in Ast()
// n.Cfg() generates a control flow graph (CFG) from AST (wiring successors in AST)
func (e *Node) Cfg() {
func (e *Node) Cfg() int {
symIndex := make(map[string]int)
maxIndex := 0
@@ -29,11 +29,11 @@ func (e *Node) Cfg() {
case token.INC:
n.run = inc
}
maxIndex++
n.findex = maxIndex
n.findex = n.Child[0].findex
case *ast.AssignStmt:
n.run = assign
wireChild(n)
n.findex = n.Child[0].findex
case *ast.ExprStmt:
wireChild(n)
// FIXME: could bypass this node at CFG and wire directly last child
@@ -98,15 +98,19 @@ func (e *Node) Cfg() {
*n.val = x.Value
}
case *ast.Ident:
// Lookup identifier in frame symbol table. If not found
// should check that ident is assign target.
n.ident = x.Name
if n.findex = symIndex[n.ident]; n.findex == 0 {
maxIndex++
symIndex[n.ident] = maxIndex
}
n.findex = symIndex[n.ident]
default:
println("unknown type:", reflect.TypeOf(*n.anode).String())
}
})
return maxIndex + 1
}
// Wire AST nodes of sequential blocks

View File

@@ -6,7 +6,7 @@ import (
)
// Function to run at CFG execution
type RunFun func(n *Node, i *Interpreter)
type RunFun func(n *Node, f *Frame)
// Structure for AST and CFG
type Node struct {
@@ -21,7 +21,7 @@ type Node struct {
val *interface{} // pointer on generic value (CFG execution)
ident string // set if node is a var or func
isNop bool // node run function us a no-op
isConst bool // node value is a constant
isConst bool // true if node value is constant
anode *ast.Node // original ast node (temporary, will be removed)
}
@@ -35,6 +35,7 @@ type Frame struct {
// Interpreter contains global resources and state
type Interpreter struct {
sym map[string]*interface{}
size int
frame *Frame
out interface{}
}
@@ -66,11 +67,11 @@ func NewInterpreter() *Interpreter {
// i.Eval(s) evaluates Go code represented as a string
func (i *Interpreter) Eval(src string) interface{} {
root := Ast(src)
root.AstDot()
//root.AstDot()
entry := root.Child[1].Child[2] // FIXME: entry point should be resolved from 'main' name
entry.Cfg()
i.size = entry.Cfg()
entry.OptimCfg()
entry.CfgDot()
//entry.CfgDot()
i.Run(entry.Start)
return i.out
}

View File

@@ -4,15 +4,17 @@ import "fmt"
func (i *Interpreter) Run(entry *Node) {
// Init Frame
f := &Frame{val: make([]interface{}, i.size)}
i.frame = f
// Start execution by runnning entry function and go to next
for n := entry; n != nil; {
n.run(n, i)
n.run(n, f)
if n.snext != nil {
n = n.snext
} else if n.next[1] == nil && n.next[0] == nil {
break
} else if (*n.val).(bool) {
} else if value(n, f).(bool) {
n = n.next[1]
} else {
n = n.next[0]
@@ -22,69 +24,48 @@ func (i *Interpreter) Run(entry *Node) {
// Functions set to run during execution of CFG
//var sym map[string]*interface{} // FIXME: should be part of interpreter
func assign(n *Node, i *Interpreter) {
fmt.Println("assign findex", n.Child[0].findex)
name := n.Child[0].ident // symbol name is in the expr LHS
i.sym[name] = n.Child[1].val // Set symbol value
n.Child[0].val = i.sym[name]
n.val = i.sym[name]
}
func and(n *Node, i *Interpreter) {
for _, child := range n.Child {
if child.ident != "" {
child.val = i.sym[child.ident]
}
func value(n *Node, f *Frame) interface{} {
if n.isConst {
return *n.val
}
*n.val = (*n.Child[0].val).(int64) & (*n.Child[1].val).(int64)
return f.val[n.findex]
}
func printa(n []*Node) {
func assign(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[1], f)
}
func and(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[0], f).(int64) & value(n.Child[1], f).(int64)
}
func printa(n []*Node, f *Frame) {
for _, m := range n {
fmt.Printf("%v", *m.val)
fmt.Printf("%v", value(m, f))
}
fmt.Println("")
}
func call(n *Node, i *Interpreter) {
for _, child := range n.Child {
if child.ident != "" {
child.val = i.sym[child.ident]
}
}
// Only builtin println is supported
func call(n *Node, f *Frame) {
switch n.Child[0].ident {
case "println":
printa(n.Child[1:])
printa(n.Child[1:], f)
default:
panic("function not implemented")
}
}
func equal(n *Node, i *Interpreter) {
for _, child := range n.Child {
if child.ident != "" {
child.val = i.sym[child.ident]
}
}
*n.val = (*n.Child[0].val).(int64) == (*n.Child[1].val).(int64)
func equal(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[0], f).(int64) == value(n.Child[1], f).(int64)
}
func inc(n *Node, i *Interpreter) {
n.Child[0].val = i.sym[n.Child[0].ident]
*n.Child[0].val = (*n.Child[0].val).(int64) + 1
*n.val = *n.Child[0].val
func inc(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[0], f).(int64) + 1
}
func lower(n *Node, i *Interpreter) {
for _, child := range n.Child {
if child.ident != "" {
child.val = i.sym[child.ident]
}
}
*n.val = (*n.Child[0].val).(int64) < (*n.Child[1].val).(int64)
func lower(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[0], f).(int64) < value(n.Child[1], f).(int64)
}
func nop(n *Node, i *Interpreter) {}
func nop(n *Node, i *Frame) {}