Source code

Revision control

Copy as Markdown

Other Tools

# 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 sys
from ipdl.cgen import CodePrinter
from ipdl.cxx.ast import MethodSpec, TypeArray, Visitor, DestructorDecl
class CxxCodeGen(CodePrinter, Visitor):
def __init__(self, outf=sys.stdout, indentCols=4):
CodePrinter.__init__(self, outf, indentCols)
def cgen(self, cxxfile):
cxxfile.accept(self)
def visitWhitespace(self, ws):
if ws.indent:
self.printdent("")
self.write(ws.ws)
def visitVerbatimNode(self, verb):
if verb.indent:
self.printdent("")
self.write(verb.text)
def visitGroupNode(self, group):
offsetCols = self.indentCols * group.offset
self.col += offsetCols
for node in group.nodes:
node.accept(self)
self.col -= offsetCols
def visitCppDirective(self, cd):
if cd.rest:
self.println("#%s %s" % (cd.directive, cd.rest))
else:
self.println("#%s" % (cd.directive))
def visitNamespace(self, ns):
self.println("namespace " + ns.name + " {")
self.visitBlock(ns)
self.println("} // namespace " + ns.name)
def visitType(self, t):
if t.const:
self.write("const ")
self.write(t.name)
if t.T is not None:
self.write("<")
if type(t.T) is list:
t.T[0].accept(self)
for tt in t.T[1:]:
self.write(", ")
tt.accept(self)
else:
t.T.accept(self)
self.write(">")
if t.inner is not None:
self.write("::")
t.inner.accept(self)
ts = ""
if t.ptr:
ts += "*"
elif t.ptrptr:
ts += "**"
elif t.ptrconstptr:
ts += "* const*"
if t.ref:
ts += "&"
elif t.rvalref:
ts += "&&"
elif t.rightconst:
ts += " const"
self.write(ts)
def visitTypeEnum(self, te):
self.write("enum")
if te.name:
self.write(" " + te.name)
self.println(" {")
self.indent()
nids = len(te.idnums)
for i, (id, num) in enumerate(te.idnums):
self.printdent(id)
if num:
self.write(" = " + str(num))
if i != (nids - 1):
self.write(",")
self.println()
self.dedent()
self.printdent("}")
def visitTypeUnion(self, u):
self.write("union")
if u.name:
self.write(" " + u.name)
self.println(" {")
self.indent()
for decl in u.components:
self.printdent()
decl.accept(self)
self.println(";")
self.dedent()
self.printdent("}")
def visitTypeFunction(self, fn):
self.write("std::function<")
fn.ret.accept(self)
self.write("(")
self.writeDeclList(fn.params)
self.write(")>")
def visitTypedef(self, td):
if td.templateargs:
formals = ", ".join(["class " + T for T in td.templateargs])
args = ", ".join(td.templateargs)
self.printdent("template<" + formals + "> using " + td.totypename + " = ")
td.fromtype.accept(self)
self.println("<" + args + ">;")
else:
self.printdent("typedef ")
td.fromtype.accept(self)
self.println(" " + td.totypename + ";")
def visitUsing(self, us):
self.printdent("using ")
us.type.accept(self)
self.println(";")
def visitForwardDecl(self, fd):
if fd.cls:
self.printdent("class ")
elif fd.struct:
self.printdent("struct ")
self.write(str(fd.pqname))
self.println(";")
def visitDecl(self, d):
# C-syntax arrays make code generation much more annoying
if isinstance(d.type, TypeArray):
d.type.basetype.accept(self)
else:
d.type.accept(self)
if d.name:
self.write(" " + d.name)
if isinstance(d.type, TypeArray):
self.write("[")
d.type.nmemb.accept(self)
self.write("]")
def visitParam(self, p):
self.visitDecl(p)
if p.default is not None:
self.write(" = ")
p.default.accept(self)
def visitClass(self, c):
if c.specializes is not None:
self.printdentln("template<>")
if c.struct:
self.printdent("struct")
else:
self.printdent("class")
self.write(" " + c.name)
if c.final:
self.write(" final")
if c.specializes is not None:
self.write(" <")
c.specializes.accept(self)
self.write(">")
ninh = len(c.inherits)
if 0 < ninh:
self.println(" :")
self.indent()
for i, inherit in enumerate(c.inherits):
self.printdent()
inherit.accept(self)
if i != (ninh - 1):
self.println(",")
self.dedent()
self.println()
self.printdentln("{")
self.indent()
self.visitBlock(c)
self.dedent()
self.printdentln("};")
def visitInherit(self, inh):
self.write(inh.viz + " ")
inh.type.accept(self)
def visitFriendClassDecl(self, fcd):
self.printdentln("friend class " + fcd.friend + ";")
def visitMethodDecl(self, md):
if md.T:
self.write("template<")
self.write("typename ")
md.T.accept(self)
self.println(">")
self.printdent()
if md.warn_unused:
self.write("[[nodiscard]] ")
if md.methodspec == MethodSpec.STATIC:
self.write("static ")
elif md.methodspec == MethodSpec.VIRTUAL or md.methodspec == MethodSpec.PURE:
self.write("virtual ")
if md.ret:
if md.only_for_definition:
self.write("auto ")
else:
md.ret.accept(self)
self.println()
self.printdent()
if md.cls is not None:
assert md.only_for_definition
self.write(md.cls.name)
if md.cls.specializes is not None:
self.write("<")
md.cls.specializes.accept(self)
self.write(">")
self.write("::")
if md.typeop is not None:
self.write("operator ")
md.typeop.accept(self)
else:
if isinstance(md, DestructorDecl):
self.write("~")
self.write(md.name)
self.write("(")
self.writeDeclList(md.params)
self.write(")")
if md.const:
self.write(" const")
if md.ret and md.only_for_definition:
self.write(" -> ")
md.ret.accept(self)
if md.methodspec == MethodSpec.OVERRIDE:
self.write(" override")
elif md.methodspec == MethodSpec.FINAL:
self.write(" final")
elif md.methodspec == MethodSpec.PURE:
self.write(" = 0")
def visitMethodDefn(self, md):
# Method specifiers are for decls, not defns.
assert md.decl.methodspec == MethodSpec.NONE
self.printdent()
md.decl.accept(self)
self.println()
self.printdentln("{")
self.indent()
self.visitBlock(md)
self.dedent()
self.printdentln("}")
def visitConstructorDecl(self, cd):
if cd.explicit:
self.write("explicit ")
else:
self.write("MOZ_IMPLICIT ")
self.visitMethodDecl(cd)
def visitConstructorDefn(self, cd):
self.printdent()
cd.decl.accept(self)
if len(cd.memberinits):
self.println(" :")
self.indent()
ninits = len(cd.memberinits)
for i, init in enumerate(cd.memberinits):
self.printdent()
init.accept(self)
if i != (ninits - 1):
self.println(",")
self.dedent()
self.println()
self.printdentln("{")
self.indent()
self.visitBlock(cd)
self.dedent()
self.printdentln("}")
def visitDestructorDecl(self, dd):
self.visitMethodDecl(dd)
def visitDestructorDefn(self, dd):
self.printdent()
dd.decl.accept(self)
self.println()
self.printdentln("{")
self.indent()
self.visitBlock(dd)
self.dedent()
self.printdentln("}")
def visitExprLiteral(self, el):
self.write(str(el))
def visitExprVar(self, ev):
self.write(ev.name)
def visitExprPrefixUnop(self, e):
self.write("(")
self.write(e.op)
self.write("(")
e.expr.accept(self)
self.write(")")
self.write(")")
def visitExprCast(self, c):
if c.static:
pfx, sfx = "static_cast<", ">"
else:
assert c.const
pfx, sfx = "const_cast<", ">"
self.write(pfx)
c.type.accept(self)
self.write(sfx + "(")
c.expr.accept(self)
self.write(")")
def visitExprBinary(self, e):
self.write("(")
e.left.accept(self)
self.write(") " + e.op + " (")
e.right.accept(self)
self.write(")")
def visitExprConditional(self, c):
self.write("(")
c.cond.accept(self)
self.write(" ? ")
c.ife.accept(self)
self.write(" : ")
c.elsee.accept(self)
self.write(")")
def visitExprSelect(self, es):
self.write("(")
es.obj.accept(self)
self.write(")")
self.write(es.op)
es.field.accept(self)
def visitExprAssn(self, ea):
ea.lhs.accept(self)
self.write(" " + ea.op + " ")
ea.rhs.accept(self)
def visitExprCall(self, ec):
ec.func.accept(self)
self.write("(")
self.writeExprList(ec.args)
self.write(")")
def visitExprNew(self, en):
self.write("new ")
if en.newargs is not None:
self.write("(")
self.writeExprList(en.newargs)
self.write(") ")
en.ctype.accept(self)
if en.args is not None:
self.write("(")
self.writeExprList(en.args)
self.write(")")
def visitExprDelete(self, ed):
self.write("delete ")
ed.obj.accept(self)
def visitExprLambda(self, l):
self.write("[")
ncaptures = len(l.captures)
for i, c in enumerate(l.captures):
c.accept(self)
if i != (ncaptures - 1):
self.write(", ")
self.write("](")
self.writeDeclList(l.params)
self.write(")")
if l.ret:
self.write(" -> ")
l.ret.accept(self)
self.println(" {")
self.indent()
self.visitBlock(l)
self.dedent()
self.printdent("}")
def visitStmtBlock(self, b):
self.printdentln("{")
self.indent()
self.visitBlock(b)
self.dedent()
self.printdentln("}")
def visitLabel(self, label):
self.dedent() # better not be at global scope ...
self.printdentln(label.name + ":")
self.indent()
def visitCaseLabel(self, cl):
self.dedent()
self.printdentln("case " + cl.name + ":")
self.indent()
def visitDefaultLabel(self, dl):
self.dedent()
self.printdentln("default:")
self.indent()
def visitStmtIf(self, si):
self.printdent("if (")
si.cond.accept(self)
self.println(") {")
self.indent()
si.ifb.accept(self)
self.dedent()
self.printdentln("}")
if si.elseb is not None:
self.printdentln("else {")
self.indent()
si.elseb.accept(self)
self.dedent()
self.printdentln("}")
def visitStmtFor(self, sf):
self.printdent("for (")
if sf.init is not None:
sf.init.accept(self)
self.write("; ")
if sf.cond is not None:
sf.cond.accept(self)
self.write("; ")
if sf.update is not None:
sf.update.accept(self)
self.println(") {")
self.indent()
self.visitBlock(sf)
self.dedent()
self.printdentln("}")
def visitStmtRangedFor(self, rf):
self.printdent("for (auto& ")
rf.var.accept(self)
self.write(" : ")
rf.iteree.accept(self)
self.println(") {")
self.indent()
self.visitBlock(rf)
self.dedent()
self.printdentln("}")
def visitStmtSwitch(self, sw):
self.printdent("switch (")
sw.expr.accept(self)
self.println(") {")
self.indent()
self.visitBlock(sw)
self.dedent()
self.printdentln("}")
def visitStmtBreak(self, sb):
self.printdentln("break;")
def visitStmtDecl(self, sd):
self.printdent()
sd.decl.accept(self)
if sd.initargs is not None:
self.write("{")
self.writeDeclList(sd.initargs)
self.write("}")
if sd.init is not None:
self.write(" = ")
sd.init.accept(self)
self.println(";")
def visitStmtExpr(self, se):
self.printdent()
se.expr.accept(self)
self.println(";")
def visitStmtReturn(self, sr):
self.printdent("return")
if sr.expr:
self.write(" ")
sr.expr.accept(self)
self.println(";")
def writeDeclList(self, decls):
# FIXME/cjones: try to do nice formatting of these guys
ndecls = len(decls)
if 0 == ndecls:
return
elif 1 == ndecls:
decls[0].accept(self)
return
self.indent()
self.indent()
for i, decl in enumerate(decls):
self.println()
self.printdent()
decl.accept(self)
if i != (ndecls - 1):
self.write(",")
self.dedent()
self.dedent()
def writeExprList(self, exprs):
# FIXME/cjones: try to do nice formatting and share code with
# writeDeclList()
nexprs = len(exprs)
for i, expr in enumerate(exprs):
expr.accept(self)
if i != (nexprs - 1):
self.write(", ")