8000 Python AST for gpython · go-python/gpython@5084eeb · GitHub
[go: up one dir, main page]

Skip to content

Commit 5084eeb

Browse files
committed
Python AST for gpython
1 parent a1f34b2 commit 5084eeb

File tree

5 files changed

+1029
-64
lines changed

5 files changed

+1029
-64
lines changed

ast/asdl_go.py

Lines changed: 79 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#! /usr/bin/env python
2-
"""Generate C code from an ASDL description."""
2+
"""Generate Go code from an ASDL description."""
33

44
# TO DO
55
# handle fields that have a type but no name
@@ -12,21 +12,30 @@
1212
TABSIZE = 4
1313
MAX_COL = 80
1414

15-
def get_c_type(name):
16-
"""Return a string for the C name of the type.
15+
def get_go_type(name):
16+
"""Return a string for the Go name of the type.
1717
1818
This function special cases the default types provided by asdl:
1919
identifier, string, int.
2020
"""
2121
# XXX ack! need to figure out where Id is useful and where string
2222
if isinstance(name, asdl.Id):
2323
name = name.value
24+
#if not name.startswith("[]"):
25+
# name= "*"+name
2426
if name in asdl.builtin_types:
2527
return name
2628
else:
2729
#return "%s_ty" % name
2830
return name
2931

32+
def go_name(name):
33+
"""Returns a name for exportable go"""
34+
name = str(name)
35+
if name[0].isupper():
36+
return name
37+
return "".join(n.title() for n in name.split("_"))
38+
3039
def is_simple(sum):
3140
"""Return True if a sum is a simple.
3241
@@ -76,7 +85,7 @@ def visitSum(self, sum, name, depth):
7685
self.sum_with_constructors(sum, name, depth)
7786

7887
def simple_sum(self, sum, name, depth):
79-
ctype = get_c_type(name)
88+
ctype = get_go_type(name)
8089
enum = []
8190
for i in range(len(sum.types)):
8291
type = sum.types[i]
@@ -87,13 +96,13 @@ def simple_sum(self, sum, name, depth):
8796
self.emit("", depth)
8897

8998
def sum_with_constructors(self, sum, name, depth):
90-
ctype = get_c_type(name)
99+
ctype = get_go_type(name)
91100
s = "type %(ctype)s * _%(name)s" % locals()
92-
self.emit(s, depth)
101+
#self.emit(s, depth)
93102
self.emit("", depth)
94103

95104
def visitProduct(self, product, name, depth):
96-
ctype = get_c_type(name)
105+
ctype = get_go_type(name)
97106
#s = "type %(ctype)s *_%(name)s" % locals()
98107
#self.emit(s, depth)
99108
#self.emit("", depth)
@@ -117,52 +126,60 @@ def sum_with_constructors(self, sum, name, depth):
117126
def emit(s, depth=depth):
118127
self.emit(s % sys._getframe(1).f_locals, depth)
119128
enum = []
129+
name = go_name(name)
120130
for i in range(len(sum.types)):
121131
type = sum.types[i]
122-
enum.append("%s_kind=%s(%d)" % (type.name, name, i + 1))
132+
enum.append("%s_kind=%s_kind(%d)" % (type.name, name, i + 1))
123133

124-
emit("type _%(name)s_kind int\nconst (\n" + "\n".join(enum) + "\n)")
134+
#emit("type %(name)s_kind int\nconst (\n" + "\n".join(enum) + "\n)")
125135

126-
emit("type _%(name)s struct {")
127-
emit("kind _%(name)s_kind;", depth + 1)
128-
emit("v struct {", depth + 1)
129-
for t in sum.types:
130-
self.visit(t, depth + 2)
131-
emit("}", depth + 1)
136+
emit('var %(name)sType = ASTType.NewType("%(name)s", "%(name)s Node", nil, nil)')
137+
self.emit("func (o *%s) Ast() {}" % name, depth)
138+
self.emit("func (o *%s) Type() *py.Type {return %sType}" % (name, name), depth)
139+
140+
emit("type %(name)s struct {")
141+
emit("kind %(name)s_kind;", depth + 1)
142+
#emit("v struct {", depth + 1)
143+
#emit("}", depth + 1)
132144
for field in sum.attributes:
133145
# rudimentary attribute handling
134146
type = str(field.type)
135147
assert type in asdl.builtin_types, type
136-
emit("%s %s" % (field.name, type), depth + 1);
148+
emit("%s %s" % (go_name(field.name), type), depth + 1);
137149
emit("}")
150+
self.name = name
151+
for t in sum.types:
152+
self.visit(t, depth + 2)
138153
emit("")
139154

