1
|
|
|
import ast |
2
|
|
|
|
3
|
|
|
|
4
|
|
|
symbols = { |
5
|
|
|
ast.Eq: "==", |
6
|
|
|
ast.NotEq: '!=', |
7
|
|
|
ast.Pass: '/*pass*/', |
8
|
|
|
ast.Mult: '*', |
9
|
|
|
ast.Add: '+', |
10
|
|
|
ast.Sub: '-', |
11
|
|
|
ast.Div: '/', |
12
|
|
|
ast.FloorDiv: '/', |
13
|
|
|
ast.Mod: '%', |
14
|
|
|
ast.Lt: '<', |
15
|
|
|
ast.Gt: '>', |
16
|
|
|
ast.GtE: '>=', |
17
|
|
|
ast.LtE: '<=', |
18
|
|
|
ast.LShift: '<<', |
19
|
|
|
ast.RShift: '>>', |
20
|
|
|
ast.BitXor: '^', |
21
|
|
|
ast.BitOr: '|', |
22
|
|
|
ast.BitAnd: '&', |
23
|
|
|
ast.Not: '!', |
24
|
|
|
ast.IsNot: '!=', |
25
|
|
|
ast.USub: '-', |
26
|
|
|
ast.And: '&&', |
27
|
|
|
ast.Or: '||' |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
|
31
|
|
|
def c_symbol(node): |
32
|
|
|
"""Find the equivalent C symbol for a Python ast symbol node""" |
33
|
|
|
symbol_type = type(node) |
34
|
|
|
return symbols[symbol_type] |
35
|
|
|
|
36
|
|
|
|
37
|
|
|
class CLikeTranspiler(ast.NodeVisitor): |
38
|
|
|
builtin_constants = frozenset(['True', 'False', 'None']) |
39
|
|
|
"""Provides a base for C-like programming languages""" |
40
|
|
|
def visit(self, node): |
41
|
|
|
if type(node) in symbols: |
42
|
|
|
return c_symbol(node) |
43
|
|
|
else: |
44
|
|
|
return super(CLikeTranspiler, self).visit(node) |
45
|
|
|
|
46
|
|
|
def visit_Name(self, node): |
47
|
|
|
if node.id in self.builtin_constants: |
48
|
|
|
return node.id.lower() |
49
|
|
|
return node.id |
50
|
|
|
|
51
|
|
|
def visit_Num(self, node): |
52
|
|
|
return str(node.n) |
53
|
|
|
|
54
|
|
|
def visit_Str(self, node): |
55
|
|
|
return '"{0}"'.format(node.s) |
56
|
|
|
|
57
|
|
|
def visit_Return(self, node): |
58
|
|
|
if node.value: |
59
|
|
|
return 'return {0};'.format(self.visit(node.value)) |
60
|
|
|
return 'return;' |
61
|
|
|
|
62
|
|
|
def visit_If(self, node): |
63
|
|
|
buf = [] |
64
|
|
|
buf.append('if({0}) {{'.format(self.visit(node.test))) |
65
|
|
|
buf.extend([self.visit(child) for child in node.body]) |
66
|
|
|
|
67
|
|
|
orelse = [self.visit(child) for child in node.orelse] |
68
|
|
|
if orelse: |
69
|
|
|
buf.append('} else {') |
70
|
|
|
buf.extend(orelse) |
71
|
|
|
buf.append("}") |
72
|
|
|
else: |
73
|
|
|
buf.append('}') |
74
|
|
|
|
75
|
|
|
return '\n'.join(buf) |
76
|
|
|
|
77
|
|
|
def visit_While(self, node): |
78
|
|
|
buf = [] |
79
|
|
|
buf.append("while ({0}) {{".format(self.visit(node.test))) |
80
|
|
|
buf.extend([self.visit(n) for n in node.body]) |
81
|
|
|
buf.append("}") |
82
|
|
|
return '\n'.join(buf) |
83
|
|
|
|
84
|
|
|
def visit_Compare(self, node): |
85
|
|
|
left = self.visit(node.left) |
86
|
|
|
op = self.visit(node.ops[0]) |
87
|
|
|
right = self.visit(node.comparators[0]) |
88
|
|
|
return "{0} {1} {2}".format(left, op, right) |
89
|
|
|
|
90
|
|
|
def visit_BoolOp(self, node): |
91
|
|
|
op = self.visit(node.op) |
92
|
|
|
return op.join([self.visit(v) for v in node.values]) |
93
|
|
|
|
94
|
|
|
def visit_BinOp(self, node): |
95
|
|
|
if isinstance(node.op, ast.Pow): |
96
|
|
|
return "std::pow({0}, {1})".format(self.visit(node.left), |
97
|
|
|
self.visit(node.right)) |
98
|
|
|
|
99
|
|
|
return " ".join([self.visit(node.left), |
100
|
|
|
self.visit(node.op), |
101
|
|
|
self.visit(node.right)]) |
102
|
|
|
|
103
|
|
|
def visit_AugAssign(self, node): |
104
|
|
|
target = self.visit(node.target) |
105
|
|
|
op = self.visit(node.op) |
106
|
|
|
val = self.visit(node.value) |
107
|
|
|
return "{0} {1}= {2};".format(target, op, val) |
108
|
|
|
|