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