123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- package std
- import (
- "container/list"
- "fmt"
- "fw/cp/node"
- "fw/cp/object"
- "fw/rt2/context"
- rt_mod "fw/rt2/module"
- "fw/rt2/scope"
- "reflect"
- "ypk/assert"
- )
- type manager struct {
- d context.Domain
- areas *list.List
- }
- type KVarea interface {
- set(scope.ID, interface{})
- get(scope.ID) interface{}
- }
- type area struct {
- root node.Node
- x map[scope.ID]interface{}
- ready bool
- }
- func (a *area) set(k scope.ID, v interface{}) {
- key := scope.ID{Name: k.Name}
- a.x[key] = v
- }
- func (a *area) get(k scope.ID) interface{} {
- key := scope.ID{Name: k.Name}
- return a.x[key]
- }
- type value interface {
- set(x interface{})
- get() interface{}
- }
- type reference interface {
- id() scope.ID
- }
- type array interface {
- set(i int64, x interface{})
- get(i int64) interface{}
- upd(x []interface{})
- sel() []interface{}
- }
- type basic struct {
- link object.Object
- data interface{}
- }
- type record interface {
- setField(field string, x interface{})
- getField(field string) interface{}
- init(root node.Node)
- }
- func (b *basic) set(i interface{}) { b.data = i }
- func (b *basic) get() interface{} { return b.data }
- type ref struct {
- link object.Object
- ref scope.ID
- }
- func (r *ref) id() scope.ID { return r.ref }
- type arr struct {
- link object.Object
- par int64
- data []interface{}
- }
- func (a *arr) get(i int64) interface{} {
- if len(a.data) == 0 {
- a.data = make([]interface{}, a.par)
- }
- return a.data[i]
- }
- func (a *arr) set(i int64, x interface{}) {
- if len(a.data) == 0 {
- a.data = make([]interface{}, a.par)
- }
- a.data[i] = x
- }
- func (a *arr) sel() []interface{} { return a.data }
- func (a *arr) upd(x []interface{}) { a.data = x }
- type rec struct {
- link object.Object
- root node.Node
- x map[scope.ID]interface{}
- }
- func (r *rec) setField(f string, x interface{}) { r.set(scope.ID{Name: f}, x) }
- func (r *rec) getField(f string) interface{} { return r.get(scope.ID{Name: f}) }
- func (r *rec) init(n node.Node) {
- r.root = n
- r.x = make(map[scope.ID]interface{})
- }
- func (a *rec) set(k scope.ID, v interface{}) { a.x[k] = v }
- func (a *rec) get(k scope.ID) interface{} { return a.x[k] }
- func nm() scope.Manager {
- m := &manager{areas: list.New()}
- return m
- }
- func init() {
- scope.New = nm
- scope.Designator = design
- scope.FindObjByName = FindObjByName
- }
- func design(n node.Node) (id scope.ID) {
- switch x := n.(type) {
- case node.VariableNode, node.ParameterNode:
- id = scope.ID{Name: x.Object().Name()}
- case node.FieldNode:
- id = scope.ID{Name: x.Left().Object().Name(), Path: [scope.DEPTH]string{x.Object().Name()}}
- case node.IndexNode:
- id = scope.ID{Name: x.Left().Object().Name()}
- default:
- panic(fmt.Sprintln("unsupported", reflect.TypeOf(n)))
- }
- return id
- }
- func odesign(o object.Object) (id scope.ID) {
- switch x := o.(type) {
- case object.VariableObject, object.ParameterObject:
- id = scope.ID{Name: x.Name()}
- default:
- panic(fmt.Sprintln("unsupported", reflect.TypeOf(o)))
- }
- return id
- }
- func obj(o object.Object) (key scope.ID, val interface{}) {
- switch x := o.(type) {
- case object.ConstantObject, object.ProcedureObject, object.TypeObject:
- case object.VariableObject, object.FieldObject:
- //fmt.Println(x.Name())
- key = scope.ID{Name: x.Name()}
- switch t := x.Complex().(type) {
- case nil:
- val = &basic{link: o}
- case object.BasicType:
- val = &basic{link: o}
- case object.ArrayType:
- val = &arr{link: o, par: t.Len()}
- case object.DynArrayType:
- val = &arr{link: o}
- case object.RecordType:
- val = &rec{link: o}
- default:
- fmt.Println("unexpected", reflect.TypeOf(t))
- }
- case object.ParameterObject:
- //fmt.Println("'" + x.Name())
- key = scope.ID{Name: x.Name()}
- val = &ref{link: o}
- default:
- fmt.Println(reflect.TypeOf(o))
- }
- return key, val
- }
- func (m *manager) Allocate(n node.Node, final bool) {
- h := &area{ready: final, root: n, x: make(map[scope.ID]interface{})}
- mod := rt_mod.DomainModule(m.Domain())
- var alloc func(h KVarea, o object.Object)
- alloc = func(h KVarea, o object.Object) {
- if k, v := obj(o); v != nil {
- h.set(k, v)
- switch rv := v.(type) {
- case record:
- rv.init(n)
- switch t := o.Complex().(type) {
- case object.RecordType:
- for rec := t; rec != nil; {
- for x := rec.Link(); x != nil; x = x.Link() {
- //fmt.Println(o.Name(), ".", x.Name())
- alloc(v.(KVarea), x)
- }
- rec = rec.BaseType()
- }
- }
- }
- } else {
- //fmt.Println("nil allocated", reflect.TypeOf(o))
- }
- }
- for _, o := range mod.Objects[n] {
- alloc(h, o)
- }
- m.areas.PushFront(h)
- //fmt.Println("allocate")
- }
- func (m *manager) Initialize(n node.Node, o object.Object, _val node.Node) {
- e := m.areas.Front()
- assert.For(e != nil, 20)
- h := e.Value.(*area)
- assert.For(h.root == n, 21)
- assert.For(!h.ready, 22)
- val := _val
- //fmt.Println("initialize")
- for next := o; next != nil; next = next.Link() {
- assert.For(val != nil, 40)
- //fmt.Println(reflect.TypeOf(next), next.Name(), ":", next.Type())
- //fmt.Println(reflect.TypeOf(val))
- switch ov := val.(type) {
- case node.ConstantNode:
- switch next.(type) {
- case object.VariableObject:
- m.Update(odesign(next), func(old interface{}) interface{} {
- return ov.Data()
- })
- case object.ParameterObject:
- k, v := scope.ID{Name: next.Name()}, &basic{link: o}
- h.set(k, v)
- m.Update(odesign(next), func(old interface{}) interface{} {
- return ov.Data()
- })
- default:
- panic("unknown value")
- }
- case node.VariableNode, node.ParameterNode:
- switch next.(type) {
- case object.VariableObject:
- m.Update(odesign(next), func(old interface{}) interface{} {
- return m.Select(odesign(ov.Object()))
- })
- case object.ParameterObject:
- h.get(scope.ID{Name: next.Name()}).(*ref).ref = design(ov)
- }
- default:
- panic("unknown value")
- }
- val = val.Link()
- }
- h.ready = true
- }
- func (m *manager) Dispose(n node.Node) {
- e := m.areas.Front()
- if e != nil {
- h := e.Value.(*area)
- assert.For(h.root == n, 21)
- m.areas.Remove(e)
- //fmt.Println("dispose")
- }
- }
- func (m *manager) Select(i scope.ID) interface{} {
- //fmt.Println("select", i)
- depth := 0
- type result struct {
- x interface{}
- }
- var res *result
- var sel func(interface{}) *result
- sel = func(x interface{}) (ret *result) {
- switch x := x.(type) {
- case value:
- ret = &result{x: x.get()}
- case reference:
- i = x.id()
- ret = nil
- case array:
- if i.Index != nil {
- ret = &result{x: x.get(*i.Index)}
- } else {
- ret = &result{x: x.sel()}
- }
- case record:
- if i.Path[depth] == "" {
- ret = &result{x: x.(*rec).link}
- } else {
- z := x.getField(i.Path[depth])
- depth++
- ret = sel(z)
- }
- case nil:
- //do nothing
- default:
- panic(0)
- }
- return ret
- }
- for e := m.areas.Front(); (e != nil) && (res == nil); e = e.Next() {
- h := e.Value.(*area)
- if h.ready {
- depth = 0
- res = sel(h.get(i))
- }
- }
- assert.For(res != nil, 40)
- //fmt.Println(res.x)
- return res.x
- }
- func arrConv(x interface{}) []interface{} {
- switch a := x.(type) {
- case string:
- s := []rune(a)
- ret := make([]interface{}, 0)
- for i := 0; i < len(s); i++ {
- ret = append(ret, s[i])
- }
- return ret
- case []interface{}:
- return a
- default:
- panic(fmt.Sprintln("unsupported", reflect.TypeOf(x)))
- }
- }
- func (m *manager) Update(i scope.ID, val scope.ValueFor) {
- assert.For(val != nil, 21)
- var x interface{}
- fmt.Println("update", i)
- depth := 0
- var upd func(x interface{}) (ret interface{})
- upd = func(x interface{}) (ret interface{}) {
- switch x := x.(type) {
- case value:
- old := x.get()
- tmp := val(old)
- assert.For(tmp != nil, 40) //если устанавливают значение NIL, значит делают что-то неверно
- //fmt.Println(tmp)
- x.set(tmp)
- ret = x
- case reference:
- i.Name = x.id().Name
- ret = nil
- case array:
- if i.Index != nil {
- old := x.get(*i.Index)
- tmp := val(old)
- assert.For(tmp != nil, 40) //если устанавливают значение NIL, значит делают что-то неверно
- //fmt.Println(tmp)
- x.set(*i.Index, tmp)
- } else {
- old := x.sel()
- tmp := val(old)
- assert.For(tmp != nil, 40) //если устанавливают значение NIL, значит делают что-то неверно
- //fmt.Println(tmp)
- x.upd(arrConv(tmp))
- }
- ret = x
- case record:
- if i.Path[depth] == "" {
- //fmt.Println(i, depth)
- panic(0) //случай выбора всей записи целиком
- } else {
- z := x.getField(i.Path[depth])
- depth++
- ret = upd(z)
- }
- case nil:
- //do nothing
- ret = x
- default:
- panic(fmt.Sprintln("unhandled", reflect.TypeOf(x)))
- }
- return ret
- }
- for e := m.areas.Front(); (e != nil) && (x == nil); e = e.Next() {
- h := e.Value.(*area)
- depth = 0
- x = upd(h.get(i))
- }
- assert.For(x != nil, 40)
- }
- func (m *manager) Init(d context.Domain) { m.d = d }
- func (m *manager) Domain() context.Domain { return m.d }
- func (m *manager) Handle(msg interface{}) {}
- func FindObjByName(mgr scope.Manager, name string) (ret object.Object) {
- assert.For(name != "", 20)
- m := mgr.(*manager)
- for e := m.areas.Front(); (e != nil) && (ret == nil); e = e.Next() {
- h := e.Value.(*area)
- x := h.get(scope.ID{Name: name})
- switch x.(type) {
- case *basic:
- ret = x.(*basic).link
- default:
- //fmt.Println("no such object")
- }
- }
- return ret
- }
|