1 ################################################################################
3 ## Pythonc--Python to C++ translator
5 ## Copyright 2011 Zach Wegner
7 ## This file is part of Pythonc.
9 ## Pythonc is free software: you can redistribute it and/or modify
10 ## it under the terms of the GNU General Public License as published by
11 ## the Free Software Foundation, either version 3 of the License, or
12 ## (at your option) any later version.
14 ## Pythonc is distributed in the hope that it will be useful,
15 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ## GNU General Public License for more details.
19 ## You should have received a copy of the GNU General Public License
20 ## along with Pythonc. If not, see <http://www.gnu.org/licenses/>.
22 ################################################################################
27 return '\n'.join(' %s;' % s
for s
in stmts
)
30 def register_int(value
):
35 def register_string(value
):
37 if value
in all_strings
:
38 return all_strings
[value
]
39 all_strings
[value
] = len(all_strings
)
40 return all_strings
[value
]
43 return 'int_singleton_neg%d' % -i
if i
< 0 else 'int_singleton_%d' % i
46 global all_ints
, all_strings
49 f
.write('int_const %s(%sll);\n' % (int_name(i
), i
))
51 for k
, v
in all_strings
.items():
52 f
.write('string_const string_singleton_%s("%s");\n' % (v
, repr(k
)[1:-1]))
58 class NoneConst(Node
):
63 return '&none_singleton'
65 class BoolConst(Node
):
66 def __init__(self
, value
):
70 return '&bool_singleton_%s' % self
.value
73 def __init__(self
, value
):
78 return '&%s' % int_name(self
.value
)
80 class StringConst(Node
):
81 def __init__(self
, value
):
83 self
.id = register_string(value
)
86 return '&string_singleton_%s' % self
.id
88 class Identifier(Node
):
89 def __init__(self
, name
):
99 def __init__(self
, ref_type
, *args
):
100 self
.ref_type
= ref_type
104 return '(new %s(%s))' % (self
.ref_type
, ', '.join(str(a
) for a
in self
.args
))
107 def __init__(self
, op
, rhs
):
112 return '%s->%s()' % (self
.rhs
, self
.op
)
114 class BinaryOp(Node
):
115 def __init__(self
, op
, lhs
, rhs
):
121 return '%s->%s(%s)' % (self
.lhs
, self
.op
, self
.rhs
)
124 def __init__(self
, name
):
128 return 'ctx->load("%s")' % self
.name
131 def __init__(self
, name
, expr
):
136 return 'ctx->store("%s", %s)' % (self
.name
, self
.expr
)
138 class StoreAttr(Node
):
139 def __init__(self
, name
, attr
, expr
):
145 return '%s->__setattr__(%s, %s)' % (self
.name
, self
.attr
, self
.expr
)
147 class StoreSubscript(Node
):
148 def __init__(self
, expr
, index
, value
):
154 return '%s->__setitem__(%s, %s)' % (self
.expr
, self
.index
, self
.value
)
156 class DeleteSubscript(Node
):
157 def __init__(self
, expr
, index
):
162 return '%s->__delitem__(%s)' % (self
.expr
, self
.index
)
165 def __init__(self
, name
):
169 return 'ctx->set_global("%s")' % self
.name
172 def __init__(self
, items
):
175 def flatten(self
, ctx
):
176 name
= ctx
.get_temp()
177 ctx
.statements
+= [Assign(name
, Ref('list'), target_type
='list')]
179 # XXX HACK: add just some C++ text instead of syntax nodes...
180 ctx
.statements
+= ['%s->append(%s)' % (name
, i
)]
187 def __init__(self
, keys
, values
):
191 def flatten(self
, ctx
):
192 name
= ctx
.get_temp()
193 ctx
.statements
+= [Assign(name
, Ref('dict'), target_type
='dict')]
194 for k
, v
in zip(self
.keys
, self
.values
):
195 # XXX HACK: add just some C++ text instead of syntax nodes...
196 ctx
.statements
+= ['%s->__setitem__(%s, %s)' % (name
, k
, v
)]
203 def __init__(self
, items
):
206 def flatten(self
, ctx
):
207 name
= ctx
.get_temp()
208 ctx
.statements
+= [Assign(name
, Ref('set'), target_type
='set')]
210 # XXX HACK: add just some C++ text instead of syntax nodes...
211 ctx
.statements
+= ['%s->add(%s)' % (name
, i
)]
218 def __init__(self
, expr
, start
, end
, step
):
225 return '%s->__slice__(%s, %s, %s)' % (self
.expr
, self
.start
, self
.end
, self
.step
)
227 class Subscript(Node
):
228 def __init__(self
, expr
, index
):
233 return '%s->__getitem__(%s)' % (self
.expr
, self
.index
)
235 class Attribute(Node
):
236 def __init__(self
, expr
, attr
):
241 return '%s->__getattr__(%s)' % (self
.expr
, self
.attr
)
244 def __init__(self
, func
, args
, kwargs
):
250 return '%s->__call__(ctx, %s, %s)' % (self
.func
, self
.args
, self
.kwargs
)
253 def __init__(self
, expr
, true_stmts
, true_expr
, false_stmts
, false_expr
):
255 self
.true_stmts
= true_stmts
256 self
.true_expr
= true_expr
257 self
.false_stmts
= false_stmts
258 self
.false_expr
= false_expr
260 def flatten(self
, ctx
):
261 self
.temp
= ctx
.get_temp()
262 ctx
.statements
+= [Assign(self
.temp
, 'NULL'), self
]
266 true_stmts
= block_str(self
.true_stmts
)
267 false_stmts
= block_str(self
.false_stmts
)
268 body
= """if (test_truth({expr})) {{
270 {temp} = {true_expr};
273 {temp} = {false_expr};
275 """.format(expr
=self
.expr
, temp
=self
.temp
.name
, true_stmts
=true_stmts
,
276 true_expr
=self
.true_expr
, false_stmts
=false_stmts
, false_expr
=self
.false_expr
)
280 def __init__(self
, op
, lhs_expr
, rhs_stmts
, rhs_expr
):
282 self
.lhs_expr
= lhs_expr
283 self
.rhs_stmts
= rhs_stmts
284 self
.rhs_expr
= rhs_expr
287 def flatten(self
, ctx
, statements
):
288 self
.temp
= ctx
.get_temp()
289 statements
+= [Assign(self
.temp
, self
.lhs_expr
), self
]
293 rhs_stmts
= block_str(self
.rhs_stmts
)
294 body
= """if ({op}test_truth({lhs_expr})) {{
298 """.format(op
='!' if self
.op
== 'or' else '', lhs_expr
=self
.lhs_expr
,
299 temp
=self
.temp
.name
, rhs_stmts
=rhs_stmts
, rhs_expr
=self
.rhs_expr
)
303 def __init__(self
, target
, expr
, target_type
='node'):
306 self
.target_type
= target_type
309 if self
.target_type
is None:
310 return '%s = %s' % (self
.target
, self
.expr
)
312 return '%s *%s = %s' % (self
.target_type
, self
.target
, self
.expr
)
315 def __init__(self
, expr
, stmts
, else_block
):
318 self
.else_block
= else_block
321 stmts
= block_str(self
.stmts
)
322 body
= """if (test_truth({expr})) {{
325 """.format(expr
=self
.expr
, stmts
=stmts
)
327 stmts
= block_str(self
.else_block
)
331 """.format(expr
=self
.expr
, stmts
=stmts
)
334 class ListComp(Node
):
335 def __init__(self
, target
, iter, stmts
, expr
):
341 def flatten(self
, ctx
):
343 self
.temp
= l
.flatten(ctx
)
344 ctx
.statements
+= [self
]
348 stmts
= block_str(self
.stmts
)
350 if isinstance(self
.target
, list):
351 for i
, arg
in enumerate(self
.target
):
352 arg_unpacking
+= [Store(arg
.id, '(*__iter)->__getitem__(%s)' % i
)]
354 arg_unpacking
= [Store(self
.target
, '*__iter')]
355 arg_unpacking
= block_str(arg_unpacking
)
357 for (node_list::iterator __iter = {iter}->list_value()->begin(); __iter != {iter}->list_value()->end(); __iter++) {{
360 {temp}->append({expr});
362 """.format(iter=self
.iter, arg_unpacking
=arg_unpacking
, stmts
=stmts
, temp
=self
.temp
, expr
=self
.expr
)
375 class Continue(Node
):
386 def __init__(self
, target
, iter, stmts
):
392 stmts
= block_str(self
.stmts
)
394 if isinstance(self
.target
, list):
395 for i
, arg
in enumerate(self
.target
):
396 arg_unpacking
+= [Store(arg
.id, '(*__iter)->__getitem__(%s)' % i
)]
398 arg_unpacking
= [Store(self
.target
, '*__iter')]
399 arg_unpacking
= block_str(arg_unpacking
)
402 for (node_list::iterator __iter = {iter}->list_value()->begin(); __iter != {iter}->list_value()->end(); __iter++) {{
406 """.format(iter=self
.iter, arg_unpacking
=arg_unpacking
, stmts
=stmts
)
410 def __init__(self
, test_stmts
, test
, stmts
):
411 self
.test_stmts
= test_stmts
416 # XXX Super hack: too lazy to do this properly now
417 dup_test_stmts
= copy
.deepcopy(self
.test_stmts
)
418 assert isinstance(dup_test_stmts
[-1], Assign
)
419 dup_test_stmts
[-1].target_type
= None
421 test_stmts
= block_str(self
.test_stmts
)
422 dup_test_stmts
= block_str(dup_test_stmts
)
423 stmts
= block_str(self
.stmts
)
426 while (test_truth({test}))
431 """.format(test_stmts
=test_stmts
, dup_test_stmts
=dup_test_stmts
, test
=self
.test
, stmts
=stmts
)
435 def __init__(self
, value
):
437 if self
.value
is None:
438 self
.value
= NoneConst()
441 return 'return %s' % self
.value
444 def __init__(self
, expr
, lineno
):
449 body
= """if (!test_truth({expr})) {{
450 error("assert failed at line {lineno}");
452 """.format(expr
=self
.expr
, lineno
=self
.lineno
)
455 class Arguments(Node
):
456 def __init__(self
, args
, defaults
):
458 self
.defaults
= defaults
460 def flatten(self
, ctx
):
461 new_def
= [None] * (len(self
.args
) - len(self
.defaults
))
462 self
.defaults
= new_def
+ self
.defaults
463 self
.name_strings
= [StringConst(a
) for a
in self
.args
]
468 for i
, (arg
, default
, name
) in enumerate(zip(self
.args
, self
.defaults
, self
.name_strings
)):
470 arg_unpacking
+= [Store(arg
, 'kwargs->lookup(%s) ? kwargs->lookup(%s) : (args->len() > %s ? args->__getitem__(%s) : %s)' % (name
, name
, i
, i
, default
))]
472 arg_unpacking
+= [Store(arg
, 'args->__getitem__(%s)' % i
)]
473 return block_str(arg_unpacking
)
475 class FunctionDef(Node
):
476 def __init__(self
, name
, args
, stmts
, exp_name
=None):
478 self
.exp_name
= exp_name
if exp_name
else name
479 self
.exp_name
= 'fn_%s' % self
.exp_name
# make sure no name collisions
483 def flatten(self
, ctx
):
484 ctx
.functions
+= [self
]
485 return [Store(self
.name
, Ref('function_def', Identifier(self
.exp_name
)))]
488 stmts
= block_str(self
.stmts
)
489 arg_unpacking
= str(self
.args
)
491 node *{name}(context *parent_ctx, list *args, dict *kwargs) {{
492 context *ctx = new context(parent_ctx);
495 return &none_singleton;
496 }}""".format(name
=self
.exp_name
, arg_unpacking
=arg_unpacking
, stmts
=stmts
)
499 class ClassDef(Node
):
500 def __init__(self
, name
, stmts
):
504 def flatten(self
, ctx
):
505 ctx
.functions
+= [self
]
506 return [Store(self
.name
, Ref('class_def', '"%s"' % self
.name
, Identifier('_%s__create__' % self
.name
)))]
509 stmts
= block_str(self
.stmts
)
511 void _{name}__create__(class_def *ctx) {{
513 }}""".format(name
=self
.name
, stmts
=stmts
)