blob: f683ddaced4d49d3cd28e4f8950bf3becdecc193 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001class QStmt
2 def set_line(val)
3 @file_line = val
4 return self
5 end
6 def q_stack_name()
7 @file_line
8 end
9 def self.method_added(name)
10 @wrapped ||= {}
11 return if(name != :q_eval && name != :q_eval_extern)
12 return if(@wrapped[name])
13 @wrapped[name] = true
14 method = self.instance_method(name)
15 define_method(name) do |*args,&blk|
16 begin
17 method.bind(self).call(*args,&blk)
18 rescue QError => e
19 e.qstacktrace << self
20 raise e
21 end
22 end
23 end
24
25end
26class ImportStmt < QStmt
27 def initialize(filename)
28 @filename = filename
29 end
30 def q_eval(locals)
31 filename = locals.globals.find_file(@filename)
32 #puts "importing #{filename.inspect}"
33 q_file = QFile.parse(filename)
34 q_output = q_file.q_eval_extern(locals.globals)
35 q_output.extern = true
36 return Target::QInclude.new(@filename + ".h")
37 end
38 def self.parse(tokens)
39 line = tokens.pos
40 to_import = (tokens.expect(:tString) do |token|
41 <<ERROR_MSG
42I found a #{token.humanize} at #{token.pos}.
43\tI was really looking for a "filename" for this import statement.
44\tSomething like: import "super_cool_file";
45\tWot.Wot
46ERROR_MSG
47 end).data
48 tokens.expect(:tSemi) do |token|
49 <<ERROR_MSG
50I found a #{token.humanize} at #{token.pos}.
51\tI was really looking for a ";" to finish off this import statement
52\tat line #{line};
53\tSomething like: import #{to_import.inspect};
54\tWot.Wot #{" "*to_import.inspect.length}^
55ERROR_MSG
56 end
57 return self.new(to_import).set_line(line)
58 end
59end
60class PackageStmt < QStmt
61 def initialize(name)
62 @name = name
63 end
64 def q_eval(locals)
65 locals.package = @name
66 return nil
67 end
68 def self.parse(tokens)
69 line = tokens.pos
70 qualified_name = QualifiedName.parse(tokens)
71 tokens.expect(:tSemi)
72 return self.new(qualified_name).set_line(line)
73 end
74end
75class QFile
76 attr_accessor :namespace
77 def initialize(filename,suite)
78 @filename,@suite = filename,suite
79 end
80 def q_eval(globals = Globals.new())
81 local_pos = LocalSituation.new(globals)
82 q_file = Target::QFile.new()
83 @suite.each do |name|
84 val = name.q_eval(local_pos)
85 if(val)
86 if(val.respond_to?(:create))
87 q_file.add_type(val)
88 end
89 end
90 end
91 @namespace = local_pos.local
92 return q_file
93 end
94 def q_eval_extern(globals)
95 local_pos = LocalSituation.new(globals)
96 q_file = Target::QFile.new()
97 @suite.each do |name|
98 if(name.respond_to?(:q_eval_extern))
99 val = name.q_eval_extern(local_pos)
100 else
101 val = name.q_eval(local_pos)
102 end
103 if(val)
104 if(val.respond_to?(:create))
105 q_file.add_type(val)
106 end
107 end
108 end
109 return q_file
110 end
111 def self.parse(filename)
112 tokens = Tokenizer.new(filename)
113 suite = []
114 while(tokens.peak != :tEnd)
115 token = tokens.expect(:tWord) do |token| #symbol
116 <<ERROR_MSG
117I found a #{token.humanize} at #{token.pos}.
118\tI was really looking for a "package", "import", "queue_group",
119\t"message", or "queue" statement to get things moving.
120\tSomething like: import "super_cool_file";
121\tWot.Wot
122ERROR_MSG
123 end
124 case token.data
125 when "package"
126 suite << PackageStmt.parse(tokens)
127 when "import"
128 suite << ImportStmt.parse(tokens)
129 when "queue_group"
130 suite << QueueGroupStmt.parse(tokens)
131 when "message"
132 suite << MessageStmt.parse(tokens)
133 when "queue"
134 suite << QueueStmt.parse(tokens)
135 when "interface"
136 suite << InterfaceStmt.parse(tokens)
137 else
138 tokens.qError(<<ERROR_MSG)
139expected a "package","import","queue","queue_group", or "message" statement rather
140 than a #{token.data.inspect}, (whatever that is?)
141 oh! no! a feature request!?
142 Wot. Wot.
143ERROR_MSG
144 end
145 end
146 return self.new(filename,suite)
147 end
148end