diff --git a/README.md b/README.md index bad2269..1b20bf8 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ hmmm - flex - bison +### Passes +- types (primitive literals) +- scope + # Flex and Bison stuff - hmmmm diff --git a/sayaka/.gitignore b/sayaka/.gitignore index fcd5b11..8f8c90e 100644 --- a/sayaka/.gitignore +++ b/sayaka/.gitignore @@ -4,3 +4,4 @@ lexer.cpp parser.h parser.cpp parser.log +*.pyc diff --git a/sayaka/Makefile b/sayaka/Makefile index e824fde..00f295d 100644 --- a/sayaka/Makefile +++ b/sayaka/Makefile @@ -3,13 +3,13 @@ CFLAGS = -g -std=c++11 -fexceptions EXECUTABLE = sayaka SRC_DIR = src BIN_DIR = bin -FILES = lexer.cpp parser.cpp main.cpp ntype.cpp node.cpp codegen.cpp codescope.cpp -SOURCES = $(FILES:%.cpp=$(SRC_DIR)/%.cpp) +SOURCES := $(wildcard $(SRC_DIR)/*.cpp) +SOURCES := $(filter-out $(SRC_DIR)/playground.cpp, $(SOURCES)) -lexer.cpp: $(SRC_DIR)/lexer.l +$(SRC_DIR)/lexer.cpp: $(SRC_DIR)/lexer.l cd $(SRC_DIR) && flex --outfile=lexer.cpp --header-file=lexer.h lexer.l -parser.cpp: $(SRC_DIR)/parser.y +$(SRC_DIR)/parser.cpp: $(SRC_DIR)/parser.y cd $(SRC_DIR) && bison --defines=parser.h --output=parser.cpp --verbose --report-file=parser.log parser.y build: $(SOURCES) @@ -20,9 +20,12 @@ prepare: clean: rm -rf $(BIN_DIR)/* - cd $(SRC_DIR) && rm -f lexer.cpp lexer.h parser.cpp parser.h + cd $(SRC_DIR) && rm -f lexer.cpp lexer.h parser.cpp parser.h parser.log playground: $(CC) $(SRC_DIR)/playground.cpp -o $(BIN_DIR)/playground.o -all: prepare clean lexer.cpp parser.cpp build +all: prepare clean build + +debug: all + gdb $(BIN_DIR)/$(EXECUTABLE) diff --git a/sayaka/src/ast_node.cpp b/sayaka/src/ast_node.cpp new file mode 100644 index 0000000..7fd1244 --- /dev/null +++ b/sayaka/src/ast_node.cpp @@ -0,0 +1,5 @@ +#include "ast_node.h" + +ASTNode::~ASTNode() { + return; +} diff --git a/sayaka/src/ast_node.h b/sayaka/src/ast_node.h new file mode 100644 index 0000000..56158bb --- /dev/null +++ b/sayaka/src/ast_node.h @@ -0,0 +1,18 @@ +#ifndef __AST_NODE_H_ +#define __AST_NODE_H_ + +#include +#include +#include "ast_type.h" +#include "codegen.h" + +class ASTNode { +public: + ASTType* type; + llvm::Value* value; + + virtual ~ASTNode() = 0; + virtual llvm::Value* gen_code(CodeGen*) = 0; +}; + +#endif /* __AST_NODE_H_ */ diff --git a/sayaka/src/ast_node_assignment.cpp b/sayaka/src/ast_node_assignment.cpp new file mode 100644 index 0000000..dc7ea5e --- /dev/null +++ b/sayaka/src/ast_node_assignment.cpp @@ -0,0 +1,29 @@ +#include "ast_node_assignment.h" + +#include + +ASTNodeAssignment::ASTNodeAssignment(ASTNodeIdentifier* lhs, ASTNode* rhs) { + this->lhs = lhs; + this->rhs = rhs; + this->type = lhs->type; +} + +ASTNodeAssignment::~ASTNodeAssignment() { + delete this->lhs; + delete this->rhs; +} + +llvm::Value* ASTNodeAssignment::gen_code(CodeGen* code_gen) { + std::cout << "Generating assignment to " << this->lhs->name << "..." << std::endl; + ASTNode* val = code_gen->scope.get(this->lhs->name); + if (val == NULL) { + std::cout << "Undeclared variable " << this->lhs->name << std::endl; + return NULL; + } + this->type = val->type; + this->rhs->type = val->type; + llvm::Value* rhs_val = this->rhs->gen_code(code_gen); + code_gen->builder.SetInsertPoint(code_gen->current_block()); + code_gen->builder.CreateStore(rhs_val, val->value, false); + return rhs_val; +} diff --git a/sayaka/src/ast_node_assignment.h b/sayaka/src/ast_node_assignment.h new file mode 100644 index 0000000..ffa76a0 --- /dev/null +++ b/sayaka/src/ast_node_assignment.h @@ -0,0 +1,18 @@ +#ifndef __AST_NODE_ASSIGNMENT_H_ +#define __AST_NODE_ASSIGNMENT_H_ + +#include "ast_node.h" +#include "ast_node_identifier.h" + +class ASTNodeAssignment : public ASTNode { +public: + ASTNodeIdentifier* lhs; + ASTNode* rhs; + + ASTNodeAssignment(ASTNodeIdentifier*, ASTNode*); + + virtual llvm::Value* gen_code(CodeGen*) override; + virtual ~ASTNodeAssignment(); +}; + +#endif /* __AST_NODE_ASSIGNMENT_H_ */ diff --git a/sayaka/src/ast_node_binaryoperator.cpp b/sayaka/src/ast_node_binaryoperator.cpp new file mode 100644 index 0000000..5cb9d97 --- /dev/null +++ b/sayaka/src/ast_node_binaryoperator.cpp @@ -0,0 +1,37 @@ +#include "ast_node_binaryoperator.h" + +#include + +ASTNodeBinaryOperator::ASTNodeBinaryOperator(EBinaryOperationType op, ASTNode* lhs, ASTNode* rhs) { + this->op = op; + this->lhs = lhs; + this->rhs = rhs; +} + +ASTNodeBinaryOperator::~ASTNodeBinaryOperator() { + delete this->lhs; + delete this->rhs; +} + +llvm::Value* ASTNodeBinaryOperator::gen_code(CodeGen* code_gen) { + std::cout << "Generating binary operator..." << std::endl; + this->lhs->type = this->type; + this->rhs->type = this->type; + llvm::Value* l = this->lhs->gen_code(code_gen); + llvm::Value* r = this->rhs->gen_code(code_gen); + if (this->lhs->type->is_primitive() && this->rhs->type->is_primitive()) { + switch (this->op) { + case eADD: + return code_gen->builder.CreateAdd(l, r, "addtmp"); + case eSUBTRACT: + return code_gen->builder.CreateSub(l, r, "subtmp"); + case eMULTIPLY: + return code_gen->builder.CreateMul(l, r, "multmp"); + case eDIVIDE: + return code_gen->builder.CreateSDiv(l, r, "divtmp"); + case ePOW: + return code_gen->builder.CreateAdd(l, r, "powtmp"); // TODO: library function + } + } + throw std::runtime_error("Unknown binary operation"); +} diff --git a/sayaka/src/ast_node_binaryoperator.h b/sayaka/src/ast_node_binaryoperator.h new file mode 100644 index 0000000..1e013d1 --- /dev/null +++ b/sayaka/src/ast_node_binaryoperator.h @@ -0,0 +1,18 @@ +#ifndef __AST_NODE_BINARYOPERATOR_H_ +#define __AST_NODE_BINARYOPERATOR_H_ + +#include "ast_node.h" + +class ASTNodeBinaryOperator : public ASTNode { +public: + EBinaryOperationType op; + ASTNode* lhs; + ASTNode* rhs; + + ASTNodeBinaryOperator(EBinaryOperationType, ASTNode*, ASTNode*); + + virtual llvm::Value* gen_code(CodeGen*) override; + virtual ~ASTNodeBinaryOperator(); +}; + +#endif /* __AST_NODE_BINARYOPERATOR_H_ */ diff --git a/sayaka/src/ast_node_block.cpp b/sayaka/src/ast_node_block.cpp new file mode 100644 index 0000000..fd1bbcc --- /dev/null +++ b/sayaka/src/ast_node_block.cpp @@ -0,0 +1,25 @@ +#include "ast_node_block.h" + +#include + +ASTNodeBlock::ASTNodeBlock() { + return; +} + +void ASTNodeBlock::push(ASTNode* node) { + this->statements.push_back(node); +} + +ASTNodeBlock::~ASTNodeBlock() { + return; +} + +llvm::Value* ASTNodeBlock::gen_code(CodeGen* code_gen) { + std::cout << "Generating block..." << std::endl; + llvm::Value* last = NULL; + for (std::vector::iterator it = this->statements.begin(); it != this->statements.end(); it++) { + last = (*it)->gen_code(code_gen); + this->type = (*it)->type; + } + return last; +} diff --git a/sayaka/src/ast_node_block.h b/sayaka/src/ast_node_block.h new file mode 100644 index 0000000..a4af87f --- /dev/null +++ b/sayaka/src/ast_node_block.h @@ -0,0 +1,17 @@ +#ifndef __AST_NODE_BLOCK_H_ +#define __AST_NODE_BLOCK_H_ + +#include "ast_node.h" + +class ASTNodeBlock : public ASTNode { +public: + std::vector statements; + + ASTNodeBlock(); + void push(ASTNode*); + + virtual llvm::Value* gen_code(CodeGen*) override; + virtual ~ASTNodeBlock(); +}; + +#endif /* __AST_NODE_BLOCK_H_ */ diff --git a/sayaka/src/ast_node_cast.cpp b/sayaka/src/ast_node_cast.cpp new file mode 100644 index 0000000..44eb277 --- /dev/null +++ b/sayaka/src/ast_node_cast.cpp @@ -0,0 +1,44 @@ +#include "ast_node_cast.h" + +#include + +ASTNodeCast::ASTNodeCast(ASTNode* val, ASTType* target_type) { + this->val = val; + this->target_type = target_type; + this->type = this->target_type; +} + +ASTNodeCast::~ASTNodeCast() { + return; +} + +llvm::Value* ASTNodeCast::gen_code(CodeGen* code_gen) { + std::cout << "Generating cast..." << std::endl; + code_gen->builder.SetInsertPoint(code_gen->current_block()); + if (this->val->type->is_primitive() && this->target_type->is_primitive()) { + llvm::Value* llvm_val = this->val->gen_code(code_gen); + if (this->val->type->is_integral()) { + if (this->target_type->is_integral()) { + return code_gen->builder.CreateIntCast(llvm_val, this->target_type->llvm_type, this->val->type->is_signed()); + } else { + if (this->val->type->is_signed()) { + return code_gen->builder.CreateSIToFP(llvm_val, this->target_type->llvm_type); + } else { + return code_gen->builder.CreateUIToFP(llvm_val, this->target_type->llvm_type); + } + } + } else { + if (this->target_type->is_floating()) { + return code_gen->builder.CreateFPCast(llvm_val, this->target_type->llvm_type); + } else { + if (this->target_type->is_signed()) { + return code_gen->builder.CreateFPToSI(llvm_val, this->target_type->llvm_type); + } else { + return code_gen->builder.CreateFPToUI(llvm_val, this->target_type->llvm_type); + } + } + } + } + std::cout << "Badness!!!" << std::endl; + return NULL; +} diff --git a/sayaka/src/ast_node_cast.h b/sayaka/src/ast_node_cast.h new file mode 100644 index 0000000..ed9bb9d --- /dev/null +++ b/sayaka/src/ast_node_cast.h @@ -0,0 +1,17 @@ +#ifndef __AST_NODE_CAST_H_ +#define __AST_NODE_CAST_H_ + +#include "ast_node.h" + +class ASTNodeCast : public ASTNode { +public: + ASTType* target_type; + ASTNode* val; + + ASTNodeCast(ASTNode*, ASTType*); + + virtual llvm::Value* gen_code(CodeGen*) override; + virtual ~ASTNodeCast(); +}; + +#endif /* __AST_NODE_CAST_H_ */ diff --git a/sayaka/src/ast_node_declaration.cpp b/sayaka/src/ast_node_declaration.cpp new file mode 100644 index 0000000..001080b --- /dev/null +++ b/sayaka/src/ast_node_declaration.cpp @@ -0,0 +1,26 @@ +#include "ast_node_declaration.h" + +#include + +ASTNodeDeclaration::ASTNodeDeclaration(ASTType* type, ASTNodeIdentifier* var_name) { + this->type = type; + this->var_name = var_name; + this->var_name->type = this->type; +} + +ASTNodeDeclaration::~ASTNodeDeclaration() { + delete this->var_name; +} + +llvm::Value* ASTNodeDeclaration::gen_code(CodeGen* code_gen) { + if (this->type == NULL || this->type->llvm_type == NULL) { + std::cout << "Unknown type " << this->type->name << std::endl; + return NULL; + } + std::cout << "Generating variable declaration for " << this->var_name->name << ", type " << this->type->name << "..." << std::endl; + code_gen->builder.SetInsertPoint(code_gen->current_block()); + llvm::AllocaInst* alloc = new llvm::AllocaInst(this->type->llvm_type, this->var_name->name.c_str(), code_gen->current_block()); + this->value = alloc; + code_gen->scope.put(this->var_name->name, this); + return alloc; +} diff --git a/sayaka/src/ast_node_declaration.h b/sayaka/src/ast_node_declaration.h new file mode 100644 index 0000000..efad774 --- /dev/null +++ b/sayaka/src/ast_node_declaration.h @@ -0,0 +1,17 @@ +#ifndef __AST_NODE_DECLARATION_H_ +#define __AST_NODE_DECLARATION_H_ + +#include "ast_node.h" +#include "ast_node_identifier.h" + +class ASTNodeDeclaration : public ASTNode { +public: + ASTNodeIdentifier* var_name; + + ASTNodeDeclaration(ASTType*, ASTNodeIdentifier*); + + virtual llvm::Value* gen_code(CodeGen*) override; + virtual ~ASTNodeDeclaration(); +}; + +#endif /* __AST_NODE_DECLARATION_H_ */ diff --git a/sayaka/src/ast_node_function.cpp b/sayaka/src/ast_node_function.cpp new file mode 100644 index 0000000..7e6df1e --- /dev/null +++ b/sayaka/src/ast_node_function.cpp @@ -0,0 +1,33 @@ +#include "ast_node_function.h" + +#include + +ASTNodeFunction::ASTNodeFunction(ASTNode* body, ASTType* return_type) { + this->body = body; + this->return_type = return_type; +} + +ASTNodeFunction::~ASTNodeFunction() { + delete this->body; +} + +llvm::Value* ASTNodeFunction::gen_code(CodeGen* code_gen) { + std::cout << "Generating function..." << std::endl; + std::vector arg_types; + llvm::FunctionType* fn_type = llvm::FunctionType::get(this->return_type->llvm_type, arg_types, false); + llvm::Function* fn = llvm::Function::Create(fn_type, llvm::Function::ExternalLinkage, "", code_gen->module); + + llvm::BasicBlock* basic_block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", fn); + code_gen->push_block(basic_block); + code_gen->builder.SetInsertPoint(basic_block); + + llvm::Value* ret_val = this->body->gen_code(code_gen); + if (ret_val != NULL) { + code_gen->builder.CreateRet(ret_val); + llvm::verifyFunction(*fn); + code_gen->pop_block(); + return fn; + } + code_gen->pop_block(); + throw std::runtime_error("Error generating function"); +} diff --git a/sayaka/src/ast_node_function.h b/sayaka/src/ast_node_function.h new file mode 100644 index 0000000..1432389 --- /dev/null +++ b/sayaka/src/ast_node_function.h @@ -0,0 +1,17 @@ +#ifndef __AST_NODE_FUNCTION_H_ +#define __AST_NODE_FUNCTION_H_ + +#include "ast_node.h" + +class ASTNodeFunction : public ASTNode { +public: + ASTNode* body; + ASTType* return_type; + + ASTNodeFunction(ASTNode*, ASTType*); + + virtual llvm::Value* gen_code(CodeGen*) override; + virtual ~ASTNodeFunction(); +}; + +#endif /* __AST_NODE_FUNCTION_H_ */ diff --git a/sayaka/src/ast_node_identifier.cpp b/sayaka/src/ast_node_identifier.cpp new file mode 100644 index 0000000..a86d758 --- /dev/null +++ b/sayaka/src/ast_node_identifier.cpp @@ -0,0 +1,25 @@ +#include "ast_node_identifier.h" + +#include +#include + +ASTNodeIdentifier::ASTNodeIdentifier(std::string name, ASTType* type) { + this->name = name; + this->type = type; +} + +ASTNodeIdentifier::~ASTNodeIdentifier() { + return; +} + +llvm::Value* ASTNodeIdentifier::gen_code(CodeGen* code_gen) { + std::cout << "Generating identifier " << this->name << std::endl; + ASTNode* val = code_gen->scope.get(this->name); + if (val == NULL) { + std::stringstream ss; + ss << "Undeclared variable " << this->name; + throw std::runtime_error(ss.str()); + } + //return new llvm::LoadInst(val->value, "", false, code_gen->current_block()); + return NULL; +} diff --git a/sayaka/src/ast_node_identifier.h b/sayaka/src/ast_node_identifier.h new file mode 100644 index 0000000..97ec1e1 --- /dev/null +++ b/sayaka/src/ast_node_identifier.h @@ -0,0 +1,16 @@ +#ifndef __AST_NODE_IDENTIFIER_H_ +#define __AST_NODE_IDENTIFIER_H_ + +#include "ast_node.h" + +class ASTNodeIdentifier : public ASTNode { +public: + std::string name; + + ASTNodeIdentifier(std::string, ASTType*); + + virtual llvm::Value* gen_code(CodeGen*) override; + virtual ~ASTNodeIdentifier(); +}; + +#endif /* __AST_NODE_IDENTIFIER_H_ */ diff --git a/sayaka/src/ast_node_primitive.cpp b/sayaka/src/ast_node_primitive.cpp new file mode 100644 index 0000000..8129b00 --- /dev/null +++ b/sayaka/src/ast_node_primitive.cpp @@ -0,0 +1,30 @@ +#include "ast_node_primitive.h" + +#include +#include +#include + +ASTNodePrimitive::ASTNodePrimitive(std::string str) { + this->str = str; + boost::replace_all(str, "_", ""); + boost::algorithm::to_upper(str); + this->type = ASTType::long_ty(); +} + +ASTNodePrimitive::~ASTNodePrimitive() { + return; +} + +llvm::Value* ASTNodePrimitive::gen_code(CodeGen* code_gen) { + std::cout << "Generating primitve number " << this->type->name << "..." << std::endl; + if (this->type == ASTType::double_ty()) { + return llvm::ConstantFP::get(this->type->llvm_type, boost::lexical_cast(this->str)); + } else if (this->type == ASTType::float_ty()) { + return llvm::ConstantFP::get(this->type->llvm_type, boost::lexical_cast(this->str)); + } + if (this->type->is_signed()) { + return llvm::ConstantInt::get(this->type->llvm_type, boost::lexical_cast(this->str), true); + } else { + return llvm::ConstantInt::get(this->type->llvm_type, boost::lexical_cast(this->str), false); + } +} diff --git a/sayaka/src/ast_node_primitive.h b/sayaka/src/ast_node_primitive.h new file mode 100644 index 0000000..670508a --- /dev/null +++ b/sayaka/src/ast_node_primitive.h @@ -0,0 +1,17 @@ +#ifndef __AST_NODE_PRIMITIVE_H_ +#define __AST_NODE_PRIMITIVE_H_ + +#include "ast_node.h" + +class ASTNodePrimitive : public ASTNode { +public: + UNumberValue val; + std::string str; + + ASTNodePrimitive(std::string); + + virtual llvm::Value* gen_code(CodeGen*) override; + virtual ~ASTNodePrimitive(); +}; + +#endif /* __AST_NODE_PRIMITIVE_H_ */ diff --git a/sayaka/src/ast_type.cpp b/sayaka/src/ast_type.cpp new file mode 100644 index 0000000..8b96ce4 --- /dev/null +++ b/sayaka/src/ast_type.cpp @@ -0,0 +1,123 @@ +#include "ast_type.h" +#include + +ASTType::ASTType(std::string name, std::vector extends = std::vector(), std::vector implements = std::vector(), llvm::Type* llvm_type = NULL) { + if (ASTType::get(name) != NULL) { + // TODO: badness + } + this->name = name; + this->extends = extends; + this->implements = implements; + ASTType::types[this->name] = this; +} + +bool ASTType::is_primitive() { + static std::vector primitives { ASTType::byte_ty(), ASTType::ubyte_ty(), ASTType::short_ty(), ASTType::ushort_ty(), ASTType::int_ty(), ASTType::uint_ty(), ASTType::long_ty(), ASTType::ulong_ty(), ASTType::float_ty(), ASTType::double_ty() }; + return std::find(primitives.begin(), primitives.end(), this) != primitives.end(); +} + +bool ASTType::is_signed() { + if (!this->is_primitive()) { + throw std::logic_error("Member function is_signed called on non primitive type"); + } + return this->name[0] != 'U'; +} + +bool ASTType::is_integral() { + if (!this->is_primitive()) { + throw std::logic_error("Member function is_integral called on non primitive type"); + } + return !this->is_floating(); +} + +bool ASTType::is_floating() { + if (!this->is_primitive()) { + throw std::logic_error("Member function is_floating called on non primitive type"); + } + return this == ASTType::float_ty() || this == ASTType::double_ty(); +} + +ASTType* ASTType::byte_ty() { + static ASTType instance("Byte"); + instance.llvm_type = llvm::Type::getInt8Ty(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::ubyte_ty() { + static ASTType instance("UByte"); + instance.llvm_type = llvm::Type::getInt8Ty(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::short_ty() { + static ASTType instance("Short"); + instance.llvm_type = llvm::Type::getInt16Ty(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::ushort_ty() { + static ASTType instance("UShort"); + instance.llvm_type = llvm::Type::getInt16Ty(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::int_ty() { + static ASTType instance("Int"); + instance.llvm_type = llvm::Type::getInt32Ty(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::uint_ty() { + static ASTType instance("UInt"); + instance.llvm_type = llvm::Type::getInt32Ty(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::long_ty() { + static ASTType instance("Long"); + instance.llvm_type = llvm::Type::getInt64Ty(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::ulong_ty() { + static ASTType instance("ULong"); + instance.llvm_type = llvm::Type::getInt64Ty(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::float_ty() { + static ASTType instance("Float"); + instance.llvm_type = llvm::Type::getFloatTy(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::double_ty() { + static ASTType instance("Double"); + instance.llvm_type = llvm::Type::getDoubleTy(llvm::getGlobalContext()); + return &instance; +} + +ASTType* ASTType::get(std::string name) { + std::map::iterator it = ASTType::types.find(name); + if (it != ASTType::types.end()) { + return it->second; + } + return NULL; +} + +int ASTType::__STATIC_INITIALIZER() { + ASTType::byte_ty(); + ASTType::ubyte_ty(); + ASTType::short_ty(); + ASTType::ushort_ty(); + ASTType::int_ty(); + ASTType::uint_ty(); + ASTType::long_ty(); + ASTType::ulong_ty(); + ASTType::float_ty(); + ASTType::double_ty(); + return 0; +} + +std::map ASTType::types; +int ASTType::__STATIC_INIT = ASTType::__STATIC_INITIALIZER(); diff --git a/sayaka/src/ntype.h b/sayaka/src/ast_type.h similarity index 61% rename from sayaka/src/ntype.h rename to sayaka/src/ast_type.h index 1903e72..bb00aac 100644 --- a/sayaka/src/ntype.h +++ b/sayaka/src/ast_type.h @@ -1,5 +1,5 @@ -#ifndef __NTYPE_H_ -#define __NTYPE_H_ +#ifndef __AST_TYPE_H_ +#define __AST_TYPE_H_ #include #include @@ -43,12 +43,12 @@ typedef enum tagEBinaryOperationType { ePOW, } EBinaryOperationType; -class NType { +class ASTType { public: - NType(std::string, std::vector, std::vector, llvm::Type*); + ASTType(std::string, std::vector, std::vector, llvm::Type*); std::string name; - std::vector extends; - std::vector implements; + std::vector extends; + std::vector implements; llvm::Type* llvm_type; bool is_primitive(); @@ -56,21 +56,21 @@ class NType { bool is_integral(); bool is_floating(); - static NType* get(std::string); + static ASTType* get(std::string); - static NType* byte_ty(); - static NType* ubyte_ty(); - static NType* short_ty(); - static NType* ushort_ty(); - static NType* int_ty(); - static NType* uint_ty(); - static NType* long_ty(); - static NType* ulong_ty(); - static NType* float_ty(); - static NType* double_ty(); + static ASTType* byte_ty(); + static ASTType* ubyte_ty(); + static ASTType* short_ty(); + static ASTType* ushort_ty(); + static ASTType* int_ty(); + static ASTType* uint_ty(); + static ASTType* long_ty(); + static ASTType* ulong_ty(); + static ASTType* float_ty(); + static ASTType* double_ty(); private: - static std::map types; + static std::map types; static int __STATIC_INIT; static int __STATIC_INITIALIZER(); }; diff --git a/sayaka/src/codegen.cpp b/sayaka/src/codegen.cpp index 9e0fd63..f58de69 100644 --- a/sayaka/src/codegen.cpp +++ b/sayaka/src/codegen.cpp @@ -1,17 +1,13 @@ -#include "node.h" #include "codegen.h" -#include "parser.h" -#include -#include -#include -CodeGen::CodeGen(llvm::Module* module) : builder(llvm::getGlobalContext()) { - this->module = module; +CodeGen::CodeGen() : builder(llvm::getGlobalContext()) { + this->module = new llvm::Module("top", llvm::getGlobalContext()); + this->execution_engine = llvm::EngineBuilder(this->module).setErrorStr(&this->execution_engine_error_str).setEngineKind(llvm::EngineKind::JIT).create(); this->push_block(llvm::BasicBlock::Create(llvm::getGlobalContext())); } CodeGen::~CodeGen() { - return; + delete this->module; } void CodeGen::push_block(llvm::BasicBlock* block) { @@ -28,170 +24,13 @@ llvm::BasicBlock* CodeGen::current_block() { return this->blocks.top(); } -void CodeGen::gen_code(NExpression* root) { -} - -void CodeGen::run_code() { -} - -llvm::Value* NPrimitive::gen_code(CodeGen* code_gen) { - std::cout << "Generating primitve number " << this->type->name << "..." << std::endl; - if (this->type == NType::double_ty()) { - return llvm::ConstantFP::get(this->type->llvm_type, boost::lexical_cast(this->str)); - } else if (this->type == NType::float_ty()) { - return llvm::ConstantFP::get(this->type->llvm_type, boost::lexical_cast(this->str)); - } - if (this->type->is_primitive()) { - if (this->type->is_signed()) { - return llvm::ConstantInt::get(this->type->llvm_type, boost::lexical_cast(this->str), true); - } else { - return llvm::ConstantInt::get(this->type->llvm_type, boost::lexical_cast(this->str), false); - } - } - std::cout << "Unknown primitive number type " << this->type->name << std::endl; - return NULL; -} - -llvm::Value* NBinaryOperator::gen_code(CodeGen* code_gen) { - std::cout << "Generating binary operator..." << std::endl; - this->lhs->type = this->type; - this->rhs->type = this->type; - llvm::Value* l = this->lhs->gen_code(code_gen); - llvm::Value* r = this->rhs->gen_code(code_gen); - if (l == NULL || r == NULL) { - return NULL; - } - switch (this->op) { - case eADD: - return code_gen->builder.CreateAdd(l, r, "addtmp"); - case eSUBTRACT: - return code_gen->builder.CreateSub(l, r, "subtmp"); - case eMULTIPLY: - return code_gen->builder.CreateMul(l, r, "multmp"); - case eDIVIDE: - return code_gen->builder.CreateSDiv(l, r, "divtmp"); - case ePOW: - return code_gen->builder.CreateAdd(l, r, "powtmp"); // TODO: library function - } - std::cout << "Unknown binary operation" << std::endl; - return NULL; -} - -llvm::Value* NFunction::gen_code(CodeGen* code_gen) { - std::cout << "Generating function..." << std::endl; - std::vector arg_types; - llvm::FunctionType* fn_type = llvm::FunctionType::get(this->return_type->llvm_type, arg_types, false); - llvm::Function* fn = llvm::Function::Create(fn_type, llvm::Function::ExternalLinkage, "", code_gen->module); - - llvm::BasicBlock* basic_block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", fn); - code_gen->push_block(basic_block); - code_gen->builder.SetInsertPoint(basic_block); - - llvm::Value* ret_val = this->body->gen_code(code_gen); - if (ret_val != NULL) { - code_gen->builder.CreateRet(ret_val); - llvm::verifyFunction(*fn); - code_gen->pop_block(); - return fn; - } - code_gen->pop_block(); - std::cerr << "Error generating function" << std::endl; - return NULL; -} - -llvm::Value* NIdentifier::gen_code(CodeGen* code_gen) { - std::cout << "Generating identifier " << this->name << std::endl; - NExpression* val = code_gen->scope.get(this->name); - if (val == NULL) { - std::stringstream ss; - ss << "Undeclared variable " << this->name; - std::cerr << ss.str() << std::endl; - return NULL; - } - return new llvm::LoadInst(val->value, "", false, code_gen->current_block()); -} - -llvm::Value* NAssignment::gen_code(CodeGen* code_gen) { - std::cout << "Generating assignment to " << this->lhs->name << "..." << std::endl; - NExpression* val = code_gen->scope.get(this->lhs->name); - if (val == NULL) { - std::cout << "Undeclared variable " << this->lhs->name << std::endl; - return NULL; - } - this->type = val->type; - this->rhs->type = val->type; - llvm::Value* rhs_val = this->rhs->gen_code(code_gen); - code_gen->builder.SetInsertPoint(code_gen->current_block()); - code_gen->builder.CreateStore(rhs_val, val->value, false); - return rhs_val; -} - -llvm::Value* NVariableDeclaration::gen_code(CodeGen* code_gen) { - if (this->type == NULL || this->type->llvm_type == NULL) { - std::cout << "Unknown type " << this->type->name << std::endl; - return NULL; - } - std::cout << "Generating variable declaration for " << this->var_name->name << ", type " << this->type->name << "..." << std::endl; - code_gen->builder.SetInsertPoint(code_gen->current_block()); - llvm::AllocaInst* alloc = new llvm::AllocaInst(this->type->llvm_type, this->var_name->name.c_str(), code_gen->current_block()); - this->value = alloc; - code_gen->scope.put(this->var_name->name, this); - return alloc; -} - -llvm::Value* NBlock::gen_code(CodeGen* code_gen) { - std::cout << "Generating block..." << std::endl; - llvm::Value* last = NULL; - for (std::vector::iterator it = this->statements.begin(); it != this->statements.end(); it++) { - last = (*it)->gen_code(code_gen); - this->type = (*it)->type; - } - return last; -} - -llvm::Value* NCast::gen_code(CodeGen* code_gen) { - std::cout << "Generating cast..." << std::endl; - code_gen->builder.SetInsertPoint(code_gen->current_block()); - if (this->val->type->is_primitive() && this->target_type->is_primitive()) { - llvm::Value* llvm_val = this->val->gen_code(code_gen); - if (this->val->type->is_integral()) { - if (this->target_type->is_integral()) { - return code_gen->builder.CreateIntCast(llvm_val, this->target_type->llvm_type, this->val->type->is_signed()); - } else { - if (this->val->type->is_signed()) { - return code_gen->builder.CreateSIToFP(llvm_val, this->target_type->llvm_type); - } else { - return code_gen->builder.CreateUIToFP(llvm_val, this->target_type->llvm_type); - } - } - } else { - if (this->target_type->is_floating()) { - return code_gen->builder.CreateFPCast(llvm_val, this->target_type->llvm_type); - } else { - if (this->target_type->is_signed()) { - return code_gen->builder.CreateFPToSI(llvm_val, this->target_type->llvm_type); - } else { - return code_gen->builder.CreateFPToUI(llvm_val, this->target_type->llvm_type); - } - } - } - } - std::cout << "Badness!!!" << std::endl; - return NULL; -} - llvm::Type* CodeGen::llvm_pointer_ty() { static llvm::Type* ty = NULL; if (ty == NULL) { if (sizeof(void*) == 8) { ty = llvm::Type::getInt64Ty(llvm::getGlobalContext()); - } else if (sizeof(void*) == 4) { - ty = llvm::Type::getInt32Ty(llvm::getGlobalContext()); } else { - std::stringstream ss; - ss << "Unknown pointer size " << sizeof(void*); - std::cerr << ss.str() << std::endl; - return NULL; + ty = llvm::Type::getInt32Ty(llvm::getGlobalContext()); } } return ty; diff --git a/sayaka/src/codegen.h b/sayaka/src/codegen.h index fd38a31..83eb766 100644 --- a/sayaka/src/codegen.h +++ b/sayaka/src/codegen.h @@ -20,27 +20,24 @@ #include #include #include "codescope.h" -#include "node.h" class CodeGen { public: llvm::Module* module; + llvm::ExecutionEngine* execution_engine; std::stack blocks; + llvm::IRBuilder<> builder; + std::string execution_engine_error_str; CodeScope scope; - CodeGen(llvm::Module*); + CodeGen(); ~CodeGen(); - void gen_code(NExpression* root); - void run_code(); // GenericValue - void push_block(llvm::BasicBlock*); void pop_block(); llvm::BasicBlock* current_block(); static llvm::Type* llvm_pointer_ty(); - - llvm::IRBuilder<> builder; }; #endif // __CODEGEN_H_ diff --git a/sayaka/src/codescope.cpp b/sayaka/src/codescope.cpp index 6e3f646..014a1b7 100644 --- a/sayaka/src/codescope.cpp +++ b/sayaka/src/codescope.cpp @@ -10,13 +10,13 @@ CodeScope::~CodeScope() { } } -void CodeScope::put(std::string key, NExpression* val) { +void CodeScope::put(std::string key, ASTNode* val) { (*this->stacks.back())[key] = val; } -NExpression* CodeScope::get(std::string key) { - for (std::deque*>::reverse_iterator it = this->stacks.rbegin(); it != this->stacks.rend(); it++) { - std::map::iterator found = (*it)->find(key); +ASTNode* CodeScope::get(std::string key) { + for (std::deque*>::reverse_iterator it = this->stacks.rbegin(); it != this->stacks.rend(); it++) { + std::map::iterator found = (*it)->find(key); if (found != (*it)->end()) { return found->second; } @@ -29,7 +29,7 @@ bool CodeScope::contains(std::string key) { } void CodeScope::push() { - std::map* scope = new std::map(); + std::map* scope = new std::map(); this->stacks.push_back(scope); } diff --git a/sayaka/src/codescope.h b/sayaka/src/codescope.h index 7bac5ce..37ebe25 100644 --- a/sayaka/src/codescope.h +++ b/sayaka/src/codescope.h @@ -4,19 +4,20 @@ #include #include #include -#include "node.h" + +class ASTNode; class CodeScope { public: CodeScope(); ~CodeScope(); - void put(std::string, NExpression*); - NExpression* get(std::string); + void put(std::string, ASTNode*); + ASTNode* get(std::string); bool contains(std::string); void push(); void pop(); private: - std::deque*> stacks; + std::deque*> stacks; }; #endif // __CODESCOPE_H_ diff --git a/sayaka/src/compiler.cpp b/sayaka/src/compiler.cpp new file mode 100644 index 0000000..5efc23c --- /dev/null +++ b/sayaka/src/compiler.cpp @@ -0,0 +1,52 @@ +#include "compiler.h" + +#include +#include "parser.h" +#include "lexer.h" + +Compiler::Compiler() { + return; +} + +Compiler::~Compiler() { + return; +} + +ASTNode* Compiler::parse(std::string code) { + ASTNode* root; + yyscan_t scanner; + YY_BUFFER_STATE state; + // (http://flex.sourceforge.net/manual/Reentrant-Overview.html) + if (yylex_init(&scanner)) { + return NULL; + } + state = yy_scan_string(code.c_str(), scanner); + if (yyparse(&root, scanner)) { + return NULL; + } + yy_delete_buffer(state, scanner); + yylex_destroy(scanner); + return root; +} + +void Compiler::run_code(ASTNode* root) { + return; +} + +void Compiler::initialize() { + llvm::InitializeNativeTarget(); +} + +/* + + CodeGen code_gen; + + NFunction main_fn(root_expr, ASTType::int_ty()); + + llvm::Function* main_fn_val = (llvm::Function*) main_fn.gen_code(&code_gen); + std::cout << "Main fn code:" << std::endl; + main_fn_val->dump(); + void* fn_ptr = code_gen.execution_engine->getPointerToFunction(main_fn_val); + int32_t ret = ((int32_t (*)()) fn_ptr)(); + std::cout << "Main fn at " << fn_ptr << "; executed: " << ret << std::endl; + */ diff --git a/sayaka/src/compiler.h b/sayaka/src/compiler.h new file mode 100644 index 0000000..8baa9f1 --- /dev/null +++ b/sayaka/src/compiler.h @@ -0,0 +1,18 @@ +#ifndef __COMPILER_H_ +#define __COMPILER_H_ + +#include +#include "ast_node.h" + +class Compiler { +public: + Compiler(); + ASTNode* parse(std::string); + void run_code(ASTNode*); + + virtual ~Compiler(); + + static void initialize(); +}; + +#endif /* __COMPILER_H_ */ diff --git a/sayaka/src/lexer.l b/sayaka/src/lexer.l index c8ade9d..4b6ca86 100644 --- a/sayaka/src/lexer.l +++ b/sayaka/src/lexer.l @@ -1,8 +1,7 @@ %{ -#include "node.h" +#include #include "parser.h" -#include // yytext, yyleng globals (http://flex.sourceforge.net/manual/Matching.html) #define SAVE_TOKEN yylval->str = new std::string(yytext, yyleng) @@ -21,6 +20,8 @@ LPAREN "(" RPAREN ")" LBRACE "{" RBRACE "}" +LBRACKET "\[" +RBRACKET "\]" SEMICOLON ";" ADD "+" MULTIPLY "*" @@ -49,10 +50,12 @@ WS [ \r\n\t]+ {RPAREN} { return TOKEN_RPAREN; } {LBRACE} { return TOKEN_LBRACE; } {RBRACE} { return TOKEN_RBRACE; } +{LBRACKET} { return TOKEN_LBRACKET; } +{RBRACKET} { return TOKEN_RBRACKET; } {SEMICOLON} { return TOKEN_SEMICOLON; } {EQUALS} { return TOKEN_EQUALS; } {IDENTIFIER} { SAVE_TOKEN; return TOKEN_IDENTIFIER; } {TYPE_NAME} { SAVE_TOKEN; return TOKEN_TYPE_NAME; } -. { printf("Unknown token!"); } +. { std::cout << "Unknown token!" << std::endl; } %% diff --git a/sayaka/src/main.cpp b/sayaka/src/main.cpp index d6f6d09..18e7da4 100644 --- a/sayaka/src/main.cpp +++ b/sayaka/src/main.cpp @@ -1,14 +1,7 @@ -#include "node.h" -#include "parser.h" -#include "codegen.h" -#include "lexer.h" - -#include -#include #include #include - #include +#include "compiler.h" #ifdef BOOST_NO_EXCEPTIONS namespace boost { @@ -18,55 +11,9 @@ namespace boost { } #endif // BOOST_NO_EXCEPTIONS -int yyparse(NExpression** expression, yyscan_t scanner); - -extern NExpression* programBlock; - -NExpression* getAST(const char* str) { - NExpression* expr; - yyscan_t scanner; - YY_BUFFER_STATE state; - // (http://flex.sourceforge.net/manual/Reentrant-Overview.html) - if (yylex_init(&scanner)) { - return NULL; - } - - state = yy_scan_string(str, scanner); - - if (yyparse(&expr, scanner)) { - return NULL; - } - - yy_delete_buffer(state, scanner); - yylex_destroy(scanner); - - return expr; -} - -void run_code(const char* code) { - NExpression* root_expr = getAST(code); - if (root_expr == NULL) { - std::cout << "Root expression was null! Ahhhhhhhhhhhhh!" << std::endl; - return; - } - - std::string error_str; - llvm::Module* module = new llvm::Module("top", llvm::getGlobalContext()); - llvm::ExecutionEngine* execution_engine = llvm::EngineBuilder(module).setErrorStr(&error_str).setEngineKind(llvm::EngineKind::JIT).create(); - CodeGen code_gen(module); - - NFunction main_fn(root_expr, NType::int_ty()); - - llvm::Function* main_fn_val = (llvm::Function*) main_fn.gen_code(&code_gen); - std::cout << "Main fn code:" << std::endl; - main_fn_val->dump(); - void* fn_ptr = execution_engine->getPointerToFunction(main_fn_val); - int32_t ret = ((int32_t (*)()) fn_ptr)(); - std::cout << "Main fn at " << fn_ptr << "; executed: " << ret << std::endl; -} - int main(int argc, char* argv[]) { - llvm::InitializeNativeTarget(); + Compiler::initialize(); + Compiler compiler; std::cout << "Started." << std::endl; if (argc > 1) { std::string str = ""; @@ -78,7 +25,13 @@ int main(int argc, char* argv[]) { } } std::cout << "Reading from file, contents:\n" << str << std::endl; - run_code(str.c_str()); + + ASTNode* node = compiler.parse(str); + if (node == NULL) { + std::cout << "Root node was null" << std::endl; + } else { + compiler.run_code(node); + } } else { std::string line; while (true) { @@ -86,7 +39,12 @@ int main(int argc, char* argv[]) { if (!std::getline(std::cin, line)) { break; } - run_code(line.c_str()); + ASTNode* node = compiler.parse(line); + if (node == NULL) { + std::cout << "Root node was null" << std::endl; + } else { + compiler.run_code(node); + } } } std::cout << "Done." << std::endl; diff --git a/sayaka/src/node.cpp b/sayaka/src/node.cpp deleted file mode 100644 index e340fc3..0000000 --- a/sayaka/src/node.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "node.h" -#include -#include -#include -#include -#include "codegen.h" -#include - -Node::~Node() { - return; -} - -NExpression::~NExpression() { - return; -} - -NPrimitive::~NPrimitive() { - return; -} - -NPrimitive::NPrimitive(std::string str) { - this->str = str; - boost::replace_all(str, "_", ""); - boost::algorithm::to_upper(str); - this->type = NType::long_ty(); -} - -NBinaryOperator::NBinaryOperator(EBinaryOperationType op, NExpression* lhs, NExpression* rhs) { - this->op = op; - this->lhs = lhs; - this->rhs = rhs; - this->type = this->lhs->type; -} - -NBinaryOperator::~NBinaryOperator() { - delete this->lhs; - delete this->rhs; -} - -NFunction::NFunction(NExpression* body, NType* return_type) { - this->body = body; - this->return_type = return_type; -} - -NFunction::~NFunction() { - delete this->body; -} - -NIdentifier::NIdentifier(std::string name, NType* type) { - this->name = name; - this->type = type; -} - -NIdentifier::~NIdentifier() { - return; -} - -NAssignment::NAssignment(NIdentifier* lhs, NExpression* rhs) { - this->lhs = lhs; - this->rhs = rhs; - this->type = lhs->type; -} - -NAssignment::~NAssignment() { - delete this->lhs; - delete this->rhs; -} - -NVariableDeclaration::NVariableDeclaration(NType* type, NIdentifier* var_name) { - this->type = type; - this->var_name = var_name; - this->var_name->type = this->type; -} - -NVariableDeclaration::~NVariableDeclaration() { - delete this->type; - delete this->var_name; -} - -NBlock::NBlock() { - return; -} - -void NBlock::push(NExpression* expr) { - this->type = expr->type; - this->statements.push_back(expr); -} - -NBlock::~NBlock() { - return; -} - -NCast::NCast(NExpression* val, NType* target_type) { - this->val = val; - this->target_type = target_type; - this->type = this->target_type; -} - -NCast::~NCast() { -} diff --git a/sayaka/src/node.h b/sayaka/src/node.h deleted file mode 100644 index a1fd5c8..0000000 --- a/sayaka/src/node.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef __NODE_H_ -#define __NODE_H_ - -#include -#include -#include -#include -#include -#include "ntype.h" - -class CodeGen; - -class Node { -public: - virtual ~Node() = 0; - virtual llvm::Value* gen_code(CodeGen*) = 0; -}; - -class NExpression : public Node { -public: - NType* type; - llvm::Value* value; - - virtual ~NExpression() = 0; - virtual llvm::Value* gen_code(CodeGen*) = 0; -}; - -class NPrimitive : public NExpression { -public: - UNumberValue val; - std::string str; - - NPrimitive(std::string); - - virtual llvm::Value* gen_code(CodeGen*) override; - virtual ~NPrimitive(); -}; - -class NBinaryOperator : public NExpression { -public: - EBinaryOperationType op; - NExpression* lhs; - NExpression* rhs; - - NBinaryOperator(EBinaryOperationType, NExpression*, NExpression*); - - virtual llvm::Value* gen_code(CodeGen*) override; - virtual ~NBinaryOperator(); -}; - -class NFunction : public NExpression { -public: - NExpression* body; - NType* return_type; - - NFunction(NExpression*, NType*); - - virtual llvm::Value* gen_code(CodeGen*) override; - virtual ~NFunction(); -}; - -class NIdentifier : public NExpression { -public: - std::string name; - - NIdentifier(std::string, NType* type); - - virtual llvm::Value* gen_code(CodeGen*) override; - virtual ~NIdentifier(); -}; - -class NAssignment : public NExpression { -public: - NIdentifier* lhs; - NExpression* rhs; - - NAssignment(NIdentifier*, NExpression*); - - virtual llvm::Value* gen_code(CodeGen*) override; - virtual ~NAssignment(); -}; - -class NVariableDeclaration : public NExpression { -public: - NIdentifier* var_name; - - NVariableDeclaration(NType*, NIdentifier*); - - virtual llvm::Value* gen_code(CodeGen*) override; - virtual ~NVariableDeclaration(); -}; - -class NCast : public NExpression { -public: - NType* target_type; - NExpression* val; - - NCast(NExpression*, NType*); - - virtual llvm::Value* gen_code(CodeGen*) override; - virtual ~NCast(); -}; - -class NBlock : public NExpression { -public: - std::vector statements; - - NBlock(); - void push(NExpression*); - - virtual llvm::Value* gen_code(CodeGen*) override; - virtual ~NBlock(); -}; - -#endif // __NODE_H_ diff --git a/sayaka/src/ntype.cpp b/sayaka/src/ntype.cpp deleted file mode 100644 index 765816c..0000000 --- a/sayaka/src/ntype.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "ntype.h" -#include - -NType::NType(std::string name, std::vector extends = std::vector(), std::vector implements = std::vector(), llvm::Type* llvm_type = NULL) { - if (NType::get(name) != NULL) { - // TODO: badness - } - this->name = name; - this->extends = extends; - this->implements = implements; - NType::types[this->name] = this; -} - -bool NType::is_primitive() { - static std::vector primitives { NType::byte_ty(), NType::ubyte_ty(), NType::short_ty(), NType::ushort_ty(), NType::int_ty(), NType::uint_ty(), NType::long_ty(), NType::ulong_ty(), NType::float_ty(), NType::double_ty() }; - return std::find(primitives.begin(), primitives.end(), this) != primitives.end(); -} - -bool NType::is_signed() { - if (!this->is_primitive()) { - throw std::logic_error("Member function is_signed called on non primitive type"); - } - return this->name[0] != 'U'; -} - -bool NType::is_integral() { - if (!this->is_primitive()) { - throw std::logic_error("Member function is_integral called on non primitive type"); - } - return !this->is_floating(); -} - -bool NType::is_floating() { - if (!this->is_primitive()) { - throw std::logic_error("Member function is_floating called on non primitive type"); - } - return this == NType::float_ty() || this == NType::double_ty(); -} - -NType* NType::byte_ty() { - static NType instance("Byte"); - instance.llvm_type = llvm::Type::getInt8Ty(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::ubyte_ty() { - static NType instance("UByte"); - instance.llvm_type = llvm::Type::getInt8Ty(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::short_ty() { - static NType instance("Short"); - instance.llvm_type = llvm::Type::getInt16Ty(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::ushort_ty() { - static NType instance("UShort"); - instance.llvm_type = llvm::Type::getInt16Ty(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::int_ty() { - static NType instance("Int"); - instance.llvm_type = llvm::Type::getInt32Ty(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::uint_ty() { - static NType instance("UInt"); - instance.llvm_type = llvm::Type::getInt32Ty(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::long_ty() { - static NType instance("Long"); - instance.llvm_type = llvm::Type::getInt64Ty(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::ulong_ty() { - static NType instance("ULong"); - instance.llvm_type = llvm::Type::getInt64Ty(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::float_ty() { - static NType instance("Float"); - instance.llvm_type = llvm::Type::getFloatTy(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::double_ty() { - static NType instance("Double"); - instance.llvm_type = llvm::Type::getDoubleTy(llvm::getGlobalContext()); - return &instance; -} - -NType* NType::get(std::string name) { - std::map::iterator it = NType::types.find(name); - if (it != NType::types.end()) { - return it->second; - } - return NULL; -} - -int NType::__STATIC_INITIALIZER() { - NType::byte_ty(); - NType::ubyte_ty(); - NType::short_ty(); - NType::ushort_ty(); - NType::int_ty(); - NType::uint_ty(); - NType::long_ty(); - NType::ulong_ty(); - NType::float_ty(); - NType::double_ty(); - return 0; -} - -std::map NType::types; -int NType::__STATIC_INIT = NType::__STATIC_INITIALIZER(); diff --git a/sayaka/src/parser.y b/sayaka/src/parser.y index 51b3881..3e8a862 100644 --- a/sayaka/src/parser.y +++ b/sayaka/src/parser.y @@ -1,30 +1,38 @@ %{ -#include "ntype.h" -#include "node.h" -#include "parser.h" -#include "lexer.h" #include #include #include - -void yyerror(YYLTYPE* llocp, NExpression**, yyscan_t scanner, const char *s) { +#include "parser.h" +#include "lexer.h" +#include "ast_type.h" +#include "ast_node.h" +#include "ast_node_identifier.h" +#include "ast_node_block.h" +#include "ast_node_assignment.h" +#include "ast_node_binaryoperator.h" +#include "ast_node_cast.h" +#include "ast_node_declaration.h" +#include "ast_node_function.h" +#include "ast_node_primitive.h" + +void yyerror(YYLTYPE* llocp, ASTNode**, yyscan_t scanner, const char *s) { std::cerr << "YYERROR: " << s << std::endl; } -static std::deque*> identifier_stack; +static std::deque*> identifier_stack; static void identifier_stack_push() { - identifier_stack.push_back(new std::map); + identifier_stack.push_back(new std::map); } static void identifier_stack_pop() { delete identifier_stack.back(); identifier_stack.pop_back(); } -static NType* identifier_stack_get(std::string name) { - for (std::deque*>::reverse_iterator it = identifier_stack.rbegin(); it != identifier_stack.rend(); it++) { - std::map::iterator found = (*it)->find(name); +static ASTType* identifier_stack_get(std::string name) { + for (std::deque*>::reverse_iterator it = identifier_stack.rbegin(); it != identifier_stack.rend(); it++) { + std::map::iterator found = (*it)->find(name); if (found != (*it)->end()) { return found->second; } @@ -33,7 +41,7 @@ static NType* identifier_stack_get(std::string name) { throw new std::runtime_error("Undeclared identifier!"); } -static void identifier_stack_put(std::string name, NType* type) { +static void identifier_stack_put(std::string name, ASTType* type) { (*identifier_stack.back())[name] = type; } @@ -41,6 +49,11 @@ static void identifier_stack_put(std::string name, NType* type) { %code requires { +class ASTNode; +class ASTNodeBlock; +class ASTNodeIdentifier; +class ASTType; + #ifndef YY_TYPEDEF_YY_SCANNER_T #define YY_TYPEDEF_YY_SCANNER_T typedef void* yyscan_t; @@ -52,15 +65,15 @@ typedef void* yyscan_t; //%define parse.error verbose %locations %lex-param { yyscan_t scanner } -%parse-param { NExpression** expression } +%parse-param { ASTNode** root } %parse-param { yyscan_t scanner } %union { - NExpression* expr; - NBlock* block; - NIdentifier* identifier; + ASTNode* node; + ASTNodeBlock* block; + ASTNodeIdentifier* identifier; std::string* str; - NType* type; + ASTType* type; } %left TOKEN_ADD TOKEN_SUBTRACT @@ -68,11 +81,11 @@ typedef void* yyscan_t; %left TOKEN_POW %left TOKEN_EQUALS TOKEN_RPAREN -%token TOKEN_LPAREN TOKEN_RPAREN TOKEN_SEMICOLON TOKEN_EQUALS TOKEN_LBRACE TOKEN_RBRACE -%token TOKEN_ADD TOKEN_MULTIPLY TOKEN_DIVIDE TOKEN_SUBTRACT TOKEN_POW +%token TOKEN_LPAREN TOKEN_RPAREN TOKEN_SEMICOLON TOKEN_EQUALS TOKEN_LBRACE TOKEN_RBRACE TOKEN_LBRACKET TOKEN_RBRACKET +%token TOKEN_ADD TOKEN_MULTIPLY TOKEN_DIVIDE TOKEN_SUBTRACT TOKEN_POW %token TOKEN_NUMBER TOKEN_IDENTIFIER TOKEN_TYPE_NAME -%type program expr number binary_operator_expr assignment_expr variable_declaration_expr cast_expr +%type program expr number binary_operator_expr assignment_expr variable_declaration_expr cast_expr %type stmts %type identifier new_identifier %type type_name @@ -90,12 +103,13 @@ program_end ; program - : program_start stmts program_end { *expression = $2; } + : program_start stmts program_end { *root = $2; } ; stmts - : expr TOKEN_SEMICOLON { $$ = new NBlock(); $$->push($1); } + : expr TOKEN_SEMICOLON { $$ = new ASTNodeBlock(); $$->push($1); } | stmts expr TOKEN_SEMICOLON { $$->push($2); } + ; expr : TOKEN_LPAREN expr TOKEN_RPAREN { $$ = $2; } @@ -108,37 +122,37 @@ expr ; identifier - : TOKEN_IDENTIFIER { $$ = new NIdentifier(*$1, identifier_stack_get(*$1)); delete $1; } + : TOKEN_IDENTIFIER { $$ = new ASTNodeIdentifier(*$1, identifier_stack_get(*$1)); delete $1; } ; new_identifier - : TOKEN_IDENTIFIER { $$ = new NIdentifier(*$1, NULL); delete $1; } + : TOKEN_IDENTIFIER { $$ = new ASTNodeIdentifier(*$1, NULL); delete $1; } ; type_name - : TOKEN_TYPE_NAME { $$ = NType::get(*$1); delete $1; } + : TOKEN_TYPE_NAME { $$ = ASTType::get(*$1); delete $1; } ; number - : TOKEN_NUMBER { $$ = new NPrimitive(*$1); delete $1; } + : TOKEN_NUMBER { $$ = new ASTNodePrimitive(*$1); delete $1; } ; assignment_expr - : identifier TOKEN_EQUALS expr { $$ = new NAssignment($1, $3); } + : identifier TOKEN_EQUALS expr { $$ = new ASTNodeAssignment($1, $3); } ; variable_declaration_expr - : type_name new_identifier { identifier_stack_put($2->name, $1); $$ = new NVariableDeclaration($1, $2); } + : type_name new_identifier { identifier_stack_put($2->name, $1); $$ = new ASTNodeDeclaration($1, $2); } ; cast_expr - : TOKEN_LPAREN type_name TOKEN_RPAREN expr { $$ = new NCast($4, $2); } + : TOKEN_LPAREN type_name TOKEN_RPAREN expr { $$ = new ASTNodeCast($4, $2); } ; binary_operator_expr - : expr TOKEN_ADD expr { $$ = new NBinaryOperator(eADD, $1, $3); } - | expr TOKEN_SUBTRACT expr { $$ = new NBinaryOperator(eSUBTRACT, $1, $3); } - | expr TOKEN_DIVIDE expr { $$ = new NBinaryOperator(eDIVIDE, $1, $3); } - | expr TOKEN_MULTIPLY expr { $$ = new NBinaryOperator(eMULTIPLY, $1, $3); } - | expr TOKEN_POW expr { $$ = new NBinaryOperator(ePOW, $1, $3); } + : expr TOKEN_ADD expr { $$ = new ASTNodeBinaryOperator(eADD, $1, $3); } + | expr TOKEN_SUBTRACT expr { $$ = new ASTNodeBinaryOperator(eSUBTRACT, $1, $3); } + | expr TOKEN_DIVIDE expr { $$ = new ASTNodeBinaryOperator(eDIVIDE, $1, $3); } + | expr TOKEN_MULTIPLY expr { $$ = new ASTNodeBinaryOperator(eMULTIPLY, $1, $3); } + | expr TOKEN_POW expr { $$ = new ASTNodeBinaryOperator(ePOW, $1, $3); } ;