| 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<std::unique_ptr<%s> >' % 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<GoAST%(n)s>(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 <typename R, typename V> 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 <typename V> 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 <typename R, typename V> |
| 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<const GoAST%(n)s>(this));""" % {'n': subtype} |
| |
| print """ default: |
| assert(false && "Invalid kind"); |
| } |
| }""" |
| |
| print """ |
| template <typename V> |
| 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 |
| """ |