blob: ea3aa8033df44d3f3063a67b70d632819877e556 [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|
Parker Schuhc587baf2014-02-09 22:09:23 -0800153 return nil if(!namespace.respond_to?(:[]))
brians343bc112013-02-10 01:53:46 +0000154 namespace = namespace[name]
155 return nil if(!namespace)
156 end
157 return namespace
158 end
159 def is_simple?()
160 return !@off_root && @names.length == 1
161 end
162 def to_simple()
163 return @names[-1]
164 end
165 def to_s()
166 if(@off_root)
167 return ".#{@names.join(".")}"
168 else
169 return @names.join(".")
170 end
171 end
172 def lookup(locals)
173 if(@off_root)
174 local = locals.globals.space
175 else
176 local = locals.local
177 end
178 target = nil
179 while(!target && local)
180 target = test_lookup(local)
181 local = local.parent
182 end
183 return target if(target)
184 if(@off_root)
185 raise QError.new(<<ERROR_MSG)
186I was looking for .#{@names.join(".")}, but alas, it was not under
187\tthe root namespace.
188\tI'm really sorry old chap.
189\tWot. Wot.
190ERROR_MSG
191 else
192 raise QError.new(<<ERROR_MSG)
193I was looking for #{@names.join(".")}, but alas, I could not find
194\tit in #{locals.local.get_name} or any parent namespaces.
195\tI'm really sorry old chap.
196\tWot. Wot.
197ERROR_MSG
198 end
199 end
200 def self.parse(tokens)
201 names = []
202 off_root = (tokens.peak == :tDot)
203 tokens.next if(off_root)
204 names << tokens.expect(:tWord).data
205 while(tokens.peak == :tDot)
206 tokens.next
207 names << tokens.expect(:tWord).data
208 end
209 return self.new(names,off_root)
210 end
211end