Compare commits
No commits in common. "be2d809986a80880a0d3c80917fc941423c5f076" and "57dc0222411f98aa6558563d2655a4e59bf77269" have entirely different histories.
be2d809986
...
57dc022241
12
src/ast.cpp
12
src/ast.cpp
@ -49,18 +49,6 @@ namespace AST {
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string RefExpression::formatted() {
|
||||
std::stringstream out{ "" };
|
||||
out << "&" << this->m_expr->formatted();
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string DerefExpression::formatted() {
|
||||
std::stringstream out{ "" };
|
||||
out << "*" << this->m_expr->formatted();
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string ExpressionStatement::formatted() {
|
||||
std::stringstream out{ "" };
|
||||
out << this->m_expr->formatted();
|
||||
|
||||
48
src/ast.h
48
src/ast.h
@ -39,7 +39,6 @@ namespace AST {
|
||||
virtual void typecheck(typecheck::State& state, typecheck::Scope& scope) = 0;
|
||||
};
|
||||
|
||||
/// @brief Any integer literal
|
||||
class IntLiteralExpression : public Expression {
|
||||
private:
|
||||
int m_value;
|
||||
@ -62,7 +61,6 @@ namespace AST {
|
||||
) override;
|
||||
};
|
||||
|
||||
/// @brief i.e. "contents"
|
||||
class StringLiteralExpression : public Expression {
|
||||
private:
|
||||
std::string m_value;
|
||||
@ -78,7 +76,6 @@ namespace AST {
|
||||
) override;
|
||||
};
|
||||
|
||||
/// @brief Anything that references by value
|
||||
class ValueReferenceExpression : public Expression {
|
||||
private:
|
||||
std::string m_name;
|
||||
@ -94,7 +91,6 @@ namespace AST {
|
||||
) override;
|
||||
};
|
||||
|
||||
/// @brief Any binary operation (i.e. lhs + rhs)
|
||||
class BinaryOperationExpression : public Expression {
|
||||
private:
|
||||
std::unique_ptr<Expression> m_lhs;
|
||||
@ -121,7 +117,6 @@ namespace AST {
|
||||
) override;
|
||||
};
|
||||
|
||||
/// @brief Same as fn()/// @brief
|
||||
class FunctionCallExpression : public Expression {
|
||||
private:
|
||||
std::unique_ptr<Expression> m_fn_expr;
|
||||
@ -145,7 +140,6 @@ namespace AST {
|
||||
) override;
|
||||
};
|
||||
|
||||
/// @brief Same as (type) value
|
||||
class CastExpression : public Expression {
|
||||
private:
|
||||
std::shared_ptr<types::Type> m_ty;
|
||||
@ -169,48 +163,6 @@ namespace AST {
|
||||
) override;
|
||||
};
|
||||
|
||||
/// @brief Same as &value
|
||||
class RefExpression : public Expression {
|
||||
private:
|
||||
std::unique_ptr<Expression> m_expr;
|
||||
public:
|
||||
RefExpression(
|
||||
token::Metadata meta,
|
||||
std::unique_ptr<Expression> expr)
|
||||
: Expression{ meta }
|
||||
, m_expr{ std::move(expr) } {
|
||||
}
|
||||
virtual ~RefExpression() 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;
|
||||
};
|
||||
|
||||
/// @brief Same as *value
|
||||
class DerefExpression : public Expression {
|
||||
private:
|
||||
std::unique_ptr<Expression> m_expr;
|
||||
public:
|
||||
DerefExpression(
|
||||
token::Metadata meta,
|
||||
std::unique_ptr<Expression> expr)
|
||||
: Expression{ meta }
|
||||
, m_expr{ std::move(expr) } {
|
||||
}
|
||||
virtual ~DerefExpression() 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 {
|
||||
private:
|
||||
|
||||
@ -16,69 +16,45 @@ namespace types {
|
||||
for (auto& ty : { int_ty, char_ty, bool_ty }) {
|
||||
definitions.push_back(BinopDefinition{
|
||||
ty, types::BinOp::Add, ty,
|
||||
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||
ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||
return builder.builder->CreateAdd(lhs, rhs, "add");
|
||||
},
|
||||
[](BinopDefinition& def, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {return def.lhs;}
|
||||
});
|
||||
} });
|
||||
|
||||
definitions.push_back(BinopDefinition{
|
||||
ty, types::BinOp::Sub, 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");
|
||||
},
|
||||
[](BinopDefinition& def, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {return def.lhs;}
|
||||
});
|
||||
} });
|
||||
}
|
||||
|
||||
// Signed comparisons
|
||||
for (auto& ty : { int_ty }) {
|
||||
definitions.push_back(BinopDefinition{
|
||||
ty, types::BinOp::LessThan, 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");
|
||||
},
|
||||
[](BinopDefinition&, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {
|
||||
return std::shared_ptr<types::Type>{
|
||||
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
|
||||
}
|
||||
});
|
||||
} });
|
||||
|
||||
definitions.push_back(BinopDefinition{
|
||||
ty, types::BinOp::GreaterThan, ty,
|
||||
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||
return builder.builder->CreateICmpSGT(lhs, rhs, "icmpsgt");
|
||||
},
|
||||
[](BinopDefinition&, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {
|
||||
return std::shared_ptr<types::Type>{
|
||||
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
|
||||
}
|
||||
});
|
||||
} });
|
||||
}
|
||||
|
||||
// Unsigned comparisons
|
||||
for (auto& ty : { bool_ty, char_ty }) {
|
||||
definitions.push_back(BinopDefinition{
|
||||
ty, types::BinOp::LessThan, ty,
|
||||
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||
return builder.builder->CreateICmpULT(lhs, rhs, "icmpslt");
|
||||
},
|
||||
[](BinopDefinition&, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {
|
||||
return std::shared_ptr<types::Type>{
|
||||
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
|
||||
}
|
||||
});
|
||||
} });
|
||||
|
||||
definitions.push_back(BinopDefinition{
|
||||
ty, types::BinOp::GreaterThan, ty,
|
||||
[](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||
bool_ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) {
|
||||
return builder.builder->CreateICmpUGT(lhs, rhs, "icmpsgt");
|
||||
},
|
||||
[](BinopDefinition&, std::shared_ptr<types::Type>, std::shared_ptr<types::Type>) {
|
||||
return std::shared_ptr<types::Type>{
|
||||
new types::FundamentalType{ types::FundamentalTypeKind::Bool } };
|
||||
}
|
||||
});
|
||||
} });
|
||||
}
|
||||
|
||||
return definitions;
|
||||
|
||||
@ -22,8 +22,8 @@ namespace types {
|
||||
std::shared_ptr<Type> lhs;
|
||||
BinOp op;
|
||||
std::shared_ptr<Type> rhs;
|
||||
std::shared_ptr<Type> result;
|
||||
llvm::Value* (*codegen)(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs);
|
||||
std::shared_ptr<Type>(*result)(BinopDefinition& def, std::shared_ptr<Type> lhs, std::shared_ptr<Type> rhs);
|
||||
};
|
||||
|
||||
std::vector<BinopDefinition> create_binops();
|
||||
|
||||
@ -74,7 +74,7 @@ namespace AST {
|
||||
if (binop) {
|
||||
return codegen::StackValue{
|
||||
binop->codegen(builder, lhs.value, rhs.value),
|
||||
binop->result(*binop, lhs.ty, rhs.ty)
|
||||
binop->result
|
||||
};
|
||||
}
|
||||
throw CompileError("invalid binop", this->m_meta);
|
||||
@ -111,26 +111,6 @@ namespace AST {
|
||||
return expr;
|
||||
}
|
||||
|
||||
codegen::StackValue RefExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||
auto with_lvalue = scope.with_lvalue();
|
||||
return this->m_expr->codegen(builder, with_lvalue);
|
||||
}
|
||||
|
||||
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) {
|
||||
auto loaded = value.ty->load(builder, value.value);
|
||||
return codegen::StackValue{
|
||||
loaded.first,
|
||||
loaded.second
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new CompileError("Tried to deref a non-pointer!", this->m_meta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
|
||||
if (!builder.block)
|
||||
return;
|
||||
@ -231,17 +211,12 @@ namespace AST {
|
||||
|
||||
int counter = 0;
|
||||
for (auto& param : this->m_params) {
|
||||
builder.builder->SetInsertPoint(BB);
|
||||
auto arg_ptr = builder.builder->CreateAlloca(param_ty_ptrs[counter]->codegen(builder));
|
||||
auto param_ty_ptr = std::shared_ptr<types::Type>{
|
||||
new types::PointerType { param_ty_ptrs[counter]}
|
||||
};
|
||||
auto param_ty_ptr = param_ty_ptrs[counter];
|
||||
auto arg = function->getArg(counter++);
|
||||
builder.builder->CreateStore(arg, arg_ptr);
|
||||
if (param.first) {
|
||||
arg->setName(*param.first);
|
||||
inner_scope.values[*param.first] = codegen::StackValue{
|
||||
arg_ptr,
|
||||
arg,
|
||||
param_ty_ptr,
|
||||
};
|
||||
}
|
||||
@ -252,8 +227,6 @@ namespace AST {
|
||||
}
|
||||
}
|
||||
|
||||
builder.builder->CreateRetVoid();
|
||||
|
||||
llvm::verifyFunction(*function);
|
||||
|
||||
builder.block = nullptr;
|
||||
|
||||
@ -101,14 +101,6 @@ namespace parsing {
|
||||
try {
|
||||
auto before_meta = inner.metadata();
|
||||
|
||||
if (inner.peek().content == "(") {
|
||||
inner.next();
|
||||
auto expr = parse_expression(inner).unwrap();
|
||||
inner.expect(token::Type::Symbol, ")");
|
||||
stream.m_position = inner.m_position;
|
||||
return expr;
|
||||
}
|
||||
|
||||
if (auto cast = parse_cast(inner); cast.ok()) {
|
||||
auto expr = parse_expression(inner).unwrap();
|
||||
stream.m_position = inner.m_position;
|
||||
@ -120,22 +112,6 @@ namespace parsing {
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (inner.peek().content == "&") {
|
||||
inner.next();
|
||||
auto expr = parse_primary_expression(inner).unwrap();
|
||||
stream.m_position = inner.m_position;
|
||||
return std::unique_ptr<AST::Expression> {
|
||||
new AST::RefExpression(before_meta + inner.metadata(), std::move(expr))
|
||||
};
|
||||
}
|
||||
else if (inner.peek().content == "*") {
|
||||
inner.next();
|
||||
auto expr = parse_primary_expression(inner).unwrap();
|
||||
stream.m_position = inner.m_position;
|
||||
return std::unique_ptr<AST::Expression> {
|
||||
new AST::DerefExpression(before_meta + inner.metadata(), std::move(expr))
|
||||
};
|
||||
}
|
||||
|
||||
auto plain_expr = parse_plain_expression(inner);
|
||||
while (inner.peek().content == "(") {
|
||||
|
||||
@ -133,7 +133,7 @@ namespace AST {
|
||||
);
|
||||
|
||||
if (binop) {
|
||||
return binop->result(*binop, lhs_ty, rhs_ty);
|
||||
return binop->result;
|
||||
}
|
||||
|
||||
// If that fails, try to find binop that matches on one side perfectly
|
||||
@ -143,7 +143,7 @@ namespace AST {
|
||||
if (expected_ty) {
|
||||
// Skip any binops that would not be immediately assignable to
|
||||
// the expected type
|
||||
if (!types::types_equal(binop.result(binop, lhs_ty, rhs_ty), *expected_ty)) {
|
||||
if (!types::types_equal(binop.result, *expected_ty)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -153,7 +153,7 @@ namespace AST {
|
||||
// Skip if not implicitly castable to lhs
|
||||
continue;
|
||||
this->m_rhs = handle_res(std::move(this->m_rhs), rhs_res, state);
|
||||
return binop.result(binop, lhs_ty, rhs_ty);
|
||||
return binop.result;
|
||||
}
|
||||
else if (types::types_equal(binop.rhs, rhs_ty)) {
|
||||
auto lhs_res = check_type(state, lhs_ty, binop.lhs);
|
||||
@ -161,7 +161,7 @@ namespace AST {
|
||||
// Skip if not implicitly castable to rhs
|
||||
continue;
|
||||
this->m_lhs = handle_res(std::move(this->m_lhs), lhs_res, state);
|
||||
return binop.result(binop, lhs_ty, rhs_ty);
|
||||
return binop.result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ namespace AST {
|
||||
if (expected_ty) {
|
||||
// Skip any binops that would not even be implicitly castable to
|
||||
// the expected result
|
||||
auto result_res = check_type(state, binop.result(binop, lhs_ty, rhs_ty), *expected_ty);
|
||||
auto result_res = check_type(state, binop.result, *expected_ty);
|
||||
if (!result_res.ok())
|
||||
continue;
|
||||
}
|
||||
@ -179,7 +179,7 @@ namespace AST {
|
||||
auto rhs_result = check_type(state, rhs_ty, binop.rhs);
|
||||
this->m_lhs = handle_res(std::move(this->m_lhs), lhs_result, state);
|
||||
this->m_rhs = handle_res(std::move(this->m_rhs), lhs_result, state);
|
||||
return binop.result(binop, lhs_ty, rhs_ty);
|
||||
return binop.result;
|
||||
}
|
||||
|
||||
// No suitable binops found :(
|
||||
@ -253,35 +253,6 @@ namespace AST {
|
||||
} };
|
||||
}
|
||||
|
||||
std::shared_ptr<types::Type> RefExpression::typecheck(
|
||||
typecheck::State& state,
|
||||
typecheck::Scope& scope,
|
||||
std::optional<std::shared_ptr<types::Type>>
|
||||
) {
|
||||
auto expr_ty = this->m_expr->typecheck(state, scope, {});
|
||||
return std::shared_ptr<types::Type> {
|
||||
new types::PointerType{ expr_ty }
|
||||
};
|
||||
}
|
||||
|
||||
std::shared_ptr<types::Type> DerefExpression::typecheck(
|
||||
typecheck::State& state,
|
||||
typecheck::Scope& scope,
|
||||
std::optional<std::shared_ptr<types::Type>>
|
||||
) {
|
||||
auto expr_ty = this->m_expr->typecheck(state, scope, {});
|
||||
if (expr_ty->m_kind != types::TypeKind::Pointer) {
|
||||
state.errors.push_back(
|
||||
CompileError("Tried to deref " + expr_ty->formatted(), this->m_meta));
|
||||
return std::shared_ptr<types::Type> {
|
||||
new types::FundamentalType{ types::FundamentalTypeKind::Void }
|
||||
};
|
||||
}
|
||||
auto ptr_ty = dynamic_cast<types::PointerType*>(expr_ty.get());
|
||||
return ptr_ty->m_inner;
|
||||
}
|
||||
|
||||
|
||||
void ReturnStatement::typecheck(typecheck::State& state, typecheck::Scope& scope) {
|
||||
auto res_ty = this->m_expr->typecheck(state, scope, scope.return_ty);
|
||||
if (scope.return_ty) {
|
||||
|
||||
@ -18,8 +18,6 @@ namespace types {
|
||||
Bool,
|
||||
Char,
|
||||
Void,
|
||||
/// @brief Mainly used for binop resolution
|
||||
Any,
|
||||
};
|
||||
|
||||
class Type {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user