Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,13 @@
add_lldb_library(lldbPluginExpressionParserGo PLUGIN
GoLexer.cpp
GoParser.cpp
GoUserExpression.cpp
LINK_LIBS
lldbCore
lldbExpression
lldbSymbol
lldbTarget
LINK_COMPONENTS
Support
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,350 @@
//===-- GoLexer.cpp ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <string.h>
#include "GoLexer.h"
using namespace lldb_private;
llvm::StringMap<GoLexer::TokenType> *GoLexer::m_keywords;
GoLexer::GoLexer(const char *src)
: m_src(src), m_end(src + strlen(src)), m_last_token(TOK_INVALID, "") {}
bool GoLexer::SkipWhitespace() {
bool saw_newline = false;
for (; m_src < m_end; ++m_src) {
if (*m_src == '\n')
saw_newline = true;
if (*m_src == '/' && !SkipComment())
return saw_newline;
else if (!IsWhitespace(*m_src))
return saw_newline;
}
return saw_newline;
}
bool GoLexer::SkipComment() {
if (m_src[0] == '/' && m_src[1] == '/') {
for (const char *c = m_src + 2; c < m_end; ++c) {
if (*c == '\n') {
m_src = c - 1;
return true;
}
}
return true;
} else if (m_src[0] == '/' && m_src[1] == '*') {
for (const char *c = m_src + 2; c < m_end; ++c) {
if (c[0] == '*' && c[1] == '/') {
m_src = c + 1;
return true;
}
}
}
return false;
}
const GoLexer::Token &GoLexer::Lex() {
bool newline = SkipWhitespace();
const char *start = m_src;
m_last_token.m_type = InternalLex(newline);
m_last_token.m_value = llvm::StringRef(start, m_src - start);
return m_last_token;
}
GoLexer::TokenType GoLexer::InternalLex(bool newline) {
if (m_src >= m_end) {
return TOK_EOF;
}
if (newline) {
switch (m_last_token.m_type) {
case TOK_IDENTIFIER:
case LIT_FLOAT:
case LIT_IMAGINARY:
case LIT_INTEGER:
case LIT_RUNE:
case LIT_STRING:
case KEYWORD_BREAK:
case KEYWORD_CONTINUE:
case KEYWORD_FALLTHROUGH:
case KEYWORD_RETURN:
case OP_PLUS_PLUS:
case OP_MINUS_MINUS:
case OP_RPAREN:
case OP_RBRACK:
case OP_RBRACE:
return OP_SEMICOLON;
default:
break;
}
}
char c = *m_src;
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return DoNumber();
case '+':
case '-':
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case '<':
case '>':
case '!':
case ':':
case ';':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case ',':
case '=':
return DoOperator();
case '.':
if (IsDecimal(m_src[1]))
return DoNumber();
return DoOperator();
case '$':
// For lldb persistent vars.
return DoIdent();
case '"':
case '`':
return DoString();
case '\'':
return DoRune();
default:
break;
}
if (IsLetterOrDigit(c))
return DoIdent();
++m_src;
return TOK_INVALID;
}
GoLexer::TokenType GoLexer::DoOperator() {
TokenType t = TOK_INVALID;
if (m_end - m_src > 2) {
t = LookupKeyword(llvm::StringRef(m_src, 3));
if (t != TOK_INVALID)
m_src += 3;
}
if (t == TOK_INVALID && m_end - m_src > 1) {
t = LookupKeyword(llvm::StringRef(m_src, 2));
if (t != TOK_INVALID)
m_src += 2;
}
if (t == TOK_INVALID) {
t = LookupKeyword(llvm::StringRef(m_src, 1));
++m_src;
}
return t;
}
GoLexer::TokenType GoLexer::DoIdent() {
const char *start = m_src++;
while (m_src < m_end && IsLetterOrDigit(*m_src)) {
++m_src;
}
TokenType kw = LookupKeyword(llvm::StringRef(start, m_src - start));
if (kw != TOK_INVALID)
return kw;
return TOK_IDENTIFIER;
}
GoLexer::TokenType GoLexer::DoNumber() {
if (m_src[0] == '0' && (m_src[1] == 'x' || m_src[1] == 'X')) {
m_src += 2;
while (IsHexChar(*m_src))
++m_src;
return LIT_INTEGER;
}
bool dot_ok = true;
bool e_ok = true;
while (true) {
while (IsDecimal(*m_src))
++m_src;
switch (*m_src) {
case 'i':
++m_src;
return LIT_IMAGINARY;
case '.':
if (!dot_ok)
return LIT_FLOAT;
++m_src;
dot_ok = false;
break;
case 'e':
case 'E':
if (!e_ok)
return LIT_FLOAT;
dot_ok = e_ok = false;
++m_src;
if (*m_src == '+' || *m_src == '-')
++m_src;
break;
default:
if (dot_ok)
return LIT_INTEGER;
return LIT_FLOAT;
}
}
}
GoLexer::TokenType GoLexer::DoRune() {
while (++m_src < m_end) {
switch (*m_src) {
case '\'':
++m_src;
return LIT_RUNE;
case '\n':
return TOK_INVALID;
case '\\':
if (m_src[1] == '\n')
return TOK_INVALID;
++m_src;
}
}
return TOK_INVALID;
}
GoLexer::TokenType GoLexer::DoString() {
if (*m_src == '`') {
while (++m_src < m_end) {
if (*m_src == '`') {
++m_src;
return LIT_STRING;
}
}
return TOK_INVALID;
}
while (++m_src < m_end) {
switch (*m_src) {
case '"':
++m_src;
return LIT_STRING;
case '\n':
return TOK_INVALID;
case '\\':
if (m_src[1] == '\n')
return TOK_INVALID;
++m_src;
}
}
return TOK_INVALID;
}
GoLexer::TokenType GoLexer::LookupKeyword(llvm::StringRef id) {
if (m_keywords == nullptr)
m_keywords = InitKeywords();
const auto &it = m_keywords->find(id);
if (it == m_keywords->end())
return TOK_INVALID;
return it->second;
}
llvm::StringRef GoLexer::LookupToken(TokenType t) {
if (m_keywords == nullptr)
m_keywords = InitKeywords();
for (const auto &e : *m_keywords) {
if (e.getValue() == t)
return e.getKey();
}
return "";
}
llvm::StringMap<GoLexer::TokenType> *GoLexer::InitKeywords() {
auto &result = *new llvm::StringMap<TokenType>(128);
result["break"] = KEYWORD_BREAK;
result["default"] = KEYWORD_DEFAULT;
result["func"] = KEYWORD_FUNC;
result["interface"] = KEYWORD_INTERFACE;
result["select"] = KEYWORD_SELECT;
result["case"] = KEYWORD_CASE;
result["defer"] = KEYWORD_DEFER;
result["go"] = KEYWORD_GO;
result["map"] = KEYWORD_MAP;
result["struct"] = KEYWORD_STRUCT;
result["chan"] = KEYWORD_CHAN;
result["else"] = KEYWORD_ELSE;
result["goto"] = KEYWORD_GOTO;
result["package"] = KEYWORD_PACKAGE;
result["switch"] = KEYWORD_SWITCH;
result["const"] = KEYWORD_CONST;
result["fallthrough"] = KEYWORD_FALLTHROUGH;
result["if"] = KEYWORD_IF;
result["range"] = KEYWORD_RANGE;
result["type"] = KEYWORD_TYPE;
result["continue"] = KEYWORD_CONTINUE;
result["for"] = KEYWORD_FOR;
result["import"] = KEYWORD_IMPORT;
result["return"] = KEYWORD_RETURN;
result["var"] = KEYWORD_VAR;
result["+"] = OP_PLUS;
result["-"] = OP_MINUS;
result["*"] = OP_STAR;
result["/"] = OP_SLASH;
result["%"] = OP_PERCENT;
result["&"] = OP_AMP;
result["|"] = OP_PIPE;
result["^"] = OP_CARET;
result["<<"] = OP_LSHIFT;
result[">>"] = OP_RSHIFT;
result["&^"] = OP_AMP_CARET;
result["+="] = OP_PLUS_EQ;
result["-="] = OP_MINUS_EQ;
result["*="] = OP_STAR_EQ;
result["/="] = OP_SLASH_EQ;
result["%="] = OP_PERCENT_EQ;
result["&="] = OP_AMP_EQ;
result["|="] = OP_PIPE_EQ;
result["^="] = OP_CARET_EQ;
result["<<="] = OP_LSHIFT_EQ;
result[">>="] = OP_RSHIFT_EQ;
result["&^="] = OP_AMP_CARET_EQ;
result["&&"] = OP_AMP_AMP;
result["||"] = OP_PIPE_PIPE;
result["<-"] = OP_LT_MINUS;
result["++"] = OP_PLUS_PLUS;
result["--"] = OP_MINUS_MINUS;
result["=="] = OP_EQ_EQ;
result["<"] = OP_LT;
result[">"] = OP_GT;
result["="] = OP_EQ;
result["!"] = OP_BANG;
result["!="] = OP_BANG_EQ;
result["<="] = OP_LT_EQ;
result[">="] = OP_GT_EQ;
result[":="] = OP_COLON_EQ;
result["..."] = OP_DOTS;
result["("] = OP_LPAREN;
result["["] = OP_LBRACK;
result["{"] = OP_LBRACE;
result[","] = OP_COMMA;
result["."] = OP_DOT;
result[")"] = OP_RPAREN;
result["]"] = OP_RBRACK;
result["}"] = OP_RBRACE;
result[";"] = OP_SEMICOLON;
result[":"] = OP_COLON;
return &result;
}

