source: proto/Compiler/py2pablo.py @ 2382

Last change on this file since 2382 was 2382, checked in by ksherdy, 7 years ago

Renamed Python to Pablo translator. Added script command line parsing.

File size: 11.1 KB
Line 
1# Ken Herdy
2# Sept. 19, 2012
3#
4# Quick and dirty script to automate the translation of
5# 'Pablo' Python language syntax to 'Pablo' Pablo language syntax.
6#
7import unparse, ast, sys
8
9class ScopeStack():
10    def __init__(self):
11        self.stack = []
12        self.depth = -1
13       
14    def openScope(self):
15        self.depth = self.depth + 1
16        self.stack.append([])
17           
18    def closeScope(self):
19        self.stack.pop()
20        self.depth = self.depth - 1
21                       
22    def append(self,item):
23        self.stack[self.depth].append(item)           
24   
25    def inScope(self,t):
26        for li in self.stack: 
27            if t in li: 
28                return True
29        return False
30   
31class Py2Pablo(unparse.Unparser):
32    def __init__(self, tree, file = sys.stdout, indent = 1):
33       
34        self.base_indent = indent       
35        self.inClassDef = False
36        self.scopeStack = ScopeStack()
37       
38        super(Py2Pablo, self).__init__(tree, file)
39             
40    def gen(self, t):
41        self.Ccode = ""
42        self._indent = self.base_indent
43        self.dispatch(t)
44        return self.Ccode         
45       
46    def enterClassDef(self):
47        self.inClassDef = True
48   
49    def leaveClassDef(self):
50        self.inClassDef = False   
51   
52    def enterFunctionDef(self):
53        self.scopeStack.openScope()
54       
55    def leaveFunctionDef(self):
56        self.scopeStack.closeScope()
57           
58    def enterScope(self):
59        self.scopeStack.openScope()
60       
61    def leaveScope(self):   
62        self.scopeStack.closeScope()
63       
64    def isFunctionParameter(self, name):
65        if isinstance(name, ast.Name) and isinstance(name.ctx, ast.Param):
66            if not self.scopeStack.inScope(name.id):
67                return True
68        return False   
69                               
70    def isLocalDecl(self, target):
71        if isinstance(target, ast.Name) and isinstance(target.ctx, ast.Store):
72            if not self.scopeStack.inScope(target.id):
73                return True
74        return False
75
76    def exitNodeNotSupported(self, t):
77        sys.stdout.write('\n\nError:  ' + ast.dump(t))
78        if (isinstance(t,ast.Expr) or isinstance(t,ast.stmt)):
79            sys.stdout.write(', Line: '   + str(t.lineno))
80            sys.stdout.write(', Column: ' + str(t.col_offset))
81        sys.stdout.write(' not supported for translation to Pablo.\n')
82        sys.exit(0)       
83         
84    def do_block(self, suite):
85        "Print '{', and increase the indentation."
86        self.scopeStack.openScope()
87        self.write("{")
88        self._indent += 1
89        for s in suite:
90            self.dispatch(s)
91        self._indent -= 1
92        self.fill("}")         
93        self.scopeStack.closeScope()
94       
95    def _Module(self, tree):
96        for stmt in tree.body:
97            self.dispatch(stmt)
98
99    def _Expr(self, tree):
100        self.fill()
101        self.dispatch(tree.value)
102        self.write(";")
103         
104    def _ClassDef(self, t):
105        self.enterClassDef() 
106        self.write("\n")
107        self.fill("struct "+t.name)
108        if t.bases:
109            self.write("(")
110            for a in t.bases:
111                self.dispatch(a)
112                self.write(", ")
113            self.write(")")
114        self.do_block(t.body)
115        self.write(";")
116        self.leaveClassDef()
117                         
118    def _FunctionDef(self, t):
119        self.enterFunctionDef()
120        self.write("\n")
121        self.fill("function void "+t.name + "(")
122       
123        for name in t.args.args:
124            self.isFunctionParameter(name)       
125
126        self.dispatch(t.args)
127        self.write(") ")
128        self.do_block(t.body)
129        self.leaveFunctionDef()
130             
131    def _If(self, t):
132        self.fill("if (")
133        self.dispatch(t.test)
134        self.write(") ")
135        self.do_block(t.body)
136###        # collapse nested ifs into equivalent elifs.
137###        while (t.orelse and len(t.orelse) == 1 and
138###               isinstance(t.orelse[0], ast.If)):
139###            t = t.orelse[0]
140###            self.fill("else if (")
141###            self.dispatch(t.test)
142###            self.write(") ")
143###            self.do_block(t.body)
144###        # final else
145        if t.orelse:
146            self.fill("else ")
147            self.do_block(t.orelse)
148             
149    def _While(self, t):
150        self.fill("while (")
151        self.dispatch(t.test)
152        self.write(") ")
153        self.do_block(t.body)
154        if t.orelse:
155            self.fill("else ")
156            self.do_block(t.orelse)
157             
158    def _Return(self, t):
159        self.fill("return")
160        if t.value:
161            self.write(" ")
162            self.dispatch(t.value)       
163       
164#    def isLocalVar(self, name):
165#        self.write(name)
166#        return (name.find('.') > 0)   
167       
168    def _Assign(self, t):       
169        self.fill()
170        for target in t.targets:
171            if self.inClassDef:
172                self.write("stream<1> ")
173            elif self.isLocalDecl(target):
174                self.write("var stream<1> ")
175                self.scopeStack.append(target.id) 
176            self.dispatch(target)
177            if not self.inClassDef:
178                self.write(" = ")
179        if not self.inClassDef:       
180            self.dispatch(t.value)
181        self.write(";")       
182       
183    def _AugAssign(self, t):
184        self.fill()
185        if self.isLocalDecl(t.target):
186            self.write("var stream<1> ")
187            self.scopeStack.append(t.target.id)
188        self.dispatch(t.target)
189        self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
190        self.dispatch(t.value)
191        self.write(";")
192
193#
194#    unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
195#    def _UnaryOp(self, t):
196#        pass
197#
198#    binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
199#                    "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
200#                    "FloorDiv":"//", "Pow": "**"}
201#    def _BinOp(self, t):
202#        pass
203#
204#    cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
205#                        "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
206#    def _Compare(self, t):
207#        pass
208#
209#    def _BoolOp(self, t):
210#        pass
211#
212#    def _Attribute(self,t):
213#        pass
214#
215#    def _Call(self, t):
216#        pass
217#
218    def _arguments(self, t):
219        first = True
220        # normal arguments
221        defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
222        for a,d in zip(t.args, defaults):
223            if first:first = False
224            else: self.write(", ")
225            self.write("struct ")   #Assume struct type
226            self.write(str(a.id[0]).upper() + str(a.id[1:]) + " ")
227            self.dispatch(a),
228            if d:
229                self.write("=")
230                self.dispatch(d)
231
232        # varargs
233        if t.vararg:
234            if first:first = False
235            else: self.write(", ")
236            self.write("*")
237            self.write(t.vararg)
238
239        # kwargs
240        if t.kwarg:
241            if first:first = False
242            else: self.write(", ")
243            self.write("**"+t.kwarg)
244#
245#    def _Str(self, tree):
246#        pass
247#   
248    def Cgen_Name(self, t):
249        self.write(t.id)
250#   
251#    def _Num(self, t):
252#        pass
253
254    def _Import(self, t):
255        self.exitNodeNotSupported(t)
256    def _ImportFrom(self, t):
257        self.exitNodeNotSupported(t)
258    def _Pass(self, t):
259        self.exitNodeNotSupported(t)
260    def _Break(self, t):
261        self.exitNodeNotSupported(t)
262    def _Continue(self, t):
263        self.exitNodeNotSupported(t)       
264    def _Delete(self, t):
265        self.exitNodeNotSupported(t)
266    def _Assert(self, t):
267        self.exitNodeNotSupported(t)
268    def _Exec(self, t):
269        self.exitNodeNotSupported(t)
270    def _Print(self, t):
271        self.exitNodeNotSupported(t)   
272    def _Global(self, t):
273        self.exitNodeNotSupported(t)
274    def _Yield(self, t):
275        self.exitNodeNotSupported(t)
276    def _Raise(self, t):
277        self.exitNodeNotSupported(t)
278    def _TryExcept(self, t):
279        self.exitNodeNotSupported(t)       
280    def _TryFinally(self, t):
281        self.exitNodeNotSupported(t)       
282    def _ExceptHandler(self, t):
283        self.exitNodeNotSupported(t)       
284    def _For(self, t):
285        self.exitNodeNotSupported(t)
286    def _With(self, t):
287        self.exitNodeNotSupported(t)
288    def _Repr(self, t):
289        self.exitNodeNotSupported(t)
290    def _List(self, t):
291        self.exitNodeNotSupported(t)
292    def _ListComp(self, t):
293        self.exitNodeNotSupported(t)
294    def _GeneratorExp(self, t):
295        self.exitNodeNotSupported(t)
296    def _SetComp(self, t):
297        self.exitNodeNotSupported(t)
298    def _DictComp(self, t):
299        self.exitNodeNotSupported(t)
300    def _comprehension(self, t):
301        self.exitNodeNotSupported(t)
302    def _Set(self, t):
303        self.exitNodeNotSupported(t)
304    def _Dict(self, t):
305        self.exitNodeNotSupported(t)
306    def _Tuple(self, t):
307        self.exitNodeNotSupported(t)
308    def _Subscript(self, t):
309        self.exitNodeNotSupported(t)
310    def _Ellipsis(self, t):
311        self.exitNodeNotSupported(t)
312    def _Index(self, t):
313        self.exitNodeNotSupported(t)
314    def _Slice(self, t):
315        self.exitNodeNotSupported(t)
316    def _ExtSlice(self, t):
317        self.exitNodeNotSupported(t)
318    def _keyword(self, t):
319        self.exitNodeNotSupported(t)
320    def _Lambda(self, t):
321        self.exitNodeNotSupported(t)
322    def _alias(self, t):
323        self.exitNodeNotSupported(t)
324
325def readfile(filename):
326    f = open(filename, 'r')
327    contents = f.read() 
328    f.close()
329    return contents
330
331def writefile(filename, code):
332    f=open(filename, 'w')
333    f.write(code)
334    f.close()
335
336# Helpers
337class Variables(ast.NodeVisitor):
338    def __init__(self,node):
339        self.params = []
340        self.stores = []
341        self.generic_visit(node)
342    def visit_Name(self, nm):
343        if isinstance(nm.ctx, ast.Param):
344            self.params.append(nm.id)
345        if isinstance(nm.ctx, ast.Store):
346            if nm.id not in self.stores: self.stores.append(nm.id)
347    def getLocals(self): 
348        return [v for v in self.stores if not v in self.params]
349    def getParams(self):
350        return [v for v in self.params]
351
352import optparse
353
354def get_option_parser():
355    """Return an C{optparse.OptionParser} instance tied to this configuration."""
356   
357    parser = optparse.OptionParser(usage='python %prog <input file> [-o output_filename]',
358                    version='1.0',
359                    )
360   
361    parser.add_option('-o', '--output', 
362              dest='output_filename', 
363              type='string',
364              default='code.pablo',
365              help='default:code.pablo',
366              )
367   
368    return parser
369   
370if __name__ == '__main__':   
371   
372    option_parser = get_option_parser() 
373    options, args = option_parser.parse_args(sys.argv[1:])
374
375    # Positional arguments
376    if len(args) != 1:
377        option_parser.print_usage()
378        sys.exit()
379
380    infile = args[0]   
381    s = ast.parse(readfile(infile))
382   
383    if options.output_filename:
384        Py2Pablo(s, open(options.output_filename, "w")) 
385    else: 
386        Py2Pablo(s)
387   
388   
389
390   
391   
Note: See TracBrowser for help on using the repository browser.