Compare commits
No commits in common. "89c397b15c4d27299c422467e53867e4f9aefbcc" and "b541cf6baf9b01a59883341f27d3394d5deaaebc" have entirely different histories.
89c397b15c
...
b541cf6baf
@ -24,7 +24,6 @@ add_executable(${PROJECT_NAME}
|
|||||||
src/types.cpp
|
src/types.cpp
|
||||||
src/typechecker.cpp
|
src/typechecker.cpp
|
||||||
src/binops.cpp
|
src/binops.cpp
|
||||||
src/casting.cpp
|
|
||||||
)
|
)
|
||||||
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
|
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
|
||||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Weffc++ -Wextra -Wpedantic -Werror)
|
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Weffc++ -Wextra -Wpedantic -Werror)
|
||||||
|
|||||||
@ -42,13 +42,6 @@ namespace AST {
|
|||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CastExpression::formatted() {
|
|
||||||
std::stringstream out{ "" };
|
|
||||||
out << "(" << this->m_ty->formatted() << ") ";
|
|
||||||
out << this->m_expr->formatted();
|
|
||||||
return out.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ExpressionStatement::formatted() {
|
std::string ExpressionStatement::formatted() {
|
||||||
std::stringstream out{ "" };
|
std::stringstream out{ "" };
|
||||||
out << this->m_expr->formatted();
|
out << this->m_expr->formatted();
|
||||||
|
|||||||
32
src/ast.h
32
src/ast.h
@ -42,15 +42,8 @@ namespace AST {
|
|||||||
class IntLiteralExpression : public Expression {
|
class IntLiteralExpression : public Expression {
|
||||||
private:
|
private:
|
||||||
int m_value;
|
int m_value;
|
||||||
std::shared_ptr<types::Type> m_ty;
|
|
||||||
public:
|
public:
|
||||||
IntLiteralExpression(token::Metadata meta, int value)
|
IntLiteralExpression(token::Metadata meta, int value) : Expression{ meta }, m_value{ value } {}
|
||||||
: Expression{ meta }
|
|
||||||
, m_value{ value }
|
|
||||||
, m_ty{ { std::shared_ptr<types::Type>{
|
|
||||||
new types::FundamentalType{types::FundamentalTypeKind::Int}
|
|
||||||
} } } {
|
|
||||||
}
|
|
||||||
virtual ~IntLiteralExpression() override = default;
|
virtual ~IntLiteralExpression() override = default;
|
||||||
virtual std::string formatted() override;
|
virtual std::string formatted() override;
|
||||||
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
|
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
|
||||||
@ -140,29 +133,6 @@ namespace AST {
|
|||||||
) override;
|
) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CastExpression : public Expression {
|
|
||||||
private:
|
|
||||||
std::shared_ptr<types::Type> m_ty;
|
|
||||||
std::unique_ptr<Expression> m_expr;
|
|
||||||
public:
|
|
||||||
CastExpression(
|
|
||||||
token::Metadata meta,
|
|
||||||
std::shared_ptr<types::Type> type,
|
|
||||||
std::unique_ptr<Expression> expr)
|
|
||||||
: Expression{ meta }
|
|
||||||
, m_ty{ type }
|
|
||||||
, m_expr{ std::move(expr) } {
|
|
||||||
}
|
|
||||||
virtual ~CastExpression() override = default;
|
|
||||||
virtual std::string formatted() override;
|
|
||||||
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
|
|
||||||
virtual std::shared_ptr<types::Type> typecheck(
|
|
||||||
typecheck::State& state,
|
|
||||||
typecheck::Scope& scope,
|
|
||||||
std::optional<std::shared_ptr<types::Type>> expected_ty
|
|
||||||
) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class ReturnStatement : public Statement {
|
class ReturnStatement : public Statement {
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -12,8 +12,8 @@ namespace types {
|
|||||||
auto bool_ty = std::shared_ptr<types::Type>{
|
auto bool_ty = std::shared_ptr<types::Type>{
|
||||||
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
|
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
|
||||||
|
|
||||||
// Integer arithmetic binops
|
|
||||||
for (auto& ty : { int_ty, char_ty, bool_ty }) {
|
for (auto& ty : { int_ty, char_ty, bool_ty }) {
|
||||||
|
// Arithmetic binops
|
||||||
definitions.push_back(BinopDefinition{
|
definitions.push_back(BinopDefinition{
|
||||||
ty, types::BinOp::Add, ty,
|
ty, types::BinOp::Add, ty,
|
||||||
ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
@ -25,14 +25,12 @@ namespace types {
|
|||||||
ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
return builder.builder->CreateSub(lhs, rhs, "sub");
|
return builder.builder->CreateSub(lhs, rhs, "sub");
|
||||||
} });
|
} });
|
||||||
}
|
|
||||||
|
|
||||||
// Signed comparisons
|
// Comparisons
|
||||||
for (auto& ty : { int_ty }) {
|
|
||||||
definitions.push_back(BinopDefinition{
|
definitions.push_back(BinopDefinition{
|
||||||
ty, types::BinOp::LessThan, ty,
|
ty, types::BinOp::LessThan, ty,
|
||||||
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||||
return builder.builder->CreateICmpSLT(lhs, rhs, "icmpslt");
|
return builder.builder->CreateICmpSLE(lhs, rhs, "icmpsle");
|
||||||
} });
|
} });
|
||||||
|
|
||||||
definitions.push_back(BinopDefinition{
|
definitions.push_back(BinopDefinition{
|
||||||
@ -42,21 +40,6 @@ namespace types {
|
|||||||
} });
|
} });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsigned comparisons
|
|
||||||
for (auto& ty : { bool_ty, char_ty }) {
|
|
||||||
definitions.push_back(BinopDefinition{
|
|
||||||
ty, types::BinOp::LessThan, ty,
|
|
||||||
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
|
||||||
return builder.builder->CreateICmpULT(lhs, rhs, "icmpslt");
|
|
||||||
} });
|
|
||||||
|
|
||||||
definitions.push_back(BinopDefinition{
|
|
||||||
ty, types::BinOp::GreaterThan, ty,
|
|
||||||
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
|
||||||
return builder.builder->CreateICmpUGT(lhs, rhs, "icmpsgt");
|
|
||||||
} });
|
|
||||||
}
|
|
||||||
|
|
||||||
return definitions;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,55 +0,0 @@
|
|||||||
|
|
||||||
#include "casting.h"
|
|
||||||
|
|
||||||
namespace types {
|
|
||||||
std::vector<CastDefinition> create_casts() {
|
|
||||||
std::vector<CastDefinition> casts{};
|
|
||||||
|
|
||||||
auto int_ty = std::shared_ptr<Type>{
|
|
||||||
new FundamentalType{ FundamentalTypeKind::Int } };
|
|
||||||
auto char_ty = std::shared_ptr<Type>{
|
|
||||||
new FundamentalType{ FundamentalTypeKind::Char } };
|
|
||||||
auto bool_ty = std::shared_ptr<Type>{
|
|
||||||
new FundamentalType{ FundamentalTypeKind::Bool } };
|
|
||||||
|
|
||||||
for (auto& source_ty : { int_ty, char_ty, bool_ty }) {
|
|
||||||
for (auto& target_ty : { int_ty, char_ty, bool_ty }) {
|
|
||||||
if (types::types_equal(source_ty, target_ty)) {
|
|
||||||
casts.push_back(CastDefinition{ source_ty, target_ty, true,
|
|
||||||
[](codegen::Builder&, std::shared_ptr<Type>, llvm::Value* value) {
|
|
||||||
return value;
|
|
||||||
} });
|
|
||||||
}
|
|
||||||
else if (target_ty->is_signed()) {
|
|
||||||
casts.push_back(CastDefinition{ source_ty, target_ty, false,
|
|
||||||
[](codegen::Builder& builder, std::shared_ptr<Type> target, llvm::Value* value) {
|
|
||||||
return builder.builder->CreateSExtOrTrunc(value, target->codegen(builder), "cast");
|
|
||||||
} });
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
casts.push_back(CastDefinition{ source_ty, target_ty, false,
|
|
||||||
[](codegen::Builder& builder, std::shared_ptr<Type> target, llvm::Value* value) {
|
|
||||||
return builder.builder->CreateZExtOrTrunc(value, target->codegen(builder), "cast");
|
|
||||||
} });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return casts;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::optional<CastDefinition> find_cast(
|
|
||||||
std::vector<CastDefinition>& casts,
|
|
||||||
std::shared_ptr<Type> casted_ty,
|
|
||||||
std::shared_ptr<Type> target_ty) {
|
|
||||||
|
|
||||||
for (auto& cast : casts) {
|
|
||||||
if (types_equal(cast.casted_ty, casted_ty) && types_equal(cast.target_ty, target_ty)) {
|
|
||||||
return cast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
#ifndef CASTING_H
|
|
||||||
#define CASTING_H
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
namespace types {
|
|
||||||
struct CastDefinition {
|
|
||||||
std::shared_ptr<Type> casted_ty;
|
|
||||||
std::shared_ptr<Type> target_ty;
|
|
||||||
bool allow_implicit;
|
|
||||||
|
|
||||||
llvm::Value* (*codegen)(codegen::Builder& builder, std::shared_ptr<types::Type> target, llvm::Value* value);
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<CastDefinition> create_casts();
|
|
||||||
|
|
||||||
std::optional<CastDefinition> find_cast(
|
|
||||||
std::vector<CastDefinition>& casts,
|
|
||||||
std::shared_ptr<Type> casted_ty,
|
|
||||||
std::shared_ptr<Type> target_ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -11,17 +11,19 @@
|
|||||||
|
|
||||||
namespace codegen {
|
namespace codegen {
|
||||||
Scope Scope::with_lvalue() {
|
Scope Scope::with_lvalue() {
|
||||||
return Scope{ this->binops, this->casts, this->values, true };
|
return Scope{ this->binops, this->values, true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace AST {
|
namespace AST {
|
||||||
codegen::StackValue IntLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope&) {
|
codegen::StackValue IntLiteralExpression::codegen(codegen::Builder& builder, codegen::Scope&) {
|
||||||
auto ty = this->m_ty->codegen(builder);
|
auto ty = builder.builder->getInt32Ty();
|
||||||
|
|
||||||
|
auto stack_type = new types::FundamentalType{ types::FundamentalTypeKind::Int };
|
||||||
|
|
||||||
return codegen::StackValue{
|
return codegen::StackValue{
|
||||||
llvm::ConstantInt::get(ty, this->m_value),
|
llvm::ConstantInt::get(ty, this->m_value),
|
||||||
this->m_ty,
|
std::unique_ptr<types::Type>{stack_type}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,18 +101,6 @@ namespace AST {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
if (cast) {
|
|
||||||
return codegen::StackValue{
|
|
||||||
cast->codegen(builder, cast->target_ty, expr.value),
|
|
||||||
cast->target_ty
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||||
if (!builder.block)
|
if (!builder.block)
|
||||||
return;
|
return;
|
||||||
@ -142,9 +132,7 @@ namespace AST {
|
|||||||
builder.builder->CreateStore(value.value, ptr, false);
|
builder.builder->CreateStore(value.value, ptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ptr_ty = std::shared_ptr<types::Type>{ new types::PointerType{ this->m_type } };
|
scope.values[this->m_name] = codegen::StackValue{ ptr, this->m_type };
|
||||||
|
|
||||||
scope.values[this->m_name] = codegen::StackValue{ ptr, ptr_ty };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IfStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
void IfStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include "builder.h"
|
#include "builder.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "binops.h"
|
#include "binops.h"
|
||||||
#include "casting.h"
|
|
||||||
#include "tokens.h"
|
#include "tokens.h"
|
||||||
|
|
||||||
namespace codegen {
|
namespace codegen {
|
||||||
@ -20,7 +19,6 @@ namespace codegen {
|
|||||||
|
|
||||||
struct Scope {
|
struct Scope {
|
||||||
std::vector<types::BinopDefinition>& binops;
|
std::vector<types::BinopDefinition>& binops;
|
||||||
std::vector<types::CastDefinition>& casts;
|
|
||||||
|
|
||||||
std::map<std::string, StackValue> values;
|
std::map<std::string, StackValue> values;
|
||||||
bool is_lvalue;
|
bool is_lvalue;
|
||||||
|
|||||||
@ -99,7 +99,6 @@ std::optional<CompileOutput> compile(std::string_view in_filename) {
|
|||||||
|
|
||||||
typecheck::State typecheck_state{};
|
typecheck::State typecheck_state{};
|
||||||
typecheck_state.binops = types::create_binops();
|
typecheck_state.binops = types::create_binops();
|
||||||
typecheck_state.casts = types::create_casts();
|
|
||||||
|
|
||||||
typecheck::Scope typecheck_scope{};
|
typecheck::Scope typecheck_scope{};
|
||||||
for (auto& tls : statements) {
|
for (auto& tls : statements) {
|
||||||
@ -119,7 +118,6 @@ std::optional<CompileOutput> compile(std::string_view in_filename) {
|
|||||||
|
|
||||||
codegen::Scope cg_scope{
|
codegen::Scope cg_scope{
|
||||||
.binops = typecheck_state.binops,
|
.binops = typecheck_state.binops,
|
||||||
.casts = typecheck_state.casts,
|
|
||||||
.values = {},
|
.values = {},
|
||||||
.is_lvalue = false,
|
.is_lvalue = false,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -80,39 +80,10 @@ namespace parsing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<std::shared_ptr<types::Type>, std::string> parse_cast(token::TokenStream& stream) {
|
|
||||||
token::TokenStream inner{ stream };
|
|
||||||
try {
|
|
||||||
inner.expect(token::Type::Symbol, "(");
|
|
||||||
auto ty = parse_type(inner).unwrap();
|
|
||||||
inner.expect(token::Type::Symbol, ")");
|
|
||||||
|
|
||||||
stream.m_position = inner.m_position;
|
|
||||||
|
|
||||||
return ty;
|
|
||||||
}
|
|
||||||
catch (std::runtime_error& error) {
|
|
||||||
return std::string{ error.what() };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<std::unique_ptr<AST::Expression>, std::string> parse_primary_expression(token::TokenStream& stream) {
|
Result<std::unique_ptr<AST::Expression>, std::string> parse_primary_expression(token::TokenStream& stream) {
|
||||||
token::TokenStream inner{ stream };
|
token::TokenStream inner{ stream };
|
||||||
try {
|
try {
|
||||||
auto before_meta = inner.metadata();
|
auto before_meta = inner.metadata();
|
||||||
|
|
||||||
if (auto cast = parse_cast(inner); cast.ok()) {
|
|
||||||
auto expr = parse_expression(inner).unwrap();
|
|
||||||
stream.m_position = inner.m_position;
|
|
||||||
return std::unique_ptr<AST::Expression>{
|
|
||||||
new AST::CastExpression{
|
|
||||||
before_meta + inner.metadata(),
|
|
||||||
cast.unwrap(),
|
|
||||||
std::move(expr)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto plain_expr = parse_plain_expression(inner);
|
auto plain_expr = parse_plain_expression(inner);
|
||||||
while (inner.peek().content == "(") {
|
while (inner.peek().content == "(") {
|
||||||
inner.next();
|
inner.next();
|
||||||
|
|||||||
@ -43,24 +43,11 @@ namespace AST {
|
|||||||
std::shared_ptr<types::Type> IntLiteralExpression::typecheck(
|
std::shared_ptr<types::Type> IntLiteralExpression::typecheck(
|
||||||
typecheck::State&,
|
typecheck::State&,
|
||||||
typecheck::Scope&,
|
typecheck::Scope&,
|
||||||
std::optional<std::shared_ptr<types::Type>> expected_ty
|
std::optional<std::shared_ptr<types::Type>>
|
||||||
) {
|
) {
|
||||||
// Allow implicitly converting IntLiteralExpression to other types
|
return std::shared_ptr<types::Type>{
|
||||||
// representable by integers.
|
new types::FundamentalType{ types::FundamentalTypeKind::Int }
|
||||||
if (expected_ty) {
|
};
|
||||||
if ((*expected_ty)->m_kind == types::TypeKind::Fundamental) {
|
|
||||||
auto ty = dynamic_cast<types::FundamentalType*>((*expected_ty).get());
|
|
||||||
if (
|
|
||||||
ty->m_ty == types::FundamentalTypeKind::Bool
|
|
||||||
|| ty->m_ty == types::FundamentalTypeKind::Char
|
|
||||||
|| ty->m_ty == types::FundamentalTypeKind::Int
|
|
||||||
) {
|
|
||||||
this->m_ty = *expected_ty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->m_ty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<types::Type> StringLiteralExpression::typecheck(
|
std::shared_ptr<types::Type> StringLiteralExpression::typecheck(
|
||||||
@ -99,8 +86,6 @@ namespace AST {
|
|||||||
auto rhs_ty = this->m_rhs->typecheck(state, scope, {});
|
auto rhs_ty = this->m_rhs->typecheck(state, scope, {});
|
||||||
|
|
||||||
if (this->m_binop == types::BinOp::Assignment) {
|
if (this->m_binop == types::BinOp::Assignment) {
|
||||||
// Re-typecheck rhs to actually match lhs
|
|
||||||
auto rhs_ty = this->m_rhs->typecheck(state, scope, lhs_ty);
|
|
||||||
return lhs_ty;
|
return lhs_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,25 +153,6 @@ namespace AST {
|
|||||||
return fn_ty->m_ret_ty;
|
return fn_ty->m_ret_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<types::Type> CastExpression::typecheck(
|
|
||||||
typecheck::State& state,
|
|
||||||
typecheck::Scope& scope,
|
|
||||||
std::optional<std::shared_ptr<types::Type>>
|
|
||||||
) {
|
|
||||||
auto expr_ty = this->m_expr->typecheck(state, scope, {});
|
|
||||||
auto cast = types::find_cast(state.casts, expr_ty, this->m_ty);
|
|
||||||
if (cast) {
|
|
||||||
return cast->target_ty;
|
|
||||||
}
|
|
||||||
state.errors.push_back(CompileError("Cast from type "
|
|
||||||
+ expr_ty->formatted() + "to type " + this->m_ty->formatted()
|
|
||||||
+ " is not permitted", this->m_meta));
|
|
||||||
return std::shared_ptr<types::Type> { new types::FundamentalType{
|
|
||||||
types::FundamentalTypeKind::Void
|
|
||||||
} };
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReturnStatement::typecheck(typecheck::State& state, typecheck::Scope& scope) {
|
void ReturnStatement::typecheck(typecheck::State& state, typecheck::Scope& scope) {
|
||||||
auto res_ty = this->m_expr->typecheck(state, scope, scope.return_ty);
|
auto res_ty = this->m_expr->typecheck(state, scope, scope.return_ty);
|
||||||
if (scope.return_ty) {
|
if (scope.return_ty) {
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "binops.h"
|
#include "binops.h"
|
||||||
#include "casting.h"
|
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
|
||||||
namespace typecheck {
|
namespace typecheck {
|
||||||
@ -16,7 +15,6 @@ namespace typecheck {
|
|||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
std::vector<types::BinopDefinition> binops;
|
std::vector<types::BinopDefinition> binops;
|
||||||
std::vector<types::CastDefinition> casts;
|
|
||||||
std::vector<CompileError> errors;
|
std::vector<CompileError> errors;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,10 +75,6 @@ namespace types {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_signed() {
|
|
||||||
false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<llvm::Value*, std::shared_ptr<Type>> FundamentalType::load(codegen::Builder&, llvm::Value* ptr) {
|
std::pair<llvm::Value*, std::shared_ptr<Type>> FundamentalType::load(codegen::Builder&, llvm::Value* ptr) {
|
||||||
auto self = std::make_shared<FundamentalType>(*this);
|
auto self = std::make_shared<FundamentalType>(*this);
|
||||||
return std::pair(ptr, self);
|
return std::pair(ptr, self);
|
||||||
@ -128,18 +124,6 @@ namespace types {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FundamentalType::is_signed() {
|
|
||||||
switch (this->m_ty) {
|
|
||||||
case FundamentalTypeKind::Int:
|
|
||||||
return true;
|
|
||||||
case FundamentalTypeKind::Bool:
|
|
||||||
case FundamentalTypeKind::Char:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Invalid type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string FunctionType::formatted() {
|
std::string FunctionType::formatted() {
|
||||||
std::stringstream out{ "" };
|
std::stringstream out{ "" };
|
||||||
out << "(";
|
out << "(";
|
||||||
|
|||||||
@ -33,7 +33,6 @@ namespace types {
|
|||||||
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
|
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
|
||||||
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
|
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
|
||||||
virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
|
virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
|
||||||
virtual bool is_signed();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FundamentalType : public Type {
|
class FundamentalType : public Type {
|
||||||
@ -48,7 +47,6 @@ namespace types {
|
|||||||
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
virtual llvm::Value* sub(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override;
|
||||||
virtual bool is_signed() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user