diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-06-03 02:36:05 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-06-03 02:36:05 +0800 |
| commit | 2d6ab4b7f207a746a7caaa93466b410cbe328626 (patch) | |
| tree | 570a2d7776e616309149adf065acc474c0c0de98 | |
| parent | cd1466f30c146e12faa0db7e1b53b508bf2274c6 (diff) | |
support for short, int64 and AST dump
| -rw-r--r-- | .clang-format | 2 | ||||
| -rw-r--r-- | CMakeLists.txt | 6 | ||||
| -rw-r--r-- | Lexer.l | 1 | ||||
| -rw-r--r-- | Parser.y | 5 | ||||
| -rw-r--r-- | Type.cc | 42 | ||||
| -rw-r--r-- | Type.hh | 9 | ||||
| -rw-r--r-- | TypeIdentifier.cc | 17 | ||||
| -rw-r--r-- | TypeManager.cc | 31 | ||||
| -rw-r--r-- | TypeManager.hh | 2 | ||||
| -rw-r--r-- | Version.cc | 26 | ||||
| -rw-r--r-- | main.cc | 13 | ||||
| -rw-r--r-- | node/BaseNode.hh | 3 | ||||
| -rw-r--r-- | node/DeclNode.cc | 4 | ||||
| -rw-r--r-- | node/DeclNode.hh | 3 | ||||
| -rw-r--r-- | node/ExprNode.cc | 12 | ||||
| -rw-r--r-- | node/ExprNode.hh | 13 | ||||
| -rw-r--r-- | node/FunctionNode.cc | 11 | ||||
| -rw-r--r-- | node/FunctionNode.hh | 2 | ||||
| -rw-r--r-- | node/LiteralNode.cc | 12 | ||||
| -rw-r--r-- | node/LiteralNode.hh | 5 | ||||
| -rw-r--r-- | node/Node.cc | 506 | ||||
| -rw-r--r-- | node/StatementNode.hh | 11 | ||||
| -rw-r--r-- | t/extern.pas | 4 | ||||
| -rw-r--r-- | t/ssl.pas | 83 | ||||
| -rw-r--r-- | traveler/AsciiTraveler.cc | 62 | ||||
| -rw-r--r-- | traveler/AsciiTraveler.hh | 28 | ||||
| -rw-r--r-- | traveler/Traveler.cc | 6 | ||||
| -rw-r--r-- | traveler/Traveler.hh | 40 |
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) @@ -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);} @@ -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]================== */ @@ -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(); }); @@ -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 { @@ -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); } @@ -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 |
