import StringIO def addNodes(): addNode("ArrayType", "Expr", "len", "Expr", "elt", "Expr") addNode( "AssignStmt", "Stmt", "lhs", "[]Expr", "rhs", "[]Expr", "define", "bool") addNode("BadDecl", "Decl") addNode("BadExpr", "Expr") addNode("BadStmt", "Stmt") addNode("BasicLit", "Expr", "value", "Token") addNode("BinaryExpr", "Expr", "x", "Expr", "y", "Expr", "op", "TokenType") addNode("BlockStmt", "Stmt", "list", "[]Stmt") addNode("Ident", "Expr", "name", "Token") addNode("BranchStmt", "Stmt", "label", "Ident", "tok", "TokenType") addNode( "CallExpr", "Expr", "fun", "Expr", "args", "[]Expr", "ellipsis", "bool") addNode("CaseClause", "Stmt", "list", "[]Expr", "body", "[]Stmt") addNode("ChanType", "Expr", "dir", "ChanDir", "value", "Expr") addNode("CommClause", "Stmt", "comm", "Stmt", "body", "[]Stmt") addNode("CompositeLit", "Expr", "type", "Expr", "elts", "[]Expr") addNode("DeclStmt", "Stmt", "decl", "Decl") addNode("DeferStmt", "Stmt", "call", "CallExpr") addNode("Ellipsis", "Expr", "elt", "Expr") addNode("EmptyStmt", "Stmt") addNode("ExprStmt", "Stmt", "x", "Expr") addNode( "Field", "Node", "names", "[]Ident", "type", "Expr", "tag", "BasicLit") addNode("FieldList", "Node", "list", "[]Field") addNode( "ForStmt", "Stmt", "init", "Stmt", "cond", "Expr", "post", "Stmt", "body", "BlockStmt") addNode("FuncType", "Expr", "params", "FieldList", "results", "FieldList") addNode( "FuncDecl", "Decl", "recv", "FieldList", "name", "Ident", "type", "FuncType", "body", "BlockStmt") addNode("FuncLit", "Expr", "type", "FuncType", "body", "BlockStmt") addNode("GenDecl", "Decl", "tok", "TokenType", "specs", "[]Spec") addNode("GoStmt", "Stmt", "call", "CallExpr") addNode( "IfStmt", "Stmt", "init", "Stmt", "cond", "Expr", "body", "BlockStmt", "els", "Stmt") addNode("ImportSpec", "Spec", "name", "Ident", "path", "BasicLit") addNode("IncDecStmt", "Stmt", "x", "Expr", "tok", "TokenType") addNode("IndexExpr", "Expr", "x", "Expr", "index", "Expr") addNode("InterfaceType", "Expr", "methods", "FieldList") addNode("KeyValueExpr", "Expr", "key", "Expr", "value", "Expr") addNode("LabeledStmt", "Stmt", "label", "Ident", "stmt", "Stmt") addNode("MapType", "Expr", "key", "Expr", "value", "Expr") addNode("ParenExpr", "Expr", "x", "Expr") addNode( "RangeStmt", "Stmt", "key", "Expr", "value", "Expr", "define", "bool", "x", "Expr", "body", "BlockStmt") addNode("ReturnStmt", "Stmt", "results", "[]Expr") addNode("SelectStmt", "Stmt", "body", "BlockStmt") addNode("SelectorExpr", "Expr", "x", "Expr", "sel", "Ident") addNode("SendStmt", "Stmt", "chan", "Expr", "value", "Expr") addNode( "SliceExpr", "Expr", "x", "Expr", "low", "Expr", "high", "Expr", "max", "Expr", "slice3", "bool") addNode("StarExpr", "Expr", "x", "Expr") addNode("StructType", "Expr", "fields", "FieldList") addNode( "SwitchStmt", "Stmt", "init", "Stmt", "tag", "Expr", "body", "BlockStmt") addNode("TypeAssertExpr", "Expr", "x", "Expr", "type", "Expr") addNode("TypeSpec", "Spec", "name", "Ident", "type", "Expr") addNode( "TypeSwitchStmt", "Stmt", "init", "Stmt", "assign", "Stmt", "body", "BlockStmt") addNode("UnaryExpr", "Expr", "op", "TokenType", "x", "Expr") addNode( "ValueSpec", "Spec", "names", "[]Ident", "type", "Expr", "values", "[]Expr") addParent("Decl", "Node") addParent("Expr", "Node") addParent("Spec", "Node") addParent("Stmt", "Node") class Member(object): def __init__(self, name, typename): self.title = name.title() self.sname = name self.mname = 'm_' + name self.is_list = typename.startswith("[]") self.is_value = isValueType(typename) if self.is_value: self.argtype = typename self.mtype = typename elif self.is_list: self.argtype = 'GoAST' + typename[2:] self.mtype = 'std::vector >' % self.argtype else: self.argtype = 'GoAST' + typename self.mtype = 'std::unique_ptr<%s>' % self.argtype self.mname = self.mname + '_up' kinds = {} parentClasses = StringIO.StringIO() childClasses = StringIO.StringIO() walker = StringIO.StringIO() def startClass(name, parent, out): out.write(""" class GoAST%s : public GoAST%s { public: """ % (name, parent)) def endClass(name, out): out.write(""" %(name)s(const %(name)s &) = delete; const %(name)s &operator=(const %(name)s &) = delete; }; """ % {'name': 'GoAST' + name}) def addNode(name, parent, *children): startClass(name, parent, childClasses) l = kinds.setdefault(parent, []) l.append(name) children = createMembers(name, children) addConstructor(name, parent, children) childClasses.write(""" const char * GetKindName() const override { return "%(name)s"; } static bool classof(const GoASTNode *n) { return n->GetKind() == e%(name)s; } """ % {'name': name}) addChildren(name, children) endClass(name, childClasses) def isValueType(typename): if typename[0].islower(): return True if typename[0].isupper(): return typename.startswith('Token') or typename == 'ChanDir' return False def createMembers(name, children): l = len(children) if (l % 2) != 0: raise Exception("Invalid children for %s: %s" % (name, children)) return [Member(children[i], children[i + 1]) for i in xrange(0, l, 2)] def addConstructor(name, parent, children): for c in children: if c.is_list: children = [x for x in children if x.is_value] break childClasses.write(' ') if len(children) == 1: childClasses.write('explicit ') childClasses.write('GoAST%s(' % name) for i in xrange(len(children)): if i > 0: childClasses.write(', ') c = children[i] if c.is_value: childClasses.write(c.argtype) childClasses.write(' ') else: childClasses.write('%s *' % c.argtype) childClasses.write(c.sname) childClasses.write(') : GoAST%s(e%s)' % (parent, name)) for c in children: childClasses.write(', ') childClasses.write('%(mname)s(%(sname)s)' % c.__dict__) childClasses.write(""" {} ~GoAST%s() override = default; """ % name) def addChildren(name, children): if len(children) == 0: return walker.write(""" case e%(n)s: { GoAST%(n)s *n = llvm::cast(this); (void)n;""" % {'n': name}) for c in children: if c.is_list: childClasses.write(""" size_t Num%(title)s() const { return %(mname)s.size(); } const %(argtype)s * Get%(title)s(int i) const { return %(mname)s[i].get(); } void Add%(title)s(%(argtype)s *%(sname)s) { %(mname)s.push_back(std::unique_ptr<%(argtype)s>(%(sname)s)); } """ % c.__dict__) walker.write(""" for (auto& e : n->%s) { v(e.get()); }""" % c.mname) else: const = '' get = '' set = '' t = c.argtype if isValueType(t): set = '%(mname)s = %(sname)s' % c.__dict__ t = t + ' ' else: t = t + ' *' const = 'const ' get = '.get()' set = '%(mname)s.reset(%(sname)s)' % c.__dict__ walker.write(""" v(n->%s.get());""" % c.mname) childClasses.write(""" %(const)s%(type)s Get%(title)s() const { return %(mname)s%(get)s; } void Set%(title)s(%(type)s%(sname)s) { %(set)s; } """ % {'const': const, 'title': c.title, 'sname': c.sname, 'get': get, 'set': set, 'type': t, 'mname': c.mname}) childClasses.write('\n private:\n friend class GoASTNode;\n') walker.write(""" return; }""") for c in children: childClasses.write(' %s %s;\n' % (c.mtype, c.mname)) def addParent(name, parent): startClass(name, parent, parentClasses) l = kinds[name] minName = l[0] maxName = l[-1] parentClasses.write(""" template R Visit(V *v) const; static bool classof(const GoASTNode *n) { return n->GetKind() >= e%s && n->GetKind() <= e%s; } protected: explicit GoAST%s(NodeKind kind) : GoASTNode(kind) { } private: """ % (minName, maxName, name)) endClass(name, parentClasses) addNodes() print """//===-- GoAST.h -------------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // DO NOT EDIT. // Generated by gen_go_ast.py #ifndef liblldb_GoAST_h #define liblldb_GoAST_h #include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" #include "llvm/Support/Casting.h" #include "Plugins/ExpressionParser/Go/GoLexer.h" namespace lldb_private { class GoASTNode { public: typedef GoLexer::TokenType TokenType; typedef GoLexer::Token Token; enum ChanDir { eChanBidir, eChanSend, eChanRecv, }; enum NodeKind {""" for l in kinds.itervalues(): for x in l: print " e%s," % x print """ }; virtual ~GoASTNode() = default; NodeKind GetKind() const { return m_kind; } virtual const char *GetKindName() const = 0; template void WalkChildren(V &v); protected: explicit GoASTNode(NodeKind kind) : m_kind(kind) { } private: const NodeKind m_kind; GoASTNode(const GoASTNode &) = delete; const GoASTNode &operator=(const GoASTNode &) = delete; }; """ print parentClasses.getvalue() print childClasses.getvalue() for k, l in kinds.iteritems(): if k == 'Node': continue print """ template R GoAST%s::Visit(V* v) const { switch(GetKind()) {""" % k for subtype in l: print """ case e%(n)s: return v->Visit%(n)s(llvm::cast(this));""" % {'n': subtype} print """ default: assert(false && "Invalid kind"); } }""" print """ template void GoASTNode::WalkChildren(V &v) { switch (m_kind) { """ print walker.getvalue() print""" case eEmptyStmt: case eBadDecl: case eBadExpr: case eBadStmt: break; } } } // namespace lldb_private #endif """