123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565 |
- package eval
- import (
- "fw/cp"
- "fw/cp/constant"
- "fw/cp/constant/operation"
- "fw/cp/constant/statement"
- "fw/cp/node"
- "fw/cp/object"
- "fw/cp/traps"
- "fw/rt2"
- "fw/rt2/context"
- "fw/rt2/frame"
- rtm "fw/rt2/module"
- "fw/rt2/scope"
- "fw/utils"
- "log"
- "math/big"
- "reflect"
- "ypk/assert"
- "ypk/halt"
- )
- func makeTrap(f frame.Frame, err traps.TRAP) (out OUT) {
- trap := node.New(constant.TRAP, cp.Some()).(node.TrapNode)
- code := node.New(constant.CONSTANT, cp.Some()).(node.ConstantNode)
- code.SetData(int32(err))
- trap.SetLeft(code)
- rt2.Push(rt2.New(trap), f)
- return Later(Tail(STOP))
- }
- func doEnter(in IN) OUT {
- e := in.IR.(node.EnterNode)
- var next Do
- tail := func(IN) (out OUT) {
- body := in.IR.Right()
- switch {
- case body == nil:
- return End()
- case body != nil && in.Parent != nil:
- rt2.Push(rt2.New(body), in.Frame)
- return Later(Tail(STOP))
- case body != nil && in.Parent == nil: //секция BEGIN
- rt2.Push(rt2.New(body), in.Frame)
- end := in.IR.Link()
- if end != nil { //секция CLOSE
- out.Do = func(in IN) OUT {
- in.Frame.Root().PushFor(rt2.New(end), in.Frame)
- return OUT{Do: Tail(STOP), Next: LATER}
- }
- } else {
- out.Do = Tail(STOP)
- }
- out.Next = BEGIN
- }
- return
- }
- sm := rt2.ThisScope(in.Frame)
- if e.Object() != nil { //параметры процедуры
- par, ok := rt2.RegOf(in.Frame)[e.Object()].(node.Node)
- //fmt.Println(rt2.DataOf(f)[n.Object()])
- //fmt.Println(ok)
- if ok {
- sm.Target().(scope.ScopeAllocator).Allocate(e, false)
- next = func(in IN) OUT {
- seq, _ := sm.Target().(scope.ScopeAllocator).Initialize(e,
- scope.PARAM{Objects: e.Object().Link(),
- Values: par,
- Frame: in.Frame,
- Tail: Propose(tail)})
- return Later(Expose(seq))
- }
- } else {
- sm.Target().(scope.ScopeAllocator).Allocate(e, true)
- next = tail
- }
- } else {
- sm.Target().(scope.ScopeAllocator).Allocate(in.IR, true)
- next = tail
- }
- return Now(next)
- }
- func inc_dec_seq(in IN, code operation.Operation) OUT {
- n := in.IR
- a := node.New(constant.ASSIGN, cp.Some()).(node.AssignNode)
- a.SetStatement(statement.ASSIGN)
- a.SetLeft(n.Left())
- op := node.New(constant.DYADIC, cp.Some()).(node.OperationNode)
- op.SetOperation(code)
- op.SetLeft(n.Left())
- op.SetRight(n.Right())
- a.SetRight(op)
- rt2.Push(rt2.New(a), in.Frame)
- /*seq = func(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
- sc := f.Domain().Discover(context.SCOPE).(scope.Manager)
- sc.Update(n.Left().Object().Adr(), scope.Simple(rt2.ValueOf(f)[op.Adr()]))
- return frame.End()
- }
- ret = frame.LATER */
- return Later(Tail(STOP))
- }
- func doAssign(in IN) (out OUT) {
- const (
- right = "assign:right"
- left = "assign:left"
- )
- a := in.IR.(node.AssignNode)
- switch a.Statement() {
- case statement.ASSIGN:
- out = GetExpression(in, right, a.Right(), func(in IN) OUT {
- id := KeyOf(in, right)
- val := rt2.ValueOf(in.Frame)[id]
- assert.For(val != nil, 40, id)
- return GetDesignator(in, left, a.Left(), func(in IN) OUT {
- id := KeyOf(in, left)
- v, ok := rt2.ValueOf(in.Frame)[id].(scope.Variable)
- assert.For(ok, 41, reflect.TypeOf(v))
- v.Set(val)
- return End()
- })
- })
- case statement.INC, statement.INCL:
- switch a.Left().(type) {
- case node.VariableNode, node.ParameterNode, node.FieldNode:
- out = inc_dec_seq(in, operation.PLUS)
- default:
- halt.As(100, "wrong left", reflect.TypeOf(a.Left()))
- }
- case statement.DEC, statement.EXCL:
- switch a.Left().(type) {
- case node.VariableNode, node.ParameterNode, node.FieldNode:
- out = inc_dec_seq(in, operation.MINUS)
- default:
- halt.As(100, "wrong left", reflect.TypeOf(a.Left()))
- }
- case statement.NEW:
- obj := a.Left().Object()
- assert.For(obj != nil, 20)
- heap := in.Frame.Domain().Discover(context.HEAP).(scope.Manager).Target().(scope.HeapAllocator)
- if a.Right() != nil {
- out = GetExpression(in, right, a.Right(), func(in IN) OUT {
- size := rt2.ValueOf(in.Frame)[KeyOf(in, right)]
- return GetDesignator(in, left, a.Left(), func(in IN) OUT {
- v := rt2.ValueOf(in.Frame)[KeyOf(in, left)].(scope.Variable)
- fn := heap.Allocate(obj, obj.Complex().(object.PointerType), size)
- v.Set(fn)
- return End()
- })
- })
- } else {
- out = GetDesignator(in, left, a.Left(), func(IN) OUT {
- v := rt2.ValueOf(in.Frame)[KeyOf(in, left)].(scope.Variable)
- fn := heap.Allocate(obj, obj.Complex().(object.PointerType))
- v.Set(fn)
- return End()
- })
- }
- default:
- halt.As(100, "unsupported assign statement", a.Statement())
- }
- return
- }
- func doIf(in IN) OUT {
- const left = "if:left:if"
- i := in.IR.(node.IfNode)
- return GetExpression(in, left, i.Left(), func(in IN) OUT {
- val := rt2.ValueOf(in.Frame)[KeyOf(in, left)]
- assert.For(val != nil, 20)
- rt2.ValueOf(in.Parent)[i.Adr()] = val
- rt2.RegOf(in.Parent)[in.Key] = i.Adr()
- return End()
- })
- }
- func doCondition(in IN) OUT {
- const left = "if:left"
- i := in.IR.(node.ConditionalNode)
- rt2.RegOf(in.Frame)[0] = i.Left() // if
- var next Do
- next = func(in IN) OUT {
- last := rt2.RegOf(in.Frame)[0].(node.Node)
- fi := rt2.ValueOf(in.Frame)[KeyOf(in, left)]
- done := scope.GoTypeFrom(fi).(bool)
- rt2.RegOf(in.Frame)[0] = nil
- rt2.ValueOf(in.Frame)[KeyOf(in, left)] = nil
- if done && last.Right() != nil {
- rt2.Push(rt2.New(last.Right()), in.Frame)
- return Later(Tail(STOP))
- } else if last.Right() == nil {
- return End()
- } else if last.Link() != nil { //elsif
- rt2.RegOf(in.Frame)[0] = last.Link()
- return GetStrange(in, left, i.Left(), next)
- } else if i.Right() != nil { //else
- rt2.Push(rt2.New(i.Right()), in.Frame)
- return Later(Tail(STOP))
- } else if i.Right() == nil {
- return End()
- } else if i.Right() == last {
- return End()
- } else {
- halt.As(100, "wrong if then else")
- panic(100)
- }
- }
- return GetStrange(in, left, i.Left(), next)
- }
- func doWhile(in IN) OUT {
- const left = "while:left"
- w := in.IR.(node.WhileNode)
- var next Do
- next = func(IN) OUT {
- key := KeyOf(in, left)
- fi := rt2.ValueOf(in.Frame)[key]
- rt2.ValueOf(in.Frame)[key] = nil
- done := scope.GoTypeFrom(fi).(bool)
- if done && w.Right() != nil {
- rt2.Push(rt2.New(w.Right()), in.Frame)
- return Later(func(IN) OUT { return GetExpression(in, left, w.Left(), next) })
- } else if !done {
- return End()
- } else if w.Right() == nil {
- return End()
- } else {
- panic("unexpected while seq")
- }
- }
- return GetExpression(in, left, w.Left(), next)
- }
- const exitFlag = 1812
- func doExit(in IN) OUT {
- in.Frame.Root().ForEach(func(f frame.Frame) (ok bool) {
- n := rt2.NodeOf(f)
- _, ok = n.(node.LoopNode)
- if ok {
- rt2.RegOf(f)[exitFlag] = true
- }
- ok = !ok
- return ok
- })
- return End()
- }
- func doLoop(in IN) OUT {
- l := in.IR.(node.LoopNode)
- exit, ok := rt2.RegOf(in.Frame)[exitFlag].(bool)
- if ok && exit {
- return End()
- }
- if l.Left() != nil {
- rt2.Push(rt2.New(l.Left()), in.Frame)
- return Later(doLoop)
- } else if l.Left() == nil {
- return End()
- } else {
- panic("unexpected loop seq")
- }
- }
- func doRepeat(in IN) OUT {
- const right = "return:right"
- r := in.IR.(node.RepeatNode)
- rt2.ValueOf(in.Frame)[r.Right().Adr()] = scope.TypeFromGo(false)
- var next Do
- next = func(in IN) OUT {
- fi := rt2.ValueOf(in.Frame)[r.Right().Adr()]
- done := scope.GoTypeFrom(fi).(bool)
- if !done && r.Left() != nil {
- rt2.Push(rt2.New(r.Left()), in.Frame)
- return Later(func(IN) OUT { return GetExpression(in, right, r.Right(), next) })
- } else if done {
- return End()
- } else if r.Left() == nil {
- return End()
- } else {
- panic("unexpected repeat seq")
- }
- }
- return Now(next)
- }
- func doTrap(in IN) OUT {
- const left = "trap:left"
- return GetExpression(in, left, in.IR.Left(), func(IN) OUT {
- val := rt2.ValueOf(in.Frame)[KeyOf(in, left)]
- log.Println("TRAP:", traps.This(scope.GoTypeFrom(val)))
- return Now(Tail(WRONG))
- })
- }
- func doReturn(in IN) OUT {
- const left = "return:left"
- r := in.IR.(node.ReturnNode)
- return GetExpression(in, left, r.Left(), func(IN) OUT {
- val := rt2.ValueOf(in.Frame)[KeyOf(in, left)]
- if val == nil {
- val, _ = rt2.RegOf(in.Frame)[context.RETURN].(scope.Value)
- }
- assert.For(val != nil, 40)
- rt2.ValueOf(in.Parent)[r.Object().Adr()] = val
- rt2.RegOf(in.Parent)[context.RETURN] = val
- return End()
- })
- }
- func doCall(in IN) (out OUT) {
- const (
- right = "call:right"
- )
- c := in.IR.(node.CallNode)
- call := func(proc node.Node, d context.Domain) {
- _, ok := proc.(node.EnterNode)
- assert.For(ok, 20, "try call", reflect.TypeOf(proc), proc.Adr(), proc.Object().Adr())
- nf := rt2.New(proc)
- rt2.Push(nf, in.Frame)
- if d != nil {
- rt2.ReplaceDomain(nf, d)
- }
- //передаем ссылку на цепочку значений параметров в данные фрейма входа в процедуру
- if (c.Right() != nil) && (proc.Object() != nil) {
- rt2.RegOf(nf)[proc.Object()] = c.Right()
- } else {
- //fmt.Println("no data for call")
- }
- out = Later(func(in IN) OUT {
- if in.Key != nil {
- val := rt2.ValueOf(in.Frame)[c.Left().Object().Adr(0, 0)]
- if val == nil {
- if rv, _ := rt2.RegOf(in.Frame)[context.RETURN].(scope.Value); rv != nil {
- val = rv
- }
- }
- assert.For(val != nil, 40, in.Key, rt2.RegOf(in.Frame), rt2.ValueOf(in.Frame), rt2.RegOf(in.Parent), rt2.ValueOf(in.Parent))
- id := cp.ID(cp.Some())
- rt2.ValueOf(in.Parent)[id] = val
- rt2.RegOf(in.Parent)[in.Key] = id
- }
- return End()
- })
- }
- switch p := c.Left().(type) {
- case node.ProcedureNode:
- m := rtm.DomainModule(in.Frame.Domain())
- ml := in.Frame.Domain().Global().Discover(context.MOD).(rtm.List)
- switch p.Object().Mode() {
- case object.LOCAL_PROC, object.EXTERNAL_PROC:
- if imp := p.Object().Imp(); imp == "" || imp == m.Name {
- proc := m.NodeByObject(p.Object())
- assert.For(proc != nil, 40, m.Name, imp, p.Object().Imp(), p.Object().Adr(0, 0), p.Object().Name())
- call(proc[0], nil)
- } else {
- m := ml.Loaded(imp)
- pl := m.ObjectByName(m.Enter, c.Left().Object().Name())
- var proc object.ProcedureObject
- var nl []node.Node
- for _, n := range pl {
- if n.Mode() == p.Object().Mode() {
- proc = n.(object.ProcedureObject)
- }
- }
- nl = m.NodeByObject(proc)
- utils.PrintFrame("foreign call", len(nl), "proc refs", proc)
- call(nl[0], in.Frame.Domain().Global().Discover(imp).(context.Domain))
- }
- case object.TYPE_PROC:
- //sc := f.Domain().Discover(context.SCOPE).(scope.Manager)
- out = GetExpression(in, right, c.Right(), func(IN) (out OUT) {
- var (
- proc []node.Node
- dm context.Domain
- )
- id := KeyOf(in, right)
- v := rt2.ValueOf(in.Frame)[id]
- t, ct := scope.Ops.TypeOf(v)
- if ct == nil {
- return makeTrap(in.Frame, traps.Default)
- }
- assert.For(ct != nil, 40, id, v, t)
- x := ml.NewTypeCalc()
- x.ConnectTo(ct)
- sup := p.Super()
- for _, ml := range x.MethodList() {
- for _, m := range ml {
- //fmt.Println(m.Obj.Name(), m.Obj.Adr())
- if m.Obj.Name() == p.Object().Name() {
- if !sup {
- proc = append(proc, m.Enter)
- break
- } else {
- sup = false //супервызов должен быть вторым методом с тем же именем
- }
- dm = in.Frame.Domain().Global().Discover(m.Mod.Name).(context.Domain)
- }
- }
- if len(proc) > 0 {
- break
- }
- }
- assert.For(len(proc) > 0, 40, p.Object().Name())
- call(proc[0], dm)
- out = Later(Tail(STOP))
- return
- })
- default:
- halt.As(100, "wrong proc mode ", p.Object().Mode(), p.Object().Adr(), p.Object().Name())
- }
- case node.VariableNode:
- m := rtm.DomainModule(in.Frame.Domain())
- sc := rt2.ScopeFor(in.Frame, p.Object().Adr())
- var obj interface{}
- sc.Select(p.Object().Adr(), func(in scope.Value) {
- obj = scope.GoTypeFrom(in)
- })
- if obj, ok := obj.(object.Object); ok {
- proc := m.NodeByObject(obj)
- call(proc[0], nil)
- } else {
- name := p.Object().Name()
- switch {
- case sys[name] != nil:
- return syscall(in)
- default:
- halt.As(100, "unknown sysproc variable", name)
- }
- }
- default:
- halt.As(100, reflect.TypeOf(p))
- }
- return
- }
- const isFlag = 1700
- func doWith(in IN) OUT {
- const left = "with:left"
- w := in.IR.(node.WithNode)
- f := in.Frame
- rt2.RegOf(f)[isFlag] = w.Left() //if
- var seq Do
- seq = func(in IN) OUT {
- last := rt2.RegOf(f)[isFlag].(node.Node)
- id := KeyOf(in, left)
- v := rt2.ValueOf(f)[id]
- assert.For(v != nil, 40)
- done := scope.GoTypeFrom(v).(bool)
- rt2.ValueOf(f)[id] = nil
- if done && last.Right() != nil {
- rt2.Push(rt2.New(last.Right()), f)
- return Later(Tail(STOP))
- } else if last.Right() == nil {
- return End()
- } else if last.Link() != nil { //elsif
- rt2.RegOf(f)[isFlag] = last.Link()
- return Later(func(IN) OUT { return GetStrange(in, left, last.Link(), seq) })
- } else if w.Right() != nil { //else
- rt2.Push(rt2.New(w.Right()), f)
- return Later(Tail(STOP))
- } else if w.Right() == nil {
- return End()
- } else if last == w.Right() {
- return End()
- } else {
- panic("conditional sequence wrong")
- }
- }
- return GetStrange(in, left, w.Left(), seq)
- }
- func int32Of(x interface{}) (a int32) {
- //fmt.Println(reflect.TypeOf(x))
- switch v := x.(type) {
- case *int32:
- z := *x.(*int32)
- a = z
- case int32:
- a = x.(int32)
- case *big.Int:
- a = int32(v.Int64())
- default:
- //panic(fmt.Sprintln("unsupported type", reflect.TypeOf(x)))
- }
- return a
- }
- func doCase(in IN) OUT {
- const left = "case:left"
- c := in.IR.(node.CaseNode)
- var e int
- do := func(in IN) (out OUT) {
- cond := c.Right().(node.ElseNode)
- //fmt.Println("case?", e, cond.Min(), cond.Max())
- if e < cond.Min() || e > cond.Max() { //case?
- if cond.Right() != nil {
- rt2.Push(rt2.New(cond.Right()), in.Frame)
- }
- out.Do = Tail(STOP)
- out.Next = LATER
- } else {
- for next := cond.Left(); next != nil && out.Do == nil; next = next.Link() {
- var ok bool
- // _c := next.Left()
- for _c := next.Left(); _c != nil && !ok; _c = _c.Link() {
- c := _c.(node.ConstantNode)
- //fmt.Println("const", c.Data(), c.Min(), c.Max())
- if (c.Min() != nil) && (c.Max() != nil) {
- //fmt.Println(e, *c.Max(), "..", *c.Min())
- ok = e >= *c.Min() && e <= *c.Max()
- } else {
- //fmt.Println(e, c.Data())
- ok = int32Of(c.Data()) == int32(e)
- }
- }
- //fmt.Println(ok)
- if ok {
- rt2.Push(rt2.New(next.Right()), in.Frame)
- out.Do = Tail(STOP)
- out.Next = LATER
- }
- }
- if out.Do == nil && cond.Right() != nil {
- rt2.Push(rt2.New(cond.Right()), in.Frame)
- out.Do = Tail(STOP)
- out.Next = LATER
- }
- }
- assert.For(out.Do != nil, 60)
- return out
- }
- return GetExpression(in, left, c.Left(), func(IN) (out OUT) {
- v := rt2.ValueOf(in.Frame)[KeyOf(in, left)]
- _x := scope.GoTypeFrom(v)
- switch x := _x.(type) {
- case nil:
- panic("nil")
- case int32:
- e = int(x)
- //fmt.Println("case", e)
- out.Do = do
- out.Next = NOW
- return out
- default:
- halt.As(100, "unsupported case expr", reflect.TypeOf(_x))
- }
- panic(0)
- })
- }
|