140155
def visitConstructor(self, cons, depth):
141-
if cons.fields:
142-
self.emit("%s struct {" % cons.name, depth)
143-
for f in cons.fields:
144-
self.visit(f, depth + 1)
145-
self.emit("}", depth)
146-
self.emit("", depth)
147-
else:
148-
# XXX not sure what I want here, nothing is probably fine
149-
pass
156+
parent = self.name
157+
name = go_name(cons.name)
158+
self.emit(('var %(name)sType = %(parent)sType.NewType("%(name)s", "%(name)s Node", nil, nil)') % locals(), 0)
159+
self.emit("type %s struct {" % cons.name, depth)
160+
self.emit("%s" % self.name, depth)
161+
for f in cons.fields:
162+
self.visit(f, depth + 1)
163+
self.emit("}", depth)
164+
self.emit("func (o *%s) Ast() {}" % cons.name, depth)
165+
self.emit("func (o *%s) Type() *py.Type {return %sType}" % (cons.name, cons.name), depth)
166+
self.emit("", depth)
150167

151168
def visitField(self, field, depth):
152169
# XXX need to lookup field.type, because it might be something
153170
# like a builtin...
154-
ctype = get_c_type(field.type)
171+
ctype = get_go_type(field.type)
155172
name = field.name
156173
if field.seq:
157174
if field.type.value in ('cmpop',):
158-
self.emit("%(name)s []asdl_int_seq" % locals(), depth)
175+
self.emit("%(name)s []Ast" % locals(), depth)
159176
else:
160-
self.emit("%(name)s []asdl_seq " % locals(), depth)
177+
self.emit("%(name)s []Ast " % locals(), depth)
161178
else:
162179
self.emit("%(name)s %(ctype)s" % locals(), depth)
163180

164181
def visitProduct(self, product, name, depth):
165-
self.emit("type _%(name)s struct {" % locals(), depth)
182+
self.emit("type %(name)s struct {" % locals(), depth)
166183
for f in product.fields:
167184
self.visit(f, depth + 1)
168185
for field in product.attributes:
@@ -192,9 +209,9 @@ def visitSum(self, sum, name):
192209
self.visit(t, name, sum.attributes)
193210

