summaryrefslogtreecommitdiffstats
path: root/ipc/ipdl/ipdl/cxx/cgen.py
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/ipdl/ipdl/cxx/cgen.py')
-rw-r--r--ipc/ipdl/ipdl/cxx/cgen.py557
1 files changed, 557 insertions, 0 deletions
diff --git a/ipc/ipdl/ipdl/cxx/cgen.py b/ipc/ipdl/ipdl/cxx/cgen.py
new file mode 100644
index 0000000000..fecb90e97b
--- /dev/null
+++ b/ipc/ipdl/ipdl/cxx/cgen.py
@@ -0,0 +1,557 @@
+# 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.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(", ")