diff --git a/a.out b/a.out new file mode 100755 index 0000000..0abd102 Binary files /dev/null and b/a.out differ diff --git a/src/ast.h b/src/ast.h index b898eb9..189f1c1 100644 --- a/src/ast.h +++ b/src/ast.h @@ -25,6 +25,7 @@ namespace AST { public: Expression(token::Metadata meta) : Node{ meta } {} virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) = 0; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) = 0; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -55,6 +56,7 @@ namespace AST { virtual ~IntLiteralExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -71,6 +73,7 @@ namespace AST { virtual ~StringLiteralExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -87,6 +90,7 @@ namespace AST { virtual ~ValueReferenceExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -114,6 +118,7 @@ namespace AST { virtual ~BinaryOperationExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -138,6 +143,7 @@ namespace AST { virtual ~FunctionCallExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -162,6 +168,7 @@ namespace AST { virtual ~CastExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -183,6 +190,7 @@ namespace AST { virtual ~RefExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -204,6 +212,7 @@ namespace AST { virtual ~DerefExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, @@ -228,6 +237,7 @@ namespace AST { virtual ~IndexAccessExpression() override = default; virtual std::string formatted() override; virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override; + virtual std::shared_ptr get_codegen_type(codegen::Scope& scope) override; virtual std::shared_ptr typecheck( typecheck::State& state, typecheck::Scope& scope, diff --git a/src/codegen.cpp b/src/codegen.cpp index d19a566..5d11dea 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -16,6 +16,10 @@ namespace codegen { } namespace AST { + std::shared_ptr IntLiteralExpression::get_codegen_type(codegen::Scope&) { + return this->m_ty; + } + codegen::StackValue IntLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope&) { auto ty = this->m_ty->codegen(builder); @@ -25,6 +29,14 @@ namespace AST { }; } + std::shared_ptr StringLiteralExpression::get_codegen_type(codegen::Scope&) { + auto stack_type = new types::ArrayType{ + std::make_unique(types::FundamentalTypeKind::Char), + static_cast(this->m_value.size()) + 1 + }; + return std::shared_ptr {stack_type}; + } + codegen::StackValue StringLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope&) { auto stack_type = new types::ArrayType{ std::make_unique(types::FundamentalTypeKind::Char), @@ -40,6 +52,16 @@ namespace AST { }; } + std::shared_ptr ValueReferenceExpression::get_codegen_type(codegen::Scope& scope) { + auto value = scope.values.find(this->m_name); + if (value != scope.values.end()) { + return value->second.ty; + } + else { + throw CompileError("Value " + this->m_name + " not found", this->m_meta); + } + } + codegen::StackValue ValueReferenceExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto value = scope.values.find(this->m_name); if (value != scope.values.end()) { @@ -59,6 +81,30 @@ namespace AST { } } + std::shared_ptr BinaryOperationExpression::get_codegen_type(codegen::Scope& scope) { + auto lhs = this->m_lhs->get_codegen_type(scope); + auto rhs = this->m_rhs->get_codegen_type(scope); + try { + switch (this->m_binop) { + case types::BinOp::Assignment: + return rhs; + default: + auto binop = types::find_binop( + scope.binops, + lhs, + this->m_binop, + rhs); + if (binop) { + return binop->result(*binop, lhs, rhs); + } + throw CompileError("invalid binop", this->m_meta); + } + } + catch (std::runtime_error& error) { + throw CompileError(error.what(), this->m_meta); + } + } + codegen::StackValue BinaryOperationExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto lvalued = scope.with_lvalue(); auto lhs = this->m_lhs->codegen(builder, this->m_binop == types::BinOp::Assignment ? lvalued : scope); @@ -88,6 +134,11 @@ namespace AST { } } + std::shared_ptr FunctionCallExpression::get_codegen_type(codegen::Scope& scope) { + auto fn_ty = this->m_fn_expr->get_codegen_type(scope); + return *fn_ty->return_type(); + } + codegen::StackValue FunctionCallExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { std::vector args{}; for (auto& arg : this->m_args) { @@ -102,6 +153,10 @@ namespace AST { }; } + std::shared_ptr CastExpression::get_codegen_type(codegen::Scope&) { + return this->m_ty; + } + codegen::StackValue CastExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto expr = this->m_expr->codegen(builder, scope); auto cast = types::find_cast(scope.casts, expr.ty, this->m_ty); @@ -122,11 +177,28 @@ namespace AST { return expr; } + std::shared_ptr RefExpression::get_codegen_type(codegen::Scope& scope) { + return std::shared_ptr { + new types::PointerType{ this->m_expr->get_codegen_type(scope) } + }; + } + codegen::StackValue RefExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto with_lvalue = scope.with_lvalue(); return this->m_expr->codegen(builder, with_lvalue); } + std::shared_ptr DerefExpression::get_codegen_type(codegen::Scope& scope) { + auto ty = this->m_expr->get_codegen_type(scope); + if (ty->m_kind == types::TypeKind::Pointer) { + auto ptr_ty = dynamic_cast(ty.get()); + return ptr_ty->m_inner; + } + else { + throw new CompileError("Tried to deref a non-pointer!", this->m_meta); + } + } + codegen::StackValue DerefExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto value = this->m_expr->codegen(builder, scope); if (value.ty->m_kind == types::TypeKind::Pointer) { @@ -141,6 +213,21 @@ namespace AST { } } + std::shared_ptr IndexAccessExpression::get_codegen_type(codegen::Scope& scope) { + auto ty = this->m_expr->get_codegen_type(scope); + if (ty->m_kind == types::TypeKind::Array) { + auto ptr_ty = dynamic_cast(ty.get()); + return ptr_ty->m_inner; + } + else if (ty->m_kind == types::TypeKind::Pointer) { + auto ptr_ty = dynamic_cast(ty.get()); + return ptr_ty->m_inner; + } + else { + throw CompileError("Tried indexing a non-pointer", this->m_meta); + } + } + codegen::StackValue IndexAccessExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) { auto lvalue_scope = scope.with_lvalue(); diff --git a/test.c b/test.c index 7708643..96b9cf3 100644 --- a/test.c +++ b/test.c @@ -6,8 +6,8 @@ int fibonacci(int n) { return fibonacci(n - 1) + fibonacci(n - 2); } -void modify_value(char* otus) { - *otus = 20; +void change_first(char otus[5]) { + otus[0] = 115; } int main() { @@ -17,8 +17,7 @@ int main() { char somelist[5]; somelist[0] = 15; - somelist[1] = 20; - somelist[2] = 25; + change_first(somelist); return somelist[0]; } \ No newline at end of file