diff --git a/include/ast/ast.h b/include/ast/ast.h index 5d67d0f..3ed929f 100644 --- a/include/ast/ast.h +++ b/include/ast/ast.h @@ -5,7 +5,7 @@ #include "Token.h" -#include "shared/type.h" +#include "shared/type/type.h" using antlr4::Token, std::make_shared, std::shared_ptr; diff --git a/include/ast/passes/type_check.h b/include/ast/passes/type_check.h index ac7b548..71e382c 100644 --- a/include/ast/passes/type_check.h +++ b/include/ast/passes/type_check.h @@ -3,12 +3,13 @@ #include #include "ast/ast.h" #include "ast/passes/pass.h" +#include "shared/type/type.h" class TypeCheck : public Pass { private: std::stack> func_stack; - void check_numeric(Type type, size_t line); - void check_bool(Type type, size_t line); + void check_numeric(TypePtr type, size_t line); + void check_bool(TypePtr type, size_t line); public: explicit TypeCheck(); diff --git a/include/ast/symbol/symbol.h b/include/ast/symbol/symbol.h index 8895e8c..5869f33 100644 --- a/include/ast/symbol/symbol.h +++ b/include/ast/symbol/symbol.h @@ -4,7 +4,7 @@ #include #include "ast/ast.h" -#include "shared/type.h" +#include "shared/type/type.h" using std::shared_ptr; @@ -23,9 +23,9 @@ class Symbol { typedef shared_ptr SymbolPtr; -class BuiltinTypeSymbol : public Symbol, public Type { +class BuiltinTypeSymbol : public Symbol { public: - BuiltinTypeSymbol(std::string name); + BuiltinTypeSymbol(TypePtr type); std::string get_name() override; }; diff --git a/include/backend/builtin/print.h b/include/backend/builtin/print.h index 8949aad..51990c2 100644 --- a/include/backend/builtin/print.h +++ b/include/backend/builtin/print.h @@ -1,6 +1,6 @@ #pragma once -#include "shared/type.h" +#include "shared/type/type.h" namespace builtin { void define_all_print(); diff --git a/include/backend/expressions/arithmetic.h b/include/backend/expressions/arithmetic.h index 093962a..342040f 100644 --- a/include/backend/expressions/arithmetic.h +++ b/include/backend/expressions/arithmetic.h @@ -1,7 +1,7 @@ #pragma once #include "ast/ast.h" -#include "shared/type.h" +#include "shared/type/type.h" #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/IR/Value.h" diff --git a/include/backend/io.h b/include/backend/io.h index 8d2e7b5..997ff1d 100644 --- a/include/backend/io.h +++ b/include/backend/io.h @@ -1,7 +1,7 @@ #pragma once #include "mlir/IR/Value.h" -#include "shared/type.h" +#include "shared/type/type.h" namespace io { void printf(mlir::Value value, TypePtr type); diff --git a/include/shared/context.h b/include/shared/context.h index 7b93647..2866149 100644 --- a/include/shared/context.h +++ b/include/shared/context.h @@ -6,7 +6,7 @@ #include #include -#include "shared/type.h" +#include "shared/type/type.h" using std::shared_ptr, std::make_shared, std::unique_ptr; diff --git a/include/shared/type.h b/include/shared/type.h deleted file mode 100644 index bb1c8c8..0000000 --- a/include/shared/type.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include -#include "mlir/IR/Types.h" - -class Type { - private: - std::string name; - - public: - explicit Type(std::string name); - std::string get_name() const; - std::string get_specifier() const; - mlir::Type get_mlir() const; - mlir::Type get_pointer(); - - bool operator==(const Type rhs) const; - - static const Type ch; - static const Type any; - static const Type i32; - static const Type f32; - static const Type none; - static const Type unset; - static const Type t_bool; -}; - -typedef std::shared_ptr TypePtr; diff --git a/include/shared/type/boolean.h b/include/shared/type/boolean.h new file mode 100644 index 0000000..7772327 --- /dev/null +++ b/include/shared/type/boolean.h @@ -0,0 +1,10 @@ +#pragma once + +#include "shared/type/type.h" + +class Boolean : public Type { + public: + Boolean(); + std::string get_specifier() const override; + mlir::Type get_mlir() const override; +}; diff --git a/include/shared/type/character.h b/include/shared/type/character.h new file mode 100644 index 0000000..5f4929d --- /dev/null +++ b/include/shared/type/character.h @@ -0,0 +1,10 @@ +#pragma once + +#include "shared/type/type.h" + +class Character : public Type { + public: + Character(); + std::string get_specifier() const override; + mlir::Type get_mlir() const override; +}; diff --git a/include/shared/type/float.h b/include/shared/type/float.h new file mode 100644 index 0000000..bf098a4 --- /dev/null +++ b/include/shared/type/float.h @@ -0,0 +1,10 @@ +#pragma once + +#include "shared/type/type.h" + +class F32 : public Type { + public: + F32(); + std::string get_specifier() const override; + mlir::Type get_mlir() const override; +}; diff --git a/include/shared/type/integer.h b/include/shared/type/integer.h new file mode 100644 index 0000000..3a9301f --- /dev/null +++ b/include/shared/type/integer.h @@ -0,0 +1,11 @@ +#pragma once + +#include "shared/type/type.h" + +class I32 : public Type { + public: + I32(); + std::string get_specifier() const override; + mlir::Type get_mlir() const override; + bool is_numeric() const override; +}; diff --git a/include/shared/type/type.h b/include/shared/type/type.h new file mode 100644 index 0000000..37cc57b --- /dev/null +++ b/include/shared/type/type.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#include "mlir/IR/Types.h" + +class Type { + protected: + std::string name; + + public: + explicit Type(std::string name); + + std::string get_name() const; + mlir::Type get_pointer(); + + virtual std::string get_specifier() const; + virtual mlir::Type get_mlir() const; + virtual bool is_numeric() const; + + bool operator==(const Type rhs) const; +}; + +class Any : public Type { + public: + Any(); + std::string get_specifier() const override; +}; + +class None : public Type { + public: + None(); + std::string get_specifier() const override; + mlir::Type get_mlir() const override; +}; + +class Unset : public Type { + public: + Unset(); + std::string get_specifier() const override; +}; + +typedef std::shared_ptr TypePtr; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a446f48..d587e55 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,7 +22,12 @@ set( "${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/def_ref.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/type_check.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/builtin.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/shared/type.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/shared/type/type.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/shared/type/character.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/shared/type/integer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/shared/type/float.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/shared/type/boolean.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/shared/type/type.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/shared/context.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/errors/syntax.cpp" ) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index f190240..b8341c0 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -312,7 +312,7 @@ ast::Call::Call(std::string name, ast::Call::Call(std::string name, std::vector> args, Token* token) - : Expression(make_shared(Type::unset), token) { + : Expression(make_shared(), token) { this->name = name; this->arguments = args; this->function = nullptr; diff --git a/src/ast/builder.cpp b/src/ast/builder.cpp index 3c01ab8..5e40eaf 100644 --- a/src/ast/builder.cpp +++ b/src/ast/builder.cpp @@ -6,6 +6,7 @@ #include "ast/ast.h" #include "ast/builder.h" #include "shared/context.h" +#include "shared/type/type.h" using std::any_cast; @@ -81,7 +82,7 @@ std::any Builder::visitType(FusionParser::TypeContext* ctx) { throw std::runtime_error("invalid type found"); } - return dynamic_pointer_cast(type.value()); + return dynamic_pointer_cast(type.value()->get_type()); } std::any Builder::visitQualifier(FusionParser::QualifierContext* ctx) { @@ -144,7 +145,7 @@ std::any Builder::visitLiteralChar(FusionParser::LiteralCharContext* ctx) { std::any Builder::visitIdentifier(FusionParser::IdentifierContext* ctx) { Token* token = ctx->ID()->getSymbol(); std::string name = ctx->ID()->getText(); - TypePtr type = make_shared(Type::unset); + TypePtr type = make_shared(); auto var = make_shared(ast::Qualifier::Let, type, name, token); @@ -361,7 +362,7 @@ std::any Builder::visitUnary(FusionParser::UnaryContext* ctx) { std::any Builder::visitAssignment(FusionParser::AssignmentContext* ctx) { Token* token = ctx->ID()->getSymbol(); std::string name = ctx->ID()->getText(); - TypePtr type = make_shared(Type::unset); + TypePtr type = make_shared(); auto var = make_shared(ast::Qualifier::Let, type, name, token); diff --git a/src/ast/passes/type_check.cpp b/src/ast/passes/type_check.cpp index 342be90..f6d63e3 100644 --- a/src/ast/passes/type_check.cpp +++ b/src/ast/passes/type_check.cpp @@ -79,11 +79,12 @@ void TypeCheck::visit_binary_operator(shared_ptr node) { visit(node->rhs); size_t line = node->token->getLine(); - Type lhs = *node->lhs->get_type(); - Type rhs = *node->rhs->get_type(); - if (lhs != rhs) { - throw TypeError(line, "mismatched lhs(" + lhs.get_name() + - ") and rhs(" + rhs.get_name() + + TypePtr lhs = node->lhs->get_type(); + TypePtr rhs = node->rhs->get_type(); + + if (*lhs != *rhs) { + throw TypeError(line, "mismatched lhs(" + lhs->get_name() + + ") and rhs(" + rhs->get_name() + ") types on binary operator: " + ast::binary_op_type_to_string(node->type)); } @@ -116,6 +117,7 @@ void TypeCheck::visit_binary_operator(shared_ptr node) { case ast::BinaryOpType::EQ: case ast::BinaryOpType::NE: node->set_type(ctx::t_bool); + break; } } @@ -137,14 +139,14 @@ void TypeCheck::visit_unary_operator(shared_ptr node) { } } -void TypeCheck::check_numeric(Type type, size_t line) { - if (type != *ctx::i32) { - throw TypeError(line, "type(" + type.get_name() + ") is not numeric"); +void TypeCheck::check_numeric(TypePtr type, size_t line) { + if (!type->is_numeric()) { + throw TypeError(line, "type(" + type->get_name() + ") is not numeric"); } } -void TypeCheck::check_bool(Type type, size_t line) { - if (type != *ctx::t_bool) { - throw TypeError(line, "type(" + type.get_name() + ") is not boolean"); +void TypeCheck::check_bool(TypePtr type, size_t line) { + if (*type != *ctx::t_bool) { + throw TypeError(line, "type(" + type->get_name() + ") is not boolean"); } } diff --git a/src/ast/symbol/symbol.cpp b/src/ast/symbol/symbol.cpp index 9fa9a20..dd2b95c 100644 --- a/src/ast/symbol/symbol.cpp +++ b/src/ast/symbol/symbol.cpp @@ -15,8 +15,8 @@ TypePtr Symbol::get_type() { return this->type; } -BuiltinTypeSymbol::BuiltinTypeSymbol(std::string name) - : Symbol(name), Type(name) {} +BuiltinTypeSymbol::BuiltinTypeSymbol(TypePtr type) + : Symbol(type->get_name(), type) {} std::string BuiltinTypeSymbol::get_name() { return Symbol::get_name(); diff --git a/src/ast/symbol/symbol_table.cpp b/src/ast/symbol/symbol_table.cpp index 3ee9865..c684b6b 100644 --- a/src/ast/symbol/symbol_table.cpp +++ b/src/ast/symbol/symbol_table.cpp @@ -52,9 +52,9 @@ SymbolTable::SymbolTable() { void SymbolTable::init_types() { for (const auto& ty : ctx::primitives) { - define(make_shared(ty->get_name())); + define(make_shared(ty)); } - define(make_shared(ctx::any->get_name())); + define(make_shared(ctx::any)); } void SymbolTable::init_builtins() { diff --git a/src/backend/builtin/print.cpp b/src/backend/builtin/print.cpp index b227abb..65a8644 100644 --- a/src/backend/builtin/print.cpp +++ b/src/backend/builtin/print.cpp @@ -9,7 +9,7 @@ namespace { void create_type_str(TypePtr type) { std::string ty = type->get_specifier(); - auto gvalue = mlir::StringRef(ty.c_str(), 3); + auto gvalue = mlir::StringRef(ty.c_str(), ty.size() + 1); auto gtype = mlir::LLVM::LLVMArrayType::get(ctx::ch->get_mlir(), gvalue.size()); diff --git a/src/shared/context.cpp b/src/shared/context.cpp index 37dd446..61962c7 100644 --- a/src/shared/context.cpp +++ b/src/shared/context.cpp @@ -1,4 +1,9 @@ #include "shared/context.h" +#include "shared/type/boolean.h" +#include "shared/type/character.h" +#include "shared/type/float.h" +#include "shared/type/integer.h" +#include "shared/type/type.h" mlir::MLIRContext ctx::context; std::unique_ptr ctx::loc = @@ -19,12 +24,12 @@ void ctx::initialize_context() { context.loadDialect(); builder = std::make_shared(&context); - ctx::ch = std::make_shared(Type::ch); - ctx::any = std::make_shared(Type::any); - ctx::i32 = std::make_shared(Type::i32); - ctx::f32 = std::make_shared(Type::f32); - ctx::none = std::make_shared(Type::none); - ctx::t_bool = std::make_shared(Type::t_bool); + ctx::any = make_shared(); + ctx::i32 = make_shared(); + ctx::f32 = make_shared(); + ctx::none = make_shared(); + ctx::ch = make_shared(); + ctx::t_bool = make_shared(); ctx::primitives = { ctx::ch, diff --git a/src/shared/type.cpp b/src/shared/type.cpp deleted file mode 100644 index 663692a..0000000 --- a/src/shared/type.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include - -#include "shared/context.h" -#include "shared/type.h" - -const Type Type::ch = Type("ch"); -const Type Type::any = Type("any"); -const Type Type::i32 = Type("i32"); -const Type Type::f32 = Type("f32"); -const Type Type::none = Type("none"); -const Type Type::unset = Type("unset"); -const Type Type::t_bool = Type("bool"); - -Type::Type(std::string name) { - this->name = name; -} - -bool Type::operator==(const Type rhs) const { - return name == rhs.name || rhs.name == "any"; -} - -std::string Type::get_name() const { - return this->name; -} - -std::string Type::get_specifier() const { - if (*this == Type::ch) { - return "%c"; - } - - if (*this == Type::i32) { - return "%d"; - } - - if (*this == Type::f32) { - return "%g"; - } - - if (*this == Type::t_bool) { - return "%d"; - } - - throw std::runtime_error("type is not printable"); -} - -mlir::Type Type::get_mlir() const { - if (*this == Type::ch) { - return ctx::builder->getI8Type(); - } - - if (*this == Type::i32) { - return ctx::builder->getI32Type(); - } - - if (*this == Type::f32) { - return ctx::builder->getF32Type(); - } - - if (*this == Type::t_bool) { - return ctx::builder->getI1Type(); - } - - if (*this == Type::none) { - return mlir::LLVM::LLVMVoidType::get(&ctx::context); - } - - throw std::runtime_error("invalid mlir type found"); -} - -mlir::Type Type::get_pointer() { - return mlir::LLVM::LLVMPointerType::get(get_mlir()); -} diff --git a/src/shared/type/boolean.cpp b/src/shared/type/boolean.cpp new file mode 100644 index 0000000..d6fd212 --- /dev/null +++ b/src/shared/type/boolean.cpp @@ -0,0 +1,12 @@ +#include "shared/type/boolean.h" +#include "shared/context.h" + +Boolean::Boolean() : Type("bool") {} + +std::string Boolean::get_specifier() const { + return "%d"; +} + +mlir::Type Boolean::get_mlir() const { + return ctx::builder->getI1Type(); +} diff --git a/src/shared/type/character.cpp b/src/shared/type/character.cpp new file mode 100644 index 0000000..6dcca07 --- /dev/null +++ b/src/shared/type/character.cpp @@ -0,0 +1,12 @@ +#include "shared/type/character.h" +#include "shared/context.h" + +Character::Character() : Type("ch") {} + +std::string Character::get_specifier() const { + return "%c"; +} + +mlir::Type Character::get_mlir() const { + return ctx::builder->getI8Type(); +} diff --git a/src/shared/type/float.cpp b/src/shared/type/float.cpp new file mode 100644 index 0000000..e9fcc74 --- /dev/null +++ b/src/shared/type/float.cpp @@ -0,0 +1,12 @@ +#include "shared/type/float.h" +#include "shared/context.h" + +F32::F32() : Type("f32") {} + +std::string F32::get_specifier() const { + return "%g"; +} + +mlir::Type F32::get_mlir() const { + return ctx::builder->getF32Type(); +} diff --git a/src/shared/type/integer.cpp b/src/shared/type/integer.cpp new file mode 100644 index 0000000..d38da35 --- /dev/null +++ b/src/shared/type/integer.cpp @@ -0,0 +1,16 @@ +#include "shared/type/integer.h" +#include "shared/context.h" + +I32::I32() : Type("i32") {} + +std::string I32::get_specifier() const { + return "%d"; +} + +mlir::Type I32::get_mlir() const { + return ctx::builder->getI32Type(); +} + +bool I32::is_numeric() const { + return true; +} diff --git a/src/shared/type/type.cpp b/src/shared/type/type.cpp new file mode 100644 index 0000000..23aeed2 --- /dev/null +++ b/src/shared/type/type.cpp @@ -0,0 +1,54 @@ +#include + +#include "shared/context.h" +#include "shared/type/type.h" + +Type::Type(std::string name) { + this->name = name; +} + +bool Type::operator==(const Type rhs) const { + return name == rhs.name || rhs.name == "any"; +} + +std::string Type::get_name() const { + return this->name; +} + +std::string Type::get_specifier() const { + throw std::runtime_error("type " + name + " is not printable"); +} + +mlir::Type Type::get_mlir() const { + throw std::runtime_error("invalid mlir type found " + name); +} + +bool Type::is_numeric() const { + return false; +} + +mlir::Type Type::get_pointer() { + return mlir::LLVM::LLVMPointerType::get(get_mlir()); +} + +Any::Any() : Type("any") {} + +std::string Any::get_specifier() const { + return "any"; +} + +None::None() : Type("none") {} + +std::string None::get_specifier() const { + return "none"; +} + +mlir::Type None::get_mlir() const { + return mlir::LLVM::LLVMVoidType::get(&ctx::context); +} + +Unset::Unset() : Type("unset") {} + +std::string Unset::get_specifier() const { + return "unset"; +}