View File

@ -0,0 +1,181 @@
//===-- GoLexer.h -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_GoLexer_h
#define liblldb_GoLexer_h
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
namespace lldb_private {
class GoLexer {
public:
explicit GoLexer(const char *src);
enum TokenType {
TOK_EOF,
TOK_INVALID,
TOK_IDENTIFIER,
LIT_INTEGER,
LIT_FLOAT,
LIT_IMAGINARY,
LIT_RUNE,
LIT_STRING,
KEYWORD_BREAK,
KEYWORD_DEFAULT,
KEYWORD_FUNC,
KEYWORD_INTERFACE,
KEYWORD_SELECT,
KEYWORD_CASE,
KEYWORD_DEFER,
KEYWORD_GO,
KEYWORD_MAP,
KEYWORD_STRUCT,
KEYWORD_CHAN,
KEYWORD_ELSE,
KEYWORD_GOTO,
KEYWORD_PACKAGE,
KEYWORD_SWITCH,
KEYWORD_CONST,
KEYWORD_FALLTHROUGH,
KEYWORD_IF,
KEYWORD_RANGE,
KEYWORD_TYPE,
KEYWORD_CONTINUE,
KEYWORD_FOR,
KEYWORD_IMPORT,
KEYWORD_RETURN,
KEYWORD_VAR,
OP_PLUS,
OP_MINUS,
OP_STAR,
OP_SLASH,
OP_PERCENT,
OP_AMP,
OP_PIPE,
OP_CARET,
OP_LSHIFT,
OP_RSHIFT,
OP_AMP_CARET,
OP_PLUS_EQ,
OP_MINUS_EQ,
OP_STAR_EQ,
OP_SLASH_EQ,
OP_PERCENT_EQ,
OP_AMP_EQ,
OP_PIPE_EQ,
OP_CARET_EQ,
OP_LSHIFT_EQ,
OP_RSHIFT_EQ,
OP_AMP_CARET_EQ,
OP_AMP_AMP,
OP_PIPE_PIPE,
OP_LT_MINUS,
OP_PLUS_PLUS,
OP_MINUS_MINUS,
OP_EQ_EQ,
OP_LT,
OP_GT,
OP_EQ,
OP_BANG,
OP_BANG_EQ,
OP_LT_EQ,
OP_GT_EQ,
OP_COLON_EQ,
OP_DOTS,
OP_LPAREN,
OP_LBRACK,
OP_LBRACE,
OP_COMMA,
OP_DOT,
OP_RPAREN,
OP_RBRACK,
OP_RBRACE,
OP_SEMICOLON,
OP_COLON,
};
struct Token {
explicit Token(TokenType t, llvm::StringRef text)
: m_type(t), m_value(text) {}
TokenType m_type;
llvm::StringRef m_value;
};
const Token &Lex();
size_t BytesRemaining() const { return m_end - m_src; }
llvm::StringRef GetString(int len) const {
return llvm::StringRef(m_src, len);
}
static TokenType LookupKeyword(llvm::StringRef id);
static llvm::StringRef LookupToken(TokenType t);
private:
bool IsDecimal(char c) { return c >= '0' && c <= '9'; }
bool IsHexChar(char c) {
if (c >= '0' && c <= '9')
return true;
if (c >= 'A' && c <= 'F')
return true;
if (c >= 'a' && c <= 'f')
return true;
return false;
}
bool IsLetterOrDigit(char c) {
if (c >= 'a' && c <= 'z')
return true;
if (c >= 'A' && c <= 'Z')
return true;
if (c == '_')
return true;
if (c >= '0' && c <= '9')
return true;
// Treat all non-ascii chars as letters for simplicity.
return 0 != (c & 0x80);
}
bool IsWhitespace(char c) {
switch (c) {
case ' ':
case '\t':
case '\r':
return true;
}
return false;
}
bool SkipWhitespace();
bool SkipComment();
TokenType InternalLex(bool newline);
TokenType DoOperator();
TokenType DoIdent();
TokenType DoNumber();
TokenType DoRune();
TokenType DoString();
static llvm::StringMap<TokenType> *InitKeywords();
static llvm::StringMap<TokenType> *m_keywords;
const char *m_src;
const char *m_end;
Token m_last_token;
};
} // namespace lldb_private
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,145 @@
//===-- GoParser.h -----------------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_GoParser_h
#define liblldb_GoParser_h
#include "Plugins/ExpressionParser/Go/GoAST.h"
#include "Plugins/ExpressionParser/Go/GoLexer.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
class GoParser {
public:
explicit GoParser(const char *src);
GoASTStmt *Statement();
GoASTStmt *GoStmt();
GoASTStmt *ReturnStmt();
GoASTStmt *BranchStmt();
GoASTStmt *EmptyStmt();
GoASTStmt *ExpressionStmt(GoASTExpr *e);
GoASTStmt *IncDecStmt(GoASTExpr *e);
GoASTStmt *Assignment(GoASTExpr *e);
GoASTBlockStmt *Block();
GoASTExpr *MoreExpressionList(); // ["," Expression]
GoASTIdent *MoreIdentifierList(); // ["," Identifier]
GoASTExpr *Expression();
GoASTExpr *UnaryExpr();
GoASTExpr *OrExpr();
GoASTExpr *AndExpr();
GoASTExpr *RelExpr();
GoASTExpr *AddExpr();
GoASTExpr *MulExpr();
GoASTExpr *PrimaryExpr();
GoASTExpr *Operand();
GoASTExpr *Conversion();
GoASTExpr *Selector(GoASTExpr *e);
GoASTExpr *IndexOrSlice(GoASTExpr *e);
GoASTExpr *TypeAssertion(GoASTExpr *e);
GoASTExpr *Arguments(GoASTExpr *e);
GoASTExpr *Type();
GoASTExpr *Type2();
GoASTExpr *ArrayOrSliceType(bool allowEllipsis);
GoASTExpr *StructType();
GoASTExpr *FunctionType();
GoASTExpr *InterfaceType();
GoASTExpr *MapType();
GoASTExpr *ChanType();
GoASTExpr *ChanType2();
GoASTExpr *Name();
GoASTExpr *QualifiedIdent(GoASTIdent *p);
GoASTIdent *Identifier();
GoASTField *FieldDecl();
GoASTExpr *AnonymousFieldType();
GoASTExpr *FieldNamesAndType(GoASTField *f);
GoASTFieldList *Params();
GoASTField *ParamDecl();
GoASTExpr *ParamType();
GoASTFuncType *Signature();
GoASTExpr *CompositeLit();
GoASTExpr *FunctionLit();
GoASTExpr *Element();
GoASTCompositeLit *LiteralValue();
bool Failed() const { return m_failed; }
bool AtEOF() const {
return m_lexer.BytesRemaining() == 0 && m_pos == m_tokens.size();
}
void GetError(Status &error);
private:
class Rule;
friend class Rule;
std::nullptr_t syntaxerror() {
m_failed = true;
return nullptr;
}
GoLexer::Token &next() {
if (m_pos >= m_tokens.size()) {
if (m_pos != 0 && (m_tokens.back().m_type == GoLexer::TOK_EOF ||
m_tokens.back().m_type == GoLexer::TOK_INVALID))
return m_tokens.back();
m_pos = m_tokens.size();
m_tokens.push_back(m_lexer.Lex());
}
return m_tokens[m_pos++];
}
GoLexer::TokenType peek() {
GoLexer::Token &tok = next();
--m_pos;
return tok.m_type;
}
GoLexer::Token *match(GoLexer::TokenType t) {
GoLexer::Token &tok = next();
if (tok.m_type == t)
return &tok;
--m_pos;
m_last_tok = t;
return nullptr;
}
GoLexer::Token *mustMatch(GoLexer::TokenType t) {
GoLexer::Token *tok = match(t);
if (tok)
return tok;
return syntaxerror();
}
bool Semicolon();
GoASTStmt *FinishStmt(GoASTStmt *s) {
if (!Semicolon())
m_failed = true;
return s;
}
llvm::StringRef CopyString(llvm::StringRef s);
GoLexer m_lexer;
std::vector<GoLexer::Token> m_tokens;
size_t m_pos;
llvm::StringRef m_error;
llvm::StringRef m_last;
GoLexer::TokenType m_last_tok;
llvm::StringMap<uint8_t> m_strings;
bool m_failed;
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
//===-- GoUserExpression.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_GoUserExpression_h_
#define liblldb_GoUserExpression_h_
// C Includes
// C++ Includes
#include <memory>
// Other libraries and framework includes
// Project includes
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
class GoParser;
class GoPersistentExpressionState : public PersistentExpressionState {
public:
GoPersistentExpressionState();
ConstString GetNextPersistentVariableName() override;
void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
lldb::addr_t LookupSymbol(const ConstString &name) override {
return LLDB_INVALID_ADDRESS;
}
static bool classof(const PersistentExpressionState *pv) {
return pv->getKind() == PersistentExpressionState::eKindGo;
}
private:
uint32_t m_next_persistent_variable_id; ///< The counter used by
///GetNextResultName().
};
//----------------------------------------------------------------------
/// @class GoUserExpression GoUserExpression.h
/// "lldb/Expression/GoUserExpression.h"
/// @brief Encapsulates a single expression for use with Go
///
/// LLDB uses expressions for various purposes, notably to call functions
/// and as a backend for the expr command. GoUserExpression encapsulates
/// the objects needed to parse and interpret an expression.
//----------------------------------------------------------------------
class GoUserExpression : public UserExpression {
public:
GoUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
llvm::StringRef prefix, lldb::LanguageType language,
ResultType desired_type,
const EvaluateExpressionOptions &options);
bool Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory, bool generate_debug_info) override;
bool CanInterpret() override { return true; }
bool FinalizeJITExecution(
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
lldb::ExpressionVariableSP &result,
lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override {
return true;
}
protected:
lldb::ExpressionResults
DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
const EvaluateExpressionOptions &options,
lldb::UserExpressionSP &shared_ptr_to_me,
lldb::ExpressionVariableSP &result) override;
private:
class GoInterpreter;
std::unique_ptr<GoInterpreter> m_interpreter;
};
} // namespace lldb_private
#endif // liblldb_GoUserExpression_h_

View File

@ -0,0 +1,464 @@
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
"""