call.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package rules
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "fw/cp/constant"
  6. "fw/cp/node"
  7. "fw/cp/object"
  8. "fw/rt2"
  9. "fw/rt2/context"
  10. "fw/rt2/frame"
  11. rt_mod "fw/rt2/module"
  12. "fw/rt2/nodeframe"
  13. "fw/rt2/scope"
  14. "ypk/assert"
  15. )
  16. /**
  17. Для CallNode
  18. .Left() указывает на процедуру или на переменную процедурного типа
  19. .Left().Object() указывает на список внутренних объектов, в т.ч. переменных
  20. .Object() указывает первый элемент из списка входных параметров/переменных,
  21. то же что и.Left().Object().Link(), далее .Link() указывает на следующие за ним входные параметры
  22. .Right() указывает на узлы, которые передаются в параметры
  23. */
  24. var sys map[string]func(f frame.Frame, par node.Node)
  25. type Msg struct {
  26. Type string
  27. Data string
  28. }
  29. func callHandler(f frame.Frame, obj object.Object, data interface{}) {
  30. //n := rt2.Utils.NodeOf(f)
  31. //fmt.Println("call handler", obj)
  32. if obj == nil {
  33. return
  34. }
  35. m := rt_mod.DomainModule(f.Domain())
  36. cn := node.New(constant.CALL)
  37. ol := m.NodeByObject(obj)
  38. assert.For(len(ol) <= 1, 40)
  39. cn.SetLeft(ol[0])
  40. cc := node.New(constant.CONSTANT).(node.ConstantNode)
  41. cc.SetData(data)
  42. cn.SetRight(cc)
  43. rt2.Push(rt2.New(cn), f)
  44. }
  45. func process(f frame.Frame, par node.Node) {
  46. assert.For(par != nil, 20)
  47. sm := scope.This(f.Domain().Discover(context.SCOPE))
  48. switch par.(type) {
  49. case node.ConstantNode:
  50. msg := &Msg{}
  51. val := par.(node.ConstantNode).Data().(string)
  52. if err := json.Unmarshal([]byte(val), msg); err == nil {
  53. switch msg.Type {
  54. case "log":
  55. fmt.Println(msg.Data)
  56. callHandler(f, scope.FindObjByName(sm, "go_handler"), `{"type":"log"}`)
  57. default:
  58. panic(40)
  59. }
  60. }
  61. default:
  62. panic(fmt.Sprintln("unsupported param"))
  63. }
  64. }
  65. func init() {
  66. sys = make(map[string]func(f frame.Frame, par node.Node))
  67. sys["go_process"] = process
  68. }
  69. func syscall(f frame.Frame) {
  70. n := rt2.NodeOf(f)
  71. name := n.Left().Object().Name()
  72. sys[name](f, n.Right())
  73. }
  74. func callSeq(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
  75. var fu nodeframe.FrameUtils
  76. n := fu.NodeOf(f)
  77. call := func(proc node.Node) {
  78. nf := fu.New(proc)
  79. fu.Push(nf, f)
  80. //передаем ссылку на цепочку значений параметров в данные фрейма входа в процедуру
  81. if (n.Right() != nil) && (proc.Object() != nil) {
  82. fu.DataOf(nf)[proc.Object()] = n.Right()
  83. } else {
  84. //fmt.Println("no data for call")
  85. }
  86. seq = func(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
  87. var fu nodeframe.FrameUtils
  88. fu.DataOf(f.Parent())[n] = fu.DataOf(f)[n.Left().Object()]
  89. return frame.End()
  90. }
  91. ret = frame.LATER
  92. }
  93. switch p := n.Left().(type) {
  94. case node.ProcedureNode:
  95. m := rt_mod.DomainModule(f.Domain())
  96. if p.Super() {
  97. fmt.Println("supercall, stop for now")
  98. seq = Propose(Tail(STOP))
  99. ret = frame.NOW
  100. } else {
  101. if m.ImportOf(n.Left().Object()) == "" {
  102. proc := m.NodeByObject(n.Left().Object())
  103. fmt.Println(len(proc), len(n.Left().Object().Ref()))
  104. call(proc[0])
  105. } else {
  106. fmt.Println("foreign call, stop for now")
  107. seq = Propose(Tail(STOP))
  108. ret = frame.NOW
  109. }
  110. }
  111. case node.VariableNode:
  112. m := rt_mod.DomainModule(f.Domain())
  113. sc := f.Domain().Discover(context.SCOPE).(scope.Manager)
  114. obj := sc.Select(scope.Designator(n.Left()))
  115. if obj, ok := obj.(object.Object); ok {
  116. proc := m.NodeByObject(obj)
  117. call(proc[0])
  118. } else {
  119. name := n.Left().Object().Name()
  120. switch {
  121. case name == "go_process":
  122. syscall(f)
  123. return frame.Tail(frame.STOP), frame.LATER
  124. default:
  125. panic(fmt.Sprintln("unknown sysproc variable", name))
  126. }
  127. }
  128. default:
  129. panic("unknown call left")
  130. }
  131. return seq, ret
  132. }