1#! /usr/bin/env python 2"""Generate C code from an ASDL description.""" 3 4import os, sys 5 6import asdl 7 8TABSIZE = 4 9MAX_COL = 80 10 11def get_c_type(name): 12 """Return a string for the C name of the type. 13 14 This function special cases the default types provided by asdl. 15 """ 16 if name in asdl.builtin_types: 17 return name 18 else: 19 return "%s_ty" % name 20 21def reflow_lines(s, depth): 22 """Reflow the line s indented depth tabs. 23 24 Return a sequence of lines where no line extends beyond MAX_COL 25 when properly indented. The first line is properly indented based 26 exclusively on depth * TABSIZE. All following lines -- these are 27 the reflowed lines generated by this function -- start at the same 28 column as the first character beyond the opening { in the first 29 line. 30 """ 31 size = MAX_COL - depth * TABSIZE 32 if len(s) < size: 33 return [s] 34 35 lines = [] 36 cur = s 37 padding = "" 38 while len(cur) > size: 39 i = cur.rfind(' ', 0, size) 40 # XXX this should be fixed for real 41 if i == -1 and 'GeneratorExp' in cur: 42 i = size + 3 43 assert i != -1, "Impossible line %d to reflow: %r" % (size, s) 44 lines.append(padding + cur[:i]) 45 if len(lines) == 1: 46 # find new size based on brace 47 j = cur.find('{', 0, i) 48 if j >= 0: 49 j += 2 # account for the brace and the space after it 50 size -= j 51 padding = " " * j 52 else: 53 j = cur.find('(', 0, i) 54 if j >= 0: 55 j += 1 # account for the paren (no space after it) 56 size -= j 57 padding = " " * j 58 cur = cur[i+1:] 59 else: 60 lines.append(padding + cur) 61 return lines 62 63def is_simple(sum): 64 """Return True if a sum is a simple. 65 66 A sum is simple if its types have no fields, e.g. 67 unaryop = Invert | Not | UAdd | USub 68 """ 69 for t in sum.types: 70 if t.fields: 71 return False 72 return True 73 74 75class EmitVisitor(asdl.VisitorBase): 76 """Visit that emits lines""" 77 78 def __init__(self, file): 79 self.file = file 80 self.identifiers = set() 81 super(EmitVisitor, self).__init__() 82 83 def emit_identifier(self, name): 84 name = str(name) 85 if name in self.identifiers: 86 return 87 self.emit("_Py_IDENTIFIER(%s);" % name, 0) 88 self.identifiers.add(name) 89 90 def emit(self, s, depth, reflow=True): 91 # XXX reflow long lines? 92 if reflow: 93 lines = reflow_lines(s, depth) 94 else: 95 lines = [s] 96 for line in lines: 97 line = (" " * TABSIZE * depth) + line + "\n" 98 self.file.write(line) 99 100 101class TypeDefVisitor(EmitVisitor): 102 def visitModule(self, mod): 103 for dfn in mod.dfns: 104 self.visit(dfn) 105 106 def visitType(self, type, depth=0): 107 self.visit(type.value, type.name, depth) 108 109 def visitSum(self, sum, name, depth): 110 if is_simple(sum): 111 self.simple_sum(sum, name, depth) 112 else: 113 self.sum_with_constructors(sum, name, depth) 114 115 def simple_sum(self, sum, name, depth): 116 enum = [] 117 for i in range(len(sum.types)): 118 type = sum.types[i] 119 enum.append("%s=%d" % (type.name, i + 1)) 120 enums = ", ".join(enum) 121 ctype = get_c_type(name) 122 s = "typedef enum _%s { %s } %s;" % (name, enums, ctype) 123 self.emit(s, depth) 124 self.emit("", depth) 125 126 def sum_with_constructors(self, sum, name, depth): 127 ctype = get_c_type(name) 128 s = "typedef struct _%(name)s *%(ctype)s;" % locals() 129 self.emit(s, depth) 130 self.emit("", depth) 131 132 def visitProduct(self, product, name, depth): 133 ctype = get_c_type(name) 134 s = "typedef struct _%(name)s *%(ctype)s;" % locals() 135 self.emit(s, depth) 136 self.emit("", depth) 137 138 139class StructVisitor(EmitVisitor): 140 """Visitor to generate typedefs for AST.""" 141 142 def visitModule(self, mod): 143 for dfn in mod.dfns: 144 self.visit(dfn) 145 146 def visitType(self, type, depth=0): 147 self.visit(type.value, type.name, depth) 148 149 def visitSum(self, sum, name, depth): 150 if not is_simple(sum): 151 self.sum_with_constructors(sum, name, depth) 152 153 def sum_with_constructors(self, sum, name, depth): 154 def emit(s, depth=depth): 155 self.emit(s % sys._getframe(1).f_locals, depth) 156 enum = [] 157 for i in range(len(sum.types)): 158 type = sum.types[i] 159 enum.append("%s_kind=%d" % (type.name, i + 1)) 160 161 emit("enum _%(name)s_kind {" + ", ".join(enum) + "};") 162 163 emit("struct _%(name)s {") 164 emit("enum _%(name)s_kind kind;", depth + 1) 165 emit("union {", depth + 1) 166 for t in sum.types: 167 self.visit(t, depth + 2) 168 emit("} v;", depth + 1) 169 for field in sum.attributes: 170 # rudimentary attribute handling 171 type = str(field.type) 172 assert type in asdl.builtin_types, type 173 emit("%s %s;" % (type, field.name), depth + 1); 174 emit("};") 175 emit("") 176 177 def visitConstructor(self, cons, depth): 178 if cons.fields: 179 self.emit("struct {", depth) 180 for f in cons.fields: 181 self.visit(f, depth + 1) 182 self.emit("} %s;" % cons.name, depth) 183 self.emit("", depth) 184 185 def visitField(self, field, depth): 186 # XXX need to lookup field.type, because it might be something 187 # like a builtin... 188 ctype = get_c_type(field.type) 189 name = field.name 190 if field.seq: 191 if field.type == 'cmpop': 192 self.emit("asdl_int_seq *%(name)s;" % locals(), depth) 193 else: 194 self.emit("asdl_seq *%(name)s;" % locals(), depth) 195 else: 196 self.emit("%(ctype)s %(name)s;" % locals(), depth) 197 198 def visitProduct(self, product, name, depth): 199 self.emit("struct _%(name)s {" % locals(), depth) 200 for f in product.fields: 201 self.visit(f, depth + 1) 202 for field in product.attributes: 203 # rudimentary attribute handling 204 type = str(field.type) 205 assert type in asdl.builtin_types, type 206 self.emit("%s %s;" % (type, field.name), depth + 1); 207 self.emit("};", depth) 208 self.emit("", depth) 209 210 211class PrototypeVisitor(EmitVisitor): 212 """Generate function prototypes for the .h file""" 213 214 def visitModule(self, mod): 215 for dfn in mod.dfns: 216 self.visit(dfn) 217 218 def visitType(self, type): 219 self.visit(type.value, type.name) 220 221 def visitSum(self, sum, name): 222 if is_simple(sum): 223 pass # XXX 224 else: 225 for t in sum.types: 226 self.visit(t, name, sum.attributes) 227 228 def get_args(self, fields): 229 """Return list of C argument into, one for each field. 230 231 Argument info is 3-tuple of a C type, variable name, and flag 232 that is true if type can be NULL. 233 """ 234 args = [] 235 unnamed = {} 236 for f in fields: 237 if f.name is None: 238 name = f.type 239 c = unnamed[name] = unnamed.get(name, 0) + 1 240 if c > 1: 241 name = "name%d" % (c - 1) 242 else: 243 name = f.name 244 # XXX should extend get_c_type() to handle this 245 if f.seq: 246 if f.type == 'cmpop': 247 ctype = "asdl_int_seq *" 248 else: 249 ctype = "asdl_seq *" 250 else: 251 ctype = get_c_type(f.type) 252 args.append((ctype, name, f.opt or f.seq)) 253 return args 254 255 def visitConstructor(self, cons, type, attrs): 256 args = self.get_args(cons.fields) 257 attrs = self.get_args(attrs) 258 ctype = get_c_type(type) 259 self.emit_function(cons.name, ctype, args, attrs) 260 261 def emit_function(self, name, ctype, args, attrs, union=True): 262 args = args + attrs 263 if args: 264 argstr = ", ".join(["%s %s" % (atype, aname) 265 for atype, aname, opt in args]) 266 argstr += ", PyArena *arena" 267 else: 268 argstr = "PyArena *arena" 269 margs = "a0" 270 for i in range(1, len(args)+1): 271 margs += ", a%d" % i 272 self.emit("#define %s(%s) _Py_%s(%s)" % (name, margs, name, margs), 0, 273 reflow=False) 274 self.emit("%s _Py_%s(%s);" % (ctype, name, argstr), False) 275 276 def visitProduct(self, prod, name): 277 self.emit_function(name, get_c_type(name), 278 self.get_args(prod.fields), 279 self.get_args(prod.attributes), 280 union=False) 281 282 283class FunctionVisitor(PrototypeVisitor): 284 """Visitor to generate constructor functions for AST.""" 285 286 def emit_function(self, name, ctype, args, attrs, union=True): 287 def emit(s, depth=0, reflow=True): 288 self.emit(s, depth, reflow) 289 argstr = ", ".join(["%s %s" % (atype, aname) 290 for atype, aname, opt in args + attrs]) 291 if argstr: 292 argstr += ", PyArena *arena" 293 else: 294 argstr = "PyArena *arena" 295 self.emit("%s" % ctype, 0) 296 emit("%s(%s)" % (name, argstr)) 297 emit("{") 298 emit("%s p;" % ctype, 1) 299 for argtype, argname, opt in args: 300 if not opt and argtype != "int": 301 emit("if (!%s) {" % argname, 1) 302 emit("PyErr_SetString(PyExc_ValueError,", 2) 303 msg = "field %s is required for %s" % (argname, name) 304 emit(' "%s");' % msg, 305 2, reflow=False) 306 emit('return NULL;', 2) 307 emit('}', 1) 308 309 emit("p = (%s)PyArena_Malloc(arena, sizeof(*p));" % ctype, 1); 310 emit("if (!p)", 1) 311 emit("return NULL;", 2) 312 if union: 313 self.emit_body_union(name, args, attrs) 314 else: 315 self.emit_body_struct(name, args, attrs) 316 emit("return p;", 1) 317 emit("}") 318 emit("") 319 320 def emit_body_union(self, name, args, attrs): 321 def emit(s, depth=0, reflow=True): 322 self.emit(s, depth, reflow) 323 emit("p->kind = %s_kind;" % name, 1) 324 for argtype, argname, opt in args: 325 emit("p->v.%s.%s = %s;" % (name, argname, argname), 1) 326 for argtype, argname, opt in attrs: 327 emit("p->%s = %s;" % (argname, argname), 1) 328 329 def emit_body_struct(self, name, args, attrs): 330 def emit(s, depth=0, reflow=True): 331 self.emit(s, depth, reflow) 332 for argtype, argname, opt in args: 333 emit("p->%s = %s;" % (argname, argname), 1) 334 for argtype, argname, opt in attrs: 335 emit("p->%s = %s;" % (argname, argname), 1) 336 337 338class PickleVisitor(EmitVisitor): 339 340 def visitModule(self, mod): 341 for dfn in mod.dfns: 342 self.visit(dfn) 343 344 def visitType(self, type): 345 self.visit(type.value, type.name) 346 347 def visitSum(self, sum, name): 348 pass 349 350 def visitProduct(self, sum, name): 351 pass 352 353 def visitConstructor(self, cons, name): 354 pass 355 356 def visitField(self, sum): 357 pass 358 359 360class Obj2ModPrototypeVisitor(PickleVisitor): 361 def visitProduct(self, prod, name): 362 code = "static int obj2ast_%s(PyObject* obj, %s* out, PyArena* arena);" 363 self.emit(code % (name, get_c_type(name)), 0) 364 365 visitSum = visitProduct 366 367 368class Obj2ModVisitor(PickleVisitor): 369 def funcHeader(self, name): 370 ctype = get_c_type(name) 371 self.emit("int", 0) 372 self.emit("obj2ast_%s(PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) 373 self.emit("{", 0) 374 self.emit("int isinstance;", 1) 375 self.emit("", 0) 376 377 def sumTrailer(self, name, add_label=False): 378 self.emit("", 0) 379 # there's really nothing more we can do if this fails ... 380 error = "expected some sort of %s, but got %%R" % name 381 format = "PyErr_Format(PyExc_TypeError, \"%s\", obj);" 382 self.emit(format % error, 1, reflow=False) 383 if add_label: 384 self.emit("failed:", 1) 385 self.emit("Py_XDECREF(tmp);", 1) 386 self.emit("return 1;", 1) 387 self.emit("}", 0) 388 self.emit("", 0) 389 390 def simpleSum(self, sum, name): 391 self.funcHeader(name) 392 for t in sum.types: 393 line = ("isinstance = PyObject_IsInstance(obj, " 394 "(PyObject *)%s_type);") 395 self.emit(line % (t.name,), 1) 396 self.emit("if (isinstance == -1) {", 1) 397 self.emit("return 1;", 2) 398 self.emit("}", 1) 399 self.emit("if (isinstance) {", 1) 400 self.emit("*out = %s;" % t.name, 2) 401 self.emit("return 0;", 2) 402 self.emit("}", 1) 403 self.sumTrailer(name) 404 405 def buildArgs(self, fields): 406 return ", ".join(fields + ["arena"]) 407 408 def complexSum(self, sum, name): 409 self.funcHeader(name) 410 self.emit("PyObject *tmp = NULL;", 1) 411 for a in sum.attributes: 412 self.visitAttributeDeclaration(a, name, sum=sum) 413 self.emit("", 0) 414 # XXX: should we only do this for 'expr'? 415 self.emit("if (obj == Py_None) {", 1) 416 self.emit("*out = NULL;", 2) 417 self.emit("return 0;", 2) 418 self.emit("}", 1) 419 for a in sum.attributes: 420 self.visitField(a, name, sum=sum, depth=1) 421 for t in sum.types: 422 line = "isinstance = PyObject_IsInstance(obj, (PyObject*)%s_type);" 423 self.emit(line % (t.name,), 1) 424 self.emit("if (isinstance == -1) {", 1) 425 self.emit("return 1;", 2) 426 self.emit("}", 1) 427 self.emit("if (isinstance) {", 1) 428 for f in t.fields: 429 self.visitFieldDeclaration(f, t.name, sum=sum, depth=2) 430 self.emit("", 0) 431 for f in t.fields: 432 self.visitField(f, t.name, sum=sum, depth=2) 433 args = [f.name for f in t.fields] + [a.name for a in sum.attributes] 434 self.emit("*out = %s(%s);" % (t.name, self.buildArgs(args)), 2) 435 self.emit("if (*out == NULL) goto failed;", 2) 436 self.emit("return 0;", 2) 437 self.emit("}", 1) 438 self.sumTrailer(name, True) 439 440 def visitAttributeDeclaration(self, a, name, sum=sum): 441 ctype = get_c_type(a.type) 442 self.emit("%s %s;" % (ctype, a.name), 1) 443 444 def visitSum(self, sum, name): 445 if is_simple(sum): 446 self.simpleSum(sum, name) 447 else: 448 self.complexSum(sum, name) 449 450 def visitProduct(self, prod, name): 451 ctype = get_c_type(name) 452 self.emit("int", 0) 453 self.emit("obj2ast_%s(PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) 454 self.emit("{", 0) 455 self.emit("PyObject* tmp = NULL;", 1) 456 for f in prod.fields: 457 self.visitFieldDeclaration(f, name, prod=prod, depth=1) 458 for a in prod.attributes: 459 self.visitFieldDeclaration(a, name, prod=prod, depth=1) 460 self.emit("", 0) 461 for f in prod.fields: 462 self.visitField(f, name, prod=prod, depth=1) 463 for a in prod.attributes: 464 self.visitField(a, name, prod=prod, depth=1) 465 args = [f.name for f in prod.fields] 466 args.extend([a.name for a in prod.attributes]) 467 self.emit("*out = %s(%s);" % (name, self.buildArgs(args)), 1) 468 self.emit("return 0;", 1) 469 self.emit("failed:", 0) 470 self.emit("Py_XDECREF(tmp);", 1) 471 self.emit("return 1;", 1) 472 self.emit("}", 0) 473 self.emit("", 0) 474 475 def visitFieldDeclaration(self, field, name, sum=None, prod=None, depth=0): 476 ctype = get_c_type(field.type) 477 if field.seq: 478 if self.isSimpleType(field): 479 self.emit("asdl_int_seq* %s;" % field.name, depth) 480 else: 481 self.emit("asdl_seq* %s;" % field.name, depth) 482 else: 483 ctype = get_c_type(field.type) 484 self.emit("%s %s;" % (ctype, field.name), depth) 485 486 def isSimpleSum(self, field): 487 # XXX can the members of this list be determined automatically? 488 return field.type in ('expr_context', 'boolop', 'operator', 489 'unaryop', 'cmpop') 490 491 def isNumeric(self, field): 492 return get_c_type(field.type) in ("int", "bool") 493 494 def isSimpleType(self, field): 495 return self.isSimpleSum(field) or self.isNumeric(field) 496 497 def visitField(self, field, name, sum=None, prod=None, depth=0): 498 ctype = get_c_type(field.type) 499 if field.opt: 500 check = "exists_not_none(obj, &PyId_%s)" % (field.name,) 501 else: 502 check = "_PyObject_HasAttrId(obj, &PyId_%s)" % (field.name,) 503 self.emit("if (%s) {" % (check,), depth, reflow=False) 504 self.emit("int res;", depth+1) 505 if field.seq: 506 self.emit("Py_ssize_t len;", depth+1) 507 self.emit("Py_ssize_t i;", depth+1) 508 self.emit("tmp = _PyObject_GetAttrId(obj, &PyId_%s);" % field.name, depth+1) 509 self.emit("if (tmp == NULL) goto failed;", depth+1) 510 if field.seq: 511 self.emit("if (!PyList_Check(tmp)) {", depth+1) 512 self.emit("PyErr_Format(PyExc_TypeError, \"%s field \\\"%s\\\" must " 513 "be a list, not a %%.200s\", tmp->ob_type->tp_name);" % 514 (name, field.name), 515 depth+2, reflow=False) 516 self.emit("goto failed;", depth+2) 517 self.emit("}", depth+1) 518 self.emit("len = PyList_GET_SIZE(tmp);", depth+1) 519 if self.isSimpleType(field): 520 self.emit("%s = _Py_asdl_int_seq_new(len, arena);" % field.name, depth+1) 521 else: 522 self.emit("%s = _Py_asdl_seq_new(len, arena);" % field.name, depth+1) 523 self.emit("if (%s == NULL) goto failed;" % field.name, depth+1) 524 self.emit("for (i = 0; i < len; i++) {", depth+1) 525 self.emit("%s value;" % ctype, depth+2) 526 self.emit("res = obj2ast_%s(PyList_GET_ITEM(tmp, i), &value, arena);" % 527 field.type, depth+2, reflow=False) 528 self.emit("if (res != 0) goto failed;", depth+2) 529 self.emit("if (len != PyList_GET_SIZE(tmp)) {", depth+2) 530 self.emit("PyErr_SetString(PyExc_RuntimeError, \"%s field \\\"%s\\\" " 531 "changed size during iteration\");" % 532 (name, field.name), 533 depth+3, reflow=False) 534 self.emit("goto failed;", depth+3) 535 self.emit("}", depth+2) 536 self.emit("asdl_seq_SET(%s, i, value);" % field.name, depth+2) 537 self.emit("}", depth+1) 538 else: 539 self.emit("res = obj2ast_%s(tmp, &%s, arena);" % 540 (field.type, field.name), depth+1) 541 self.emit("if (res != 0) goto failed;", depth+1) 542 543 self.emit("Py_CLEAR(tmp);", depth+1) 544 self.emit("} else {", depth) 545 if not field.opt: 546 message = "required field \\\"%s\\\" missing from %s" % (field.name, name) 547 format = "PyErr_SetString(PyExc_TypeError, \"%s\");" 548 self.emit(format % message, depth+1, reflow=False) 549 self.emit("return 1;", depth+1) 550 else: 551 if self.isNumeric(field): 552 self.emit("%s = 0;" % field.name, depth+1) 553 elif not self.isSimpleType(field): 554 self.emit("%s = NULL;" % field.name, depth+1) 555 else: 556 raise TypeError("could not determine the default value for %s" % field.name) 557 self.emit("}", depth) 558 559 560class MarshalPrototypeVisitor(PickleVisitor): 561 562 def prototype(self, sum, name): 563 ctype = get_c_type(name) 564 self.emit("static int marshal_write_%s(PyObject **, int *, %s);" 565 % (name, ctype), 0) 566 567 visitProduct = visitSum = prototype 568 569 570class PyTypesDeclareVisitor(PickleVisitor): 571 572 def visitProduct(self, prod, name): 573 self.emit("static PyTypeObject *%s_type;" % name, 0) 574 self.emit("static PyObject* ast2obj_%s(void*);" % name, 0) 575 if prod.attributes: 576 for a in prod.attributes: 577 self.emit_identifier(a.name) 578 self.emit("static char *%s_attributes[] = {" % name, 0) 579 for a in prod.attributes: 580 self.emit('"%s",' % a.name, 1) 581 self.emit("};", 0) 582 if prod.fields: 583 for f in prod.fields: 584 self.emit_identifier(f.name) 585 self.emit("static char *%s_fields[]={" % name,0) 586 for f in prod.fields: 587 self.emit('"%s",' % f.name, 1) 588 self.emit("};", 0) 589 590 def visitSum(self, sum, name): 591 self.emit("static PyTypeObject *%s_type;" % name, 0) 592 if sum.attributes: 593 for a in sum.attributes: 594 self.emit_identifier(a.name) 595 self.emit("static char *%s_attributes[] = {" % name, 0) 596 for a in sum.attributes: 597 self.emit('"%s",' % a.name, 1) 598 self.emit("};", 0) 599 ptype = "void*" 600 if is_simple(sum): 601 ptype = get_c_type(name) 602 tnames = [] 603 for t in sum.types: 604 tnames.append(str(t.name)+"_singleton") 605 tnames = ", *".join(tnames) 606 self.emit("static PyObject *%s;" % tnames, 0) 607 self.emit("static PyObject* ast2obj_%s(%s);" % (name, ptype), 0) 608 for t in sum.types: 609 self.visitConstructor(t, name) 610 611 def visitConstructor(self, cons, name): 612 self.emit("static PyTypeObject *%s_type;" % cons.name, 0) 613 if cons.fields: 614 for t in cons.fields: 615 self.emit_identifier(t.name) 616 self.emit("static char *%s_fields[]={" % cons.name, 0) 617 for t in cons.fields: 618 self.emit('"%s",' % t.name, 1) 619 self.emit("};",0) 620 621class PyTypesVisitor(PickleVisitor): 622 623 def visitModule(self, mod): 624 self.emit(""" 625typedef struct { 626 PyObject_HEAD 627 PyObject *dict; 628} AST_object; 629 630static void 631ast_dealloc(AST_object *self) 632{ 633 Py_CLEAR(self->dict); 634 Py_TYPE(self)->tp_free(self); 635} 636 637static int 638ast_traverse(AST_object *self, visitproc visit, void *arg) 639{ 640 Py_VISIT(self->dict); 641 return 0; 642} 643 644static void 645ast_clear(AST_object *self) 646{ 647 Py_CLEAR(self->dict); 648} 649 650static int 651ast_type_init(PyObject *self, PyObject *args, PyObject *kw) 652{ 653 _Py_IDENTIFIER(_fields); 654 Py_ssize_t i, numfields = 0; 655 int res = -1; 656 PyObject *key, *value, *fields; 657 fields = _PyObject_GetAttrId((PyObject*)Py_TYPE(self), &PyId__fields); 658 if (!fields) 659 PyErr_Clear(); 660 if (fields) { 661 numfields = PySequence_Size(fields); 662 if (numfields == -1) 663 goto cleanup; 664 } 665 res = 0; /* if no error occurs, this stays 0 to the end */ 666 if (PyTuple_GET_SIZE(args) > 0) { 667 if (numfields != PyTuple_GET_SIZE(args)) { 668 PyErr_Format(PyExc_TypeError, "%.400s constructor takes %s" 669 "%zd positional argument%s", 670 Py_TYPE(self)->tp_name, 671 numfields == 0 ? "" : "either 0 or ", 672 numfields, numfields == 1 ? "" : "s"); 673 res = -1; 674 goto cleanup; 675 } 676 for (i = 0; i < PyTuple_GET_SIZE(args); i++) { 677 /* cannot be reached when fields is NULL */ 678 PyObject *name = PySequence_GetItem(fields, i); 679 if (!name) { 680 res = -1; 681 goto cleanup; 682 } 683 res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i)); 684 Py_DECREF(name); 685 if (res < 0) 686 goto cleanup; 687 } 688 } 689 if (kw) { 690 i = 0; /* needed by PyDict_Next */ 691 while (PyDict_Next(kw, &i, &key, &value)) { 692 res = PyObject_SetAttr(self, key, value); 693 if (res < 0) 694 goto cleanup; 695 } 696 } 697 cleanup: 698 Py_XDECREF(fields); 699 return res; 700} 701 702/* Pickling support */ 703static PyObject * 704ast_type_reduce(PyObject *self, PyObject *unused) 705{ 706 PyObject *res; 707 _Py_IDENTIFIER(__dict__); 708 PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__); 709 if (dict == NULL) { 710 if (PyErr_ExceptionMatches(PyExc_AttributeError)) 711 PyErr_Clear(); 712 else 713 return NULL; 714 } 715 if (dict) { 716 res = Py_BuildValue("O()O", Py_TYPE(self), dict); 717 Py_DECREF(dict); 718 return res; 719 } 720 return Py_BuildValue("O()", Py_TYPE(self)); 721} 722 723static PyMethodDef ast_type_methods[] = { 724 {"__reduce__", ast_type_reduce, METH_NOARGS, NULL}, 725 {NULL} 726}; 727 728static PyGetSetDef ast_type_getsets[] = { 729 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, 730 {NULL} 731}; 732 733static PyTypeObject AST_type = { 734 PyVarObject_HEAD_INIT(&PyType_Type, 0) 735 "_ast.AST", 736 sizeof(AST_object), 737 0, 738 (destructor)ast_dealloc, /* tp_dealloc */ 739 0, /* tp_print */ 740 0, /* tp_getattr */ 741 0, /* tp_setattr */ 742 0, /* tp_reserved */ 743 0, /* tp_repr */ 744 0, /* tp_as_number */ 745 0, /* tp_as_sequence */ 746 0, /* tp_as_mapping */ 747 0, /* tp_hash */ 748 0, /* tp_call */ 749 0, /* tp_str */ 750 PyObject_GenericGetAttr, /* tp_getattro */ 751 PyObject_GenericSetAttr, /* tp_setattro */ 752 0, /* tp_as_buffer */ 753 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 754 0, /* tp_doc */ 755 (traverseproc)ast_traverse, /* tp_traverse */ 756 (inquiry)ast_clear, /* tp_clear */ 757 0, /* tp_richcompare */ 758 0, /* tp_weaklistoffset */ 759 0, /* tp_iter */ 760 0, /* tp_iternext */ 761 ast_type_methods, /* tp_methods */ 762 0, /* tp_members */ 763 ast_type_getsets, /* tp_getset */ 764 0, /* tp_base */ 765 0, /* tp_dict */ 766 0, /* tp_descr_get */ 767 0, /* tp_descr_set */ 768 offsetof(AST_object, dict),/* tp_dictoffset */ 769 (initproc)ast_type_init, /* tp_init */ 770 PyType_GenericAlloc, /* tp_alloc */ 771 PyType_GenericNew, /* tp_new */ 772 PyObject_GC_Del, /* tp_free */ 773}; 774 775 776static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int num_fields) 777{ 778 PyObject *fnames, *result; 779 int i; 780 fnames = PyTuple_New(num_fields); 781 if (!fnames) return NULL; 782 for (i = 0; i < num_fields; i++) { 783 PyObject *field = PyUnicode_FromString(fields[i]); 784 if (!field) { 785 Py_DECREF(fnames); 786 return NULL; 787 } 788 PyTuple_SET_ITEM(fnames, i, field); 789 } 790 result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}", 791 type, base, "_fields", fnames, "__module__", "_ast"); 792 Py_DECREF(fnames); 793 return (PyTypeObject*)result; 794} 795 796static int add_attributes(PyTypeObject* type, char**attrs, int num_fields) 797{ 798 int i, result; 799 _Py_IDENTIFIER(_attributes); 800 PyObject *s, *l = PyTuple_New(num_fields); 801 if (!l) 802 return 0; 803 for (i = 0; i < num_fields; i++) { 804 s = PyUnicode_FromString(attrs[i]); 805 if (!s) { 806 Py_DECREF(l); 807 return 0; 808 } 809 PyTuple_SET_ITEM(l, i, s); 810 } 811 result = _PyObject_SetAttrId((PyObject*)type, &PyId__attributes, l) >= 0; 812 Py_DECREF(l); 813 return result; 814} 815 816/* Conversion AST -> Python */ 817 818static PyObject* ast2obj_list(asdl_seq *seq, PyObject* (*func)(void*)) 819{ 820 Py_ssize_t i, n = asdl_seq_LEN(seq); 821 PyObject *result = PyList_New(n); 822 PyObject *value; 823 if (!result) 824 return NULL; 825 for (i = 0; i < n; i++) { 826 value = func(asdl_seq_GET(seq, i)); 827 if (!value) { 828 Py_DECREF(result); 829 return NULL; 830 } 831 PyList_SET_ITEM(result, i, value); 832 } 833 return result; 834} 835 836static PyObject* ast2obj_object(void *o) 837{ 838 if (!o) 839 o = Py_None; 840 Py_INCREF((PyObject*)o); 841 return (PyObject*)o; 842} 843#define ast2obj_singleton ast2obj_object 844#define ast2obj_constant ast2obj_object 845#define ast2obj_identifier ast2obj_object 846#define ast2obj_string ast2obj_object 847#define ast2obj_bytes ast2obj_object 848 849static PyObject* ast2obj_int(long b) 850{ 851 return PyLong_FromLong(b); 852} 853 854/* Conversion Python -> AST */ 855 856static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena) 857{ 858 if (obj != Py_None && obj != Py_True && obj != Py_False) { 859 PyErr_SetString(PyExc_ValueError, 860 "AST singleton must be True, False, or None"); 861 return 1; 862 } 863 *out = obj; 864 return 0; 865} 866 867static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena) 868{ 869 if (obj == Py_None) 870 obj = NULL; 871 if (obj) { 872 if (PyArena_AddPyObject(arena, obj) < 0) { 873 *out = NULL; 874 return -1; 875 } 876 Py_INCREF(obj); 877 } 878 *out = obj; 879 return 0; 880} 881 882static int obj2ast_constant(PyObject* obj, PyObject** out, PyArena* arena) 883{ 884 if (obj) { 885 if (PyArena_AddPyObject(arena, obj) < 0) { 886 *out = NULL; 887 return -1; 888 } 889 Py_INCREF(obj); 890 } 891 *out = obj; 892 return 0; 893} 894 895static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena) 896{ 897 if (!PyUnicode_CheckExact(obj) && obj != Py_None) { 898 PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); 899 return 1; 900 } 901 return obj2ast_object(obj, out, arena); 902} 903 904static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena) 905{ 906 if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { 907 PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); 908 return 1; 909 } 910 return obj2ast_object(obj, out, arena); 911} 912 913static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena) 914{ 915 if (!PyBytes_CheckExact(obj)) { 916 PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes"); 917 return 1; 918 } 919 return obj2ast_object(obj, out, arena); 920} 921 922static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) 923{ 924 int i; 925 if (!PyLong_Check(obj)) { 926 PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); 927 return 1; 928 } 929 930 i = _PyLong_AsInt(obj); 931 if (i == -1 && PyErr_Occurred()) 932 return 1; 933 *out = i; 934 return 0; 935} 936 937static int add_ast_fields(void) 938{ 939 PyObject *empty_tuple, *d; 940 if (PyType_Ready(&AST_type) < 0) 941 return -1; 942 d = AST_type.tp_dict; 943 empty_tuple = PyTuple_New(0); 944 if (!empty_tuple || 945 PyDict_SetItemString(d, "_fields", empty_tuple) < 0 || 946 PyDict_SetItemString(d, "_attributes", empty_tuple) < 0) { 947 Py_XDECREF(empty_tuple); 948 return -1; 949 } 950 Py_DECREF(empty_tuple); 951 return 0; 952} 953 954static int exists_not_none(PyObject *obj, _Py_Identifier *id) 955{ 956 int isnone; 957 PyObject *attr = _PyObject_GetAttrId(obj, id); 958 if (!attr) { 959 PyErr_Clear(); 960 return 0; 961 } 962 isnone = attr == Py_None; 963 Py_DECREF(attr); 964 return !isnone; 965} 966 967""", 0, reflow=False) 968 969 self.emit("static int init_types(void)",0) 970 self.emit("{", 0) 971 self.emit("static int initialized;", 1) 972 self.emit("if (initialized) return 1;", 1) 973 self.emit("if (add_ast_fields() < 0) return 0;", 1) 974 for dfn in mod.dfns: 975 self.visit(dfn) 976 self.emit("initialized = 1;", 1) 977 self.emit("return 1;", 1); 978 self.emit("}", 0) 979 980 def visitProduct(self, prod, name): 981 if prod.fields: 982 fields = name+"_fields" 983 else: 984 fields = "NULL" 985 self.emit('%s_type = make_type("%s", &AST_type, %s, %d);' % 986 (name, name, fields, len(prod.fields)), 1) 987 self.emit("if (!%s_type) return 0;" % name, 1) 988 if prod.attributes: 989 self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" % 990 (name, name, len(prod.attributes)), 1) 991 else: 992 self.emit("if (!add_attributes(%s_type, NULL, 0)) return 0;" % name, 1) 993 994 def visitSum(self, sum, name): 995 self.emit('%s_type = make_type("%s", &AST_type, NULL, 0);' % 996 (name, name), 1) 997 self.emit("if (!%s_type) return 0;" % name, 1) 998 if sum.attributes: 999 self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" % 1000 (name, name, len(sum.attributes)), 1) 1001 else: 1002 self.emit("if (!add_attributes(%s_type, NULL, 0)) return 0;" % name, 1) 1003 simple = is_simple(sum) 1004 for t in sum.types: 1005 self.visitConstructor(t, name, simple) 1006 1007 def visitConstructor(self, cons, name, simple): 1008 if cons.fields: 1009 fields = cons.name+"_fields" 1010 else: 1011 fields = "NULL" 1012 self.emit('%s_type = make_type("%s", %s_type, %s, %d);' % 1013 (cons.name, cons.name, name, fields, len(cons.fields)), 1) 1014 self.emit("if (!%s_type) return 0;" % cons.name, 1) 1015 if simple: 1016 self.emit("%s_singleton = PyType_GenericNew(%s_type, NULL, NULL);" % 1017 (cons.name, cons.name), 1) 1018 self.emit("if (!%s_singleton) return 0;" % cons.name, 1) 1019 1020 1021class ASTModuleVisitor(PickleVisitor): 1022 1023 def visitModule(self, mod): 1024 self.emit("static struct PyModuleDef _astmodule = {", 0) 1025 self.emit(' PyModuleDef_HEAD_INIT, "_ast"', 0) 1026 self.emit("};", 0) 1027 self.emit("PyMODINIT_FUNC", 0) 1028 self.emit("PyInit__ast(void)", 0) 1029 self.emit("{", 0) 1030 self.emit("PyObject *m, *d;", 1) 1031 self.emit("if (!init_types()) return NULL;", 1) 1032 self.emit('m = PyModule_Create(&_astmodule);', 1) 1033 self.emit("if (!m) return NULL;", 1) 1034 self.emit("d = PyModule_GetDict(m);", 1) 1035 self.emit('if (PyDict_SetItemString(d, "AST", (PyObject*)&AST_type) < 0) return NULL;', 1) 1036 self.emit('if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0)', 1) 1037 self.emit("return NULL;", 2) 1038 for dfn in mod.dfns: 1039 self.visit(dfn) 1040 self.emit("return m;", 1) 1041 self.emit("}", 0) 1042 1043 def visitProduct(self, prod, name): 1044 self.addObj(name) 1045 1046 def visitSum(self, sum, name): 1047 self.addObj(name) 1048 for t in sum.types: 1049 self.visitConstructor(t, name) 1050 1051 def visitConstructor(self, cons, name): 1052 self.addObj(cons.name) 1053 1054 def addObj(self, name): 1055 self.emit('if (PyDict_SetItemString(d, "%s", (PyObject*)%s_type) < 0) return NULL;' % (name, name), 1) 1056 1057 1058_SPECIALIZED_SEQUENCES = ('stmt', 'expr') 1059 1060def find_sequence(fields, doing_specialization): 1061 """Return True if any field uses a sequence.""" 1062 for f in fields: 1063 if f.seq: 1064 if not doing_specialization: 1065 return True 1066 if str(f.type) not in _SPECIALIZED_SEQUENCES: 1067 return True 1068 return False 1069 1070def has_sequence(types, doing_specialization): 1071 for t in types: 1072 if find_sequence(t.fields, doing_specialization): 1073 return True 1074 return False 1075 1076 1077class StaticVisitor(PickleVisitor): 1078 CODE = '''Very simple, always emit this static code. Override CODE''' 1079 1080 def visit(self, object): 1081 self.emit(self.CODE, 0, reflow=False) 1082 1083 1084class ObjVisitor(PickleVisitor): 1085 1086 def func_begin(self, name): 1087 ctype = get_c_type(name) 1088 self.emit("PyObject*", 0) 1089 self.emit("ast2obj_%s(void* _o)" % (name), 0) 1090 self.emit("{", 0) 1091 self.emit("%s o = (%s)_o;" % (ctype, ctype), 1) 1092 self.emit("PyObject *result = NULL, *value = NULL;", 1) 1093 self.emit('if (!o) {', 1) 1094 self.emit("Py_INCREF(Py_None);", 2) 1095 self.emit('return Py_None;', 2) 1096 self.emit("}", 1) 1097 self.emit('', 0) 1098 1099 def func_end(self): 1100 self.emit("return result;", 1) 1101 self.emit("failed:", 0) 1102 self.emit("Py_XDECREF(value);", 1) 1103 self.emit("Py_XDECREF(result);", 1) 1104 self.emit("return NULL;", 1) 1105 self.emit("}", 0) 1106 self.emit("", 0) 1107 1108 def visitSum(self, sum, name): 1109 if is_simple(sum): 1110 self.simpleSum(sum, name) 1111 return 1112 self.func_begin(name) 1113 self.emit("switch (o->kind) {", 1) 1114 for i in range(len(sum.types)): 1115 t = sum.types[i] 1116 self.visitConstructor(t, i + 1, name) 1117 self.emit("}", 1) 1118 for a in sum.attributes: 1119 self.emit("value = ast2obj_%s(o->%s);" % (a.type, a.name), 1) 1120 self.emit("if (!value) goto failed;", 1) 1121 self.emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) < 0)' % a.name, 1) 1122 self.emit('goto failed;', 2) 1123 self.emit('Py_DECREF(value);', 1) 1124 self.func_end() 1125 1126 def simpleSum(self, sum, name): 1127 self.emit("PyObject* ast2obj_%s(%s_ty o)" % (name, name), 0) 1128 self.emit("{", 0) 1129 self.emit("switch(o) {", 1) 1130 for t in sum.types: 1131 self.emit("case %s:" % t.name, 2) 1132 self.emit("Py_INCREF(%s_singleton);" % t.name, 3) 1133 self.emit("return %s_singleton;" % t.name, 3) 1134 self.emit("default:", 2) 1135 self.emit('/* should never happen, but just in case ... */', 3) 1136 code = "PyErr_Format(PyExc_SystemError, \"unknown %s found\");" % name 1137 self.emit(code, 3, reflow=False) 1138 self.emit("return NULL;", 3) 1139 self.emit("}", 1) 1140 self.emit("}", 0) 1141 1142 def visitProduct(self, prod, name): 1143 self.func_begin(name) 1144 self.emit("result = PyType_GenericNew(%s_type, NULL, NULL);" % name, 1); 1145 self.emit("if (!result) return NULL;", 1) 1146 for field in prod.fields: 1147 self.visitField(field, name, 1, True) 1148 for a in prod.attributes: 1149 self.emit("value = ast2obj_%s(o->%s);" % (a.type, a.name), 1) 1150 self.emit("if (!value) goto failed;", 1) 1151 self.emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) < 0)' % a.name, 1) 1152 self.emit('goto failed;', 2) 1153 self.emit('Py_DECREF(value);', 1) 1154 self.func_end() 1155 1156 def visitConstructor(self, cons, enum, name): 1157 self.emit("case %s_kind:" % cons.name, 1) 1158 self.emit("result = PyType_GenericNew(%s_type, NULL, NULL);" % cons.name, 2); 1159 self.emit("if (!result) goto failed;", 2) 1160 for f in cons.fields: 1161 self.visitField(f, cons.name, 2, False) 1162 self.emit("break;", 2) 1163 1164 def visitField(self, field, name, depth, product): 1165 def emit(s, d): 1166 self.emit(s, depth + d) 1167 if product: 1168 value = "o->%s" % field.name 1169 else: 1170 value = "o->v.%s.%s" % (name, field.name) 1171 self.set(field, value, depth) 1172 emit("if (!value) goto failed;", 0) 1173 emit('if (_PyObject_SetAttrId(result, &PyId_%s, value) == -1)' % field.name, 0) 1174 emit("goto failed;", 1) 1175 emit("Py_DECREF(value);", 0) 1176 1177 def emitSeq(self, field, value, depth, emit): 1178 emit("seq = %s;" % value, 0) 1179 emit("n = asdl_seq_LEN(seq);", 0) 1180 emit("value = PyList_New(n);", 0) 1181 emit("if (!value) goto failed;", 0) 1182 emit("for (i = 0; i < n; i++) {", 0) 1183 self.set("value", field, "asdl_seq_GET(seq, i)", depth + 1) 1184 emit("if (!value1) goto failed;", 1) 1185 emit("PyList_SET_ITEM(value, i, value1);", 1) 1186 emit("value1 = NULL;", 1) 1187 emit("}", 0) 1188 1189 def set(self, field, value, depth): 1190 if field.seq: 1191 # XXX should really check for is_simple, but that requires a symbol table 1192 if field.type == "cmpop": 1193 # While the sequence elements are stored as void*, 1194 # ast2obj_cmpop expects an enum 1195 self.emit("{", depth) 1196 self.emit("Py_ssize_t i, n = asdl_seq_LEN(%s);" % value, depth+1) 1197 self.emit("value = PyList_New(n);", depth+1) 1198 self.emit("if (!value) goto failed;", depth+1) 1199 self.emit("for(i = 0; i < n; i++)", depth+1) 1200 # This cannot fail, so no need for error handling 1201 self.emit("PyList_SET_ITEM(value, i, ast2obj_cmpop((cmpop_ty)asdl_seq_GET(%s, i)));" % value, 1202 depth+2, reflow=False) 1203 self.emit("}", depth) 1204 else: 1205 self.emit("value = ast2obj_list(%s, ast2obj_%s);" % (value, field.type), depth) 1206 else: 1207 ctype = get_c_type(field.type) 1208 self.emit("value = ast2obj_%s(%s);" % (field.type, value), depth, reflow=False) 1209 1210 1211class PartingShots(StaticVisitor): 1212 1213 CODE = """ 1214PyObject* PyAST_mod2obj(mod_ty t) 1215{ 1216 if (!init_types()) 1217 return NULL; 1218 return ast2obj_mod(t); 1219} 1220 1221/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */ 1222mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) 1223{ 1224 mod_ty res; 1225 PyObject *req_type[3]; 1226 char *req_name[] = {"Module", "Expression", "Interactive"}; 1227 int isinstance; 1228 1229 req_type[0] = (PyObject*)Module_type; 1230 req_type[1] = (PyObject*)Expression_type; 1231 req_type[2] = (PyObject*)Interactive_type; 1232 1233 assert(0 <= mode && mode <= 2); 1234 1235 if (!init_types()) 1236 return NULL; 1237 1238 isinstance = PyObject_IsInstance(ast, req_type[mode]); 1239 if (isinstance == -1) 1240 return NULL; 1241 if (!isinstance) { 1242 PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s", 1243 req_name[mode], Py_TYPE(ast)->tp_name); 1244 return NULL; 1245 } 1246 if (obj2ast_mod(ast, &res, arena) != 0) 1247 return NULL; 1248 else 1249 return res; 1250} 1251 1252int PyAST_Check(PyObject* obj) 1253{ 1254 if (!init_types()) 1255 return -1; 1256 return PyObject_IsInstance(obj, (PyObject*)&AST_type); 1257} 1258""" 1259 1260class ChainOfVisitors: 1261 def __init__(self, *visitors): 1262 self.visitors = visitors 1263 1264 def visit(self, object): 1265 for v in self.visitors: 1266 v.visit(object) 1267 v.emit("", 0) 1268 1269common_msg = "/* File automatically generated by %s. */\n\n" 1270 1271def main(srcfile, dump_module=False): 1272 argv0 = sys.argv[0] 1273 components = argv0.split(os.sep) 1274 argv0 = os.sep.join(components[-2:]) 1275 auto_gen_msg = common_msg % argv0 1276 mod = asdl.parse(srcfile) 1277 if dump_module: 1278 print('Parsed Module:') 1279 print(mod) 1280 if not asdl.check(mod): 1281 sys.exit(1) 1282 if INC_DIR: 1283 p = "%s/%s-ast.h" % (INC_DIR, mod.name) 1284 f = open(p, "w") 1285 f.write(auto_gen_msg) 1286 f.write('#include "asdl.h"\n\n') 1287 c = ChainOfVisitors(TypeDefVisitor(f), 1288 StructVisitor(f), 1289 PrototypeVisitor(f), 1290 ) 1291 c.visit(mod) 1292 f.write("PyObject* PyAST_mod2obj(mod_ty t);\n") 1293 f.write("mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode);\n") 1294 f.write("int PyAST_Check(PyObject* obj);\n") 1295 f.close() 1296 1297 if SRC_DIR: 1298 p = os.path.join(SRC_DIR, str(mod.name) + "-ast.c") 1299 f = open(p, "w") 1300 f.write(auto_gen_msg) 1301 f.write('#include <stddef.h>\n') 1302 f.write('\n') 1303 f.write('#include "Python.h"\n') 1304 f.write('#include "%s-ast.h"\n' % mod.name) 1305 f.write('\n') 1306 f.write("static PyTypeObject AST_type;\n") 1307 v = ChainOfVisitors( 1308 PyTypesDeclareVisitor(f), 1309 PyTypesVisitor(f), 1310 Obj2ModPrototypeVisitor(f), 1311 FunctionVisitor(f), 1312 ObjVisitor(f), 1313 Obj2ModVisitor(f), 1314 ASTModuleVisitor(f), 1315 PartingShots(f), 1316 ) 1317 v.visit(mod) 1318 f.close() 1319 1320if __name__ == "__main__": 1321 import getopt 1322 1323 INC_DIR = '' 1324 SRC_DIR = '' 1325 dump_module = False 1326 opts, args = getopt.getopt(sys.argv[1:], "dh:c:") 1327 for o, v in opts: 1328 if o == '-h': 1329 INC_DIR = v 1330 if o == '-c': 1331 SRC_DIR = v 1332 if o == '-d': 1333 dump_module = True 1334 if INC_DIR and SRC_DIR: 1335 print('Must specify exactly one output file') 1336 sys.exit(1) 1337 elif len(args) != 1: 1338 print('Must specify single input file') 1339 sys.exit(1) 1340 main(args[0], dump_module) 1341