1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5import copy 6import functools 7 8from ipdl.util import hash_str 9 10 11class Visitor: 12 def defaultVisit(self, node): 13 raise Exception( 14 "INTERNAL ERROR: no visitor for node type `%s'" % (node.__class__.__name__) 15 ) 16 17 def visitWhitespace(self, ws): 18 pass 19 20 def visitVerbatimNode(self, verb): 21 pass 22 23 def visitGroupNode(self, group): 24 for node in group.nodes: 25 node.accept(self) 26 27 def visitFile(self, f): 28 for thing in f.stuff: 29 thing.accept(self) 30 31 def visitCppDirective(self, ppd): 32 pass 33 34 def visitBlock(self, block): 35 for stmt in block.stmts: 36 stmt.accept(self) 37 38 def visitNamespace(self, ns): 39 self.visitBlock(ns) 40 41 def visitType(self, type): 42 pass 43 44 def visitTypeArray(self, ta): 45 ta.basetype.accept(self) 46 ta.nmemb.accept(self) 47 48 def visitTypeEnum(self, enum): 49 pass 50 51 def visitTypeFunction(self, fn): 52 pass 53 54 def visitTypeUnion(self, union): 55 for t, name in union.components: 56 t.accept(self) 57 58 def visitTypedef(self, tdef): 59 tdef.fromtype.accept(self) 60 61 def visitUsing(self, us): 62 us.type.accept(self) 63 64 def visitForwardDecl(self, fd): 65 pass 66 67 def visitDecl(self, decl): 68 decl.type.accept(self) 69 70 def visitParam(self, param): 71 self.visitDecl(param) 72 if param.default is not None: 73 param.default.accept(self) 74 75 def visitClass(self, cls): 76 for inherit in cls.inherits: 77 inherit.accept(self) 78 self.visitBlock(cls) 79 80 def visitInherit(self, inh): 81 pass 82 83 def visitFriendClassDecl(self, fcd): 84 pass 85 86 def visitMethodDecl(self, meth): 87 for param in meth.params: 88 param.accept(self) 89 if meth.ret is not None: 90 meth.ret.accept(self) 91 if meth.typeop is not None: 92 meth.typeop.accept(self) 93 if meth.T is not None: 94 meth.T.accept(self) 95 96 def visitMethodDefn(self, meth): 97 meth.decl.accept(self) 98 self.visitBlock(meth) 99 100 def visitFunctionDecl(self, fun): 101 self.visitMethodDecl(fun) 102 103 def visitFunctionDefn(self, fd): 104 self.visitMethodDefn(fd) 105 106 def visitConstructorDecl(self, ctor): 107 self.visitMethodDecl(ctor) 108 109 def visitConstructorDefn(self, cd): 110 cd.decl.accept(self) 111 for init in cd.memberinits: 112 init.accept(self) 113 self.visitBlock(cd) 114 115 def visitDestructorDecl(self, dtor): 116 self.visitMethodDecl(dtor) 117 118 def visitDestructorDefn(self, dd): 119 dd.decl.accept(self) 120 self.visitBlock(dd) 121 122 def visitExprLiteral(self, l): 123 pass 124 125 def visitExprVar(self, v): 126 pass 127 128 def visitExprPrefixUnop(self, e): 129 e.expr.accept(self) 130 131 def visitExprBinary(self, e): 132 e.left.accept(self) 133 e.right.accept(self) 134 135 def visitExprConditional(self, c): 136 c.cond.accept(self) 137 c.ife.accept(self) 138 c.elsee.accept(self) 139 140 def visitExprAddrOf(self, eao): 141 self.visitExprPrefixUnop(eao) 142 143 def visitExprDeref(self, ed): 144 self.visitExprPrefixUnop(ed) 145 146 def visitExprNot(self, en): 147 self.visitExprPrefixUnop(en) 148 149 def visitExprCast(self, ec): 150 ec.expr.accept(self) 151 152 def visitExprSelect(self, es): 153 es.obj.accept(self) 154 155 def visitExprAssn(self, ea): 156 ea.lhs.accept(self) 157 ea.rhs.accept(self) 158 159 def visitExprCall(self, ec): 160 ec.func.accept(self) 161 for arg in ec.args: 162 arg.accept(self) 163 164 def visitExprNew(self, en): 165 en.ctype.accept(self) 166 if en.newargs is not None: 167 for arg in en.newargs: 168 arg.accept(self) 169 if en.args is not None: 170 for arg in en.args: 171 arg.accept(self) 172 173 def visitExprDelete(self, ed): 174 ed.obj.accept(self) 175 176 def visitExprMemberInit(self, minit): 177 self.visitExprCall(minit) 178 179 def visitExprLambda(self, l): 180 self.visitBlock(l) 181 182 def visitStmtBlock(self, sb): 183 self.visitBlock(sb) 184 185 def visitStmtDecl(self, sd): 186 sd.decl.accept(self) 187 if sd.init is not None: 188 sd.init.accept(self) 189 190 def visitLabel(self, label): 191 pass 192 193 def visitCaseLabel(self, case): 194 pass 195 196 def visitDefaultLabel(self, dl): 197 pass 198 199 def visitStmtIf(self, si): 200 si.cond.accept(self) 201 si.ifb.accept(self) 202 if si.elseb is not None: 203 si.elseb.accept(self) 204 205 def visitStmtFor(self, sf): 206 if sf.init is not None: 207 sf.init.accept(self) 208 if sf.cond is not None: 209 sf.cond.accept(self) 210 if sf.update is not None: 211 sf.update.accept(self) 212 213 def visitStmtSwitch(self, ss): 214 ss.expr.accept(self) 215 self.visitBlock(ss) 216 217 def visitStmtBreak(self, sb): 218 pass 219 220 def visitStmtExpr(self, se): 221 se.expr.accept(self) 222 223 def visitStmtReturn(self, sr): 224 if sr.expr is not None: 225 sr.expr.accept(self) 226 227 228# ------------------------------ 229 230 231class Node: 232 def __init__(self): 233 pass 234 235 def accept(self, visitor): 236 visit = getattr(visitor, "visit" + self.__class__.__name__, None) 237 if visit is None: 238 return getattr(visitor, "defaultVisit")(self) 239 return visit(self) 240 241 242class Whitespace(Node): 243 # yes, this is silly. but we need to stick comments in the 244 # generated code without resorting to more serious hacks 245 def __init__(self, ws, indent=False): 246 Node.__init__(self) 247 self.ws = ws 248 self.indent = indent 249 250 251Whitespace.NL = Whitespace("\n") 252 253 254class VerbatimNode(Node): 255 # A block of text to be written verbatim to the output file. 256 # 257 # NOTE: This node is usually created by `code`. See `code.py` for details. 258 # FIXME: Merge Whitespace and VerbatimNode? They're identical. 259 def __init__(self, text, indent=0): 260 Node.__init__(self) 261 self.text = text 262 self.indent = indent 263 264 265class GroupNode(Node): 266 # A group of nodes to be treated as a single node. These nodes have an 267 # optional indentation level which should be applied when generating them. 268 # 269 # NOTE: This node is usually created by `code`. See `code.py` for details. 270 def __init__(self, nodes, offset=0): 271 Node.__init__(self) 272 self.nodes = nodes 273 self.offset = offset 274 275 276class File(Node): 277 def __init__(self, filename): 278 Node.__init__(self) 279 self.name = filename 280 # array of stuff in the file --- stmts and preprocessor thingies 281 self.stuff = [] 282 283 def addthing(self, thing): 284 assert thing is not None 285 assert not isinstance(thing, list) 286 self.stuff.append(thing) 287 288 def addthings(self, things): 289 for t in things: 290 self.addthing(t) 291 292 # "look like" a Block so code doesn't have to care whether they're 293 # in global scope or not 294 def addstmt(self, stmt): 295 assert stmt is not None 296 assert not isinstance(stmt, list) 297 self.stuff.append(stmt) 298 299 def addstmts(self, stmts): 300 for s in stmts: 301 self.addstmt(s) 302 303 def addcode(self, tmpl, **context): 304 from ipdl.cxx.code import StmtCode 305 306 self.addstmt(StmtCode(tmpl, **context)) 307 308 309class CppDirective(Node): 310 """represents |#[directive] [rest]|, where |rest| is any string""" 311 312 def __init__(self, directive, rest=None): 313 Node.__init__(self) 314 self.directive = directive 315 self.rest = rest 316 317 318class Block(Node): 319 def __init__(self): 320 Node.__init__(self) 321 self.stmts = [] 322 323 def addstmt(self, stmt): 324 assert stmt is not None 325 assert not isinstance(stmt, tuple) 326 self.stmts.append(stmt) 327 328 def addstmts(self, stmts): 329 for s in stmts: 330 self.addstmt(s) 331 332 def addcode(self, tmpl, **context): 333 from ipdl.cxx.code import StmtCode 334 335 self.addstmt(StmtCode(tmpl, **context)) 336 337 338# ------------------------------ 339# type and decl thingies 340 341 342class Namespace(Block): 343 def __init__(self, name): 344 assert isinstance(name, str) 345 346 Block.__init__(self) 347 self.name = name 348 349 350class Type(Node): 351 def __init__( 352 self, 353 name, 354 const=False, 355 ptr=False, 356 ptrptr=False, 357 ptrconstptr=False, 358 ref=False, 359 rvalref=False, 360 hasimplicitcopyctor=True, 361 T=None, 362 inner=None, 363 ): 364 """ 365 Represents the type |name<T>::inner| with the ptr and const 366 modifiers as specified. 367 368 To avoid getting fancy with recursive types, we limit the kinds 369 of pointer types that can be be constructed. 370 371 ptr => T* 372 ptrptr => T** 373 ptrconstptr => T* const* 374 ref => T& 375 rvalref => T&& 376 377 Any type, naked or pointer, can be const (const T) or ref (T&).""" 378 assert isinstance(name, str) 379 assert isinstance(const, bool) 380 assert isinstance(ptr, bool) 381 assert isinstance(ptrptr, bool) 382 assert isinstance(ptrconstptr, bool) 383 assert isinstance(ref, bool) 384 assert isinstance(rvalref, bool) 385 assert not isinstance(T, str) 386 387 Node.__init__(self) 388 self.name = name 389 self.const = const 390 self.ptr = ptr 391 self.ptrptr = ptrptr 392 self.ptrconstptr = ptrconstptr 393 self.ref = ref 394 self.rvalref = rvalref 395 self.hasimplicitcopyctor = hasimplicitcopyctor 396 self.T = T 397 self.inner = inner 398 # XXX could get serious here with recursive types, but shouldn't 399 # need that for this codegen 400 401 def __deepcopy__(self, memo): 402 return Type( 403 self.name, 404 const=self.const, 405 ptr=self.ptr, 406 ptrptr=self.ptrptr, 407 ptrconstptr=self.ptrconstptr, 408 ref=self.ref, 409 rvalref=self.rvalref, 410 T=copy.deepcopy(self.T, memo), 411 inner=copy.deepcopy(self.inner, memo), 412 ) 413 414 415Type.BOOL = Type("bool") 416Type.INT = Type("int") 417Type.INT32 = Type("int32_t") 418Type.INTPTR = Type("intptr_t") 419Type.NSRESULT = Type("nsresult") 420Type.UINT32 = Type("uint32_t") 421Type.UINT32PTR = Type("uint32_t", ptr=True) 422Type.SIZE = Type("size_t") 423Type.VOID = Type("void") 424Type.VOIDPTR = Type("void", ptr=True) 425Type.AUTO = Type("auto") 426Type.AUTORVAL = Type("auto", rvalref=True) 427 428 429class TypeArray(Node): 430 def __init__(self, basetype, nmemb): 431 """the type |basetype DECLNAME[nmemb]|. |nmemb| is an Expr""" 432 self.basetype = basetype 433 self.nmemb = nmemb 434 435 436class TypeEnum(Node): 437 def __init__(self, name=None): 438 """name can be None""" 439 Node.__init__(self) 440 self.name = name 441 self.idnums = [] # pairs of ('Foo', [num]) or ('Foo', None) 442 443 def addId(self, id, num=None): 444 self.idnums.append((id, num)) 445 446 447class TypeUnion(Node): 448 def __init__(self, name=None): 449 Node.__init__(self) 450 self.name = name 451 self.components = [] # [ Decl ] 452 453 def addComponent(self, type, name): 454 self.components.append(Decl(type, name)) 455 456 457class TypeFunction(Node): 458 def __init__(self, params=[], ret=Type("void")): 459 """Anonymous function type std::function<>""" 460 self.params = params 461 self.ret = ret 462 463 464@functools.total_ordering 465class Typedef(Node): 466 def __init__(self, fromtype, totypename, templateargs=[]): 467 assert isinstance(totypename, str) 468 469 Node.__init__(self) 470 self.fromtype = fromtype 471 self.totypename = totypename 472 self.templateargs = templateargs 473 474 def __lt__(self, other): 475 return self.totypename < other.totypename 476 477 def __eq__(self, other): 478 return self.__class__ == other.__class__ and self.totypename == other.totypename 479 480 def __hash__(self): 481 return hash_str(self.totypename) 482 483 484class Using(Node): 485 def __init__(self, type): 486 Node.__init__(self) 487 self.type = type 488 489 490class ForwardDecl(Node): 491 def __init__(self, pqname, cls=False, struct=False): 492 # Exactly one of cls and struct must be set 493 assert cls ^ struct 494 495 self.pqname = pqname 496 self.cls = cls 497 self.struct = struct 498 499 500class Decl(Node): 501 """represents |Foo bar|, e.g. in a function signature""" 502 503 def __init__(self, type, name): 504 assert type is not None 505 assert not isinstance(type, str) 506 assert isinstance(name, str) 507 508 Node.__init__(self) 509 self.type = type 510 self.name = name 511 512 def __deepcopy__(self, memo): 513 return Decl(copy.deepcopy(self.type, memo), self.name) 514 515 516class Param(Decl): 517 def __init__(self, type, name, default=None): 518 Decl.__init__(self, type, name) 519 self.default = default 520 521 def __deepcopy__(self, memo): 522 return Param( 523 copy.deepcopy(self.type, memo), self.name, copy.deepcopy(self.default, memo) 524 ) 525 526 527# ------------------------------ 528# class stuff 529 530 531class Class(Block): 532 def __init__( 533 self, 534 name, 535 inherits=[], 536 interface=False, 537 abstract=False, 538 final=False, 539 specializes=None, 540 struct=False, 541 ): 542 assert not (interface and abstract) 543 assert not (abstract and final) 544 assert not (interface and final) 545 assert not (inherits and specializes) 546 547 Block.__init__(self) 548 self.name = name 549 self.inherits = inherits # [ Type ] 550 self.interface = interface # bool 551 self.abstract = abstract # bool 552 self.final = final # bool 553 self.specializes = specializes # Type or None 554 self.struct = struct # bool 555 556 557class Inherit(Node): 558 def __init__(self, type, viz="public"): 559 assert isinstance(viz, str) 560 Node.__init__(self) 561 self.type = type 562 self.viz = viz 563 564 565class FriendClassDecl(Node): 566 def __init__(self, friend): 567 Node.__init__(self) 568 self.friend = friend 569 570 571# Python2 polyfill for Python3's Enum() functional API. 572 573 574def make_enum(name, members_str): 575 members_list = members_str.split() 576 members_dict = {} 577 for member_value, member in enumerate(members_list, start=1): 578 members_dict[member] = member_value 579 return type(name, (), members_dict) 580 581 582MethodSpec = make_enum("MethodSpec", "NONE VIRTUAL PURE OVERRIDE STATIC") 583 584 585class MethodDecl(Node): 586 def __init__( 587 self, 588 name, 589 params=[], 590 ret=Type("void"), 591 methodspec=MethodSpec.NONE, 592 const=False, 593 warn_unused=False, 594 force_inline=False, 595 typeop=None, 596 T=None, 597 cls=None, 598 ): 599 assert not (name and typeop) 600 assert name is None or isinstance(name, str) 601 assert not isinstance(ret, list) 602 for decl in params: 603 assert not isinstance(decl, str) 604 assert not isinstance(T, int) 605 assert isinstance(const, bool) 606 assert isinstance(warn_unused, bool) 607 assert isinstance(force_inline, bool) 608 609 if typeop is not None: 610 assert methodspec == MethodSpec.NONE 611 ret = None 612 613 Node.__init__(self) 614 self.name = name 615 self.params = params # [ Param ] 616 self.ret = ret # Type or None 617 self.methodspec = methodspec # enum 618 self.const = const # bool 619 self.warn_unused = warn_unused # bool 620 self.force_inline = force_inline or bool(T) # bool 621 self.typeop = typeop # Type or None 622 self.T = T # Type or None 623 self.cls = cls # Class or None 624 self.only_for_definition = False 625 626 def __deepcopy__(self, memo): 627 return MethodDecl( 628 self.name, 629 params=copy.deepcopy(self.params, memo), 630 ret=copy.deepcopy(self.ret, memo), 631 methodspec=self.methodspec, 632 const=self.const, 633 warn_unused=self.warn_unused, 634 force_inline=self.force_inline, 635 typeop=copy.deepcopy(self.typeop, memo), 636 T=copy.deepcopy(self.T, memo), 637 ) 638 639 640class MethodDefn(Block): 641 def __init__(self, decl): 642 Block.__init__(self) 643 self.decl = decl 644 645 646class FunctionDecl(MethodDecl): 647 def __init__( 648 self, 649 name, 650 params=[], 651 ret=Type("void"), 652 methodspec=MethodSpec.NONE, 653 warn_unused=False, 654 force_inline=False, 655 T=None, 656 ): 657 assert methodspec == MethodSpec.NONE or methodspec == MethodSpec.STATIC 658 MethodDecl.__init__( 659 self, 660 name, 661 params=params, 662 ret=ret, 663 methodspec=methodspec, 664 warn_unused=warn_unused, 665 force_inline=force_inline, 666 T=T, 667 ) 668 669 670class FunctionDefn(MethodDefn): 671 def __init__(self, decl): 672 MethodDefn.__init__(self, decl) 673 674 675class ConstructorDecl(MethodDecl): 676 def __init__(self, name, params=[], explicit=False, force_inline=False): 677 MethodDecl.__init__( 678 self, name, params=params, ret=None, force_inline=force_inline 679 ) 680 self.explicit = explicit 681 682 def __deepcopy__(self, memo): 683 return ConstructorDecl( 684 self.name, copy.deepcopy(self.params, memo), self.explicit 685 ) 686 687 688class ConstructorDefn(MethodDefn): 689 def __init__(self, decl, memberinits=[]): 690 MethodDefn.__init__(self, decl) 691 self.memberinits = memberinits 692 693 694class DestructorDecl(MethodDecl): 695 def __init__(self, name, methodspec=MethodSpec.NONE, force_inline=False): 696 # C++ allows pure or override destructors, but ipdl cgen does not. 697 assert methodspec == MethodSpec.NONE or methodspec == MethodSpec.VIRTUAL 698 MethodDecl.__init__( 699 self, 700 name, 701 params=[], 702 ret=None, 703 methodspec=methodspec, 704 force_inline=force_inline, 705 ) 706 707 def __deepcopy__(self, memo): 708 return DestructorDecl( 709 self.name, methodspec=self.methodspec, force_inline=self.force_inline 710 ) 711 712 713class DestructorDefn(MethodDefn): 714 def __init__(self, decl): 715 MethodDefn.__init__(self, decl) 716 717 718# ------------------------------ 719# expressions 720 721 722class ExprVar(Node): 723 def __init__(self, name): 724 assert isinstance(name, str) 725 726 Node.__init__(self) 727 self.name = name 728 729 730ExprVar.THIS = ExprVar("this") 731 732 733class ExprLiteral(Node): 734 def __init__(self, value, type): 735 """|type| is a Python format specifier; 'd' for example""" 736 Node.__init__(self) 737 self.value = value 738 self.type = type 739 740 @staticmethod 741 def Int(i): 742 return ExprLiteral(i, "d") 743 744 @staticmethod 745 def String(s): 746 return ExprLiteral('"' + s + '"', "s") 747 748 def __str__(self): 749 return ("%" + self.type) % (self.value) 750 751 752ExprLiteral.ZERO = ExprLiteral.Int(0) 753ExprLiteral.ONE = ExprLiteral.Int(1) 754ExprLiteral.NULL = ExprVar("nullptr") 755ExprLiteral.TRUE = ExprVar("true") 756ExprLiteral.FALSE = ExprVar("false") 757 758 759class ExprPrefixUnop(Node): 760 def __init__(self, expr, op): 761 assert not isinstance(expr, tuple) 762 self.expr = expr 763 self.op = op 764 765 766class ExprNot(ExprPrefixUnop): 767 def __init__(self, expr): 768 ExprPrefixUnop.__init__(self, expr, "!") 769 770 771class ExprAddrOf(ExprPrefixUnop): 772 def __init__(self, expr): 773 ExprPrefixUnop.__init__(self, expr, "&") 774 775 776class ExprDeref(ExprPrefixUnop): 777 def __init__(self, expr): 778 ExprPrefixUnop.__init__(self, expr, "*") 779 780 781class ExprCast(Node): 782 def __init__(self, expr, type, static=False, const=False): 783 # Exactly one of these should be set 784 assert static ^ const 785 786 Node.__init__(self) 787 self.expr = expr 788 self.type = type 789 self.static = static 790 self.const = const 791 792 793class ExprBinary(Node): 794 def __init__(self, left, op, right): 795 Node.__init__(self) 796 self.left = left 797 self.op = op 798 self.right = right 799 800 801class ExprConditional(Node): 802 def __init__(self, cond, ife, elsee): 803 Node.__init__(self) 804 self.cond = cond 805 self.ife = ife 806 self.elsee = elsee 807 808 809class ExprSelect(Node): 810 def __init__(self, obj, op, field): 811 assert obj and op and field 812 assert not isinstance(obj, str) 813 assert isinstance(op, str) 814 815 Node.__init__(self) 816 self.obj = obj 817 self.op = op 818 if isinstance(field, str): 819 self.field = ExprVar(field) 820 else: 821 self.field = field 822 823 824class ExprAssn(Node): 825 def __init__(self, lhs, rhs, op="="): 826 Node.__init__(self) 827 self.lhs = lhs 828 self.op = op 829 self.rhs = rhs 830 831 832class ExprCall(Node): 833 def __init__(self, func, args=[]): 834 assert hasattr(func, "accept") 835 assert isinstance(args, list) 836 for arg in args: 837 assert arg and not isinstance(arg, str) 838 839 Node.__init__(self) 840 self.func = func 841 self.args = args 842 843 844class ExprMove(ExprCall): 845 def __init__(self, arg): 846 ExprCall.__init__(self, ExprVar("std::move"), args=[arg]) 847 848 849class ExprNew(Node): 850 # XXX taking some poetic license ... 851 def __init__(self, ctype, args=[], newargs=None): 852 assert not (ctype.const or ctype.ref or ctype.rvalref) 853 854 Node.__init__(self) 855 self.ctype = ctype 856 self.args = args 857 self.newargs = newargs 858 859 860class ExprDelete(Node): 861 def __init__(self, obj): 862 Node.__init__(self) 863 self.obj = obj 864 865 866class ExprMemberInit(ExprCall): 867 def __init__(self, member, args=[]): 868 ExprCall.__init__(self, member, args) 869 870 871class ExprLambda(Block): 872 def __init__(self, captures=[], params=[], ret=None): 873 Block.__init__(self) 874 assert isinstance(captures, list) 875 assert isinstance(params, list) 876 self.captures = captures 877 self.params = params 878 self.ret = ret 879 880 881# ------------------------------ 882# statements etc. 883 884 885class StmtBlock(Block): 886 def __init__(self, stmts=[]): 887 Block.__init__(self) 888 self.addstmts(stmts) 889 890 891class StmtDecl(Node): 892 def __init__(self, decl, init=None, initargs=None): 893 assert not (init and initargs) 894 assert not isinstance(init, str) # easy to confuse with Decl 895 assert not isinstance(init, list) 896 assert not isinstance(decl, tuple) 897 898 Node.__init__(self) 899 self.decl = decl 900 self.init = init 901 self.initargs = initargs 902 903 904class Label(Node): 905 def __init__(self, name): 906 Node.__init__(self) 907 self.name = name 908 909 910Label.PUBLIC = Label("public") 911Label.PROTECTED = Label("protected") 912Label.PRIVATE = Label("private") 913 914 915class CaseLabel(Node): 916 def __init__(self, name): 917 Node.__init__(self) 918 self.name = name 919 920 921class DefaultLabel(Node): 922 def __init__(self): 923 Node.__init__(self) 924 925 926class StmtIf(Node): 927 def __init__(self, cond): 928 Node.__init__(self) 929 self.cond = cond 930 self.ifb = Block() 931 self.elseb = None 932 933 def addifstmt(self, stmt): 934 self.ifb.addstmt(stmt) 935 936 def addifstmts(self, stmts): 937 self.ifb.addstmts(stmts) 938 939 def addelsestmt(self, stmt): 940 if self.elseb is None: 941 self.elseb = Block() 942 self.elseb.addstmt(stmt) 943 944 def addelsestmts(self, stmts): 945 if self.elseb is None: 946 self.elseb = Block() 947 self.elseb.addstmts(stmts) 948 949 950class StmtFor(Block): 951 def __init__(self, init=None, cond=None, update=None): 952 Block.__init__(self) 953 self.init = init 954 self.cond = cond 955 self.update = update 956 957 958class StmtRangedFor(Block): 959 def __init__(self, var, iteree): 960 assert isinstance(var, ExprVar) 961 assert iteree 962 963 Block.__init__(self) 964 self.var = var 965 self.iteree = iteree 966 967 968class StmtSwitch(Block): 969 def __init__(self, expr): 970 Block.__init__(self) 971 self.expr = expr 972 self.nr_cases = 0 973 974 def addcase(self, case, block): 975 """NOTE: |case| is not checked for uniqueness""" 976 assert not isinstance(case, str) 977 assert ( 978 isinstance(block, StmtBreak) 979 or isinstance(block, StmtReturn) 980 or isinstance(block, StmtSwitch) 981 or isinstance(block, GroupNode) 982 or isinstance(block, VerbatimNode) 983 or ( 984 hasattr(block, "stmts") 985 and ( 986 isinstance(block.stmts[-1], StmtBreak) 987 or isinstance(block.stmts[-1], StmtReturn) 988 or isinstance(block.stmts[-1], GroupNode) 989 or isinstance(block.stmts[-1], VerbatimNode) 990 ) 991 ) 992 ) 993 self.addstmt(case) 994 self.addstmt(block) 995 self.nr_cases += 1 996 997 998class StmtBreak(Node): 999 def __init__(self): 1000 Node.__init__(self) 1001 1002 1003class StmtExpr(Node): 1004 def __init__(self, expr): 1005 assert expr is not None 1006 1007 Node.__init__(self) 1008 self.expr = expr 1009 1010 1011class StmtReturn(Node): 1012 def __init__(self, expr=None): 1013 Node.__init__(self) 1014 self.expr = expr 1015 1016 1017StmtReturn.TRUE = StmtReturn(ExprLiteral.TRUE) 1018StmtReturn.FALSE = StmtReturn(ExprLiteral.FALSE) 1019