Use frames
This commit is contained in:
6
gi.go
6
gi.go
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
Reference in New Issue
Block a user