tagged release 0.6.4
[parrot.git] / languages / pheme / lib / pge2past.tg
blob982962bbca50eb988f57b8134f521686302f9d25
1 grammar Pheme::AST::Grammar is TGE::Grammar;
3 transform past (ROOT) :language('PIR') {
4     .local pmc result
5     result = new 'PAST::Block'
6     result.'namespace'( 'Pheme' )
8     .local pmc lists
9     lists = node['pheme_list']
11     .local pmc iter
12     iter = new 'Iterator', lists
14     .local pmc elem
16   iter_loop:
17     unless iter goto iter_end
18     elem = shift iter
19     elem = tree.'get'( 'past', elem, 'pheme_list' )
21     result.'push'( elem )
22     goto iter_loop
24   iter_end:
25     .return( result )
28 transform past (pheme_list) :language('PIR') {
29     .local pmc iter
30     iter = new 'Iterator', node
32     .local string key_name
33     key_name = shift iter
35     .local pmc elem
36     elem = node[key_name]
38     .local pmc op
39     op = new 'PAST::Op'
40     op.'name'( '__list_to_cons' )
41     op.'pasttype'( 'call' )
43   check_for_atom:
44     .local int has_atom
45     has_atom = exists elem['atom']
46     unless has_atom goto check_for_special
48     .local pmc atom
49     atom = elem['atom']
50     atom = tree.'get'( 'past', atom, 'atom' )
51     op.'push'( atom )
53   check_for_special:
54     .local int has_special
55     has_special = exists elem['special']
56     unless has_special goto make_cons
58     .local pmc special
59     special = elem['special']
61     .local string special_name
62     special_name = special
64     special = new 'PAST::Op'
65     special.'name'( special_name )
66     op.'push'( special )
68   make_cons:
69     .local pmc list
70     list = elem['list_item']
72     .local pmc iter
73     iter = new 'Iterator', list
75     .local pmc item
76   iter_loop:
77     unless iter goto iter_end
78     item = shift iter
79     item = tree.'get'( 'past', item, 'list_item' )
80     op.'push'( item )
81     goto iter_loop
83   iter_end:
84     .local pmc result
85     result = new 'PAST::Op'
86     result.'name'( '__evaluate' )
87     result.'pasttype'( 'call' )
88     result.'push'( op )
90     .return tree.'get'( key_name, result )
93 transform past (list_item) :language('PIR') {
94     .local pmc iter
95     iter = new 'Iterator', node
97     .local string key_name
98     key_name = shift iter
100     .local pmc    elem
101     elem     = node[key_name]
103     .return tree.'get'( 'past', elem, key_name )
106 transform special_form (PAST::Op) :language('PIR') {
107     .local pmc make_cons
108     make_cons = node[0]
110     .local pmc cons_iter
111     cons_iter = make_cons.'iterator'()
113     .local pmc form_op
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') {
124     .local pmc make_cons
125     make_cons = node[0]
127     .local pmc cons_iter
128     cons_iter = make_cons.'iterator'()
130     .local pmc maybe_op
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
140     name_length -= 2
141     func_name    = substr func_name, 1, name_length
143     .local pmc func_func
144     func_func = find_global 'Pheme', func_name
146     .local int have_func
147     have_func = defined func_func
149     if have_func goto rewrite_to_call
150     .return( node )
152   rewrite_to_call:
153     .local pmc result
154     result = new 'PAST::Op'
155     result.'pasttype'( 'call' )
156     result.'name'( func_name )
158     .local pmc item
159   iter_loop:
160     unless cons_iter goto iter_end
161     item = shift cons_iter
162     result.'push'( item )
163     goto iter_loop
165   iter_end:
166     .return( result )
169 transform cons (PAST::Op) :language('PIR') {
170     .local pmc make_cons
171     make_cons = node[0]
172     .return( make_cons )
175 transform make_cons (list) :language('PIR') {
176     .local pmc iter
177     iter = new 'Iterator', node
179     .local pmc cons
180     cons = new 'PAST::Op'
181     cons.'name'( '__list_to_cons' )
182     cons.'pasttype'( 'call' )
184     .local pmc child
186   iter_loop:
187     unless iter, iter_end
188     child = shift iter
189     child = tree.get( 'past', child, 'list_item' )
190     cons.'push'( child )
191     goto iter_loop
193   iter_end:
194     .local pmc eval
195     eval = new 'PAST::Op'
196     eval.'name'( '__evaluate' )
197     eval.'pasttype'( 'call' )
198     eval.'push'( cons )
200     .return( eval )
203 transform special_form (define) :language('PIR') {
204     .local pmc iter
205     iter   = node.'iterator'()
207     .local pmc op, name, lambda
208     op     = shift iter
209     name   = shift iter
210     lambda = shift iter
212     .local pmc name_str
213     name_str = name.'name'()
215     .local pmc result
216     result = new 'PAST::Block'
218     result.'name'( name_str )
219     result.'push'( lambda )
221     .return( result )
224 transform quote (PAST::Op) :language( 'PIR' ) {
225     .local pmc children
226     children = node.'get_array'()
228     # first kid is quote op; remove
229     .local pmc quote_op
230     quote_op = shift children
232     .local pmc quoted_item
233     quoted_item = children[0]
235     .local string name
236     name = quoted_item.'name'()
237     ne name, '__evaluate', quote_item
239     # splice out eval
240     quoted_item = quoted_item[0]
242   quote_item:
243     quoted_item = tree.'get'( 'force_to_val', quoted_item )
244     children[0] = quoted_item
246     .local int num_kids
247     num_kids = children
249     if num_kids > 1 goto return_node
250     .return( quoted_item )
252   return_node:
253     .return( node )
256 transform force_to_val (PAST::Op) :language('PIR') {
257     .local pmc result
258     result = new 'PAST::Val'
260     .local string name
261     name = node.'name'()
262     ne name, '__make_empty_cons', really_rewrite
263     .return( node )
265   really_rewrite:
266     node.'name'( '__list_to_cons' )
267     name  = "'" . name
268     name .= "'"
269     result.'value'( name )
270     result.'returns'( 'Undef' )
272     .local pmc children
273     children = node.'get_array'()
274     unshift children, result
276     .return( node )
279 transform force_to_val (PAST::Val) :language('PIR') {
280     .return( node )
283 transform force_to_val (PAST::Var) :language('PIR') {
284     .return( node )
287 transform cond (PAST::Op) :language( 'PIR' ) {
288     .local pmc result
289     result = new 'PAST::Op'
290     result.'pasttype'( 'if' )
292     .local pmc iter
293     iter = node.'iterator'()
295     # throw away first child; it's 'cond'
296     .local pmc child
297     child = shift iter
299     .local pmc parent_if
300     parent_if = result
302   append_children:
303     .local pmc if_op
304     if_op = shift iter
305     parent_if.'push'( if_op )
306     unless iter goto return_result
308     .local pmc then_node
309     then_node = shift iter
310     parent_if.'push'( then_node )
311     unless iter goto return_result
313     .local int num_children
314     num_children = iter
315     unless num_children == 1 goto nest_if
317     .local pmc else_node
318     else_node = shift iter
319     parent_if.'push'( else_node )
320     goto return_result
322   nest_if:
323     .local pmc new_if
324     new_if = new 'PAST::Op'
325     new_if.'pasttype'( 'if' )
326     parent_if.'push'( new_if )
327     parent_if = new_if
328     goto append_children
330   return_result:
331     .return( result )
334 transform lambda (PAST::Op) :language('PIR') {
335     .local pmc result
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
343     .local pmc child
344     child = shift child_iter
346     .local pmc args
347     args = shift child_iter
349     .local pmc args_iter
350     args_iter = args.'iterator'()
352     .local pmc    rewrite_args
353     rewrite_args = new 'Hash'
355     .local string arg_name
356     .local pmc    arg
357   args_iter_loop:
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' )
364     result.'push'( arg )
365     rewrite_args[arg_name] = 1
366     goto args_iter_loop
367   args_iter_end:
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
378   add_names_to_stack:
379     push arg_names_stack, rewrite_args
381   child_iter_loop:
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 )
386     goto child_iter_loop
388     # XXX - must rewrite all PAST::Val in children to PAST::Var as appropriate
389   child_iter_end:
390     rewrite_args = pop arg_names_stack
391     .return( result )
394 transform rewrite_var_name (PAST::Op) :language('PIR') {
395     .local pmc children
396     children = node.'get_array'()
398     .local int elements
399     elements = children
401     .local int i
402     i = 0
404     .local pmc child
405   start_loop:
406     if i == elements goto end_loop
407     child       = children[i]
408     child       = tree.'get'( 'rewrite_var_name', child )
409     children[i] = child
410     inc i
411     goto start_loop
413   end_loop:
414     .return( node )
417 transform rewrite_var_name (PAST::Val) :language('PIR') {
418     .local pmc arg_names_stack
419     arg_names_stack = find_global 'arg_names_stack'
421     .local pmc arg_names
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
431     .return( node )
433   rewrite_to_var:
434     .local pmc var
435     var = new 'PAST::Var'
436     var.'scope'( 'lexical' )
437     var.'name'( arg_name )
438     .return( var )
441 transform rewrite_var_name (PAST::Var) :language('PIR') {
442     .return( node )
445 transform define (PAST::Op) :language('PIR') {
446     .local pmc iter
447     iter = node.'iterator'()
449     # throw away first child; it's the define op
450     .local pmc define_op
451     define_op = shift iter
453     .local pmc name
454     name = shift iter
456     .local string name_str
457     name_str = name.'name'()
459     .local pmc lambda
460     lambda = shift iter
461     lambda.'name'( name_str )
463     .return( lambda )
466 # XXX: almost certainly wrong
467 transform past (empty_list) :language('PIR') {
468     .local pmc result
470     result = new 'PAST::Op'
471     result.'name'( '__make_empty_cons' )
473     .return( result )
476 transform past (atom) :language('PIR') {
477     .local pmc result
478     result   = new 'PAST::Val'
480     .local string value
481     value    = node
483     # if this is a quoted atom, strip off the quote; it's meaningless here
484     .local int is_quoted
485     is_quoted = exists node['quote']
486     unless is_quoted goto add_quotes
488     value = substr value, 1
490   add_quotes:
491     .local string quoted_value
492     quoted_value  = "'"
493     quoted_value .= value
494     quoted_value .= "'"
496     result.'value'( quoted_value )
497     result.'name'( quoted_value )
498     result.'returns'( 'Undef' )
500     .return( result )
503 transform past (quoted_string) :language('PIR') {
504     .local pmc result
505     result = new 'PAST::Val'
507     .local string value
508     value  = node
510     result.'name'( value )
511     result.'value'( value )
512     result.'returns'( 'Undef' )
514     .return( result )