class
compiler::OrderByInheritance
sys::Obj
compiler::CompilerSupport
compiler::CompilerStep
compiler::OrderByInheritance
1 //
2 // Copyright (c) 2006, Brian Frank and Andy Frank
3 // Licensed under the Academic Free License version 3.0
4 //
5 // History:
6 // 23 Sep 06 Brian Frank Creation
7 //
8
9 **
10 ** OrderByInheritance orders the list of TypeDefs from top to bottom
11 ** such that any inherited types are guaranteed to be positioned first
12 ** in the types list. During this process we check for duplicate type
13 ** names and cyclic inheritance.
14 **
15 class OrderByInheritance : CompilerStep
16 {
17
18 //////////////////////////////////////////////////////////////////////////
19 // Constructor
20 //////////////////////////////////////////////////////////////////////////
21
22 new make(Compiler compiler)
23 : super(compiler)
24 {
25 }
26
27 //////////////////////////////////////////////////////////////////////////
28 // Run
29 //////////////////////////////////////////////////////////////////////////
30
31 override Void run()
32 {
33 log.verbose("OrderByInheritance")
34 ordered = TypeDef[,]
35 ordered.capacity = types.size
36 processing = Str:TypeDef[:]
37
38 // create the todo map which is our working input,
39 // check for duplicate type names in this loop
40 todo = Str:TypeDef[:]
41 types.each |TypeDef t|
42 {
43 todo[t.qname] = t
44 }
45 bombIfErr
46
47 // process each type in order
48 types.each |TypeDef t| { process(t) }
49 bombIfErr
50
51 // use ordered types for rest of pipeline
52 if (ordered.size != compiler.types.size) throw Err.make("Internal error")
53 compiler.types = ordered
54 }
55
56 //////////////////////////////////////////////////////////////////////////
57 // Process
58 //////////////////////////////////////////////////////////////////////////
59
60 private Void process(CType t)
61 {
62 // check that this type is still in the todo
63 // list, otherwise we've already processed it
64 // or it is imported from another pod
65 def := todo[t.qname]
66 if (def == null) return
67
68 // check if this guy is in the processing queue,
69 // in which case we have cyclic inheritance
70 if (processing.containsKey(def.qname))
71 {
72 err("Cyclic inheritance for '$def.name'", def.location)
73 return
74 }
75 processing[def.qname] = def
76
77 // process inheritance
78 if (def.base != null) process(def.base)
79 def.mixins.each |CType m| { process(m) }
80
81 // now that is has been processed, removed it the
82 // todo map and add it to the ordered result list
83 processing.remove(def.qname)
84 todo.remove(def.qname)
85 ordered.add(def)
86 }
87
88 //////////////////////////////////////////////////////////////////////////
89 // Fields
90 //////////////////////////////////////////////////////////////////////////
91
92 Str:TypeDef processing // map of qname to typse being processed
93 Str:TypeDef todo // map of qname to types left to process
94 TypeDef[] ordered // ordered result list
95 }
2 // Copyright (c) 2006, Brian Frank and Andy Frank
3 // Licensed under the Academic Free License version 3.0
4 //
5 // History:
6 // 23 Sep 06 Brian Frank Creation
7 //
8
9 **
10 ** OrderByInheritance orders the list of TypeDefs from top to bottom
11 ** such that any inherited types are guaranteed to be positioned first
12 ** in the types list. During this process we check for duplicate type
13 ** names and cyclic inheritance.
14 **
15 class OrderByInheritance : CompilerStep
16 {
17
18 //////////////////////////////////////////////////////////////////////////
19 // Constructor
20 //////////////////////////////////////////////////////////////////////////
21
22 new make(Compiler compiler)
23 : super(compiler)
24 {
25 }
26
27 //////////////////////////////////////////////////////////////////////////
28 // Run
29 //////////////////////////////////////////////////////////////////////////
30
31 override Void run()
32 {
33 log.verbose("OrderByInheritance")
34 ordered = TypeDef[,]
35 ordered.capacity = types.size
36 processing = Str:TypeDef[:]
37
38 // create the todo map which is our working input,
39 // check for duplicate type names in this loop
40 todo = Str:TypeDef[:]
41 types.each |TypeDef t|
42 {
43 todo[t.qname] = t
44 }
45 bombIfErr
46
47 // process each type in order
48 types.each |TypeDef t| { process(t) }
49 bombIfErr
50
51 // use ordered types for rest of pipeline
52 if (ordered.size != compiler.types.size) throw Err.make("Internal error")
53 compiler.types = ordered
54 }
55
56 //////////////////////////////////////////////////////////////////////////
57 // Process
58 //////////////////////////////////////////////////////////////////////////
59
60 private Void process(CType t)
61 {
62 // check that this type is still in the todo
63 // list, otherwise we've already processed it
64 // or it is imported from another pod
65 def := todo[t.qname]
66 if (def == null) return
67
68 // check if this guy is in the processing queue,
69 // in which case we have cyclic inheritance
70 if (processing.containsKey(def.qname))
71 {
72 err("Cyclic inheritance for '$def.name'", def.location)
73 return
74 }
75 processing[def.qname] = def
76
77 // process inheritance
78 if (def.base != null) process(def.base)
79 def.mixins.each |CType m| { process(m) }
80
81 // now that is has been processed, removed it the
82 // todo map and add it to the ordered result list
83 processing.remove(def.qname)
84 todo.remove(def.qname)
85 ordered.add(def)
86 }
87
88 //////////////////////////////////////////////////////////////////////////
89 // Fields
90 //////////////////////////////////////////////////////////////////////////
91
92 Str:TypeDef processing // map of qname to typse being processed
93 Str:TypeDef todo // map of qname to types left to process
94 TypeDef[] ordered // ordered result list
95 }