blob: 74f7197bbc2fbd3b392d5e13118e4abd5b2773b6 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001class LocalSituation
2 attr_accessor :globals,:local
3 def initialize(globals)
4 @globals = globals
5 @local = nil
6 end
7 def package=(qualified)
8 if(@local)
9 raise QSyntaxError.new(<<ERROR_MSG)
10You are redefining the package path.
11 Stuff might break if you do that.
12 Other options include: using another header file, and just using the same namespace.
13 If you are confident that you need this you can remove this check at
14 #{__FILE__}:#{__LINE__}.
15 Or file a feature request.
16 But that would be weird...
17 Wot. Wot.
18ERROR_MSG
19 end
20 @local = @globals.space
21 qualified.names.each do |name|
22 @local = @local.get_make(name)
23 end
24 end
25 def register(value)
26 if(!@local)
27 raise QError.new(<<ERROR_MSG)
28There is no package path defined, This is a big problem because
29 we are kindof expecting you to have a package path...
30 use a :
31 package my_super.cool.project;
32 statement to remedy this situation. (or file a feature request)
33 Wot. Wot.
34ERROR_MSG
35 end
36 @local[value.name] = value
37 value.parent = @local if(value.respond_to?(:parent=))
38 value.loc = @local
39 end
40 def bind(bind_to)
41 return BoundSituation.new(self,bind_to)
42 end
43end
44class BoundSituation < LocalSituation
45 def initialize(locals,bind_to)
Parker Schuh343481e2014-02-09 18:28:43 -080046 @globals = locals.globals
brians343bc112013-02-10 01:53:46 +000047 @local = bind_to
48 end
49end
50class NameSpace
51 attr_accessor :parent,:name
52 def initialize(name = nil,parent = nil)
53 @name = name
54 @parent = parent
55 @spaces = {}
56 end
57 def []=(key,val)
58 if(old_val = @spaces[key])
59 old_val = old_val.created_by if(old_val.respond_to?(:created_by) && old_val.created_by)
60 if(old_val.respond_to?(:q_stack_name))
61 old_val = old_val.q_stack_name
62 else
63 old_val = "eh, it is a #{old_val.class} thats all I know..."
64 end
65 raise QNamespaceCollision.new(<<ERROR_MSG)
66Woah! The name #{queue_name(key).inspect} is already taken by some chap at #{old_val}.
67\tFind somewhere else to peddle your wares.
68\tWot. Wot.
69ERROR_MSG
70 end
71 @spaces[key] = val
72 end
73 def to_cpp_id(name)
74 txt = @name + "::" + name
75 return @parent.to_cpp_id(txt) if(@parent && parent.name)
76 return "::" + txt
77 end
78 def queue_name(queue)
79 get_name() + "." + queue
80 end
81 def [](key)
82 #puts "getting #{get_name}.#{key}"
83 @spaces[key]
84 end
85 def get_make(name)
86 @spaces[name] ||= self.class.new(name,self)
87 end
88 def get_name()
89 if(@parent)
90 return "#{@parent.get_name}.#{@name}"
91 else
92 return "#{@name}"
93 end
94 end
95 def create(cpp_tree)
96 if(@parent && @parent.name)
97 parent = cpp_tree.get(@parent)
98 else
99 parent = cpp_tree
100 end
101 return cpp_tree.add_namespace(@name,parent)
102 end
103 def to_s()
104 "<NameSpace: #{get_name()}>"
105 end
106 def inspect()
107 "<NameSpace: #{get_name()}>"
108 end
109 def root()
110 return self if(@parent == nil)
111 return @parent.root
112 end
113end
114class Globals
115 attr_accessor :space
116 def initialize()
117 @space = NameSpace.new()
118 @space.get_make("aos")
119 @include_paths = []
120 end
121 def paths()
122 @include_paths
123 end
124 def add_path(path)
125 @include_paths << path
126 end
127 def find_file(filename)
128 @include_paths.each do |path_name|
129 new_path = File.expand_path(path_name) + "/" + filename
130 if(File.exists?(new_path))
131 return new_path
132 end
133 end
134 raise QImportNotFoundError.new(<<ERROR_MSG)
135Problem Loading:#{filename.inspect} I looked in:
136\t#{(@include_paths.collect {|name| name.inspect}).join("\n\t")}
137\tbut alas, it was nowhere to be found.
138\tIt is popular to include the top of the repository as the include path start,
139\tand then reference off of that.
140\tI would suggest doing that and then trying to build again.
141\tWot. Wot.
142ERROR_MSG
143 end
144end
145class QualifiedName
146 attr_accessor :names,:off_root
147 def initialize(names,off_root = false)
148 @names = names
149 @off_root = off_root
150 end
151 def test_lookup(namespace)
152 @names.each do |name|
153 namespace = namespace[name]
154 return nil if(!namespace)
155 end
156 return namespace
157 end
158 def is_simple?()
159 return !@off_root && @names.length == 1
160 end
161 def to_simple()
162 return @names[-1]
163 end
164 def to_s()
165 if(@off_root)
166 return ".#{@names.join(".")}"
167 else
168 return @names.join(".")
169 end
170 end
171 def lookup(locals)
172 if(@off_root)
173 local = locals.globals.space
174 else
175 local = locals.local
176 end
177 target = nil
178 while(!target && local)
179 target = test_lookup(local)
180 local = local.parent
181 end
182 return target if(target)
183 if(@off_root)
184 raise QError.new(<<ERROR_MSG)
185I was looking for .#{@names.join(".")}, but alas, it was not under
186\tthe root namespace.
187\tI'm really sorry old chap.
188\tWot. Wot.
189ERROR_MSG
190 else
191 raise QError.new(<<ERROR_MSG)
192I was looking for #{@names.join(".")}, but alas, I could not find
193\tit in #{locals.local.get_name} or any parent namespaces.
194\tI'm really sorry old chap.
195\tWot. Wot.
196ERROR_MSG
197 end
198 end
199 def self.parse(tokens)
200 names = []
201 off_root = (tokens.peak == :tDot)
202 tokens.next if(off_root)
203 names << tokens.expect(:tWord).data
204 while(tokens.peak == :tDot)
205 tokens.next
206 names << tokens.expect(:tWord).data
207 end
208 return self.new(names,off_root)
209 end
210end