Explorar o código

добавил рантайм, проинтерпретировал простой пример
todo: рефакторинг, обобщение кода

kpmy %!s(int64=10) %!d(string=hai) anos
pai
achega
c0d1c59cdb
Modificáronse 9 ficheiros con 373 adicións e 28 borrados
  1. 12 0
      cp/node/class.go
  2. 50 13
      cp/node/node.go
  3. 7 2
      cp/object/object.go
  4. 15 1
      fw/fw.go
  5. 41 0
      rt/heap.go
  6. 170 0
      rt/proc.go
  7. 48 0
      rt/stack.go
  8. 4 2
      xev/cmds.go
  9. 26 10
      xev/converter.go

+ 12 - 0
cp/node/class.go

@@ -20,9 +20,21 @@ type EnterNode interface {
 
 type OperationNode interface {
 	SetOperation(op Operation)
+	Operation() Operation
 }
 
 type ConstantNode interface {
 	SetType(typ object.Type)
 	SetData(data interface{})
+	Data() interface{}
+	Type() object.Type
+}
+
+// Self-designator for empty interfaces
+type AssignNode interface {
+	Self() AssignNode
+}
+
+type VariableNode interface {
+	Self() VariableNode
 }

+ 50 - 13
cp/node/node.go

@@ -1,8 +1,6 @@
 package node
 
-import (
-	"cp/object"
-)
+import "cp/object"
 
 type Class int
 
@@ -19,6 +17,11 @@ type Node interface {
 	SetRight(n Node)
 	SetLink(n Node)
 	SetObject(o object.Object)
+
+	Left() Node
+	Right() Node
+	Link() Node
+	Object() object.Object
 }
 
 func New(class Class) Node {
@@ -43,28 +46,44 @@ type nodeFields struct {
 	obj               object.Object
 }
 
-func (nf nodeFields) SetLeft(n Node) {
+func (nf *nodeFields) SetLeft(n Node) {
 	nf.left = n
 }
 
-func (nf nodeFields) SetRight(n Node) {
+func (nf *nodeFields) SetRight(n Node) {
 	nf.right = n
 }
 
-func (nf nodeFields) SetLink(n Node) {
+func (nf *nodeFields) SetLink(n Node) {
 	nf.link = n
 }
 
-func (nf nodeFields) SetObject(o object.Object) {
+func (nf *nodeFields) SetObject(o object.Object) {
 	nf.obj = o
 }
 
+func (nf *nodeFields) Left() Node {
+	return nf.left
+}
+
+func (nf *nodeFields) Right() Node {
+	return nf.right
+}
+
+func (nf *nodeFields) Link() Node {
+	return nf.link
+}
+
+func (nf *nodeFields) Object() object.Object {
+	return nf.obj
+}
+
 type enterNode struct {
 	nodeFields
 	enter Enter
 }
 
-func (e enterNode) SetEnter(enter Enter) {
+func (e *enterNode) SetEnter(enter Enter) {
 	e.enter = enter
 }
 
@@ -74,16 +93,20 @@ type constantNode struct {
 	data interface{}
 }
 
-func (c constantNode) SetType(t object.Type) {
+func (c *constantNode) SetType(t object.Type) {
 	c.typ = t
 }
 
-func (c constantNode) SetData(data interface{}) {
+func (c *constantNode) SetData(data interface{}) {
 	c.data = data
 }
 
-type variableNode struct {
-	nodeFields
+func (c *constantNode) Data() interface{} {
+	return c.data
+}
+
+func (c *constantNode) Type() object.Type {
+	return c.typ
 }
 
 type dyadicNode struct {
@@ -91,10 +114,24 @@ type dyadicNode struct {
 	operation Operation
 }
 
-func (d dyadicNode) SetOperation(op Operation) {
+func (d *dyadicNode) SetOperation(op Operation) {
 	d.operation = op
 }
 
+func (d *dyadicNode) Operation() Operation {
+	return d.operation
+}
+
 type assignNode struct {
 	nodeFields
 }
+
+func (a *assignNode) Self() AssignNode {
+	return a
+}
+
+type variableNode struct {
+	nodeFields
+}
+
+func (v *variableNode) Self() VariableNode { return v }

+ 7 - 2
cp/object/object.go

@@ -16,6 +16,7 @@ const (
 type Object interface {
 	SetName(name string)
 	SetType(typ Type)
+	Type() Type
 }
 
 func New(mode Mode) Object {
@@ -34,14 +35,18 @@ type objectFields struct {
 	typ  Type
 }
 
-func (of objectFields) SetType(typ Type) {
+func (of *objectFields) SetType(typ Type) {
 	of.typ = typ
 }
 
-func (of objectFields) SetName(name string) {
+func (of *objectFields) SetName(name string) {
 	of.name = name
 }
 
+func (of *objectFields) Type() Type {
+	return of.typ
+}
+
 type variableObject struct {
 	objectFields
 }

+ 15 - 1
fw/fw.go

@@ -1,11 +1,25 @@
 package main
 
 import (
+	"fmt"
 	"os"
+	"rt"
 	"xev"
 )
 
 func main() {
 	path, _ := os.Getwd()
-	xev.Load(path, "PrivDemo1.oxf")
+	ret := xev.Load(path, "PrivDemo1.oxf")
+	if ret != nil {
+		p := rt.NewProcessor()
+		p.ConnectTo(ret)
+		for {
+			fmt.Print(".")
+			res, _ := p.Do()
+			if res != rt.OK {
+				break
+			}
+		}
+		fmt.Println("")
+	}
 }

+ 41 - 0
rt/heap.go

@@ -0,0 +1,41 @@
+package rt
+
+import (
+	"cp/object"
+	"fmt"
+)
+
+type INTEGER int
+
+type Heap interface {
+	ThisVariable(obj object.Object) interface{}
+}
+
+type stdHeap struct {
+	inner map[interface{}]interface{}
+}
+
+func NewHeap() Heap {
+	return new(stdHeap).Init()
+}
+
+func (h *stdHeap) Init() *stdHeap {
+	h.inner = make(map[interface{}]interface{}, 0)
+	return h
+}
+
+func (h *stdHeap) ThisVariable(obj object.Object) (ptr interface{}) {
+	fmt.Println(obj)
+	ptr = h.inner[obj]
+	if ptr == nil {
+		switch obj.Type() {
+		case object.INTEGER:
+			ptr = new(int)
+			h.inner[obj] = ptr
+		default:
+			fmt.Println(obj.Type())
+			panic("unknown object type")
+		}
+	}
+	return ptr
+}

+ 170 - 0
rt/proc.go

@@ -0,0 +1,170 @@
+package rt
+
+import (
+	"cp/node"
+	"errors"
+	"fmt"
+	"reflect"
+)
+
+type Result int
+
+const (
+	OK Result = iota
+	END
+	ERROR
+)
+
+type Processor interface {
+	ConnectTo(head node.Node) error
+	Do() (Result, error)
+}
+
+func NewProcessor() Processor {
+	return new(procImpl).Init()
+}
+
+type frame struct {
+	Frame
+	prologue, epilogue interface{}
+	ir, ret            node.Node
+}
+
+type procImpl struct {
+	stack Stack
+	heap  Heap
+}
+
+func (p *procImpl) Init() *procImpl {
+	p.stack = NewStack()
+	p.heap = NewHeap()
+	return p
+}
+
+func (p *procImpl) ConnectTo(head node.Node) (err error) {
+	if head != nil {
+		switch head.(type) {
+		case node.EnterNode:
+			f := new(frame)
+			f.ir = head.Right()
+			f.prologue = prologue
+			f.epilogue = prologue
+			p.stack.Push(f)
+		default:
+			panic("oops")
+		}
+	} else {
+		err = errors.New("not a head node")
+	}
+	return err
+}
+
+func prologue() {
+
+}
+
+func (p *procImpl) doExpression() {
+	f := p.stack.Top().(*frame)
+	fmt.Println(reflect.TypeOf(f.ir))
+	switch f.ir.(type) {
+	//assign works like .left := .right
+	case node.AssignNode:
+		if f.prologue != nil {
+			f.ret = f.ir.Link()
+			switch f.ir.Left().(type) {
+			case node.VariableNode: //nothing to do
+			default:
+				panic("left is not variable")
+			}
+			switch f.ir.Right().(type) {
+			case node.ConstantNode:
+				x := p.heap.ThisVariable(f.ir.Left().Object())
+				_ = x
+				*x.(*int) = f.ir.Right().(node.ConstantNode).Data().(int)
+				fmt.Println(x)
+				x = p.heap.ThisVariable(f.ir.Left().Object())
+				fmt.Println(*x.(*int))
+			case node.OperationNode:
+				nf := new(frame)
+				nf.ir = f.ir.Right()
+				nf.ret = f.ir
+				nf.prologue = prologue
+				nf.epilogue = node.New(node.CONSTANT)
+				f.epilogue = nf.epilogue
+				p.stack.Push(nf)
+			default:
+				panic("unknown right assign")
+			}
+			f.prologue = nil
+		} else if f.epilogue != nil {
+			switch f.epilogue.(type) {
+			case node.ConstantNode:
+				x := p.heap.ThisVariable(f.ir.Left().Object())
+				_ = x
+				*x.(*int) = f.epilogue.(node.ConstantNode).Data().(int)
+				fmt.Println(*x.(*int))
+			default:
+				fmt.Println("no custom epilogue")
+			}
+			p.stack.Pop()
+			if f.ret != nil {
+				nf := new(frame)
+				nf.ir = f.ret
+				nf.prologue = prologue
+				nf.epilogue = prologue
+				p.stack.Push(nf)
+			}
+
+		}
+	case node.OperationNode:
+		switch f.ir.(node.OperationNode).Operation() {
+		case node.PLUS:
+			var a, b int
+			switch f.ir.Left().(type) {
+			case node.ConstantNode:
+				a = f.ir.Left().(node.ConstantNode).Data().(int)
+			case node.VariableNode:
+				x := p.heap.ThisVariable(f.ir.Left().Object())
+				a = *x.(*int)
+			default:
+				panic("unknown left operand")
+			}
+			switch f.ir.Right().(type) {
+			case node.ConstantNode:
+				b = f.ir.Right().(node.ConstantNode).Data().(int)
+			case node.VariableNode:
+				x := p.heap.ThisVariable(f.ir.Right().Object())
+				b = *x.(*int)
+			default:
+				panic("unknown right operand")
+			}
+			switch f.epilogue.(type) {
+			case node.ConstantNode:
+				fmt.Println(a, b)
+				f.epilogue.(node.ConstantNode).SetData(a + b)
+				p.stack.Pop()
+			default:
+				panic("unknown epilogue")
+			}
+		default:
+			panic("unknown operation")
+		}
+	default:
+		panic("ooops")
+	}
+}
+
+func (p *procImpl) Do() (res Result, err error) {
+	if p.stack.Top() != nil {
+		p.doExpression()
+	} else {
+		err = errors.New("no program")
+	}
+	if p.stack.Top() != nil {
+		res = OK
+	} else {
+		res = END
+		fmt.Println(p.heap)
+	}
+	return res, err
+}

+ 48 - 0
rt/stack.go

@@ -0,0 +1,48 @@
+package rt
+
+import "container/list"
+
+type Stack interface {
+	Push(frame Frame)
+	Pop() Frame
+	Top() Frame
+}
+
+type Frame interface {
+}
+
+func NewStack() Stack {
+	return new(stdStack).Init()
+}
+
+type stdStack struct {
+	inner list.List
+}
+
+func (s *stdStack) Init() *stdStack {
+	s.inner = *list.New()
+	return s
+}
+
+func (s *stdStack) Push(frame Frame) {
+	s.inner.PushFront(frame)
+}
+
+func (s *stdStack) Pop() (frame Frame) {
+	if s.inner.Front() != nil {
+		elem := s.inner.Front()
+		frame = elem.Value.(Frame)
+		s.inner.Remove(elem)
+	} else {
+		panic("it's empty stack")
+	}
+	return frame
+}
+
+func (s *stdStack) Top() (frame Frame) {
+	elem := s.inner.Front()
+	if elem != nil {
+		frame = elem.Value.(Frame)
+	}
+	return frame
+}

+ 4 - 2
xev/cmds.go

@@ -1,18 +1,20 @@
 package xev
 
 import (
+	"cp/node"
 	"fmt"
 	"io/ioutil"
 	"path/filepath"
 )
 
-func Load(path, name string) {
+func Load(path, name string) (ret node.Node) {
 	fmt.Println(path + ` ` + name)
 	var data []byte
 	data, _ = ioutil.ReadFile(filepath.Join(path, name))
 	fmt.Println(len(data))
 	if data != nil {
 		result := LoadOXF(data)
-		DoAST(result)
+		ret = DoAST(result)
 	}
+	return ret
 }

+ 26 - 10
xev/converter.go

@@ -84,11 +84,10 @@ func (r *Result) buildObjectList(list []Node) []object.Object {
 	return ret
 }
 
-func (r *Result) buildNode(n *Node) node.Node {
+func (r *Result) buildNode(n *Node) (ret node.Node) {
 	if n == nil {
 		panic("n is nil")
 	}
-	var ret node.Node
 	ret = nodeMap[n.Id]
 	if ret == nil {
 		switch n.Data.Nod.Class {
@@ -131,44 +130,61 @@ func (r *Result) buildNode(n *Node) node.Node {
 		left := r.findLink(n, "left")
 		if left != nil {
 			ret.SetLeft(r.buildNode(left))
+			if ret.Left() == nil {
+				panic("error in node")
+			}
 		}
 		right := r.findLink(n, "right")
 		if right != nil {
 			ret.SetRight(r.buildNode(right))
+			if ret.Right() == nil {
+				panic("error in node")
+			}
 		}
 		link := r.findLink(n, "link")
 		if link != nil {
 			ret.SetLink(r.buildNode(link))
+			if ret.Link() == nil {
+				panic("error in node")
+			}
 		}
 		object := r.findLink(n, "object")
 		if object != nil {
 			ret.SetObject(r.buildObject(object))
+			if ret.Object() == nil {
+				panic("error in node")
+			}
 		}
 	}
 	return ret
 }
 
-func buildMod(r *Result) (node.Node, []object.Object) {
-	var root node.Node
-	var list []object.Object
+func buildMod(r *Result) (nodeList []node.Node, objList []object.Object, root node.Node) {
 	for i := range r.GraphList {
 		if r.GraphList[i].CptScope != "" {
-			list = r.buildObjectList(r.GraphList[i].NodeList)
+			objList = r.buildObjectList(r.GraphList[i].NodeList)
 		}
 		if r.GraphList[i].CptProc != "" {
+			nodeList = make([]node.Node, 0)
 			for j := range r.GraphList[i].NodeList {
-				root = r.buildNode(&r.GraphList[i].NodeList[j])
+				node := &r.GraphList[i].NodeList[j]
+				ret := r.buildNode(&r.GraphList[i].NodeList[j])
+				nodeList = append(nodeList, ret)
+				if node.Data.Nod.Class == "enter" {
+					root = ret
+				}
 			}
 		}
 	}
-	return root, list
+	return nodeList, objList, root
 }
 
-func DoAST(r *Result) {
+func DoAST(r *Result) (ret node.Node) {
 	nodeMap = make(map[string]node.Node)
 	objectMap = make(map[string]object.Object)
-	_, _ = buildMod(r)
+	_, _, ret = buildMod(r)
 	fmt.Println(len(nodeMap), len(objectMap))
 	nodeMap = nil
 	objectMap = nil
+	return ret
 }