Browse Source

модули загружаются и выполняют код секций в правильном порядке, как в ББ.
осталось оформить доступ к объектам

p.kushnir 10 năm trước cách đây
mục cha
commit
f43fc4cd8c

+ 1 - 1
.mailmap

@@ -1 +1 @@
-kpmy <petryxa.clever@gmail.com> p.kushnir <p.kushnir@gismps.ru>
+kpmy <petryxa.clever@gmail.com> p.kushnir <p.kushnir@ctt.com.rzd>

BIN
code/XevDemo21.oz


BIN
code/XevDemo22.oz


+ 26 - 2
cp/module/module.go

@@ -7,11 +7,18 @@ import (
 	"ypk/assert"
 )
 
+type Import struct {
+	Name    string
+	Objects []object.Object
+}
+
 type Module struct {
+	Name    string
 	Enter   node.Node
 	Objects map[node.Node][]object.Object
 	Nodes   []node.Node
 	Types   map[node.Node][]object.ComplexType
+	Imports map[string]Import
 }
 
 type named interface {
@@ -30,12 +37,29 @@ func (m *Module) TypeByName(scope node.Node, name string) (ret object.ComplexTyp
 	return ret
 }
 
-func (m *Module) NodeByObject(obj object.Object) (ret node.Node) {
+func (m *Module) ImportOf(obj object.Object) string {
+	contains := func(v []object.Object) bool {
+		for _, o := range v {
+			if o == obj {
+				return true
+			}
+		}
+		return false
+	}
+	for _, v := range m.Imports {
+		if contains(v.Objects) {
+			return v.Name
+		}
+	}
+	return ""
+}
+
+func (m *Module) NodeByObject(obj object.Object) (ret []node.Node) {
 	assert.For(obj != nil, 20)
 	for i := 0; (i < len(m.Nodes)) && (ret == nil); i++ {
 		node := m.Nodes[i]
 		if node.Object() == obj {
-			ret = node
+			ret = append(ret, node)
 		}
 	}
 	return ret

+ 9 - 5
domain.go

@@ -6,13 +6,15 @@ import (
 )
 
 type stdDomain struct {
-	list   map[string]context.ContextAware
-	parent context.Domain
+	list map[string]context.ContextAware
+	//parent context.Domain
 	global context.Domain
 	god    bool
 }
 
-func (d *stdDomain) ConnectTo(name string, x context.ContextAware) {
+func (d *stdDomain) New() context.Domain { return &stdDomain{global: d.global} }
+
+func (d *stdDomain) Attach(name string, x context.ContextAware) {
 	assert.For(x != nil, 20)
 	assert.For(name != context.UNIVERSE, 21)
 	if d.list == nil {
@@ -36,11 +38,13 @@ func (d *stdDomain) Discover(name string) (ret context.ContextAware) {
 			ret = d.global.Discover(name)
 		}
 	}
+	assert.For(ret != nil, 60) //все плохо
 	return ret
 }
 
 func (d *stdDomain) Domain() context.Domain {
-	return d.parent
+	return d.global
+	//return d.parent
 }
 
 func (d *stdDomain) Handle(msg interface{}) {}
@@ -48,7 +52,7 @@ func (d *stdDomain) Handle(msg interface{}) {}
 func (d *stdDomain) Init(dd context.Domain) {
 	glob := dd.(*stdDomain)
 	assert.For(glob.god == true, 20) //допустим только один уровень вложенности доменов пока
-	d.parent = dd
+	//	d.parent = dd
 	d.global = dd
 }
 

+ 12 - 27
fw.go

@@ -3,10 +3,10 @@ package main
 import (
 	"flag"
 	"fmt"
+	mod "fw/cp/module"
 	"fw/rt2/context"
-	"fw/rt2/frame"
-	"fw/rt2/module"
-	"fw/rt2/nodeframe"
+	"fw/rt2/decision"
+	rtmod "fw/rt2/module"
 	_ "fw/rt2/rules"
 	"fw/rt2/scope"
 	_ "fw/rt2/scope/std"
@@ -30,32 +30,17 @@ func main() {
 		name = "XevDemo22"
 	}
 	global := &stdDomain{god: true}
-	modList := module.New()
-	global.ConnectTo(context.MOD, modList)
-	global.ConnectTo(context.HEAP, scope.NewHeap())
+	modList := rtmod.New()
+	global.Attach(context.MOD, modList)
+	global.Attach(context.HEAP, scope.NewHeap())
 	t0 := time.Now()
-	ret, err := modList.Load(name)
+	var init []*mod.Module
+	_, err := modList.Load(name, func(m *mod.Module) {
+		init = append(init, m)
+	})
 	t1 := time.Now()
 	fmt.Println("load", t1.Sub(t0))
-	assert.For(ret != nil, 40)
-	assert.For(err == nil, 41)
+	assert.For(err == nil, 40)
 	defer close()
-	{
-		domain := new(stdDomain)
-		global.ConnectTo(name, domain)
-		root := frame.NewRoot()
-		domain.ConnectTo(context.STACK, root)
-		domain.ConnectTo(context.SCOPE, scope.NewStack())
-		var fu nodeframe.FrameUtils
-		root.PushFor(fu.New(ret.Enter), nil)
-		i := 0
-		t0 := time.Now()
-		for x := frame.NOW; x == frame.NOW; x = root.Do() {
-			//fmt.Println(x)
-			i++
-		}
-		t1 := time.Now()
-		fmt.Println("total steps", i)
-		fmt.Println("spent", t1.Sub(t0))
-	}
+	decision.Run(global, init)
 }

+ 5 - 0
fw_test.bat

@@ -41,6 +41,11 @@ fw -i=XevDemo19
 IF ERRORLEVEL 1 GOTO err
 fw -i=XevDemo20
 IF ERRORLEVEL 1 GOTO err
+fw -i=XevDemo21
+IF ERRORLEVEL 1 GOTO err
+fw -i=XevDemo22
+IF ERRORLEVEL 1 GOTO err
+
 GOTO ok
 :err
 echo FAILED

+ 5 - 1
rt2/context/ctx.go

@@ -8,8 +8,12 @@ const (
 	HEAP     = "fw/rt2/scope,heap"
 )
 
+type Factory interface {
+	New() Domain
+}
+
 type Domain interface {
-	ConnectTo(name string, c ContextAware)
+	Attach(name string, c ContextAware)
 	Discover(name string) ContextAware
 	Id(c ContextAware) string
 	ContextAware

+ 3 - 0
rt2/decision/table.go

@@ -1,11 +1,14 @@
 package decision
 
 import (
+	"fw/cp/module"
 	"fw/cp/node"
+	"fw/rt2/context"
 	"fw/rt2/frame"
 )
 
 var (
+	Run         func(global context.Domain, init []*module.Module)
 	PrologueFor func(n node.Node) frame.Sequence
 	EpilogueFor func(n node.Node) frame.Sequence
 )

+ 22 - 0
rt2/frame/frame.go

@@ -11,8 +11,30 @@ const (
 	STOP
 	LATER
 	NOW
+	//спец коды для начальной и конечной стадии
+	BEGIN
+	END
 )
 
+func (w WAIT) String() string {
+	switch w {
+	case NOW:
+		return "NOW"
+	case LATER:
+		return "LATER"
+	case STOP:
+		return "STOP"
+	case WRONG:
+		return "WRONG"
+	case BEGIN:
+		return "BEGIN"
+	case END:
+		return "END"
+	default:
+		panic("wrong wait value")
+	}
+}
+
 // LIFO-стек, позволяет затолкнуть фрейм связанный с другим фреймом
 type Stack interface {
 	PushFor(f, parent Frame)

+ 131 - 0
rt2/frame/std/sf.go

@@ -0,0 +1,131 @@
+package std
+
+import (
+	"container/list"
+	"fmt"
+	"fw/rt2/context"
+	"fw/rt2/frame"
+	"fw/rt2/scope"
+	"ypk/assert"
+)
+
+type FlowFrame interface {
+}
+
+type RootFrame struct {
+	inner  list.List
+	domain context.Domain
+}
+
+func (f *RootFrame) init() *RootFrame {
+	f.inner = *list.New()
+	return f
+}
+
+func NewRoot() *RootFrame {
+	return new(RootFrame).init()
+}
+
+func (f *RootFrame) PushFor(fr, parent frame.Frame) {
+	_, ok := fr.(*RootFrame)
+	if ok {
+		panic("impossibru")
+	}
+	f.inner.PushFront(fr)
+	if parent == nil {
+		domain := f.Domain().(context.Factory).New()
+		domain.Attach(context.SCOPE, scope.NewStack())
+		fr.Init(domain)
+	} else {
+		fr.Init(parent.Domain())
+	}
+	fr.OnPush(f, parent)
+}
+
+func (f *RootFrame) Pop() {
+	if f.inner.Front() != nil {
+		elem := f.inner.Front()
+		frame := elem.Value.(frame.Frame)
+		frame.OnPop()
+		f.inner.Remove(elem)
+	} else {
+		panic("it's empty stack")
+	}
+}
+
+func (f *RootFrame) Top() (fr frame.Frame) {
+	elem := f.inner.Front()
+	if elem != nil {
+		fr = elem.Value.(frame.Frame)
+	}
+	return fr
+}
+
+func (f *RootFrame) Drop() (fr frame.Frame) {
+	elem := f.inner.Front()
+	if elem != nil {
+		fr = elem.Value.(frame.Frame)
+		f.inner.Remove(elem)
+	}
+	return fr
+}
+
+func (f *RootFrame) Do() (res frame.WAIT) {
+	var (
+		trapped bool
+	)
+	if f.Top() != nil {
+		x := f.Top()
+		//цикл дейкстры
+		for {
+			wait := x.Do()
+			//fmt.Println(wait)
+			if wait == frame.LATER || wait == frame.BEGIN || wait == frame.END {
+				break
+			} else if wait == frame.NOW {
+			} else if wait == frame.WRONG {
+				trapped = true
+				fmt.Println("it's a trap")
+				break
+				//panic("something wrong") do nothing, it's a trap
+			} else if wait == frame.STOP {
+				if x == f.Top() {
+					f.Pop()
+				} else {
+					panic("do not stop if not top on stack")
+				}
+				break
+			} else {
+				panic("wrong wait code")
+			}
+		}
+	}
+	if f.Top() != nil && !trapped {
+		res = frame.NOW
+	} else {
+		res = frame.STOP
+	}
+	return res
+}
+
+func (f *RootFrame) ForEach(run func(x frame.Frame) bool) {
+	e := f.inner.Front()
+	ok := true
+	for (e != nil) && ok {
+		ok = run(e.Value.(frame.Frame))
+		e = e.Next()
+	}
+}
+
+func (f *RootFrame) OnPush(a frame.Stack, b frame.Frame) {}
+func (f *RootFrame) OnPop()                              {}
+func (f *RootFrame) Parent() frame.Frame                 { return nil }
+func (f *RootFrame) Root() frame.Stack                   { return nil }
+func (f *RootFrame) Domain() context.Domain              { return f.domain }
+func (f *RootFrame) Init(d context.Domain) {
+	assert.For(f.domain == nil, 20)
+	assert.For(d != nil, 21)
+	f.domain = d
+}
+
+func (f *RootFrame) Handle(msg interface{}) {}

+ 0 - 122
rt2/frame/stdFrame.go

@@ -1,122 +0,0 @@
-package frame
-
-import (
-	"container/list"
-	"fw/rt2/context"
-	"ypk/assert"
-)
-
-type RootFrame struct {
-	inner  list.List
-	domain context.Domain
-}
-
-func (f *RootFrame) init() *RootFrame {
-	f.inner = *list.New()
-	return f
-}
-
-func NewRoot() *RootFrame {
-	return new(RootFrame).init()
-}
-
-func (f *RootFrame) PushFor(frame, parent Frame) {
-	_, ok := frame.(*RootFrame)
-	if ok {
-		panic("impossibru")
-	}
-	f.inner.PushFront(frame)
-	frame.Init(f.Domain())
-	frame.OnPush(f, parent)
-}
-
-func (f *RootFrame) Pop() {
-	if f.inner.Front() != nil {
-		elem := f.inner.Front()
-		frame := elem.Value.(Frame)
-		frame.OnPop()
-		f.inner.Remove(elem)
-	} else {
-		panic("it's empty stack")
-	}
-}
-
-func (f *RootFrame) Top() (frame Frame) {
-	elem := f.inner.Front()
-	if elem != nil {
-		frame = elem.Value.(Frame)
-	}
-	return frame
-}
-
-func (f *RootFrame) Do() (res WAIT) {
-	var trapped bool
-	if f.Top() != nil {
-		x := f.Top()
-		//цикл дейкстры
-		for {
-			wait := x.Do()
-			//fmt.Println(wait)
-			if wait == LATER {
-				break
-			} else if wait == NOW {
-			} else if wait == WRONG {
-				trapped = true
-				break
-				//panic("something wrong") do nothing, it's a trap
-			} else if wait == STOP {
-				if x == f.Top() {
-					f.Pop()
-				} else {
-					panic("do not stop if not top on stack")
-				}
-				break
-			} else {
-				panic("wrong wait code")
-			}
-		}
-	}
-	if f.Top() != nil && !trapped {
-		res = NOW
-	} else {
-		res = STOP
-	}
-	return res
-}
-
-func (f *RootFrame) ForEach(run func(x Frame) bool) {
-	e := f.inner.Front()
-	ok := true
-	for (e != nil) && ok {
-		ok = run(e.Value.(Frame))
-		e = e.Next()
-	}
-}
-
-func (f *RootFrame) OnPush(a Stack, b Frame) {}
-func (f *RootFrame) OnPop()                  {}
-func (f *RootFrame) Parent() Frame           { return nil }
-func (f *RootFrame) Root() Stack             { return nil }
-func (f *RootFrame) Domain() context.Domain  { return f.domain }
-func (f *RootFrame) Init(d context.Domain) {
-	assert.For(f.domain == nil, 20)
-	assert.For(d != nil, 21)
-	f.domain = d
-}
-
-func (f *RootFrame) Handle(msg interface{}) {}
-
-func (w WAIT) String() string {
-	switch w {
-	case NOW:
-		return "NOW"
-	case LATER:
-		return "LATER"
-	case STOP:
-		return "STOP"
-	case WRONG:
-		return "WRONG"
-	default:
-		panic("wrong wait value")
-	}
-}

+ 25 - 6
rt2/module/ml.go

@@ -1,6 +1,7 @@
 package module
 
 import (
+	"fmt"
 	mod "fw/cp/module"
 	"fw/rt2/context"
 	"fw/xev"
@@ -8,11 +9,13 @@ import (
 	"ypk/assert"
 )
 
+type Loader func(*mod.Module)
+
 type List interface {
 	context.ContextAware
 	AsList() []*mod.Module
-	Load(name string) (*mod.Module, error)
-	Loaded(name string) *mod.Module
+	Load(string, ...Loader) (*mod.Module, error)
+	Loaded(string) *mod.Module
 }
 
 func New() List {
@@ -48,15 +51,30 @@ func (l *list) Init(d context.Domain) {
 }
 
 func (l *list) Handle(msg interface{}) {}
-func (l *list) Load(name string) (*mod.Module, error) {
+
+func (l *list) Load(name string, ldr ...Loader) (ret *mod.Module, err error) {
 	assert.For(name != "", 20)
-	ret := l.Loaded(name)
+	fmt.Println("loading", name, "loaded", l.Loaded(name) != nil)
+	ret = l.Loaded(name)
+	var loader Loader = func(m *mod.Module) {}
+	if len(ldr) > 0 {
+		loader = ldr[0]
+	}
 	if ret == nil {
 		path, _ := os.Getwd()
 		ret = xev.Load(path, name+".oz")
-		l.inner[name] = ret
+		ret.Name = name
+		for _, imp := range ret.Imports {
+			fmt.Println("imports", imp.Name, "loaded", l.Loaded(imp.Name) != nil)
+			_, err = l.Load(imp.Name, loader)
+		}
+		if err == nil {
+			l.inner[name] = ret
+			loader(ret)
+			fmt.Println("loaded", name)
+		}
 	}
-	return ret, nil
+	return ret, err
 }
 
 func (l *list) Loaded(name string) *mod.Module {
@@ -67,6 +85,7 @@ func (l *list) Loaded(name string) *mod.Module {
 func DomainModule(d context.Domain) *mod.Module {
 	uni := d.Discover(context.UNIVERSE).(context.Domain)
 	name := uni.Id(d)
+	assert.For(name != "", 40)
 	ml := uni.Discover(context.MOD).(List)
 	return ml.Loaded(name)
 }

+ 13 - 4
rt2/rules/call.go

@@ -39,7 +39,9 @@ func callHandler(f frame.Frame, obj object.Object, data interface{}) {
 	}
 	m := rt_mod.DomainModule(f.Domain())
 	cn := node.New(constant.CALL)
-	cn.SetLeft(m.NodeByObject(obj))
+	ol := m.NodeByObject(obj)
+	assert.For(len(ol) <= 1, 40)
+	cn.SetLeft(ol[0])
 	cc := node.New(constant.CONSTANT).(node.ConstantNode)
 	cc.SetData(data)
 	cn.SetRight(cc)
@@ -107,8 +109,15 @@ func callSeq(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
 			seq = Propose(Tail(STOP))
 			ret = frame.NOW
 		} else {
-			proc := m.NodeByObject(n.Left().Object())
-			call(proc)
+			if m.ImportOf(n.Left().Object()) == "" {
+				proc := m.NodeByObject(n.Left().Object())
+				fmt.Println(len(proc), len(n.Left().Object().Ref()))
+				call(proc[0])
+			} else {
+				fmt.Println("foreign call, stop for now")
+				seq = Propose(Tail(STOP))
+				ret = frame.NOW
+			}
 		}
 	case node.VariableNode:
 		m := rt_mod.DomainModule(f.Domain())
@@ -117,7 +126,7 @@ func callSeq(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
 
 		if obj, ok := obj.(object.Object); ok {
 			proc := m.NodeByObject(obj)
-			call(proc)
+			call(proc[0])
 		} else {
 			name := n.Left().Object().Name()
 			switch {

+ 6 - 3
rt2/rules/enter.go

@@ -1,9 +1,11 @@
 package rules
 
 import (
+	"fmt"
 	"fw/cp/node"
 	"fw/rt2/context"
 	"fw/rt2/frame"
+	"fw/rt2/module"
 	"fw/rt2/nodeframe"
 	"fw/rt2/scope"
 )
@@ -23,18 +25,19 @@ func enterSeq(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
 		} else {
 			//Особый случай, вход в модуль, секция BEGIN
 			fu.Push(fu.New(body), f)
-
+			fmt.Println("begin", module.DomainModule(f.Domain()).Name)
 			//Выход из модуля, секция CLOSE
 			next := n.Link()
 			if next != nil {
 				seq = func(f frame.Frame) (frame.Sequence, frame.WAIT) {
+					fmt.Println("end", module.DomainModule(f.Domain()).Name)
 					f.Root().PushFor(fu.New(next), f)
-					return frame.Tail(frame.STOP), frame.LATER
+					return frame.Tail(frame.STOP), frame.END
 				}
 			} else {
 				seq = frame.Tail(frame.STOP)
 			}
-			return seq, frame.LATER
+			return seq, frame.BEGIN
 
 		}
 	}

+ 10 - 0
rt2/rules/seq.go

@@ -11,6 +11,8 @@ const (
 	STOP
 	LATER
 	NOW
+	BEGIN
+	END
 )
 
 type Do func(...IN) OUT
@@ -34,6 +36,10 @@ func (n WAIT) wait() frame.WAIT {
 		return frame.LATER
 	case NOW:
 		return frame.NOW
+	case BEGIN:
+		return frame.BEGIN
+	case END:
+		return frame.END
 	default:
 		panic(n)
 	}
@@ -49,6 +55,10 @@ func waiting(n frame.WAIT) WAIT {
 		return LATER
 	case frame.NOW:
 		return NOW
+	case frame.BEGIN:
+		return BEGIN
+	case frame.END:
+		return END
 	default:
 		panic(n)
 	}

+ 104 - 0
rt2/rules/table.go

@@ -3,15 +3,20 @@ package rules
 
 import (
 	"fmt"
+	"fw/cp/module"
 	"fw/cp/node"
 	"fw/rt2"
 	"fw/rt2/context"
 	"fw/rt2/decision"
 	"fw/rt2/frame"
+	"fw/rt2/frame/std"
+	rt_module "fw/rt2/module"
 	"fw/rt2/nodeframe"
 	"fw/rt2/scope"
 	"fw/utils"
 	"reflect"
+	"time"
+	"ypk/assert"
 )
 
 func prologue(n node.Node) frame.Sequence {
@@ -109,6 +114,7 @@ func epilogue(n node.Node) frame.Sequence {
 		}
 	case node.EnterNode:
 		return func(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
+			fmt.Println(rt_module.DomainModule(f.Domain()).Name)
 			sm := scope.This(f.Domain().Discover(context.SCOPE))
 			sm.Target().(scope.ScopeAllocator).Dispose(n)
 			return frame.End()
@@ -122,7 +128,105 @@ func epilogue(n node.Node) frame.Sequence {
 	}
 }
 
+type flow struct {
+	root   frame.Stack
+	parent frame.Frame
+	domain context.Domain
+	fl     []frame.Frame
+	cl     []frame.Frame
+	this   int
+}
+
+func (f *flow) Do() (ret frame.WAIT) {
+	const Z WAIT = -1
+	x := Z
+	if f.this >= 0 {
+		x = waiting(f.fl[f.this].Do())
+	}
+	switch x {
+	case NOW, WRONG, LATER, BEGIN:
+		ret = WAIT.wait(x)
+	case END:
+		old := f.Root().(*std.RootFrame).Drop()
+		assert.For(old != nil, 40)
+		f.cl = append(f.cl, old)
+		ret = WAIT.wait(LATER)
+	case STOP, Z:
+		f.this--
+		if f.this >= 0 {
+			ret = WAIT.wait(LATER)
+		} else {
+			if len(f.cl) > 0 {
+				for _, old := range f.cl {
+					n := rt2.NodeOf(old)
+					rt2.Push(rt2.New(n), old.Parent())
+				}
+				f.cl = nil
+				ret = WAIT.wait(LATER)
+			} else {
+				ret = WAIT.wait(STOP)
+			}
+		}
+	}
+	fmt.Println(">", ret)
+	return ret
+}
+
+func (f *flow) OnPush(root frame.Stack, parent frame.Frame) {
+	f.root = root
+	f.parent = parent
+	fmt.Println("flow control pushed")
+	f.this = len(f.fl) - 1
+}
+
+func (f *flow) OnPop() {
+	fmt.Println("flow control poped")
+}
+
+func (f *flow) Parent() frame.Frame    { return f.parent }
+func (f *flow) Root() frame.Stack      { return f.root }
+func (f *flow) Domain() context.Domain { return f.domain }
+func (f *flow) Init(d context.Domain) {
+	assert.For(f.domain == nil, 20)
+	assert.For(d != nil, 21)
+	f.domain = d
+}
+
+func (f *flow) Handle(msg interface{}) {
+	assert.For(msg != nil, 20)
+}
+
+func run(global context.Domain, init []*module.Module) {
+	{
+		var (
+			root *std.RootFrame = std.NewRoot()
+			nf   frame.Frame
+			ff   []frame.Frame
+		)
+		global.Attach(context.STACK, root)
+		for i := len(init) - 1; i >= 0; i-- {
+			ret := init[i]
+			fmt.Println("queue", ret.Name)
+			nf = rt2.New(ret.Enter)
+			root.PushFor(nf, nil)
+			ff = append(ff, nf)
+			global.Attach(ret.Name, nf.Domain())
+		}
+		root.PushFor(&flow{fl: ff}, nil)
+		i := 0
+		t0 := time.Now()
+		for x := frame.NOW; x == frame.NOW; x = root.Do() {
+			//fmt.Println(x)
+			i++
+		}
+		t1 := time.Now()
+		fmt.Println("total steps", i)
+		fmt.Println("spent", t1.Sub(t0))
+	}
+}
+
 func init() {
 	decision.PrologueFor = prologue
 	decision.EpilogueFor = epilogue
+	decision.Run = run
 }

+ 1 - 1
rt2/scope/std/scope.go

@@ -335,7 +335,7 @@ func (m *manager) Dispose(n node.Node) {
 		h := e.Value.(*area)
 		assert.For(h.root == n, 21)
 		m.areas.Remove(e)
-		//fmt.Println("dispose")
+		fmt.Println("dispose")
 	}
 }
 

+ 29 - 17
xev/converter.go

@@ -175,6 +175,16 @@ var nodeMap map[int]node.Node
 var objectMap map[int]object.Object
 var typeMap map[int]object.ComplexType
 
+func reset() {
+	nodeMap = make(map[int]node.Node)
+	objectMap = make(map[int]object.Object)
+	typeMap = make(map[int]object.ComplexType)
+	ncache = make(map[int]*Node)
+	ecache = make(map[eid]*Node)
+}
+
+func init() { reset() }
+
 func (r *Result) doType(n *Node) (ret object.ComplexType) {
 	//fmt.Println("type", n.Id)
 	ret = typeMap[n.Id]
@@ -497,7 +507,8 @@ func (r *Result) buildNode(n *Node) (ret node.Node) {
 	return ret
 }
 
-func buildMod(r *Result) (nodeList []node.Node, scopeList map[node.Node][]object.Object, typeList map[node.Node][]object.ComplexType, root node.Node) {
+func buildMod(r *Result) *module.Module {
+	//временные структуры создаем по очереди, чтобы корректно заполнять все ссылки на объекты/узлы
 	type scope struct {
 		mod    string
 		scopes map[int][]object.Object
@@ -527,11 +538,16 @@ func buildMod(r *Result) (nodeList []node.Node, scopeList map[node.Node][]object
 			fmt.Println(sc, len(this.scopes[sc]), len(this.types[sc]))
 		}
 	}
-	scopeList = make(map[node.Node][]object.Object, 0)
-	typeList = make(map[node.Node][]object.ComplexType, 0)
+	//временные структуры перегоняем в рабочие
+	var (
+		nodeList  []node.Node                        = make([]node.Node, 0)
+		scopeList map[node.Node][]object.Object      = make(map[node.Node][]object.Object, 0)
+		typeList  map[node.Node][]object.ComplexType = make(map[node.Node][]object.ComplexType, 0)
+		impList   map[string]module.Import           = make(map[string]module.Import, 0)
+		root      node.Node
+	)
 	for _, g := range r.GraphList {
 		if g.CptScope == "" {
-			nodeList = make([]node.Node, 0)
 			for _, nl := range g.NodeList {
 				node := &nl
 				ret := r.buildNode(node)
@@ -548,22 +564,18 @@ func buildMod(r *Result) (nodeList []node.Node, scopeList map[node.Node][]object
 			}
 		}
 	}
-	return nodeList, scopeList, typeList, root
+	for k, v := range scopes {
+		if k < 0 {
+			impList[v.mod] = module.Import{Objects: v.scopes[k], Name: v.mod}
+			fmt.Println("типы не учтены", len(v.types[k]))
+		}
+	}
+	return &module.Module{Nodes: nodeList, Objects: scopeList, Types: typeList, Enter: root, Imports: impList}
 }
 
 func DoAST(r *Result) (mod *module.Module) {
-	nodeMap = make(map[int]node.Node)
-	objectMap = make(map[int]object.Object)
-	typeMap = make(map[int]object.ComplexType)
-	ncache = make(map[int]*Node)
-	ecache = make(map[eid]*Node)
-	mod = new(module.Module)
-	mod.Nodes, mod.Objects, mod.Types, mod.Enter = buildMod(r)
+	mod = buildMod(r)
 	fmt.Println(len(mod.Nodes), len(mod.Objects))
-	nodeMap = nil
-	objectMap = nil
-	typeMap = nil
-	ecache = nil
-	ncache = nil
+	reset()
 	return mod
 }