tenfourfox/ipc/ipdl/ipdl/cxx/ast.py
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

800 lines
22 KiB
Python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import copy, sys
class Visitor:
def defaultVisit(self, node):
raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
node.__class__.__name__)
def visitWhitespace(self, ws):
pass
def visitFile(self, f):
for thing in f.stuff:
thing.accept(self)
def visitCppDirective(self, ppd):
pass
def visitBlock(self, block):
for stmt in block.stmts:
stmt.accept(self)
def visitNamespace(self, ns):
self.visitBlock(ns)
def visitType(self, type):
pass
def visitTypeArray(self, ta):
ta.basetype.accept(self)
ta.nmemb.accept(self)
def visitTypeEnum(self, enum):
pass
def visitTypeUnion(self, union):
for t, name in union.components:
t.accept(self)
def visitTypedef(self, tdef):
tdef.fromtype.accept(self)
def visitUsing(self, us):
us.type.accept(self)
def visitForwardDecl(self, fd):
pass
def visitDecl(self, decl):
decl.type.accept(self)
def visitParam(self, param):
self.visitDecl(param)
if param.default is not None:
param.default.accept(self)
def visitClass(self, cls):
for inherit in cls.inherits:
inherit.accept(self)
self.visitBlock(cls)
def visitInherit(self, inh):
pass
def visitFriendClassDecl(self, fcd):
pass
def visitMethodDecl(self, meth):
for param in meth.params:
param.accept(self)
if meth.ret is not None:
meth.ret.accept(self)
if meth.typeop is not None:
meth.typeop.accept(self)
if meth.T is not None:
meth.T.accept(self)
def visitMethodDefn(self, meth):
meth.decl.accept(self)
self.visitBlock(meth)
def visitFunctionDecl(self, fun):
self.visitMethodDecl(fun)
def visitFunctionDefn(self, fd):
self.visitMethodDefn(fd)
def visitConstructorDecl(self, ctor):
self.visitMethodDecl(ctor)
def visitConstructorDefn(self, cd):
cd.decl.accept(self)
for init in cd.memberinits:
init.accept(self)
self.visitBlock(cd)
def visitDestructorDecl(self, dtor):
self.visitMethodDecl(dtor)
def visitDestructorDefn(self, dd):
dd.decl.accept(self)
self.visitBlock(dd)
def visitExprLiteral(self, l):
pass
def visitExprVar(self, v):
pass
def visitExprPrefixUnop(self, e):
e.expr.accept(self)
def visitExprBinary(self, e):
e.left.accept(self)
e.right.accept(self)
def visitExprConditional(self, c):
c.cond.accept(self)
c.ife.accept(self)
c.elsee.accept(self)
def visitExprAddrOf(self, eao):
self.visitExprPrefixUnop(eao)
def visitExprDeref(self, ed):
self.visitExprPrefixUnop(ed)
def visitExprNot(self, en):
self.visitExprPrefixUnop(en)
def visitExprCast(self, ec):
ec.expr.accept(self)
def visitExprIndex(self, ei):
ei.arr.accept(self)
ei.idx.accept(self)
def visitExprSelect(self, es):
es.obj.accept(self)
def visitExprAssn(self, ea):
ea.lhs.accept(self)
ea.rhs.accept(self)
def visitExprCall(self, ec):
ec.func.accept(self)
for arg in ec.args:
arg.accept(self)
def visitExprNew(self, en):
en.ctype.accept(self)
if en.newargs is not None:
for arg in en.newargs:
arg.accept(self)
if en.args is not None:
for arg in en.args:
arg.accept(self)
def visitExprDelete(self, ed):
ed.obj.accept(self)
def visitExprMemberInit(self, minit):
self.visitExprCall(minit)
def visitExprSizeof(self, es):
self.visitExprCall(es)
def visitStmtBlock(self, sb):
self.visitBlock(sb)
def visitStmtDecl(self, sd):
sd.decl.accept(self)
if sd.init is not None:
sd.init.accept(self)
def visitLabel(self, label):
pass
def visitCaseLabel(self, case):
pass
def visitDefaultLabel(self, dl):
pass
def visitStmtIf(self, si):
si.cond.accept(self)
si.ifb.accept(self)
if si.elseb is not None:
si.elseb.accept(self)
def visitStmtFor(self, sf):
if sf.init is not None:
sf.init.accept(self)
if sf.cond is not None:
sf.cond.accept(self)
if sf.update is not None:
sf.update.accept(self)
def visitStmtSwitch(self, ss):
ss.expr.accept(self)
self.visitBlock(ss)
def visitStmtBreak(self, sb):
pass
def visitStmtExpr(self, se):
se.expr.accept(self)
def visitStmtReturn(self, sr):
if sr.expr is not None:
sr.expr.accept(self)
##------------------------------
class Node:
def __init__(self):
pass
def accept(self, visitor):
visit = getattr(visitor, 'visit'+ self.__class__.__name__, None)
if visit is None:
return getattr(visitor, 'defaultVisit')(self)
return visit(self)
class Whitespace(Node):
# yes, this is silly. but we need to stick comments in the
# generated code without resorting to more serious hacks
def __init__(self, ws, indent=0):
Node.__init__(self)
self.ws = ws
self.indent = indent
Whitespace.NL = Whitespace('\n')
class File(Node):
def __init__(self, filename):
Node.__init__(self)
self.name = filename
# array of stuff in the file --- stmts and preprocessor thingies
self.stuff = [ ]
def addthing(self, thing):
assert thing is not None
assert not isinstance(thing, list)
self.stuff.append(thing)
def addthings(self, things):
for t in things: self.addthing(t)
# "look like" a Block so code doesn't have to care whether they're
# in global scope or not
def addstmt(self, stmt):
assert stmt is not None
assert not isinstance(stmt, list)
self.stuff.append(stmt)
def addstmts(self, stmts):
for s in stmts: self.addstmt(s)
class CppDirective(Node):
'''represents |#[directive] [rest]|, where |rest| is any string'''
def __init__(self, directive, rest=None):
Node.__init__(self)
self.directive = directive
self.rest = rest
class Block(Node):
def __init__(self):
Node.__init__(self)
self.stmts = [ ]
def addstmt(self, stmt):
assert stmt is not None
assert not isinstance(stmt, tuple)
self.stmts.append(stmt)
def addstmts(self, stmts):
for s in stmts: self.addstmt(s)
##------------------------------
# type and decl thingies
class Namespace(Block):
def __init__(self, name):
assert isinstance(name, str)
Block.__init__(self)
self.name = name
class Type(Node):
def __init__(self, name, const=0,
ptr=0, ptrconst=0, ptrptr=0, ptrconstptr=0,
ref=0,
hasimplicitcopyctor=True,
T=None):
"""
To avoid getting fancy with recursive types, we limit the kinds
of pointer types that can be be constructed.
ptr => T*
ptrconst => T* const
ptrptr => T**
ptrconstptr => T* const*
Any type, naked or pointer, can be const (const T) or ref (T&).
"""
assert isinstance(name, str)
assert not isinstance(const, str)
assert not isinstance(T, str)
Node.__init__(self)
self.name = name
self.const = const
self.ptr = ptr
self.ptrconst = ptrconst
self.ptrptr = ptrptr
self.ptrconstptr = ptrconstptr
self.ref = ref
self.hasimplicitcopyctor = hasimplicitcopyctor
self.T = T
# XXX could get serious here with recursive types, but shouldn't
# need that for this codegen
def __deepcopy__(self, memo):
return Type(self.name,
const=self.const,
ptr=self.ptr, ptrconst=self.ptrconst,
ptrptr=self.ptrptr, ptrconstptr=self.ptrconstptr,
ref=self.ref,
T=copy.deepcopy(self.T, memo))
Type.BOOL = Type('bool')
Type.INT = Type('int')
Type.INT32 = Type('int32_t')
Type.INTPTR = Type('intptr_t')
Type.NSRESULT = Type('nsresult')
Type.UINT32 = Type('uint32_t')
Type.UINT32PTR = Type('uint32_t', ptr=1)
Type.SIZE = Type('size_t')
Type.VOID = Type('void')
Type.VOIDPTR = Type('void', ptr=1)
Type.AUTO = Type('auto')
class TypeArray(Node):
def __init__(self, basetype, nmemb):
'''the type |basetype DECLNAME[nmemb]|. |nmemb| is an Expr'''
self.basetype = basetype
self.nmemb = nmemb
def __deepcopy__(self, memo):
return TypeArray(deepcopy(self.basetype, memo), nmemb)
class TypeEnum(Node):
def __init__(self, name=None):
'''name can be None'''
Node.__init__(self)
self.name = name
self.idnums = [ ] # pairs of ('Foo', [num]) or ('Foo', None)
def addId(self, id, num=None):
self.idnums.append((id, num))
class TypeUnion(Node):
def __init__(self, name=None):
Node.__init__(self)
self.name = name
self.components = [ ] # [ Decl ]
def addComponent(self, type, name):
self.components.append(Decl(type, name))
class Typedef(Node):
def __init__(self, fromtype, totypename):
assert isinstance(totypename, str)
Node.__init__(self)
self.fromtype = fromtype
self.totypename = totypename
def __cmp__(self, o):
return cmp(self.totypename, o.totypename)
def __eq__(self, o):
return (self.__class__ == o.__class__
and 0 == cmp(self, o))
def __hash__(self):
return hash(self.totypename)
class Using(Node):
def __init__(self, type):
Node.__init__(self)
self.type = type
class ForwardDecl(Node):
def __init__(self, pqname, cls=0, struct=0):
assert (not cls and struct) or (cls and not struct)
self.pqname = pqname
self.cls = cls
self.struct = struct
class Decl(Node):
'''represents |Foo bar|, e.g. in a function signature'''
def __init__(self, type, name):
assert type is not None
assert not isinstance(type, str)
assert isinstance(name, str)
Node.__init__(self)
self.type = type
self.name = name
def __deepcopy__(self, memo):
return Decl(copy.deepcopy(self.type, memo), self.name)
class Param(Decl):
def __init__(self, type, name, default=None):
Decl.__init__(self, type, name)
self.default = default
def __deepcopy__(self, memo):
return Param(copy.deepcopy(self.type, memo), self.name,
copy.deepcopy(self.default, memo))
##------------------------------
# class stuff
class Class(Block):
def __init__(self, name, inherits=[ ],
interface=0, abstract=0, final=0,
specializes=None, struct=0):
assert not (interface and abstract)
assert not (abstract and final)
assert not (interface and final)
assert not (inherits and specializes)
Block.__init__(self)
self.name = name
self.inherits = inherits # [ Type ]
self.interface = interface # bool
self.abstract = abstract # bool
self.final = final # bool
self.specializes = specializes # Type or None
self.struct = struct # bool
class Inherit(Node):
def __init__(self, type, viz='public'):
assert isinstance(viz, str)
Node.__init__(self)
self.type = type
self.viz = viz
class FriendClassDecl(Node):
def __init__(self, friend):
Node.__init__(self)
self.friend = friend
class MethodDecl(Node):
def __init__(self, name, params=[ ], ret=Type('void'),
virtual=0, const=0, pure=0, static=0, warn_unused=0,
inline=0, force_inline=0, never_inline=0,
typeop=None,
T=None):
assert not (virtual and static)
assert not pure or virtual # pure => virtual
assert not (static and typeop)
assert not (name and typeop)
assert name is None or isinstance(name, str)
assert not isinstance(ret, list)
for decl in params: assert not isinstance(decl, str)
assert not isinstance(T, int)
assert not (inline and never_inline)
assert not (force_inline and never_inline)
if typeop is not None:
ret = None
Node.__init__(self)
self.name = name
self.params = params # [ Param ]
self.ret = ret # Type or None
self.virtual = virtual # bool
self.const = const # bool
self.pure = pure # bool
self.static = static # bool
self.warn_unused = warn_unused # bool
self.force_inline = (force_inline or T) # bool
self.inline = inline # bool
self.never_inline = never_inline # bool
self.typeop = typeop # Type or None
self.T = T # Type or None
self.only_for_definition = False
def __deepcopy__(self, memo):
return MethodDecl(
self.name,
params=copy.deepcopy(self.params, memo),
ret=copy.deepcopy(self.ret, memo),
virtual=self.virtual,
const=self.const,
pure=self.pure,
static=self.static,
warn_unused=self.warn_unused,
inline=self.inline,
force_inline=self.force_inline,
never_inline=self.never_inline,
typeop=copy.deepcopy(self.typeop, memo),
T=copy.deepcopy(self.T, memo))
class MethodDefn(Block):
def __init__(self, decl):
Block.__init__(self)
self.decl = decl
class FunctionDecl(MethodDecl):
def __init__(self, name, params=[ ], ret=Type('void'),
static=0, warn_unused=0,
inline=0, force_inline=0,
T=None):
MethodDecl.__init__(self, name, params=params, ret=ret,
static=static, warn_unused=warn_unused,
inline=inline, force_inline=force_inline,
T=T)
class FunctionDefn(MethodDefn):
def __init__(self, decl):
MethodDefn.__init__(self, decl)
class ConstructorDecl(MethodDecl):
def __init__(self, name, params=[ ], explicit=0, force_inline=0):
MethodDecl.__init__(self, name, params=params, ret=None,
force_inline=force_inline)
self.explicit = explicit
def __deepcopy__(self, memo):
return ConstructorDecl(self.name,
copy.deepcopy(self.params, memo),
self.explicit)
class ConstructorDefn(MethodDefn):
def __init__(self, decl, memberinits=[ ]):
MethodDefn.__init__(self, decl)
self.memberinits = memberinits
class DestructorDecl(MethodDecl):
def __init__(self, name, virtual=0, force_inline=0, inline=0):
MethodDecl.__init__(self, name, params=[ ], ret=None,
virtual=virtual,
force_inline=force_inline, inline=inline)
def __deepcopy__(self, memo):
return DestructorDecl(self.name,
virtual=self.virtual,
force_inline=self.force_inline,
inline=self.inline)
class DestructorDefn(MethodDefn):
def __init__(self, decl): MethodDefn.__init__(self, decl)
##------------------------------
# expressions
class ExprVar(Node):
def __init__(self, name):
assert isinstance(name, str)
Node.__init__(self)
self.name = name
ExprVar.THIS = ExprVar('this')
class ExprLiteral(Node):
def __init__(self, value, type):
'''|type| is a Python format specifier; 'd' for example'''
Node.__init__(self)
self.value = value
self.type = type
@staticmethod
def Int(i): return ExprLiteral(i, 'd')
@staticmethod
def String(s): return ExprLiteral('"'+ s +'"', 's')
@staticmethod
def WString(s): return ExprLiteral('L"'+ s +'"', 's')
def __str__(self):
return ('%'+ self.type)% (self.value)
ExprLiteral.ZERO = ExprLiteral.Int(0)
ExprLiteral.ONE = ExprLiteral.Int(1)
ExprLiteral.NULL = ExprVar('nullptr')
ExprLiteral.TRUE = ExprVar('true')
ExprLiteral.FALSE = ExprVar('false')
class ExprPrefixUnop(Node):
def __init__(self, expr, op):
assert not isinstance(expr, tuple)
self.expr = expr
self.op = op
class ExprNot(ExprPrefixUnop):
def __init__(self, expr):
ExprPrefixUnop.__init__(self, expr, '!')
class ExprAddrOf(ExprPrefixUnop):
def __init__(self, expr):
ExprPrefixUnop.__init__(self, expr, '&')
class ExprDeref(ExprPrefixUnop):
def __init__(self, expr):
ExprPrefixUnop.__init__(self, expr, '*')
class ExprCast(Node):
def __init__(self, expr, type,
dynamic=0, static=0, reinterpret=0, const=0, C=0):
assert 1 == reduce(lambda a, x: a+x, [ dynamic, static, reinterpret, const, C ])
Node.__init__(self)
self.expr = expr
self.type = type
self.dynamic = dynamic
self.static = static
self.reinterpret = reinterpret
self.const = const
self.C = C
class ExprBinary(Node):
def __init__(self, left, op, right):
Node.__init__(self)
self.left = left
self.op = op
self.right = right
class ExprConditional(Node):
def __init__(self, cond, ife, elsee):
Node.__init__(self)
self.cond = cond
self.ife = ife
self.elsee = elsee
class ExprIndex(Node):
def __init__(self, arr, idx):
Node.__init__(self)
self.arr = arr
self.idx = idx
class ExprSelect(Node):
def __init__(self, obj, op, field):
assert obj and op and field
assert not isinstance(obj, str)
assert isinstance(field, str)
Node.__init__(self)
self.obj = obj
self.op = op
self.field = field
class ExprAssn(Node):
def __init__(self, lhs, rhs, op='='):
Node.__init__(self)
self.lhs = lhs
self.op = op
self.rhs = rhs
class ExprCall(Node):
def __init__(self, func, args=[ ]):
assert hasattr(func, 'accept')
assert isinstance(args, list)
for arg in args: assert arg and not isinstance(arg, str)
Node.__init__(self)
self.func = func
self.args = args
class ExprMove(ExprCall):
def __init__(self, arg):
ExprCall.__init__(self, ExprVar("mozilla::Move"), args=[arg])
class ExprNew(Node):
# XXX taking some poetic license ...
def __init__(self, ctype, args=[ ], newargs=None):
assert not (ctype.const or ctype.ref)
Node.__init__(self)
self.ctype = ctype
self.args = args
self.newargs = newargs
class ExprDelete(Node):
def __init__(self, obj):
Node.__init__(self)
self.obj = obj
class ExprMemberInit(ExprCall):
def __init__(self, member, args=[ ]):
ExprCall.__init__(self, member, args)
class ExprSizeof(ExprCall):
def __init__(self, t):
ExprCall.__init__(self, ExprVar('sizeof'), [ t ])
##------------------------------
# statements etc.
class StmtBlock(Block):
def __init__(self, stmts=[ ]):
Block.__init__(self)
self.addstmts(stmts)
class StmtDecl(Node):
def __init__(self, decl, init=None, initargs=None):
assert not (init and initargs)
assert not isinstance(init, str) # easy to confuse with Decl
assert not isinstance(init, list)
assert not isinstance(decl, tuple)
Node.__init__(self)
self.decl = decl
self.init = init
self.initargs = initargs
class Label(Node):
def __init__(self, name):
Node.__init__(self)
self.name = name
Label.PUBLIC = Label('public')
Label.PROTECTED = Label('protected')
Label.PRIVATE = Label('private')
class CaseLabel(Node):
def __init__(self, name):
Node.__init__(self)
self.name = name
class DefaultLabel(Node):
def __init__(self):
Node.__init__(self)
class StmtIf(Node):
def __init__(self, cond):
Node.__init__(self)
self.cond = cond
self.ifb = Block()
self.elseb = None
def addifstmt(self, stmt):
self.ifb.addstmt(stmt)
def addifstmts(self, stmts):
self.ifb.addstmts(stmts)
def addelsestmt(self, stmt):
if self.elseb is None: self.elseb = Block()
self.elseb.addstmt(stmt)
def addelsestmts(self, stmts):
if self.elseb is None: self.elseb = Block()
self.elseb.addstmts(stmts)
class StmtFor(Block):
def __init__(self, init=None, cond=None, update=None):
Block.__init__(self)
self.init = init
self.cond = cond
self.update = update
class StmtSwitch(Block):
def __init__(self, expr):
Block.__init__(self)
self.expr = expr
self.nr_cases = 0
def addcase(self, case, block):
'''NOTE: |case| is not checked for uniqueness'''
assert not isinstance(case, str)
assert (isinstance(block, StmtBreak)
or isinstance(block, StmtReturn)
or isinstance(block, StmtSwitch)
or (hasattr(block, 'stmts')
and (isinstance(block.stmts[-1], StmtBreak)
or isinstance(block.stmts[-1], StmtReturn))))
self.addstmt(case)
self.addstmt(block)
self.nr_cases += 1
def addfallthrough(self, case):
self.addstmt(case)
self.nr_cases += 1
class StmtBreak(Node):
def __init__(self):
Node.__init__(self)
class StmtExpr(Node):
def __init__(self, expr):
assert expr is not None
Node.__init__(self)
self.expr = expr
class StmtReturn(Node):
def __init__(self, expr=None):
Node.__init__(self)
self.expr = expr
StmtReturn.TRUE = StmtReturn(ExprLiteral.TRUE)
StmtReturn.FALSE = StmtReturn(ExprLiteral.FALSE)