1 grammar Pheme::AST::Grammar is TGE::Grammar;
3 transform past (ROOT) :language('PIR') {
5 result = new 'PAST::Block'
6 result.'namespace'( 'Pheme' )
9 lists = node['pheme_list']
12 iter = new 'Iterator', lists
17 unless iter goto iter_end
19 elem = tree.'get'( 'past', elem, 'pheme_list' )
28 transform past (pheme_list) :language('PIR') {
30 iter = new 'Iterator', node
32 .local string key_name
40 op.'name'( '__list_to_cons' )
41 op.'pasttype'( 'call' )
45 has_atom = exists elem['atom']
46 unless has_atom goto check_for_special
50 atom = tree.'get'( 'past', atom, 'atom' )
54 .local int has_special
55 has_special = exists elem['special']
56 unless has_special goto make_cons
59 special = elem['special']
61 .local string special_name
62 special_name = special
64 special = new 'PAST::Op'
65 special.'name'( special_name )
70 list = elem['list_item']
73 iter = new 'Iterator', list
77 unless iter goto iter_end
79 item = tree.'get'( 'past', item, 'list_item' )
85 result = new 'PAST::Op'
86 result.'name'( '__evaluate' )
87 result.'pasttype'( 'call' )
90 .return tree.'get'( key_name, result )
93 transform past (list_item) :language('PIR') {
95 iter = new 'Iterator', node
97 .local string key_name
101 elem = node[key_name]
103 .return tree.'get'( 'past', elem, key_name )
106 transform special_form (PAST::Op) :language('PIR') {
111 cons_iter = make_cons.'iterator'()
114 form_op = shift cons_iter
116 .local string form_name
117 form_name = form_op.'name'()
119 .return tree.'get'( form_name, make_cons )
122 # this *may* be an application; this is an optimization
123 transform application (PAST::Op) :language('PIR') {
128 cons_iter = make_cons.'iterator'()
131 maybe_op = shift cons_iter
133 .local string func_name
134 func_name = maybe_op.'name'()
136 .local int name_length
137 name_length = length func_name
139 # strip off the quotes from the atom name
141 func_name = substr func_name, 1, name_length
144 func_func = find_global 'Pheme', func_name
147 have_func = defined func_func
149 if have_func goto rewrite_to_call
154 result = new 'PAST::Op'
155 result.'pasttype'( 'call' )
156 result.'name'( func_name )
160 unless cons_iter goto iter_end
161 item = shift cons_iter
162 result.'push'( item )
169 transform cons (PAST::Op) :language('PIR') {
175 transform make_cons (list) :language('PIR') {
177 iter = new 'Iterator', node
180 cons = new 'PAST::Op'
181 cons.'name'( '__list_to_cons' )
182 cons.'pasttype'( 'call' )
187 unless iter, iter_end
189 child = tree.get( 'past', child, 'list_item' )
195 eval = new 'PAST::Op'
196 eval.'name'( '__evaluate' )
197 eval.'pasttype'( 'call' )
203 transform special_form (define) :language('PIR') {
205 iter = node.'iterator'()
207 .local pmc op, name, lambda
213 name_str = name.'name'()
216 result = new 'PAST::Block'
218 result.'name'( name_str )
219 result.'push'( lambda )
224 transform quote (PAST::Op) :language( 'PIR' ) {
226 children = node.'get_array'()
228 # first kid is quote op; remove
230 quote_op = shift children
232 .local pmc quoted_item
233 quoted_item = children[0]
236 name = quoted_item.'name'()
237 ne name, '__evaluate', quote_item
240 quoted_item = quoted_item[0]
243 quoted_item = tree.'get'( 'force_to_val', quoted_item )
244 children[0] = quoted_item
249 if num_kids > 1 goto return_node
250 .return( quoted_item )
256 transform force_to_val (PAST::Op) :language('PIR') {
258 result = new 'PAST::Val'
262 ne name, '__make_empty_cons', really_rewrite
266 node.'name'( '__list_to_cons' )
269 result.'value'( name )
270 result.'returns'( 'Undef' )
273 children = node.'get_array'()
274 unshift children, result
279 transform force_to_val (PAST::Val) :language('PIR') {
283 transform force_to_val (PAST::Var) :language('PIR') {
287 transform cond (PAST::Op) :language( 'PIR' ) {
289 result = new 'PAST::Op'
290 result.'pasttype'( 'if' )
293 iter = node.'iterator'()
295 # throw away first child; it's 'cond'
305 parent_if.'push'( if_op )
306 unless iter goto return_result
309 then_node = shift iter
310 parent_if.'push'( then_node )
311 unless iter goto return_result
313 .local int num_children
315 unless num_children == 1 goto nest_if
318 else_node = shift iter
319 parent_if.'push'( else_node )
324 new_if = new 'PAST::Op'
325 new_if.'pasttype'( 'if' )
326 parent_if.'push'( new_if )
334 transform lambda (PAST::Op) :language('PIR') {
336 result = new 'PAST::Block'
337 result.'blocktype'( 'declaration' )
339 .local pmc child_iter
340 child_iter = node.'iterator'()
342 # discard first child; it's the lambda op
344 child = shift child_iter
347 args = shift child_iter
350 args_iter = args.'iterator'()
352 .local pmc rewrite_args
353 rewrite_args = new 'Hash'
355 .local string arg_name
358 unless args_iter goto args_iter_end
359 child = shift args_iter
360 arg = new 'PAST::Var'
361 arg_name = child.'name'()
362 arg.'name'( arg_name )
363 arg.'scope'( 'parameter' )
365 rewrite_args[arg_name] = 1
368 .local pmc arg_names_stack
369 arg_names_stack = find_global 'arg_names_stack'
371 .local int have_stack
372 have_stack = defined arg_names_stack
373 if have_stack goto add_names_to_stack
375 arg_names_stack = new 'ResizablePMCArray'
376 store_global 'arg_names_stack', arg_names_stack
379 push arg_names_stack, rewrite_args
382 unless child_iter goto child_iter_end
383 child = shift child_iter
384 child = tree.'get'( 'rewrite_var_name', child )
385 result.'push'( child )
388 # XXX - must rewrite all PAST::Val in children to PAST::Var as appropriate
390 rewrite_args = pop arg_names_stack
394 transform rewrite_var_name (PAST::Op) :language('PIR') {
396 children = node.'get_array'()
406 if i == elements goto end_loop
408 child = tree.'get'( 'rewrite_var_name', child )
417 transform rewrite_var_name (PAST::Val) :language('PIR') {
418 .local pmc arg_names_stack
419 arg_names_stack = find_global 'arg_names_stack'
422 arg_names = arg_names_stack[-1]
424 .local string arg_name
425 arg_name = node.'name'()
427 .local int name_exists
428 name_exists = exists arg_names[arg_name]
430 if name_exists goto rewrite_to_var
435 var = new 'PAST::Var'
436 var.'scope'( 'lexical' )
437 var.'name'( arg_name )
441 transform rewrite_var_name (PAST::Var) :language('PIR') {
445 transform define (PAST::Op) :language('PIR') {
447 iter = node.'iterator'()
449 # throw away first child; it's the define op
451 define_op = shift iter
456 .local string name_str
457 name_str = name.'name'()
461 lambda.'name'( name_str )
466 # XXX: almost certainly wrong
467 transform past (empty_list) :language('PIR') {
470 result = new 'PAST::Op'
471 result.'name'( '__make_empty_cons' )
476 transform past (atom) :language('PIR') {
478 result = new 'PAST::Val'
483 # if this is a quoted atom, strip off the quote; it's meaningless here
485 is_quoted = exists node['quote']
486 unless is_quoted goto add_quotes
488 value = substr value, 1
491 .local string quoted_value
493 quoted_value .= value
496 result.'value'( quoted_value )
497 result.'name'( quoted_value )
498 result.'returns'( 'Undef' )
503 transform past (quoted_string) :language('PIR') {
505 result = new 'PAST::Val'
510 result.'name'( value )
511 result.'value'( value )
512 result.'returns'( 'Undef' )