Convert Call and Send to AST.
Cat's Eye Technologies
10 years ago
40 | 40 | return And(self.analyze(ast.lhs), self.analyze(ast.rhs)) |
41 | 41 | elif isinstance(ast, Using): |
42 | 42 | return Using(self.analyze(ast.lhs), ast.prodref) |
43 | elif ast[0] == 'CALL': | |
44 | # ('CALL', prodref, args, ibuf) | |
45 | prodref = ast[1] | |
43 | elif isinstance(ast, Call): | |
44 | prodref = ast.prodref | |
46 | 45 | if prodref.module == '' and prodref.name not in self.prodnames: |
47 | 46 | raise ValueError("no '%s' production defined" % prodref.name) |
48 | 47 | # TODO: also check builtins? |
49 | return ('CALL', prodref, ast[2], ast[3]) | |
50 | elif ast[0] == 'SEND': | |
51 | return ('SEND', self.analyze(ast[1]), ast[2]) | |
48 | return ast | |
49 | elif isinstance(ast, Send): | |
50 | assert isinstance(ast.variable, Variable), ast | |
51 | return Send(self.analyze(ast.rule), ast.variable) | |
52 | 52 | elif ast[0] == 'SET': |
53 | 53 | return ast |
54 | 54 | elif ast[0] == 'NOT': |
68 | 68 | self.collect_locals(ast.rhs, locals_) |
69 | 69 | elif isinstance(ast, Using): |
70 | 70 | self.collect_locals(ast.lhs, locals_) |
71 | elif ast[0] == 'SEND': | |
72 | locals_.add(ast[2].name) | |
71 | elif isinstance(ast, Call): | |
72 | pass | |
73 | elif isinstance(ast, Send): | |
74 | locals_.add(ast.variable.name) | |
73 | 75 | elif ast[0] == 'SET': |
74 | 76 | locals_.add(ast[1].name) |
75 | 77 | elif ast[0] == 'WHILE': |
83 | 83 | self.rhs |
84 | 84 | ) |
85 | 85 | |
86 | class Call(AST): | |
87 | def __init__(self, prodref, args, ibuf): | |
88 | self.prodref = prodref | |
89 | self.args = args | |
90 | self.ibuf = ibuf | |
91 | ||
92 | def __repr__(self): | |
93 | return u"Call(%r, %r, %r)" % ( | |
94 | self.prodref, | |
95 | self.args, | |
96 | self.ibuf | |
97 | ) | |
98 | ||
99 | class Send(AST): | |
100 | def __init__(self, rule, variable): | |
101 | self.rule = rule | |
102 | self.variable = variable | |
103 | ||
104 | def __repr__(self): | |
105 | return u"Send(%r, %r)" % ( | |
106 | self.rule, | |
107 | self.variable | |
108 | ) | |
109 | ||
86 | 110 | class Using(AST): |
87 | 111 | def __init__(self, lhs, prodref): |
88 | 112 | self.lhs = lhs |
196 | 196 | self.emit("}") |
197 | 197 | self.outdent() |
198 | 198 | self.emit("}") |
199 | elif ast[0] == 'CALL': | |
200 | prodref = ast[1] | |
199 | elif isinstance(ast, Send): | |
200 | self.compile_r(ast.rule) | |
201 | # TODO: if ok? | |
202 | self.emit("%s = result;" % ast.variable.name) | |
203 | elif isinstance(ast, Call): | |
204 | prodref = ast.prodref | |
201 | 205 | prodmod = prodref.module |
202 | 206 | name = prodref.name |
203 | args = ast[2] | |
207 | args = ast.args | |
204 | 208 | |
205 | 209 | if prodmod == '$': |
206 | 210 | if name == 'expect': |
239 | 243 | |
240 | 244 | args = ', '.join(["temp_arg%s" % p for p in xrange(0, i)]) |
241 | 245 | self.emit("%s_%s0(%s);" % (prodmod, name, args)) |
242 | elif ast[0] == 'SEND': | |
243 | self.compile_r(ast[1]) | |
244 | # TODO: if ok? | |
245 | self.emit("%s = result;" % ast[2].name) | |
246 | 246 | elif ast[0] == 'SET': |
247 | 247 | self.emit_term(ast[2], "temp") |
248 | 248 | self.emit("result = temp;") |
198 | 198 | self.context = saved_context |
199 | 199 | self.scanner.install_state(saved_scanner_state) |
200 | 200 | return self.interpret(ast.rhs) |
201 | elif isinstance(ast, Call): | |
202 | prodref = ast.prodref | |
203 | #prodmod = prodref[1] | |
204 | name = prodref.name | |
205 | args = ast.args | |
206 | ibuf = ast.ibuf | |
207 | prods = self.program.find_productions(prodref) | |
208 | self.event('call_candidates', prods) | |
209 | args = [x.expand(self.context) for x in args] | |
210 | for prod in prods: | |
211 | formals = prod.formals | |
212 | self.event('call_args', formals, args) | |
213 | if isinstance(formals, list): | |
214 | bindings = self.match_all(formals, args) | |
215 | self.event('call_bindings', bindings) | |
216 | if bindings != False: | |
217 | if ibuf is not None: | |
218 | return self.interpret_on_buffer( | |
219 | prod, unicode(ibuf.expand(self.context)), | |
220 | bindings=bindings | |
221 | ) | |
222 | else: | |
223 | return self.interpret(prod, bindings=bindings) | |
224 | else: | |
225 | self.event('call_newfangled_parsing_args', prod) | |
226 | # start a new scope. arg bindings will appear here. | |
227 | self.context.push_scope(prod.name) | |
228 | (success, result) = self.interpret_on_buffer( | |
229 | formals, unicode(args[0]) | |
230 | ) | |
231 | # we do not want to start a new scope here, and we | |
232 | # interpret the rule directly, not the prod. | |
233 | if success: | |
234 | self.event('begin_interpret_rule', prod.body) | |
235 | (success, result) = self.interpret(prod.body) | |
236 | self.event('end_interpret_rule', prod.body) | |
237 | self.context.pop_scope(prod.name) | |
238 | return (success, result) | |
239 | else: | |
240 | self.context.pop_scope(prod.name) | |
241 | raise ValueError("No '%s' production matched arguments %r" % | |
242 | (name, args) | |
243 | ) | |
244 | elif isinstance(ast, Send): | |
245 | (success, result) = self.interpret(ast.rule) | |
246 | self.context.store(ast.variable.name, result) | |
247 | return (success, result) | |
201 | 248 | elif isinstance(ast, Using): |
202 | 249 | sub = ast.lhs |
203 | 250 | prodref = ast.prodref |
217 | 264 | self.event('leave_with', succeeded, result) |
218 | 265 | self.scanner.pop_engine() |
219 | 266 | return (succeeded, result) |
220 | elif ast[0] == 'CALL': | |
221 | prodref = ast[1] | |
222 | #prodmod = prodref[1] | |
223 | name = prodref.name | |
224 | args = ast[2] | |
225 | ibuf = ast[3] | |
226 | prods = self.program.find_productions(prodref) | |
227 | self.event('call_candidates', prods) | |
228 | args = [x.expand(self.context) for x in args] | |
229 | for prod in prods: | |
230 | formals = prod.formals | |
231 | self.event('call_args', formals, args) | |
232 | if isinstance(formals, list): | |
233 | bindings = self.match_all(formals, args) | |
234 | self.event('call_bindings', bindings) | |
235 | if bindings != False: | |
236 | if ibuf is not None: | |
237 | return self.interpret_on_buffer( | |
238 | prod, unicode(ibuf.expand(self.context)), | |
239 | bindings=bindings | |
240 | ) | |
241 | else: | |
242 | return self.interpret(prod, bindings=bindings) | |
243 | else: | |
244 | self.event('call_newfangled_parsing_args', prod) | |
245 | # start a new scope. arg bindings will appear here. | |
246 | self.context.push_scope(prod.name) | |
247 | (success, result) = self.interpret_on_buffer( | |
248 | formals, unicode(args[0]) | |
249 | ) | |
250 | # we do not want to start a new scope here, and we | |
251 | # interpret the rule directly, not the prod. | |
252 | if success: | |
253 | self.event('begin_interpret_rule', prod.body) | |
254 | (success, result) = self.interpret(prod.body) | |
255 | self.event('end_interpret_rule', prod.body) | |
256 | self.context.pop_scope(prod.name) | |
257 | return (success, result) | |
258 | else: | |
259 | self.context.pop_scope(prod.name) | |
260 | raise ValueError("No '%s' production matched arguments %r" % | |
261 | (name, args) | |
262 | ) | |
263 | elif ast[0] == 'SEND': | |
264 | (success, result) = self.interpret(ast[1]) | |
265 | assert isinstance(ast[2], Variable), ast | |
266 | self.context.store(ast[2].name, result) | |
267 | return (success, result) | |
268 | 267 | elif ast[0] == 'SET': |
269 | 268 | assert isinstance(ast[1], Variable), ast |
270 | 269 | assert isinstance(ast[2], Term), ast |
107 | 107 | lhs = self.expr4() |
108 | 108 | if self.consume(u'→') or self.consume('->'): |
109 | 109 | v = self.variable() |
110 | lhs = ('SEND', lhs, v) | |
110 | lhs = Send(lhs, v) | |
111 | 111 | return lhs |
112 | 112 | |
113 | 113 | def expr4(self): |
119 | 119 | e = self.expr0() |
120 | 120 | self.expect(']') |
121 | 121 | return Or(e, |
122 | ('CALL', Prodref('$', 'return'), [Term(u'nil')], None) | |
122 | Call(Prodref('$', 'return'), [Term(u'nil')], None) | |
123 | 123 | ) |
124 | 124 | elif self.consume('{'): |
125 | 125 | e = self.expr0() |
128 | 128 | elif self.peek()[0] == '"': |
129 | 129 | s = unicode(self.consume_any()[1:-1]) |
130 | 130 | literal = Term(s) |
131 | return ('CALL', Prodref('$', 'expect'), [literal], None) | |
131 | return Call(Prodref('$', 'expect'), [literal], None) | |
132 | 132 | elif self.consume(u'«') or self.consume('<<'): |
133 | 133 | t = self.term() |
134 | 134 | if self.consume(u'»') or self.consume('>>'): |
135 | return ('CALL', Prodref('$', 'expect'), [t], None) | |
135 | return Call(Prodref('$', 'expect'), [t], None) | |
136 | 136 | else: |
137 | 137 | self.error("'>>'") |
138 | 138 | elif self.consume('!'): |
149 | 149 | if self.consume(u'←') or self.consume('<-'): |
150 | 150 | t = self.term() |
151 | 151 | else: |
152 | return ('CALL', Prodref('$', 'return'), [v], None) | |
152 | return Call(Prodref('$', 'return'), [v], None) | |
153 | 153 | return ('SET', v, t) |
154 | 154 | else: |
155 | 155 | # implied return of term |
156 | 156 | if self.peek()[0].isupper() or self.peek()[0] == "'": |
157 | 157 | t = self.term() |
158 | return ('CALL', Prodref('$', 'return'), [t], None) | |
158 | return Call(Prodref('$', 'return'), [t], None) | |
159 | 159 | prodref = self.prodref() |
160 | 160 | args = [] |
161 | 161 | name = prodref.name |
177 | 177 | ibuf = None |
178 | 178 | if self.consume('@'): |
179 | 179 | ibuf = self.term() |
180 | return ('CALL', prodref, args, ibuf) | |
180 | return Call(prodref, args, ibuf) | |
181 | 181 | |
182 | 182 | def prodref(self): |
183 | 183 | if self.consume('$'): |