194211
def get_args(self, fields):
195-
"""Return list of C argument into, one for each field.
212+
"""Return list of Go argument into, one for each field.
196213
197-
Argument info is 3-tuple of a C type, variable name, and flag
214+
Argument info is 3-tuple of a Go type, variable name, and flag
198215
that is true if type can be NULL.
199216
"""
200217
args = []
@@ -207,21 +224,21 @@ def get_args(self, fields):
207224
name = "name%d" % (c - 1)
208225
else:
209226
name = f.name
210-
# XXX should extend get_c_type() to handle this
227+
# XXX should extend get_go_type() to handle this
211228
if f.seq:
212229
if f.type.value in ('cmpop',):
213230
ctype = "[]asdl_int_seq"
214231
else:
215232
ctype = "[]asdl_seq"
216233
else:
217-
ctype = get_c_type(f.type)
234+
ctype = get_go_type(f.type)
218235
args.append((ctype, name, f.opt or f.seq))
219236
return args
220237

221238
def visitConstructor(self, cons, type, attrs):
222239
args = self.get_args(cons.fields)
223240
attrs = self.get_args(attrs)
224-
ctype = get_c_type(type)
241+
ctype = get_go_type(type)
225242
self.emit_function(cons.name, ctype, args, attrs)
226243

227244
def emit_function(self, name, ctype, args, attrs, union=True):
@@ -240,28 +257,28 @@ def emit_function(self, name, ctype, args, attrs, union=True):
240257
self.emit("%s %s(%s);" % (ctype, name, argstr), False)
241258

242259
def visitProduct(self, prod, name):
243-
self.emit_function(name, get_c_type(name),
260+
self.emit_function(name, get_go_type(name),
244261
self.get_args(prod.fields), [], union=False)
245262

246263

247264
class FunctionVisitor(PrototypeVisitor):
248265
"""Visitor to generate constructor functions for AST."""
249266

250267
def emit_function(self, name, ctype, args, attrs, union=True):
268+
return # FIXME
251269
def emit(s, depth=0):
252270
self.emit(s, depth)
253-
argstr = ", ".join(["%s %s" % (aname, atype)
254-
for atype, aname, opt in args + attrs])
255-
emit("func %s(%s) *%s {" % (name, argstr, ctype))
256-
emit("var p %s;" % ctype, 1)
271+
argl = []
272+
for atype, aname, opt in args + attrs:
273+
argl.append("%s %s" % (go_name(aname), atype))
274+
argstr = ", ".join(argl)
275+
emit("func New%s(%s) *%s {" % (name, argstr, name))
276+
emit("var p %s;" % name, 1)
257277
for argtype, argname, opt in args:
258278
if not opt and argtype != "int":
259-
emit("if (!%s) {" % argname, 1)
260-
emit("PyErr_SetString(PyExc_ValueError,", 2)
279+
emit("if %s == nil {" % argname, 1)
261280
msg = "field %s is required for %s" % (argname, name)
262-
emit(' "%s");' % msg,
263-
2)
264-
emit('return NULL;', 2)
281+
emit('panic(py.ExceptionNewf(py.ValueError, "%s"))' % msg)
265282
emit('}', 1)
266283

267284
#emit("p = (%s)PyArena_Malloc(arena, sizeof(*p));" % ctype, 1);
@@ -280,14 +297,17 @@ def emit(s, depth=0):
280297
self.emit(s, depth)
281298
emit("p.kind = %s_kind;" % name, 1)
282299
for argtype, argname, opt in args:
283-
emit("p.v.%s.%s = %s;" % (name, argname, argname), 1)
300+
argname = go_name(argname)
301+
emit("p.%s = %s;" % (argname, argname), 1)
284302
for argtype, argname, opt in attrs:
303+
argname = go_name(argname)
285304
emit("p.%s = %s;" % (argname, argname), 1)
286305

287306
def emit_body_struct(self, name, args, attrs):
288307
def emit(s, depth=0):
289308
self.emit(s, depth)
290309
for argtype, argname, opt in args:
310+
argname = go_name(argname)
291311
emit("p.%s = %s;" % (argname, argname), 1)
292312
assert not attrs
293313

@@ -317,14 +337,14 @@ def visitField(self, sum):
317337
class Obj2ModPrototypeVisitor(PickleVisitor):
318338
def visitProduct(self, prod, name):
319339
code = "int obj2ast_%s(PyObject* obj, %s* out, PyArena* arena);"
320-
#self.emit(code % (name, get_c_type(name)), 0)
340+
#self.emit(code % (name, get_go_type(name)), 0)
321341

322342
visitSum = visitProduct
323343

324344

325345
class Obj2ModVisitor(PickleVisitor):
326346
def funcHeader(self, name):
327-
ctype = get_c_type(name)
347+
ctype = get_go_type(name)
328348
self.emit("int", 0)
329349
self.emit("obj2ast_%s(PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0)
330350
self.emit("{", 0)
@@ -395,7 +415,7 @@ def complexSum(self, sum, name):
395415
self.sumTrailer(name, True)
396416

397417
def visitAttributeDeclaration(self, a, name, sum=sum):
398-
ctype = get_c_type(a.type)
418+
ctype = get_go_type(a.type)
399419
self.emit("%s %s;" % (ctype, a.name), 1)
400420

401421
def visitSum(self, sum, name):
@@ -405,7 +425,7 @@ def visitSum(self, sum, name):
405425
self.complexSum(sum, name)
406426

407427
def visitProduct(self, prod, name):
408-
ctype = get_c_type(name)
428+
ctype = get_go_type(name)
409429
self.emit("int", 0)
410430
self.emit("obj2ast_%s(PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0)
411431
self.emit("{", 0)
@@ -425,14 +445,14 @@ def visitProduct(self, prod, name):
425445
self.emit("", 0)
426446

427447
def visitFieldDeclaration(self, field, name, sum=None, prod=None, depth=0):
428-
ctype = get_c_type(field.type)
448+
ctype = get_go_type(field.type)
429449
if field.seq:
430450
if self.isSimpleType(field):
431451
self.emit("%s []asdl_int_seq;" % field.name, depth)
432452
else:
433453
self.emit("%s []asdl_seq;" % field.name, depth)
434454
else:
435-
ctype = get_c_type(field.type)
455+
ctype = get_go_type(field.type)
436456
self.emit("%s %s" % (field.name, ctype), depth)
437457

438458
def isSimpleSum(self, field):
@@ -441,13 +461,13 @@ def isSimpleSum(self, field):
441461
'unaryop', 'cmpop')
442462

443463
def isNumeric(self, field):
444-
return get_c_type(field.type) in ("int", "bool")
464+
return get_go_type(field.type) in ("int", "bool")
445465

446466
def isSimpleType(self, field):
447467
return self.isSimpleSum(field) or self.isNumeric(field)
448468

449469
def visitField(self, field, name, sum=None, prod=None, depth=0):
450-
ctype = get_c_type(field.type)
470+
ctype = get_go_type(field.type)
451471
if field.opt:
452472
check = "exists_not_none(obj, &PyId_%s)" % (field.name,)
453473
else:
@@ -505,7 +525,7 @@ def visitField(self, field, name, sum=None, prod=None, depth=0):
505525
class MarshalPrototypeVisitor(PickleVisitor):
506526

507527
def prototype(self, sum, name):
508-
ctype = get_c_type(name)
528+
ctype = get_go_type(name)
509529
self.emit("int marshal_write_%s(PyObject **, int *, %s);"
510530
% (name, ctype), 0)
511531

@@ -543,7 +563,7 @@ def visitSum(self, sum, name):
543563
self.emit("};", 0)
544564
ptype = "void*"
545565
if is_simple(sum):
546-
ptype = get_c_type(name)
566+
ptype = get_go_type(name)
< B83A code>547567
tnames = []
548568
for t in sum.types:
549569
tnames.append(str(t.name)+"_singleton")
@@ -1016,7 +1036,7 @@ def visit(self, object):
10161036
class ObjVisitor(PickleVisitor):
10171037

10181038
def func_begin(self, name):
1019-
ctype = get_c_type(name)
1039+
ctype = get_go_type(name)
10201040
self.emit("func ast2obj_%s(void* _o) py.Object" % (name), 0)
10211041
self.emit("{", 0)
10221042
self.emit("%s o = (%s)_o;" % (ctype, ctype), 1)
@@ -1135,7 +1155,7 @@ def set(self, field, value, depth):
11351155
else:
11361156
self.emit("value = ast2obj_list(%s, ast2obj_%s);" % (value, field.type), depth)
11371157
else:
1138-
ctype = get_c_type(field.type)
1158+
ctype = get_go_type(field.type)
11391159
self.emit("value = ast2obj_%s(%s);" % (field.type, value), depth)
11401160

11411161

@@ -1210,7 +1230,8 @@ def main(srcfile):
12101230
p = "%s-ast.go" % mod.name
12111231
f = open(p, "w")
12121232
f.write(auto_gen_msg)
1213-
f.write('package parser\n')
1233+
f.write('package ast\n')
1234+
f.write('import "github.com/ncw/gpython/py"\n')
12141235
c = ChainOfVisitors(TypeDefVisitor(f),
12151236
StructVisitor(f),
12161237
PrototypeVisitor(f),

0 commit comments

Comments
 (0)
0