123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- package rules
- import (
- "encoding/json"
- "fmt"
- "fw/cp"
- "fw/cp/constant"
- cpm "fw/cp/module"
- "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"
- "math"
- "reflect"
- "ypk/assert"
- "ypk/halt"
- "ypk/mathe"
- )
- /**
- Для CallNode
- .Left() указывает на процедуру или на переменную процедурного типа
- .Left().Object() указывает на список внутренних объектов, в т.ч. переменных
- .Object() указывает первый элемент из списка входных параметров/переменных,
- то же что и.Left().Object().Link(), далее .Link() указывает на следующие за ним входные параметры
- .Right() указывает на узлы, которые передаются в параметры
- */
- var sys map[string]func(f frame.Frame, par node.Node) (frame.Sequence, frame.WAIT)
- type Msg struct {
- Type string
- Command string
- Data string
- }
- func callHandler(f frame.Frame, obj object.Object, data interface{}) {
- //n := rt2.Utils.NodeOf(f)
- //fmt.Println("call handler", obj)
- if obj == nil {
- return
- }
- m := rtm.DomainModule(f.Domain())
- cn := node.New(constant.CALL, cp.Some())
- ol := m.NodeByObject(obj)
- assert.For(len(ol) <= 1, 40)
- cn.SetLeft(ol[0])
- cc := node.New(constant.CONSTANT, cp.Some()).(node.ConstantNode)
- cc.SetData(data)
- cc.SetType(object.SHORTSTRING)
- cn.SetRight(cc)
- rt2.Push(rt2.New(cn), f)
- }
- func go_process(f frame.Frame, par node.Node) (frame.Sequence, frame.WAIT) {
- assert.For(par != nil, 20)
- sm := rt2.ThisScope(f)
- do := func(val string) {
- if val != "" {
- msg := &Msg{}
- if err := json.Unmarshal([]byte(val), msg); err == nil {
- switch msg.Type {
- case "log":
- fmt.Print(msg.Data)
- callHandler(f, scope.FindObjByName(sm, "go_handler"), `{"type":"log"}`)
- case "core":
- switch msg.Command {
- case "load":
- //fmt.Println("try to load", msg.Data)
- glob := f.Domain().Discover(context.UNIVERSE).(context.Domain)
- modList := glob.Discover(context.MOD).(rtm.List)
- fl := glob.Discover(context.MT).(*flow)
- ml := make([]*cpm.Module, 0)
- _, err := modList.Load(msg.Data, func(m *cpm.Module) {
- ml = append(ml, m)
- })
- for i := len(ml) - 1; i >= 0; i-- {
- fl.grow(glob, ml[i])
- }
- assert.For(err == nil, 60)
- default:
- halt.As(100, msg.Command)
- }
- default:
- panic(40)
- }
- } else {
- fmt.Println(val, "not a json")
- }
- }
- }
- var val string
- switch p := par.(type) {
- case node.ConstantNode:
- val = par.(node.ConstantNode).Data().(string)
- do(val)
- return frame.Tail(frame.STOP), frame.LATER
- case node.VariableNode, node.ParameterNode:
- val = scope.GoTypeFrom(sm.Select(p.Object().Adr())).(string)
- do(val)
- return frame.Tail(frame.STOP), frame.LATER
- case node.DerefNode:
- rt2.Push(rt2.New(p), f)
- return This(expectExpr(f, p, func(...IN) (out OUT) {
- v := rt2.ValueOf(f)[p.Adr()]
- assert.For(v != nil, 60)
- val = scope.GoTypeFrom(v).(string)
- do(val)
- out.do = Tail(STOP)
- out.next = LATER
- return out
- }))
- default:
- halt.As(100, "unsupported param", reflect.TypeOf(p))
- }
- panic(0)
- }
- func me(f float64) {
- }
- func go_math(f frame.Frame, par node.Node) (seq frame.Sequence, ret frame.WAIT) {
- const (
- LN = 1.0
- MANT = 2.0
- EXP = 3.0
- )
- assert.For(par != nil, 20)
- sm := rt2.ThisScope(f)
- res := math.NaN()
- switch p := par.(type) {
- case node.VariableNode:
- val := sm.Select(p.Object().Adr())
- rv, ok := scope.GoTypeFrom(val).([]float64)
- assert.For(ok && (len(rv) > 1), 100, rv)
- switch rv[0] {
- case LN:
- res = math.Log(rv[1])
- case MANT:
- res, _ = mathe.Me(rv[1])
- case EXP:
- _, res = mathe.Me(rv[1])
- default:
- halt.As(100, rv[0])
- }
- default:
- halt.As(100, reflect.TypeOf(p))
- }
- rt2.RegOf(f.Parent())[context.RETURN] = scope.TypeFromGo(res)
- return frame.End()
- }
- func init() {
- sys = make(map[string]func(f frame.Frame, par node.Node) (frame.Sequence, frame.WAIT))
- sys["go_process"] = go_process
- sys["go_math"] = go_math
- }
- func syscall(f frame.Frame) (frame.Sequence, frame.WAIT) {
- n := rt2.NodeOf(f)
- name := n.Left().Object().Name()
- return sys[name](f, n.Right())
- }
- func callSeq(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
- n := rt2.NodeOf(f)
- 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, f)
- if d != nil {
- rt2.ReplaceDomain(nf, d)
- }
- //передаем ссылку на цепочку значений параметров в данные фрейма входа в процедуру
- if (n.Right() != nil) && (proc.Object() != nil) {
- rt2.RegOf(nf)[proc.Object()] = n.Right()
- } else {
- //fmt.Println("no data for call")
- }
- seq = func(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
- if f.Parent() != nil {
- rt2.ValueOf(f.Parent())[n.Adr()] = rt2.ValueOf(f)[n.Left().Object().Adr(0, 0)]
- }
- return frame.End()
- }
- ret = frame.LATER
- }
- switch p := n.Left().(type) {
- case node.EnterNode:
- call(p, nil)
- case node.ProcedureNode:
- m := rtm.DomainModule(f.Domain())
- ml := f.Domain().Discover(context.UNIVERSE).(context.Domain).Discover(context.MOD).(rtm.List)
- if p.Super() {
- fmt.Println("supercall, stop for now")
- seq = Propose(Tail(STOP))
- ret = frame.NOW
- } else {
- switch p.Object().Mode() {
- case object.LOCAL_PROC, object.EXTERNAL_PROC:
- if imp := m.ImportOf(n.Left().Object()); imp == "" || imp == m.Name {
- proc := m.NodeByObject(n.Left().Object())
- assert.For(proc != nil, 40)
- call(proc[0], nil)
- } else {
- m := ml.Loaded(imp)
- pl := m.ObjectByName(m.Enter, n.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], f.Domain().Discover(context.UNIVERSE).(context.Domain).Discover(imp).(context.Domain))
- }
- case object.TYPE_PROC:
- //sc := f.Domain().Discover(context.SCOPE).(scope.Manager)
- return This(expectExpr(f, n.Right(), func(...IN) (out OUT) {
- var (
- proc []node.Node
- dm context.Domain
- )
- v := rt2.ValueOf(f)[n.Right().Adr()]
- t, c := scope.Ops.TypeOf(v)
- if c == nil {
- return thisTrap(f, traps.Default)
- }
- assert.For(c != nil, 40, n.Right().Adr(), v, t)
- x := ml.NewTypeCalc()
- x.ConnectTo(c)
- for _, ml := range x.MethodList() {
- for _, m := range ml {
- if m.Obj.Name() == p.Object().Name() {
- proc = append(proc, m.Enter)
- dm = f.Domain().Discover(context.UNIVERSE).(context.Domain).Discover(m.Mod.Name).(context.Domain)
- break
- }
- }
- if len(proc) > 0 {
- break
- }
- }
- assert.For(len(proc) > 0, 40, p.Object().Name())
- call(proc[0], dm)
- out.do = Tail(STOP)
- out.next = LATER
- return out
- }))
- default:
- halt.As(100, "wrong proc mode ", p.Object().Mode(), p.Object().Adr(), p.Object().Name())
- }
- }
- case node.VariableNode:
- m := rtm.DomainModule(f.Domain())
- sc := rt2.ScopeFor(f, n.Left().Object().Adr())
- obj := scope.GoTypeFrom(sc.Select(n.Left().Object().Adr()))
- if obj, ok := obj.(object.Object); ok {
- proc := m.NodeByObject(obj)
- call(proc[0], nil)
- } else {
- name := n.Left().Object().Name()
- switch {
- case sys[name] != nil:
- return syscall(f)
- default:
- panic(fmt.Sprintln("unknown sysproc variable", name))
- }
- }
- default:
- halt.As(100, "unknown call left: ", reflect.TypeOf(p))
- }
- return seq, ret
- }
|