summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-06-03 02:36:05 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-06-03 02:36:05 +0800
commit2d6ab4b7f207a746a7caaa93466b410cbe328626 (patch)
tree570a2d7776e616309149adf065acc474c0c0de98
parentcd1466f30c146e12faa0db7e1b53b508bf2274c6 (diff)
support for short, int64 and AST dump
-rw-r--r--.clang-format2
-rw-r--r--CMakeLists.txt6
-rw-r--r--Lexer.l1
-rw-r--r--Parser.y5
-rw-r--r--Type.cc42
-rw-r--r--Type.hh9
-rw-r--r--TypeIdentifier.cc17
-rw-r--r--TypeManager.cc31
-rw-r--r--TypeManager.hh2
-rw-r--r--Version.cc26
-rw-r--r--main.cc13
-rw-r--r--node/BaseNode.hh3
-rw-r--r--node/DeclNode.cc4
-rw-r--r--node/DeclNode.hh3
-rw-r--r--node/ExprNode.cc12
-rw-r--r--node/ExprNode.hh13
-rw-r--r--node/FunctionNode.cc11
-rw-r--r--node/FunctionNode.hh2
-rw-r--r--node/LiteralNode.cc12
-rw-r--r--node/LiteralNode.hh5
-rw-r--r--node/Node.cc506
-rw-r--r--node/StatementNode.hh11
-rw-r--r--t/extern.pas4
-rw-r--r--t/ssl.pas83
-rw-r--r--traveler/AsciiTraveler.cc62
-rw-r--r--traveler/AsciiTraveler.hh28
-rw-r--r--traveler/Traveler.cc6
-rw-r--r--traveler/Traveler.hh40
28 files changed, 896 insertions, 63 deletions
diff --git a/.clang-format b/.clang-format
index 497ab0b..a602d70 100644
--- a/.clang-format
+++ b/.clang-format
@@ -34,3 +34,5 @@ SpaceAfterCStyleCast: true
#tab键盘的宽度
TabWidth: 4
UseTab: Never
+#在模板参数声明后换行
+AlwaysBreakTemplateDeclarations: true
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f1dbd46..902869a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,11 +24,17 @@ list(APPEND PCC_SOURCE
node/ExprNode.cc
node/FunctionNode.cc
node/LiteralNode.cc
+ node/Node.cc
node/StatementNode.cc)
+list(APPEND PCC_SOURCE
+ traveler/AsciiTraveler.cc
+ traveler/Traveler.cc)
+
set(PCC_INCLUDE
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/node
+ ${CMAKE_SOURCE_DIR}/traveler
${CMAKE_CURRENT_BINARY_DIR})
if(WIN32)
diff --git a/Lexer.l b/Lexer.l
index be168f3..c65d358 100644
--- a/Lexer.l
+++ b/Lexer.l
@@ -118,6 +118,7 @@ comment {comment1}|{comment2}|{comment3}
"void" {return Parser::make_VOID(loc);}
"boolean" {return Parser::make_BOOLEAN(loc);}
"char" {return Parser::make_CHAR(loc);}
+"short" {return Parser::make_SHORT(loc);}
"integer" {return Parser::make_INTEGER(loc);}
"int64" {return Parser::make_INT64(loc);}
"real" {return Parser::make_REAL(loc);}
diff --git a/Parser.y b/Parser.y
index 429e88d..9f9a7b4 100644
--- a/Parser.y
+++ b/Parser.y
@@ -45,7 +45,7 @@ YY_DECL;
%token COLON SEMICOLON COMMA DOTDOT DOT ASSIGN LBRACKET RBRACKET LPARENTHESIS RPARENTHESIS
%token PROGRAM IDENTIFIER VAR CONST TYPE BEGINS ENDS FUNCTION EXTERN DOTDOTDOT
%token IF THEN ELSE WHILE DO REPEAT UNTIL BREAK CONTINUE FOR TO
-%token VOID BOOLEAN CHAR INTEGER INT64 REAL STRING ARRAY OF RECORD
+%token VOID BOOLEAN CHAR SHORT INTEGER INT64 REAL STRING ARRAY OF RECORD
%token ADD SUB MUL REAL_DIV DIV MOD LT LE GT GE EQ NE CARET AT
%token AND NOT OR XOR SHL SHR
%token INTEGER_LITERAL REAL_LITERAL STRING_LITERAL BOOLEAN_LITERAL CHAR_LITERAL
@@ -164,6 +164,7 @@ type
: VOID {$$=std::make_shared<TrivialTypeIdentifier>(ctx, ctx->GetTypeManager()->GetBuiltinType(pcc::BuiltinType::VOID));}
| BOOLEAN {$$=std::make_shared<TrivialTypeIdentifier>(ctx, ctx->GetTypeManager()->GetBuiltinType(pcc::BuiltinType::BOOLEAN));}
| CHAR {$$=std::make_shared<TrivialTypeIdentifier>(ctx, ctx->GetTypeManager()->GetBuiltinType(pcc::BuiltinType::CHAR));}
+ | SHORT {$$=std::make_shared<TrivialTypeIdentifier>(ctx, ctx->GetTypeManager()->GetBuiltinType(pcc::BuiltinType::SHORT));}
| INTEGER {$$=std::make_shared<TrivialTypeIdentifier>(ctx, ctx->GetTypeManager()->GetBuiltinType(pcc::BuiltinType::INTEGER));}
| INT64 {$$=std::make_shared<TrivialTypeIdentifier>(ctx, ctx->GetTypeManager()->GetBuiltinType(pcc::BuiltinType::INT64));}
| REAL {$$=std::make_shared<TrivialTypeIdentifier>(ctx, ctx->GetTypeManager()->GetBuiltinType(pcc::BuiltinType::REAL));}
@@ -198,7 +199,7 @@ function
| FUNCTION IDENTIFIER LPARENTHESIS RPARENTHESIS COLON type SEMICOLON decls statement_block {$$=std::make_shared<pcc::FunctionNode>(ctx, std::move($2), std::list<Declaration>(), std::move($8), $6, $9);}
| EXTERN IDENTIFIER LPARENTHESIS var_decls RPARENTHESIS COLON type {$$=std::make_shared<pcc::ExternNode>(ctx, std::move($2), std::move($4), $7, false);}
| EXTERN IDENTIFIER LPARENTHESIS RPARENTHESIS COLON type {$$=std::make_shared<pcc::ExternNode>(ctx, std::move($2), std::list<Declaration>(), $6, false);}
- | EXTERN IDENTIFIER LPARENTHESIS var_decls COMMA DOTDOTDOT RPARENTHESIS COLON type {$$=std::make_shared<pcc::ExternNode>(ctx, std::move($2), std::move($4), $9, true);}
+ | EXTERN IDENTIFIER LPARENTHESIS var_decls SEMICOLON DOTDOTDOT RPARENTHESIS COLON type {$$=std::make_shared<pcc::ExternNode>(ctx, std::move($2), std::move($4), $9, true);}
;
/* ==================[statements part]================== */
diff --git a/Type.cc b/Type.cc
index 69196b9..0a03525 100644
--- a/Type.cc
+++ b/Type.cc
@@ -1,3 +1,5 @@
+#include <iterator>
+
#include <llvm/IR/InstrTypes.h>
#include "Context.hh"
@@ -6,9 +8,9 @@
namespace pcc {
const char* GetOperatorName(BinaryOperator op) {
- static const char* names[ToUnderlying(BinaryOperator::BINARYOP_NUMBER)] = {
- "+", "-", "*", "/", "%", "<", "<=", ">",
- ">=", "=", "<>", "and", "or", "xor", "shl", "shr"};
+ static const char* names[] = {"+", "-", "*", "/", "%", "<",
+ "<=", ">", ">=", "=", "<>", "and",
+ "or", "xor", "shl", "shr", "", "div"};
return names[ToUnderlying(op)];
}
@@ -226,6 +228,30 @@ Value CharType::CreateUnaryOperation(UnaryOperator op, Value v,
return (this->*operations[ToUnderlying(op)])(v, context);
}
+ShortType::ShortType()
+ : IntegerBaseType("short", 16, llvm::Type::getInt16Ty(GlobalLLVMContext)) {}
+
+Value ShortType::CreateBinaryOperation(BinaryOperator op, Value v0, Value v1,
+ Context* context) {
+ static Value (pcc::ShortType::*operations[ToUnderlying(
+ BinaryOperator::BINARYOP_NUMBER)])(Value, Value, Context*) = {
+ &ShortType::CreateAdd, &ShortType::CreateSub, &ShortType::CreateMul,
+ &ShortType::CreateDiv, &ShortType::CreateMod, &ShortType::CreateLt,
+ &ShortType::CreateLe, &ShortType::CreateGt, &ShortType::CreateGe,
+ &ShortType::CreateEq, &ShortType::CreateNe, &ShortType::CreateAnd,
+ &ShortType::CreateOr, &ShortType::CreateXor, &ShortType::CreateShl,
+ &ShortType::CreateShr};
+ return (this->*operations[ToUnderlying(op)])(v0, v1, context);
+}
+
+Value ShortType::CreateUnaryOperation(UnaryOperator op, Value v,
+ Context* context) {
+ static Value (pcc::ShortType::*operations[ToUnderlying(
+ UnaryOperator::UNARYOP_NUMEBR)])(Value, Context*) = {
+ &ShortType::CreatePos, &ShortType::CreateNeg, &ShortType::CreateNot};
+ return (this->*operations[ToUnderlying(op)])(v, context);
+}
+
IntegerType::IntegerType()
: IntegerBaseType("integer", 32,
llvm::Type::getInt32Ty(GlobalLLVMContext)) {}
@@ -363,9 +389,10 @@ FunctionType::FunctionType(std::shared_ptr<Type> ReturnType,
, ReturnType_(ReturnType)
, ArgTypes_(ArgTypes)
, IsVariadic_(IsVariadic) {
- std::vector<llvm::Type*> params(ArgTypes_.size());
+ std::vector<llvm::Type*> params;
+ params.reserve(ArgTypes_.size());
std::transform(
- ArgTypes_.cbegin(), ArgTypes_.cend(), params.begin(),
+ ArgTypes_.cbegin(), ArgTypes_.cend(), std::back_inserter(params),
[](std::shared_ptr<Type> decl) { return decl->GetLLVMType(); });
LLVMType_ = llvm::FunctionType::get(ReturnType_->GetLLVMType(), params,
IsVariadic_);
@@ -386,9 +413,10 @@ RecordType::RecordType(const std::vector<RecordMember>& members,
for (auto&& member : members) {
members_.insert({std::get<0>(member), {i++, std::get<1>(member)}});
}
- std::vector<llvm::Type*> MemberTypes(members.size());
+ std::vector<llvm::Type*> MemberTypes;
+ MemberTypes.reserve(members.size());
std::transform(
- members.cbegin(), members.cend(), MemberTypes.begin(),
+ members.cbegin(), members.cend(), std::back_inserter(MemberTypes),
[](const std::pair<std::string, std::shared_ptr<Type>>& member) {
return std::get<1>(member)->GetLLVMType();
});
diff --git a/Type.hh b/Type.hh
index b3779d4..6233c1f 100644
--- a/Type.hh
+++ b/Type.hh
@@ -132,6 +132,15 @@ class CharType : public IntegerBaseType {
Context* context) override;
};
+class ShortType : public IntegerBaseType {
+ public:
+ ShortType();
+ virtual Value CreateBinaryOperation(BinaryOperator op, Value v0, Value v1,
+ Context* context) override;
+ virtual Value CreateUnaryOperation(UnaryOperator op, Value v,
+ Context* context) override;
+};
+
class IntegerType : public IntegerBaseType {
public:
IntegerType();
diff --git a/TypeIdentifier.cc b/TypeIdentifier.cc
index 3a249da..98daa2f 100644
--- a/TypeIdentifier.cc
+++ b/TypeIdentifier.cc
@@ -56,19 +56,20 @@ std::shared_ptr<Type> ArrayTypeIdentifier::GetType() {
}
RecordTypeIdentifier::RecordTypeIdentifier(Context* context,
- std::list<Declaration>&& members)
+ std::list<Declaration>&& members)
: TypeIdentifier(context)
, members_(std::move(members)) {}
std::shared_ptr<Type> RecordTypeIdentifier::GetType() {
if (type_ == nullptr) {
- std::vector<RecordMember> MemberTypes(members_.size());
- std::transform(members_.cbegin(), members_.cend(), MemberTypes.begin(),
- [](const Declaration& member) {
- return std::make_pair(
- std::get<0>(member),
- std::get<1>(member)->GetType());
- });
+ std::vector<RecordMember> MemberTypes;
+ MemberTypes.reserve(members_.size());
+ std::transform(
+ members_.cbegin(), members_.cend(), std::back_inserter(MemberTypes),
+ [](const Declaration& member) {
+ return std::make_pair(std::get<0>(member),
+ std::get<1>(member)->GetType());
+ });
type_ = context_->GetTypeManager()->CreateRecordType(MemberTypes);
}
return type_;
diff --git a/TypeManager.cc b/TypeManager.cc
index 0cfbe75..f866660 100644
--- a/TypeManager.cc
+++ b/TypeManager.cc
@@ -5,9 +5,11 @@
namespace pcc {
TypeManager::TypeManager()
- : builtins_{std::make_shared<VoidType>(), std::make_shared<BooleanType>(),
- std::make_shared<CharType>(), std::make_shared<IntegerType>(),
- std::make_shared<Int64Type>(), std::make_shared<RealType>()} {
+ : builtins_{
+ std::make_shared<VoidType>(), std::make_shared<BooleanType>(),
+ std::make_shared<CharType>(), std::make_shared<ShortType>(),
+ std::make_shared<IntegerType>(), std::make_shared<Int64Type>(),
+ std::make_shared<RealType>()} {
PointerIndexType_ = GetBuiltinType(BuiltinType::INT64);
PointerDifferenceType_ = GetBuiltinType(BuiltinType::INT64);
// llvm seems doesn't support GEP with i64 index type on records
@@ -15,11 +17,11 @@ TypeManager::TypeManager()
builtins_.push_back(
GetPointerType(GetBuiltinType(BuiltinType::CHAR), "string"));
// llvm doesn't have void* type, we use char* instead
- PointerTypes_.emplace(
- GetBuiltinType(BuiltinType::VOID),
- std::make_shared<PointerType>(GetBuiltinType(BuiltinType::CHAR),
- PointerDifferenceType_, PointerIndexType_,
- "^void"));
+ std::shared_ptr<PointerType> VoidPtr = std::make_shared<PointerType>(
+ GetBuiltinType(BuiltinType::CHAR), PointerDifferenceType_,
+ PointerIndexType_, "^void");
+ builtins_.push_back(VoidPtr);
+ PointerTypes_.insert({GetBuiltinType(BuiltinType::VOID), VoidPtr});
}
std::shared_ptr<Type> TypeManager::GetBuiltinType(BuiltinType type) {
@@ -164,17 +166,22 @@ Value TypeManager::CreateCast(std::shared_ptr<Type> DstType,
}
}
- // array to pointer decay
std::shared_ptr<PointerType> SrcPointerType =
std::dynamic_pointer_cast<PointerType>(SrcType);
std::shared_ptr<PointerType> DstPointerType =
std::dynamic_pointer_cast<PointerType>(DstType);
if (SrcPointerType != nullptr && DstPointerType != nullptr) {
+ // pointer cast between void* and others
+ std::shared_ptr<Type> VoidPtr = GetBuiltinType(BuiltinType::VOIDPTR);
+ if (SrcPointerType == VoidPtr || DstPointerType == VoidPtr) {
+ return builder->CreatePointerCast(v, DstType->GetLLVMType());
+ }
+ // array to pointer decay
std::shared_ptr<ArrayType> SrcInnerType =
std::dynamic_pointer_cast<ArrayType>(
SrcPointerType->GetElementType());
- if (SrcInnerType->GetElementType() ==
- DstPointerType->GetElementType()) {
+ if (SrcInnerType != nullptr && SrcInnerType->GetElementType() ==
+ DstPointerType->GetElementType()) {
Value zero =
llvm::ConstantInt::get(PointerIndexType_->GetLLVMType(), 0);
Value indices[2] = {zero, zero};
@@ -252,7 +259,7 @@ std::shared_ptr<FunctionType>
std::vector<std::shared_ptr<Type>> ArgTypes,
bool IsVariadic) {
decltype(ArgTypes)::const_iterator ArgIt = ArgTypes.cbegin();
- std::string name = " (*)(";
+ std::string name = "(*)(";
if (!ArgTypes.empty()) {
name.append((*ArgIt)->GetCommonName());
for (++ArgIt; ArgIt != ArgTypes.cend(); ++ArgIt) {
diff --git a/TypeManager.hh b/TypeManager.hh
index ce54dcb..e9da94b 100644
--- a/TypeManager.hh
+++ b/TypeManager.hh
@@ -15,10 +15,12 @@ enum class BuiltinType {
VOID,
BOOLEAN,
CHAR,
+ SHORT,
INTEGER,
INT64,
REAL,
STRING,
+ VOIDPTR,
BUILTIN_NUMBER
};
class TypeManager {
diff --git a/Version.cc b/Version.cc
index 9fd924d..bb0007d 100644
--- a/Version.cc
+++ b/Version.cc
@@ -27,17 +27,21 @@ PCC_NORETURN void ShowVersion() {
PCC_NORETURN void ShowHelp() {
std::cerr << PCC_NAME " version " PCC_VERSION_STRING "\n"
<< "Usage: " << GetExecutableName()
- << " [-vVhiSc] [-O <0,1,2,3>] [-o <output>] file...\n"
- << " -v Verbose mode.\n"
- << " -vv Very verbose mode.\n"
- << " -V Show version and exit.\n"
- << " -h Show this help and exit.\n"
- << "\n"
- << " -i Generate LLVM IR (default behavior).\n"
- << " -S Compile to assembly file.\n"
- << " -c Compile to object file.\n"
- << " -o <output> Specify output file name.\n"
- << " -O <0,1,2,3> Specify optimization level." << std::endl;
+ << " [-vVhiSc] [-O <0,1,2,3>] [-o <output>] "
+ "file...\n"
+ " -v Verbose mode.\n"
+ " -vv Very verbose mode.\n"
+ " -V Show version and exit.\n"
+ " -h Show this help and exit.\n"
+ "\n"
+ " -i Generate LLVM IR (default behavior).\n"
+ " -S Compile to assembly file.\n"
+ " -c Compile to object file.\n"
+ " -o <output> Specify output file name.\n"
+ " -O <0,1,2,3> Specify optimization level.\n"
+ "\n"
+ " -a Also dump the AST."
+ << std::endl;
std::exit(0);
}
diff --git a/main.cc b/main.cc
index 54255bf..e208820 100644
--- a/main.cc
+++ b/main.cc
@@ -12,6 +12,7 @@
#include <llvm/Support/TargetSelect.h>
#include <llvm/Target/TargetMachine.h>
+#include "AsciiTraveler.hh"
#include "Driver.hh"
#include "Log.hh"
#include "Version.hh"
@@ -25,9 +26,10 @@ int main(int argc, char* argv[]) {
std::string OutputFileName;
enum { IR, ASSEMBLY, OBJECT } CompileType = IR;
int OptLevel = 2;
+ bool AsciiTravel = false;
pcc::SetExecutableName(argv[0]);
- while ((rv = getopt(argc, argv, "vVhiSco:O:")) != -1) {
+ while ((rv = getopt(argc, argv, "vVhiScao:O:")) != -1) {
switch (rv) {
case 'v':
level = (level == 0 ? 0 : level - 1);
@@ -45,6 +47,9 @@ int main(int argc, char* argv[]) {
case 'c':
CompileType = OBJECT;
break;
+ case 'a':
+ AsciiTravel = true;
+ break;
case 'o':
OutputFileName = optarg;
break;
@@ -144,6 +149,12 @@ int main(int argc, char* argv[]) {
pcc::Log(pcc::PCC_INFO, "%s compiled to %s", argv[i],
OutputFileName.c_str());
OutputFileName.clear();
+ if (AsciiTravel == true) {
+ pcc::Log(pcc::PCC_INFO, "dumping abstract syntax tree of %s",
+ argv[i]);
+ pcc::AsciiTraveler traveler(std::cerr);
+ root->Travel(traveler);
+ }
}
return 0;
}
diff --git a/node/BaseNode.hh b/node/BaseNode.hh
index 22ab93a..8916ef1 100644
--- a/node/BaseNode.hh
+++ b/node/BaseNode.hh
@@ -4,12 +4,14 @@
#include <list>
#include "Context.hh"
+#include "Traveler.hh"
namespace pcc {
class BaseNode {
public:
BaseNode(Context* context);
virtual Value CodeGen() = 0;
+ virtual int Travel(Traveler& traveler) = 0;
protected:
Context* context_;
@@ -24,6 +26,7 @@ class ProgramNode : public BaseNode {
std::list<std::shared_ptr<DeclNode>>&& GlobalDeclarations,
std::list<std::shared_ptr<FunctionNode>>&& functions);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::string name_;
diff --git a/node/DeclNode.cc b/node/DeclNode.cc
index 4d2f8aa..d22c847 100644
--- a/node/DeclNode.cc
+++ b/node/DeclNode.cc
@@ -75,9 +75,9 @@ TypeDeclNode::TypeDeclNode(Context* context, VariableList* scope,
, decls_(std::move(decls)) {}
Value TypeDeclNode::CodeGen() {
- scope_ = (scope_ == nullptr ? context_->GetGlobals() : scope_);
+ VariableList* scope = (scope_ == nullptr ? context_->GetGlobals() : scope_);
for (auto&& decl : decls_) {
- scope_->AddTypeAlias(std::get<0>(decl), std::get<1>(decl)->GetType());
+ scope->AddTypeAlias(std::get<0>(decl), std::get<1>(decl)->GetType());
}
return nullptr;
}
diff --git a/node/DeclNode.hh b/node/DeclNode.hh
index 3858fc6..735ba4e 100644
--- a/node/DeclNode.hh
+++ b/node/DeclNode.hh
@@ -25,6 +25,7 @@ class VarDeclNode : public DeclNode {
VarDeclNode(Context* context, VariableList* scope,
std::list<Declaration>&& decls);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::list<Declaration> decls_;
@@ -38,6 +39,7 @@ class ConstDeclNode : public DeclNode {
ConstDeclNode(Context* context, VariableList* scope,
std::list<Constant>&& decls);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::list<Constant> decls_;
@@ -48,6 +50,7 @@ class TypeDeclNode : public DeclNode {
TypeDeclNode(Context* context, VariableList* scope,
std::list<Declaration>&& decls);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::list<Declaration> decls_;
diff --git a/node/ExprNode.cc b/node/ExprNode.cc
index c0a3f41..9610420 100644
--- a/node/ExprNode.cc
+++ b/node/ExprNode.cc
@@ -242,9 +242,9 @@ Value FunctionCallNode::CodeGen() {
args_.size());
return nullptr;
}
- std::vector<Value> ArgValues(args_.size());
+ std::vector<Value> ArgValues;
+ ArgValues.reserve(args_.size());
auto ArgIt = args_.begin();
- auto ArgValueIt = ArgValues.begin();
for (auto&& ArgType : ArgTypes) {
Value argv = (*ArgIt)->CodeGen();
Value ConvertedArgv =
@@ -255,12 +255,12 @@ Value FunctionCallNode::CodeGen() {
"of type %s needed",
type->GetCommonName(), ArgType->GetCommonName());
}
- *ArgValueIt = ConvertedArgv;
- ++ArgIt, ++ArgValueIt;
+ ArgValues.push_back(ConvertedArgv);
+ ++ArgIt;
}
while (ArgIt != args_.end()) {
- *ArgValueIt = (*ArgIt)->CodeGen();
- ++ArgIt, ++ArgValueIt;
+ ArgValues.push_back((*ArgIt)->CodeGen());
+ ++ArgIt;
}
type_ = type->GetReturnType();
return context_->GetBuilder()->CreateCall(std::get<1>(function), ArgValues);
diff --git a/node/ExprNode.hh b/node/ExprNode.hh
index aeb3ef8..291186c 100644
--- a/node/ExprNode.hh
+++ b/node/ExprNode.hh
@@ -22,7 +22,8 @@ class BinaryExprNode : public ExprNode {
BinaryExprNode(Context* context, BinaryOperator op,
std::shared_ptr<ExprNode> left,
std::shared_ptr<ExprNode> right);
- virtual Value CodeGen();
+ virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
BinaryOperator op_;
@@ -33,7 +34,8 @@ class UnaryExprNode : public ExprNode {
public:
UnaryExprNode(Context* context, UnaryOperator op,
std::shared_ptr<ExprNode> value);
- virtual Value CodeGen();
+ virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
UnaryOperator op_;
@@ -55,6 +57,7 @@ class L2RCastingNode : public ExprNode {
public:
L2RCastingNode(Context* context, std::shared_ptr<ExprNode> lvalue);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> lvalue_;
@@ -66,6 +69,7 @@ class PointerAccessNode : public ExprNode {
PointerAccessNode(Context* context, std::shared_ptr<ExprNode> lhs,
std::shared_ptr<ExprNode> rhs);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> lhs_;
@@ -78,6 +82,7 @@ class ArrayAccessNode : public ExprNode {
ArrayAccessNode(Context* context, std::shared_ptr<ExprNode> lhs,
std::shared_ptr<ExprNode> rhs);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> lhs_;
@@ -88,6 +93,7 @@ class DereferenceNode : public ExprNode {
public:
DereferenceNode(Context* context, std::shared_ptr<ExprNode> lhs);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> lhs_;
@@ -98,6 +104,7 @@ class MemberAccessNode : public ExprNode {
MemberAccessNode(Context* context, std::shared_ptr<ExprNode> lhs,
std::string&& rhs);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> lhs_;
@@ -108,6 +115,7 @@ class IdentifierNode : public ExprNode {
public:
IdentifierNode(Context* context, const std::string& name);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::string name_;
@@ -118,6 +126,7 @@ class FunctionCallNode : public ExprNode {
FunctionCallNode(Context* context, const std::string& name,
std::list<std::shared_ptr<ExprNode>>&& args);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::string name_;
diff --git a/node/FunctionNode.cc b/node/FunctionNode.cc
index 4fb5138..eaf2a0d 100644
--- a/node/FunctionNode.cc
+++ b/node/FunctionNode.cc
@@ -1,3 +1,4 @@
+#include <iterator>
#include <memory>
#include <vector>
@@ -31,9 +32,10 @@ Value FunctionNode::CodeGen() {
llvm::Module* module = context_->GetModule();
llvm::IRBuilder<>* builder = context_->GetBuilder();
TypeManager* manager = context_->GetTypeManager();
- std::vector<std::shared_ptr<Type>> params(arguments_.size());
+ std::vector<std::shared_ptr<Type>> params;
+ params.reserve(arguments_.size());
std::transform(
- arguments_.cbegin(), arguments_.cend(), params.begin(),
+ arguments_.cbegin(), arguments_.cend(), std::back_inserter(params),
[](const Declaration& decl) { return std::get<1>(decl)->GetType(); });
std::shared_ptr<Type> ReturnType = ReturnTypeIdentifier_->GetType();
std::shared_ptr<FunctionType> type =
@@ -104,9 +106,10 @@ Value ExternNode::CodeGen() {
llvm::Module* module = context_->GetModule();
llvm::IRBuilder<>* builder = context_->GetBuilder();
TypeManager* manager = context_->GetTypeManager();
- std::vector<std::shared_ptr<Type>> params(arguments_.size());
+ std::vector<std::shared_ptr<Type>> params;
+ params.reserve(arguments_.size());
std::transform(
- arguments_.cbegin(), arguments_.cend(), params.begin(),
+ arguments_.cbegin(), arguments_.cend(), std::back_inserter(params),
[](const Declaration& decl) { return std::get<1>(decl)->GetType(); });
std::shared_ptr<Type> ReturnType = ReturnTypeIdentifier_->GetType();
std::shared_ptr<FunctionType> type =
diff --git a/node/FunctionNode.hh b/node/FunctionNode.hh
index 6860c45..56a019b 100644
--- a/node/FunctionNode.hh
+++ b/node/FunctionNode.hh
@@ -16,6 +16,7 @@ class FunctionNode : public BaseNode {
std::shared_ptr<TypeIdentifier> ReturnTypeIdentifier,
std::shared_ptr<StatementListNode> body);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::string name_;
@@ -33,6 +34,7 @@ class ExternNode : public FunctionNode {
std::shared_ptr<TypeIdentifier> ReturnTypeIdentifier,
bool IsVariadic);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
bool IsVariadic_;
diff --git a/node/LiteralNode.cc b/node/LiteralNode.cc
index 43bddb6..2c5d6c6 100644
--- a/node/LiteralNode.cc
+++ b/node/LiteralNode.cc
@@ -5,7 +5,8 @@
#include "LiteralNode.hh"
namespace pcc {
-template <> Value BooleanLiteralNode::CodeGen() {
+template <>
+Value BooleanLiteralNode::CodeGen() {
if (value_ == true) {
return llvm::ConstantInt::getTrue(GlobalLLVMContext);
} else {
@@ -13,15 +14,18 @@ template <> Value BooleanLiteralNode::CodeGen() {
}
}
-template <> Value CharLiteralNode::CodeGen() {
+template <>
+Value CharLiteralNode::CodeGen() {
return llvm::ConstantInt::get(type_->GetLLVMType(), value_, true);
}
-template <> Value IntegerLiteralNode::CodeGen() {
+template <>
+Value IntegerLiteralNode::CodeGen() {
return llvm::ConstantInt::get(type_->GetLLVMType(), value_, true);
}
-template <> Value RealLiteralNode::CodeGen() {
+template <>
+Value RealLiteralNode::CodeGen() {
llvm::APFloat value(value_);
return llvm::ConstantFP::get(GlobalLLVMContext, value);
}
diff --git a/node/LiteralNode.hh b/node/LiteralNode.hh
index f93c171..3923334 100644
--- a/node/LiteralNode.hh
+++ b/node/LiteralNode.hh
@@ -7,10 +7,12 @@
#include "ExprNode.hh"
namespace pcc {
-template <typename T> class LiteralNode : public ExprNode {
+template <typename T>
+class LiteralNode : public ExprNode {
public:
LiteralNode(Context* context, std::shared_ptr<Type> type, T value);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
private:
T value_;
@@ -36,6 +38,7 @@ class StringLiteralNode : public ExprNode {
StringLiteralNode(Context* context, std::shared_ptr<Type> type,
std::vector<char> value);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
private:
std::vector<char> value_;
diff --git a/node/Node.cc b/node/Node.cc
new file mode 100644
index 0000000..d9eb806
--- /dev/null
+++ b/node/Node.cc
@@ -0,0 +1,506 @@
+#include <cctype>
+#include <type_traits>
+
+#include "Node.hh"
+#include "Type.hh"
+#include "TypeIdentifier.hh"
+
+namespace pcc {
+Traveler& Traveler::operator<<(std::shared_ptr<Type> type) {
+ out_ << type->GetCommonName();
+ return *this;
+}
+
+Traveler& Traveler::operator<<(std::shared_ptr<TypeIdentifier> identifier) {
+ return *this << identifier->GetType();
+}
+
+template <typename Lambda, typename Container>
+void NonterminalContainerTravel(Traveler& traveler, Lambda&& lambda,
+ Container&& childs) {
+ for (auto&& child : childs) {
+ traveler << TravelPart::CHILD_BEGIN;
+ std::forward<Lambda>(lambda)(traveler, child);
+ traveler << TravelPart::CHILD_END;
+ }
+}
+
+template <typename Lambda, typename Container>
+void TerminalContainerTravel(Traveler& traveler, Lambda&& lambda,
+ Container&& childs) {
+ if (childs.empty()) {
+ return;
+ }
+ auto LastOne = childs.end();
+ --LastOne;
+ for (auto child = childs.begin(); child != LastOne; ++child) {
+ traveler << TravelPart::CHILD_BEGIN;
+ std::forward<Lambda>(lambda)(traveler, *child);
+ traveler << TravelPart::CHILD_END;
+ }
+ traveler << TravelPart::LAST_CHILD_BEGIN;
+ std::forward<Lambda>(lambda)(traveler, *LastOne);
+ traveler << TravelPart::LAST_CHILD_END;
+}
+
+template <typename L0, typename C0, typename L1, typename C1>
+void MultipleContainerTravel(Traveler& traveler, L0&& ThisLambda, C0&& ThisOne,
+ L1&& LastLambda, C1&& LastOne) {
+ if (LastOne.empty()) {
+ TerminalContainerTravel(traveler, std::forward<L0>(ThisLambda),
+ std::forward<C0>(ThisOne));
+ return;
+ }
+ NonterminalContainerTravel(traveler, std::forward<L0>(ThisLambda),
+ std::forward<C0>(ThisOne));
+ TerminalContainerTravel(traveler, std::forward<L1>(LastLambda),
+ std::forward<C1>(LastOne));
+}
+
+int ProgramNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "ProgramNode" << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "program " + name_
+ << TravelPart::DESCRPTION_END;
+ MultipleContainerTravel(
+ traveler,
+ [](Traveler& traveler, auto&& decl) { decl->Travel(traveler); },
+ GlobalDeclarations_,
+ [](Traveler& traveler, auto&& decl) { decl->Travel(traveler); },
+ functions_);
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int VarDeclNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "VarDeclNode" << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << (scope_ == nullptr ? "global size=" : "local size=")
+ << decls_.size() << TravelPart::DESCRPTION_END;
+ TerminalContainerTravel(
+ traveler,
+ [](Traveler& traveler, Declaration& decl) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "Variable"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << "name=" << std::get<0>(decl)
+ << " type=" << (std::get<1>(decl)->GetType())
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ },
+ decls_);
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int ConstDeclNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "ConstDeclNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "const size=" << decls_.size()
+ << TravelPart::DESCRPTION_END;
+ TerminalContainerTravel(
+ traveler,
+ [](Traveler& traveler, Constant& decl) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "Constant"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << "name=" << std::get<0>(decl)
+ << " type=" << (std::get<1>(decl)->GetType())
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ },
+ decls_);
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int TypeDeclNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "TypeDeclNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << (scope_ == nullptr ? "global size=" : "local size=")
+ << decls_.size() << TravelPart::DESCRPTION_END;
+ TerminalContainerTravel(
+ traveler,
+ [](Traveler& traveler, Declaration& decl) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "TypeAlias"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << "name=" << std::get<0>(decl)
+ << " type=" << (std::get<1>(decl)->GetType())
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ },
+ decls_);
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int BinaryExprNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "BinaryExprNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "op='" << GetOperatorName(op_)
+ << "' ResultType=" << type_ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::CHILD_BEGIN;
+ left_->Travel(traveler);
+ traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN;
+ right_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int UnaryExprNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "UnaryExprNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "op='" << GetOperatorName(op_)
+ << " ResultType='" << type_ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::LAST_CHILD_BEGIN;
+ value_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int L2RCastingNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "L2RCastingNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "ResultType=" << type_
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::LAST_CHILD_BEGIN;
+ lvalue_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int PointerAccessNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "PointerAccessNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "ResultType=" << type_
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::CHILD_BEGIN;
+ lhs_->Travel(traveler);
+ traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN;
+ rhs_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int ArrayAccessNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "ArrayAccessNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "ResultType=" << type_
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::CHILD_BEGIN;
+ lhs_->Travel(traveler);
+ traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN;
+ rhs_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int DereferenceNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "DereferenceNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "ResultType=" << type_
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::LAST_CHILD_BEGIN;
+ lhs_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int MemberAccessNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "MemberAccessNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "MemberName=" << rhs_
+ << " ResultType=" << type_ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::LAST_CHILD_BEGIN;
+ lhs_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int IdentifierNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "IdentifierNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "lvalue name=" << name_
+ << " type=" << type_ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int FunctionCallNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "FunctionCallNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "FunctionName=" << name_
+ << " ResultType=" << type_ << TravelPart::DESCRPTION_END;
+ TerminalContainerTravel(
+ traveler, [](Traveler& traveler, auto&& arg) { arg->Travel(traveler); },
+ args_);
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int FunctionNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "FunctionNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "FunctionName=" << name_
+ << " ReturnType=" << ReturnTypeIdentifier_
+ << TravelPart::DESCRPTION_END;
+ NonterminalContainerTravel(
+ traveler,
+ [](Traveler& traveler, auto& arg) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "Argument"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << "name=" << std::get<0>(arg)
+ << " type=" << std::get<1>(arg)
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ },
+ arguments_);
+ NonterminalContainerTravel(
+ traveler,
+ [](Traveler& traveler, auto&& decl) { decl->Travel(traveler); },
+ LocalDeclarations_);
+ traveler << TravelPart::LAST_CHILD_BEGIN;
+ body_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int ExternNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "ExternNode" << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "FunctionName=" << name_
+ << " ReturnType=" << ReturnTypeIdentifier_
+ << (IsVariadic_ ? "Variadic" : "") << TravelPart::DESCRPTION_END;
+ TerminalContainerTravel(
+ traveler,
+ [](Traveler& traveler, auto& arg) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "Argument"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << "name=" << std::get<0>(arg)
+ << " type=" << std::get<1>(arg)
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ },
+ arguments_);
+ traveler << TravelPart::END;
+ return 0;
+}
+
+template <>
+int BooleanLiteralNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "BooleanLiteralNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << "value=" << (value_ == true ? "true" : "false")
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+template <>
+int CharLiteralNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "CharLiteralNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "value=0x" << std::hex
+ << (int) value_ << std::dec << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+template <>
+int IntegerLiteralNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "IntegerLiteralNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "value=" << value_
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+template <>
+int RealLiteralNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "RealLiteralNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "value=" << value_
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int StringLiteralNode::Travel(Traveler& traveler) {
+ const char HexChars[] = "0123456789abcdef";
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "StringLiteralNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "value=\'";
+ std::string escaped;
+ escaped.reserve(value_.size() * 2);
+ for (char c : value_) {
+ if (std::isprint(c)) {
+ escaped.push_back(c);
+ } else {
+ auto hex = {'\\', 'x', HexChars[c & 0xf], HexChars[(c >> 4) & 0xf]};
+ escaped.append(hex);
+ }
+ }
+ traveler << escaped << '\'' << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int StatementListNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "StatementListNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "size=" << childs_.size()
+ << TravelPart::DESCRPTION_END;
+ TerminalContainerTravel(
+ traveler,
+ [](Traveler& traveler, auto&& child) { child->Travel(traveler); },
+ childs_);
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int EmptyStatementNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "EmptyStatementNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "empty"
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int AssignStatementNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "AssignStatementNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "ValueType=" << rhs_->GetType()
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::CHILD_BEGIN;
+ lhs_->Travel(traveler);
+ traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN;
+ rhs_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int IfStatementNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "IfStatementNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << "HasElse=" << (ElsePart_ == nullptr ? "false" : "true")
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::CHILD_BEGIN;
+ expr_->Travel(traveler);
+ traveler << TravelPart::CHILD_END;
+ if (ElsePart_ == nullptr) {
+ traveler << TravelPart::LAST_CHILD_BEGIN;
+ ThenPart_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END;
+ } else {
+ traveler << TravelPart::CHILD_BEGIN;
+ ThenPart_->Travel(traveler);
+ traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN;
+ ElsePart_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END;
+ }
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int WhileStatementNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "WhileStatementNode"
+ << TravelPart::NAME_END << TravelPart::DESCRPTION_BEGIN
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::CHILD_BEGIN;
+ expr_->Travel(traveler);
+ traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN;
+ WhileBody_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int RepeatStatementNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "RepeatStatementNode"
+ << TravelPart::NAME_END << TravelPart::DESCRPTION_BEGIN
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::CHILD_BEGIN;
+ expr_->Travel(traveler);
+ traveler << TravelPart::CHILD_END << TravelPart::LAST_CHILD_BEGIN;
+ RepeatBody_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int ForStatementNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "ForStatementNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN
+ << "direction=" << (IsUpward_ ? "up" : "down")
+ << TravelPart::DESCRPTION_END;
+ auto childs = {variable_, start_, end_};
+ NonterminalContainerTravel(
+ traveler,
+ [](Traveler& traveler, auto&& child) { child->Travel(traveler); },
+ childs);
+ traveler << TravelPart::LAST_CHILD_BEGIN;
+ ForBody_->Travel(traveler);
+ traveler << TravelPart::LAST_CHILD_END << TravelPart::END;
+ return 0;
+}
+
+int BreakStatementNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "BreakStatementNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "break"
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+
+int ContinueStatementNode::Travel(Traveler& traveler) {
+ traveler << TravelPart::PREFIX;
+ traveler << TravelPart::NAME_BEGIN << "ContinueStatementNode"
+ << TravelPart::NAME_END;
+ traveler << TravelPart::DESCRPTION_BEGIN << "continue"
+ << TravelPart::DESCRPTION_END;
+ traveler << TravelPart::END;
+ return 0;
+}
+} // namespace pcc
diff --git a/node/StatementNode.hh b/node/StatementNode.hh
index fa8fbe4..b729001 100644
--- a/node/StatementNode.hh
+++ b/node/StatementNode.hh
@@ -11,7 +11,8 @@ class StatementListNode : public BaseNode {
public:
StatementListNode(Context* context);
void Append(std::shared_ptr<BaseNode> child);
- virtual Value CodeGen();
+ virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
private:
std::list<std::shared_ptr<BaseNode>> childs_;
@@ -21,6 +22,7 @@ class EmptyStatementNode : public BaseNode {
public:
EmptyStatementNode(Context* context);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
};
class AssignStatementNode : public BaseNode {
@@ -28,6 +30,7 @@ class AssignStatementNode : public BaseNode {
AssignStatementNode(Context* context, std::shared_ptr<ExprNode> lhs,
std::shared_ptr<ExprNode> rhs);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> lhs_;
@@ -40,6 +43,7 @@ class IfStatementNode : public BaseNode {
std::shared_ptr<BaseNode> ThenPart,
std::shared_ptr<BaseNode> ElsePart);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> expr_;
@@ -52,6 +56,7 @@ class WhileStatementNode : public BaseNode {
WhileStatementNode(Context* context, std::shared_ptr<ExprNode> expr,
std::shared_ptr<BaseNode> WhileBody);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> expr_;
@@ -63,6 +68,7 @@ class RepeatStatementNode : public BaseNode {
RepeatStatementNode(Context* context, std::shared_ptr<ExprNode> expr,
std::shared_ptr<BaseNode> RepeatBody);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> expr_;
@@ -76,6 +82,7 @@ class ForStatementNode : public BaseNode {
std::shared_ptr<ExprNode> end, bool IsUpward,
std::shared_ptr<BaseNode> ForBody);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
protected:
std::shared_ptr<ExprNode> variable_;
@@ -89,12 +96,14 @@ class BreakStatementNode : public BaseNode {
public:
BreakStatementNode(Context* context);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
};
class ContinueStatementNode : public BaseNode {
public:
ContinueStatementNode(Context* context);
virtual Value CodeGen() override;
+ virtual int Travel(Traveler& traveler) override;
};
} // namespace pcc
diff --git a/t/extern.pas b/t/extern.pas
index 92c0481..f5cf617 100644
--- a/t/extern.pas
+++ b/t/extern.pas
@@ -1,8 +1,8 @@
program hello_world;
extern Pascal_puts(s:string):integer;
-extern Pascal_printf(s:string, ...):integer;
-extern Pascal_scanf(s:string, ...):integer;
+extern Pascal_printf(s:string; ...):integer;
+extern Pascal_scanf(s:string; ...):integer;
function main():integer;
var
diff --git a/t/ssl.pas b/t/ssl.pas
new file mode 100644
index 0000000..22d4d79
--- /dev/null
+++ b/t/ssl.pas
@@ -0,0 +1,83 @@
+program ssl;
+
+type
+ hostent=record
+ h_name:^char;
+ h_aliases:^^char;
+ h_addrtype:integer;
+ h_length:integer;
+ h_addr_list:^^char
+ end;
+ sockaddr_in=record
+ sin_family:short;
+ sin_port:short;
+ sin_addr:array[0..3] of char;
+ sin_zero:array[0..7] of char
+ end;
+
+const
+ AF_INET=2;
+ SOCK_STREAM=1;
+ IPPROTO_TCP=6;
+
+extern memset(dst:^void; n:integer; size:int64):^void;
+extern memcpy(dst:^void; src:^void; size:int64):^void;
+extern sprintf(s:^char; fmt:^char; ...):integer;
+extern printf(fmt:^char; ...):int64;
+
+extern socket(domain:integer; socktype:integer; protocol:integer):integer;
+extern htons(port:short):short;
+extern gethostbyname(name:^char):^hostent;
+extern connect(s:integer; addr:^sockaddr_in; size:integer):integer;
+
+extern TLS_method():^void;
+extern SSL_CTX_new(meth:^void):^void;
+extern SSL_new(meth:^void):^void;
+extern SSL_set_fd(ssl:^void; fd:integer):integer;
+extern SSL_connect(ssl:^void):integer;
+extern SSL_write(ssl:^void; buf:^void; num:integer):integer;
+extern SSL_read(ssl:^void; buf:^void; num:integer):integer;
+extern SSL_shutdown(ssl:^void):integer;
+extern SSL_free(ssl:^void):void;
+extern SSL_CTX_free(ssl:^void):void;
+
+function main(argc:integer; argv:^^char):integer;
+var
+ s, len, size, thissize:integer;
+ ssl, ctx:^void;
+ host:^hostent;
+ addr:sockaddr_in;
+ buf:array[0..1023] of char;
+ p:^char;
+begin
+ s := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ memset(@addr, 0, 16);
+ addr.sin_family := AF_INET;
+ addr.sin_port := htons(443);
+ host := gethostbyname(argv[1]);
+ p := host^.h_addr_list[0];
+ memcpy(@addr.sin_addr, p, 4);
+ connect(s, @addr, 16);
+ ctx := SSL_CTX_new(TLS_method());
+ ssl := SSL_new(ctx);
+ SSL_set_fd(ssl, s);
+ SSL_connect(ssl);
+ len := sprintf(@buf, 'GET / HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n', argv[1]);
+ size := 0;
+ while len>0 do begin
+ thissize := SSL_write(ssl, @buf[size], len - size);
+ len := len - thissize;
+ size := size + thissize;
+ end;
+ while true do begin
+ size := SSL_read(ssl, @buf, 1023);
+ if size<=0 then break;
+ buf[size] := '\0';
+ printf('%s', @buf);
+ end;
+ SSL_shutdown(ssl);
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ main := 0;
+end;
+
diff --git a/traveler/AsciiTraveler.cc b/traveler/AsciiTraveler.cc
new file mode 100644
index 0000000..db4088d
--- /dev/null
+++ b/traveler/AsciiTraveler.cc
@@ -0,0 +1,62 @@
+#include "AsciiTraveler.hh"
+
+namespace pcc {
+const std::string AsciiTraveler::MiddleLevelPrefix_ = "|-";
+const std::string AsciiTraveler::LastLevelPrefix_ = "`-";
+const std::string AsciiTraveler::MiddleChildPrefix_ = "| ";
+const std::string AsciiTraveler::LastChildPrefix_ = " ";
+const size_t AsciiTraveler::LevelWidth_ =
+ AsciiTraveler::MiddleLevelPrefix_.size();
+
+AsciiTraveler::AsciiTraveler(std::ostream& out)
+ : Traveler(out)
+ , prefix_("")
+ , level_(0) {
+ IsLastChild_.push(true);
+}
+
+Traveler& AsciiTraveler::operator<<(TravelPart part) {
+ switch (part) {
+ case TravelPart::PREFIX:
+ out_ << prefix_
+ << (IsLastChild_.top() ? LastLevelPrefix_ : MiddleLevelPrefix_);
+ break;
+ case TravelPart::NAME_BEGIN:
+ out_ << '<';
+ break;
+ case TravelPart::NAME_END:
+ out_ << '>';
+ break;
+ break;
+ case TravelPart::DESCRPTION_BEGIN:
+ out_ << '<';
+ break;
+ case TravelPart::DESCRPTION_END:
+ out_ << ">\n";
+ break;
+ case TravelPart::CHILD_BEGIN:
+ prefix_.append(IsLastChild_.top() ? LastChildPrefix_
+ : MiddleChildPrefix_);
+ IsLastChild_.push(false);
+ ++level_;
+ break;
+ case TravelPart::LAST_CHILD_BEGIN:
+ prefix_.append(IsLastChild_.top() ? LastChildPrefix_
+ : MiddleChildPrefix_);
+ IsLastChild_.push(true);
+ ++level_;
+ break;
+ case TravelPart::CHILD_END:
+ case TravelPart::LAST_CHILD_END:
+ prefix_.erase(prefix_.size() - LevelWidth_);
+ IsLastChild_.pop();
+ --level_;
+ break;
+ case TravelPart::END:
+ break;
+ default:
+ break;
+ }
+ return *this;
+}
+} // namespace pcc
diff --git a/traveler/AsciiTraveler.hh b/traveler/AsciiTraveler.hh
new file mode 100644
index 0000000..11c39f0
--- /dev/null
+++ b/traveler/AsciiTraveler.hh
@@ -0,0 +1,28 @@
+#ifndef PCC_ASCIITRAVELER_HH
+#define PCC_ASCIITRAVELER_HH
+
+#include <stack>
+#include <string>
+
+#include "Traveler.hh"
+
+namespace pcc {
+class AsciiTraveler : public Traveler {
+ public:
+ AsciiTraveler(std::ostream& out);
+ virtual Traveler& operator<<(TravelPart part);
+
+ protected:
+ int level_;
+ std::string prefix_;
+ std::stack<bool> IsLastChild_;
+
+ static const std::string MiddleLevelPrefix_;
+ static const std::string LastLevelPrefix_;
+ static const std::string MiddleChildPrefix_;
+ static const std::string LastChildPrefix_;
+ static const size_t LevelWidth_;
+};
+} // namespace pcc
+
+#endif // !PCC_ASCIITRAVELER_HH
diff --git a/traveler/Traveler.cc b/traveler/Traveler.cc
new file mode 100644
index 0000000..e365b28
--- /dev/null
+++ b/traveler/Traveler.cc
@@ -0,0 +1,6 @@
+#include "Traveler.hh"
+
+namespace pcc {
+Traveler::Traveler(std::ostream& out)
+ : out_(out) {}
+} // namespace pcc
diff --git a/traveler/Traveler.hh b/traveler/Traveler.hh
new file mode 100644
index 0000000..09f8d0d
--- /dev/null
+++ b/traveler/Traveler.hh
@@ -0,0 +1,40 @@
+#ifndef PCC_TRAVELER_HH
+#define PCC_TRAVELER_HH
+
+#include <ostream>
+
+#include "Type.hh"
+#include "TypeIdentifier.hh"
+
+namespace pcc {
+enum class TravelPart {
+ PREFIX,
+ NAME_BEGIN,
+ NAME_END,
+ DESCRPTION_BEGIN,
+ DESCRPTION_END,
+ CHILD_BEGIN,
+ CHILD_END,
+ LAST_CHILD_BEGIN,
+ LAST_CHILD_END,
+ END
+};
+class Traveler {
+ public:
+ Traveler(std::ostream& out);
+ virtual Traveler& operator<<(TravelPart part) = 0;
+ Traveler& operator<<(std::shared_ptr<Type> type);
+ Traveler& operator<<(std::shared_ptr<TypeIdentifier> identifier);
+
+ template <typename T>
+ Traveler& operator<<(T value) {
+ out_ << value;
+ return *this;
+ }
+
+ protected:
+ std::ostream& out_;
+};
+} // namespace pcc
+
+#endif // !PCC_TRAVELER_HH