123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- package modern
- import (
- "fmt"
- "fw/cp"
- "fw/cp/constant/enter"
- cpm "fw/cp/module"
- "fw/cp/node"
- "fw/cp/object"
- "fw/rt2"
- "fw/rt2/context"
- "fw/rt2/frame"
- rtm "fw/rt2/module"
- "fw/rt2/scope"
- "fw/utils"
- "reflect"
- "ypk/assert"
- "ypk/halt"
- )
- type level struct {
- k map[cp.ID]int
- v map[int]scope.Variable
- r map[int]scope.Ref
- l map[int]*level
- next int
- ready bool
- nested bool
- }
- type area struct {
- d context.Domain
- data []*level
- all scope.Allocator
- }
- type salloc struct {
- area *area
- }
- type ref struct {
- scope.Ref
- id cp.ID
- link object.Object
- sc scope.Manager
- }
- func (r *ref) String() string {
- var m string
- if r.sc != nil {
- m = rtm.DomainModule(r.sc.Domain()).Name
- }
- return fmt.Sprint(m, " ", r.link.Name(), "@", r.id)
- }
- func newRef(x object.Object) *ref {
- return &ref{link: x}
- }
- func newlvl() *level {
- return &level{next: 1,
- k: make(map[cp.ID]int), ready: true,
- v: make(map[int]scope.Variable),
- r: make(map[int]scope.Ref),
- l: make(map[int]*level)}
- }
- func (a *area) top() *level {
- if len(a.data) > 0 {
- return a.data[len(a.data)-1]
- }
- return nil
- }
- func (a *area) Provide(x interface{}) scope.ValueFor {
- return func(scope.Value) scope.Value {
- switch z := x.(type) {
- case node.ConstantNode:
- return newConst(z)
- case object.ProcedureObject:
- return newProc(z)
- default:
- halt.As(100, reflect.TypeOf(z))
- }
- panic(0)
- }
- }
- //var alloc func(*level, []object.Object, map[cp.ID]interface{})
- func (l *level) alloc(mod *cpm.Module, root node.Node, ol []object.Object, skip map[cp.ID]interface{}) {
- for _, o := range ol {
- imp := mod.ImportOf(o)
- utils.PrintScope(reflect.TypeOf(o), o.Adr())
- _, field := o.(object.FieldObject)
- if imp == "" && (skip[o.Adr()] == nil || (field && l.nested)) {
- utils.PrintScope("next", l.next)
- switch x := o.(type) {
- case object.VariableObject, object.FieldObject:
- switch t := o.Complex().(type) {
- case nil, object.BasicType, object.ArrayType, object.DynArrayType:
- l.v[l.next] = newData(x)
- l.k[x.Adr()] = l.next
- l.next++
- case object.RecordType:
- l.v[l.next] = newRec(x)
- nl := newlvl()
- nl.nested = true
- l.l[l.next] = nl
- l.k[x.Adr()] = l.next
- fl := make([]object.Object, 0)
- for rec := t; rec != nil; {
- for x := rec.Link(); x != nil; x = x.Link() {
- //fmt.Println(o.Name(), ".", x.Name(), x.Adr())
- fl = append(fl, x)
- }
- rec = rec.BaseType()
- }
- //fmt.Println("record")
- l.v[l.next].(*rec).l = nl
- nl.alloc(mod, root, fl, skip)
- l.next++
- case object.PointerType:
- l.v[l.next] = newPtr(x)
- l.k[x.Adr()] = l.next
- l.next++
- default:
- halt.As(20, reflect.TypeOf(t))
- }
- case object.TypeObject, object.ConstantObject, object.ProcedureObject, object.Module:
- //do nothing
- case object.ParameterObject:
- if root.(node.EnterNode).Enter() == enter.PROCEDURE {
- l.r[l.next] = newRef(x)
- l.k[x.Adr()] = l.next
- l.next++
- }
- default:
- halt.As(20, reflect.TypeOf(x))
- }
- }
- }
- }
- func (a *salloc) Allocate(n node.Node, final bool) {
- mod := rtm.DomainModule(a.area.d)
- utils.PrintScope("ALLOCATE FOR", mod.Name, n.Adr())
- tl := mod.Types[n]
- skip := make(map[cp.ID]interface{}) //для процедурных типов в общей куче могут валяться переменные, скипаем их
- for _, t := range tl {
- switch x := t.(type) {
- case object.BasicType:
- for link := x.Link(); link != nil; link = link.Link() {
- skip[link.Adr()] = link
- }
- case object.RecordType:
- for link := x.Link(); link != nil; link = link.Link() {
- skip[link.Adr()] = link
- }
- }
- }
- nl := newlvl()
- nl.ready = final
- a.area.data = append(a.area.data, nl)
- nl.alloc(mod, n, mod.Objects[n], skip)
- }
- func (a *salloc) Dispose(n node.Node) {
- x := a.area.data
- a.area.data = nil
- for i := 0; i < len(x)-1; i++ {
- a.area.data = append(a.area.data, x[i])
- }
- }
- func (a *salloc) Initialize(n node.Node, par scope.PARAM) (seq frame.Sequence, ret frame.WAIT) {
- utils.PrintScope("INITIALIZE")
- l := a.area.top()
- assert.For(l != nil && !l.ready, 20)
- val := par.Values
- f := par.Frame
- end := func(frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
- l.ready = true
- if par.Tail != nil {
- return par.Tail(f)
- } else {
- return frame.End()
- }
- }
- seq = end
- ret = frame.NOW
- var sm scope.Manager
- for next := par.Objects; next != nil; next = next.Link() {
- mod := rtm.ModuleOfNode(f.Domain(), val)
- if mod != nil {
- global := f.Domain().Discover(context.UNIVERSE).(context.Domain)
- fmt.Println(mod.Name)
- global = global.Discover(mod.Name).(context.Domain)
- sm = global.Discover(context.SCOPE).(scope.Manager)
- } else {
- sm = a.area
- }
- switch o := next.(type) {
- case object.VariableObject:
- switch nv := val.(type) {
- case node.ConstantNode:
- v := newConst(nv)
- l.v[l.k[o.Adr()]].Set(v)
- case node.VariableNode:
- v := sm.Select(nv.Object().Adr())
- l.v[l.k[o.Adr()]].Set(v)
- default:
- halt.As(40, reflect.TypeOf(nv))
- }
- case object.ParameterObject:
- switch nv := val.(type) {
- case node.VariableNode:
- old := l.r[l.k[o.Adr()]].(*ref)
- l.r[l.k[o.Adr()]] = &ref{link: old.link, sc: sm, id: nv.Object().Adr()}
- case node.ConstantNode: //array :) заменяем ссылку на переменную
- old := l.r[l.k[o.Adr()]].(*ref)
- l.r[l.k[o.Adr()]] = nil
- data := newConst(nv)
- switch data.(type) {
- case STRING, SHORTSTRING:
- val := &dynarr{link: old.link}
- val.Set(data)
- l.v[l.k[o.Adr()]] = val
- default:
- halt.As(100, reflect.TypeOf(data))
- }
- case node.DerefNode:
- rt2.Push(rt2.New(nv), f)
- rt2.Assert(f, func(f frame.Frame) (bool, int) {
- return rt2.ValueOf(f)[nv.Adr()] != nil, 60
- })
- dn := next
- old := l.r[l.k[dn.Adr()]].(*ref)
- seq = func(f frame.Frame) (frame.Sequence, frame.WAIT) {
- switch dn.(type) {
- case object.VariableObject, object.ParameterObject:
- l.r[l.k[dn.Adr()]] = nil
- data := rt2.ValueOf(f)[nv.Adr()]
- switch deref := data.(type) {
- case STRING, SHORTSTRING:
- val := &dynarr{link: old.link}
- val.Set(deref)
- l.v[l.k[dn.Adr()]] = val
- case *rec:
- l.v[l.k[dn.Adr()]] = deref
- default:
- halt.As(100, reflect.TypeOf(data))
- }
- default:
- panic(fmt.Sprintln("unknown value", reflect.TypeOf(next)))
- }
- return end, frame.NOW
- }
- ret = frame.LATER
- default:
- halt.As(40, reflect.TypeOf(nv))
- }
- default:
- halt.As(40, reflect.TypeOf(o))
- }
- val = val.Link()
- }
- return seq, ret
- }
- func (a *salloc) Join(m scope.Manager) { a.area = m.(*area) }
- func (a *area) Update(id cp.ID, fval scope.ValueFor) {
- assert.For(id != 0, 20)
- var upd func(x int, id cp.ID)
- var k int
- upd = func(x int, id cp.ID) {
- utils.PrintScope("UPDATE", id)
- for i := x - 1; i >= 0 && k == 0; i-- {
- l := a.data[i]
- if l.ready {
- k = l.k[id]
- if k != 0 {
- v := a.data[i].v[k]
- if v == nil { //ref?
- r := l.r[k]
- if r != nil {
- utils.PrintScope("ref")
- if r.(*ref).sc == a {
- upd(i, r.(*ref).id)
- } else {
- k = -1
- r.(*ref).sc.Update(r.(*ref).id, fval)
- }
- break
- }
- } else {
- v.Set(fval(a.data[i].v[k]))
- }
- }
- }
- }
- }
- k = 0
- upd(len(a.data), id)
- assert.For(k != 0, 60)
- }
- func (a *area) Select(id cp.ID, val ...scope.ValueOf) (ret scope.Value) {
- var sel func(x int, id cp.ID)
- sel = func(x int, id cp.ID) {
- utils.PrintScope("SELECT", id)
- for i := x - 1; i >= 0 && ret == nil; i-- {
- l := a.data[i]
- k := 0
- if l.ready {
- k = l.k[id]
- if k != 0 {
- ret = l.v[k]
- if ret == nil { //ref?
- r := l.r[k]
- if r != nil {
- if l.l[k] != nil { //rec
- panic(0)
- } else {
- utils.PrintScope("ref")
- if r.(*ref).sc == a {
- sel(i, r.(*ref).id)
- } else {
- ret = r.(*ref).sc.Select(r.(*ref).id)
- }
- }
- break
- }
- } else if len(val) > 0 {
- val[0](ret)
- }
- }
- }
- }
- }
- sel(len(a.data), id)
- assert.For(ret != nil, 60)
- return ret
- }
- func (a *area) Target(all ...scope.Allocator) scope.Allocator {
- if len(all) > 0 {
- a.all = all[0]
- }
- if a.all == nil {
- return &salloc{area: a}
- } else {
- a.all.Join(a)
- return a.all
- }
- }
- func (a *area) String() (ret string) {
- for _, l := range a.data {
- ret = fmt.Sprintln(ret, l)
- }
- return ret
- }
- func (l *level) String() (ret string) {
- for k, v := range l.k {
- ret = fmt.Sprint(ret, "@", k, v, l.v[v])
- if l.v[v] == nil {
- ret = fmt.Sprintln(ret, l.r[v])
- } else if l.l[v] != nil {
- ret = fmt.Sprintln(ret, "{")
- ret = fmt.Sprintln(ret, l.l[v], "}")
- } else {
- ret = fmt.Sprintln(ret)
- }
- }
- return ret
- }
- func (a *area) Init(d context.Domain) { a.d = d }
- func (a *area) Domain() context.Domain { return a.d }
- func (a *area) Handle(msg interface{}) {}
- func fn(mgr scope.Manager, name string) (ret object.Object) {
- utils.PrintScope("FIND", name)
- a, ok := mgr.(*area)
- assert.For(ok, 20)
- assert.For(name != "", 21)
- for i := len(a.data) - 1; i >= 0 && ret == nil; i-- {
- l := a.data[i]
- for _, v := range l.v {
- switch vv := v.(type) {
- case *data:
- utils.PrintScope(vv.link.Name())
- if vv.link.Name() == name {
- ret = vv.link
- }
- default:
- utils.PrintScope(reflect.TypeOf(vv))
- }
- }
- }
- return ret
- }
- func nn(role string) scope.Manager {
- if role == context.SCOPE {
- return &area{all: &salloc{}}
- } else if role == context.HEAP {
- return &area{all: &halloc{}}
- } else {
- panic(0)
- }
- }
- func init() {
- scope.New = nn
- scope.FindObjByName = fn
- }
|