Add decrement and negation unops
This commit is contained in:
parent
dd632b6bcc
commit
43df7efd6f
@ -99,6 +99,15 @@ namespace AST {
|
|||||||
case types::Unary::AddPrefix:
|
case types::Unary::AddPrefix:
|
||||||
out << "++" << this->m_expr->formatted();
|
out << "++" << this->m_expr->formatted();
|
||||||
break;
|
break;
|
||||||
|
case types::Unary::SubPostfix:
|
||||||
|
out << this->m_expr->formatted() << "--";
|
||||||
|
break;
|
||||||
|
case types::Unary::SubPrefix:
|
||||||
|
out << "--" << this->m_expr->formatted();
|
||||||
|
break;
|
||||||
|
case types::Unary::Negation:
|
||||||
|
out << "!" << this->m_expr->formatted();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,8 +109,10 @@ namespace types {
|
|||||||
new types::FundamentalType{ false, types::FundamentalTypeKind::Int } };
|
new types::FundamentalType{ false, types::FundamentalTypeKind::Int } };
|
||||||
auto char_ty = std::shared_ptr<types::Type>{
|
auto char_ty = std::shared_ptr<types::Type>{
|
||||||
new types::FundamentalType{ false, types::FundamentalTypeKind::Char } };
|
new types::FundamentalType{ false, types::FundamentalTypeKind::Char } };
|
||||||
|
auto bool_ty = std::shared_ptr<types::Type>{
|
||||||
|
new types::FundamentalType{ false, types::FundamentalTypeKind::Bool } };
|
||||||
|
|
||||||
// Integer arithmetic binops
|
// Integer Increment/Decrement unaries
|
||||||
for (auto& ty : { int_ty, char_ty }) {
|
for (auto& ty : { int_ty, char_ty }) {
|
||||||
definitions.push_back(UnopDefinition{
|
definitions.push_back(UnopDefinition{
|
||||||
ty, types::Unary::AddPostfix, ty,
|
ty, types::Unary::AddPostfix, ty,
|
||||||
@ -137,6 +139,48 @@ namespace types {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
definitions.push_back(UnopDefinition{
|
||||||
|
ty, types::Unary::SubPostfix, ty,
|
||||||
|
[](codegen::Builder& builder, std::shared_ptr<Type> ty, llvm::Value* ptr) {
|
||||||
|
codegen::TypeMap structs {};
|
||||||
|
auto llvm_ty = ty->codegen(builder, structs);
|
||||||
|
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr);
|
||||||
|
auto const_1 = llvm::ConstantInt::get(llvm_ty, 1);
|
||||||
|
auto result = builder.builder->CreateSub(loaded, const_1, "sub");
|
||||||
|
builder.builder->CreateStore(result, ptr);
|
||||||
|
return reinterpret_cast<llvm::Value*>(loaded);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
definitions.push_back(UnopDefinition{
|
||||||
|
ty, types::Unary::SubPrefix, ty,
|
||||||
|
[](codegen::Builder& builder, std::shared_ptr<Type> ty, llvm::Value* ptr) {
|
||||||
|
codegen::TypeMap structs {};
|
||||||
|
auto llvm_ty = ty->codegen(builder, structs);
|
||||||
|
auto loaded = builder.builder->CreateLoad(llvm_ty, ptr);
|
||||||
|
auto const_1 = llvm::ConstantInt::get(llvm_ty, 1);
|
||||||
|
auto result = builder.builder->CreateSub(loaded, const_1, "sub");
|
||||||
|
builder.builder->CreateStore(result, ptr);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negation
|
||||||
|
for (auto& ty : { int_ty, char_ty, bool_ty }) {
|
||||||
|
definitions.push_back(UnopDefinition{
|
||||||
|
ty, types::Unary::Negation, ty,
|
||||||
|
[](codegen::Builder& builder, std::shared_ptr<Type> ty, llvm::Value* value) {
|
||||||
|
codegen::TypeMap structs {};
|
||||||
|
auto llvm_ty = ty->codegen(builder, structs);
|
||||||
|
auto const_1 = llvm::ConstantInt::get(llvm_ty, 1);
|
||||||
|
auto const_0 = llvm::ConstantInt::get(llvm_ty, 0);
|
||||||
|
|
||||||
|
auto cmp = builder.builder->CreateICmp(llvm::CmpInst::Predicate::ICMP_EQ, value, const_0, "not_cmp");
|
||||||
|
return builder.builder->CreateSelect(cmp, const_1, const_0, "not_select");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return definitions;
|
return definitions;
|
||||||
|
|||||||
@ -18,6 +18,9 @@ namespace types {
|
|||||||
enum class Unary {
|
enum class Unary {
|
||||||
AddPostfix,
|
AddPostfix,
|
||||||
AddPrefix,
|
AddPrefix,
|
||||||
|
SubPostfix,
|
||||||
|
SubPrefix,
|
||||||
|
Negation,
|
||||||
};
|
};
|
||||||
|
|
||||||
int operator_precedence(BinOp& op);
|
int operator_precedence(BinOp& op);
|
||||||
|
|||||||
@ -454,6 +454,9 @@ namespace AST {
|
|||||||
|
|
||||||
codegen::StackValue UnaryExpression::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) {
|
codegen::StackValue UnaryExpression::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) {
|
||||||
auto unary = types::find_unop(scope.unops, this->m_expr->get_codegen_type(scope), this->m_unary);
|
auto unary = types::find_unop(scope.unops, this->m_expr->get_codegen_type(scope), this->m_unary);
|
||||||
|
|
||||||
|
if (this->m_unary == types::Unary::AddPostfix || this->m_unary == types::Unary::AddPrefix
|
||||||
|
|| this->m_unary == types::Unary::SubPostfix || this->m_unary == types::Unary::SubPrefix) {
|
||||||
auto lvalue = scope.with_lvalue();
|
auto lvalue = scope.with_lvalue();
|
||||||
auto expr_ptr = this->m_expr->codegen(builder, lvalue, allocator);
|
auto expr_ptr = this->m_expr->codegen(builder, lvalue, allocator);
|
||||||
return {
|
return {
|
||||||
@ -461,6 +464,15 @@ namespace AST {
|
|||||||
unary->res
|
unary->res
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
auto expr_ptr = this->m_expr->codegen(builder, scope, allocator);
|
||||||
|
return {
|
||||||
|
unary->codegen(builder, this->m_expr->get_codegen_type(scope), expr_ptr.value),
|
||||||
|
unary->res
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) {
|
void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope, codegen::StackAllocator& allocator) {
|
||||||
if (!builder.block)
|
if (!builder.block)
|
||||||
|
|||||||
@ -324,6 +324,23 @@ namespace parsing {
|
|||||||
new AST::UnaryExpression(before_meta + inner.metadata(), std::move(expr), types::Unary::AddPrefix)
|
new AST::UnaryExpression(before_meta + inner.metadata(), std::move(expr), types::Unary::AddPrefix)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else if (inner.peek().content == "-" && inner.peek(1).content == "-") {
|
||||||
|
inner.next();
|
||||||
|
inner.next();
|
||||||
|
auto expr = parse_primary_expression(inner, scope).unwrap();
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return std::unique_ptr<AST::Expression> {
|
||||||
|
new AST::UnaryExpression(before_meta + inner.metadata(), std::move(expr), types::Unary::SubPrefix)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (inner.peek().content == "!") {
|
||||||
|
inner.next();
|
||||||
|
auto expr = parse_primary_expression(inner, scope).unwrap();
|
||||||
|
stream.m_position = inner.m_position;
|
||||||
|
return std::unique_ptr<AST::Expression> {
|
||||||
|
new AST::UnaryExpression(before_meta + inner.metadata(), std::move(expr), types::Unary::Negation)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
auto plain_expr = parse_plain_expression(inner, scope);
|
auto plain_expr = parse_plain_expression(inner, scope);
|
||||||
while (inner.peek().content == "(" || inner.peek().content == "[" || inner.peek().content == ".") {
|
while (inner.peek().content == "(" || inner.peek().content == "[" || inner.peek().content == ".") {
|
||||||
@ -366,6 +383,13 @@ namespace parsing {
|
|||||||
new AST::UnaryExpression{before_meta + inner.metadata(), plain_expr.unwrap(), types::Unary::AddPostfix}
|
new AST::UnaryExpression{before_meta + inner.metadata(), plain_expr.unwrap(), types::Unary::AddPostfix}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else if (inner.peek().content == "-" && inner.peek(1).content == "-") {
|
||||||
|
inner.next();
|
||||||
|
inner.next();
|
||||||
|
plain_expr = std::unique_ptr<AST::Expression>{
|
||||||
|
new AST::UnaryExpression{before_meta + inner.metadata(), plain_expr.unwrap(), types::Unary::SubPostfix}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
stream.m_position = inner.m_position;
|
stream.m_position = inner.m_position;
|
||||||
|
|||||||
@ -547,7 +547,8 @@ namespace AST {
|
|||||||
std::optional<std::shared_ptr<types::Type>> expected_ty
|
std::optional<std::shared_ptr<types::Type>> expected_ty
|
||||||
) {
|
) {
|
||||||
auto expr_res = this->m_expr->typecheck(state, scope, expected_ty);
|
auto expr_res = this->m_expr->typecheck(state, scope, expected_ty);
|
||||||
if (this->m_unary == types::Unary::AddPostfix || this->m_unary == types::Unary::AddPrefix) {
|
if (this->m_unary == types::Unary::AddPostfix || this->m_unary == types::Unary::AddPrefix
|
||||||
|
|| this->m_unary == types::Unary::SubPostfix || this->m_unary == types::Unary::SubPrefix) {
|
||||||
if (!expr_res.lvalue) {
|
if (!expr_res.lvalue) {
|
||||||
state.errors.push_back(CompileError("Value must be a modifyable l-value", this->m_meta));
|
state.errors.push_back(CompileError("Value must be a modifyable l-value", this->m_meta));
|
||||||
}
|
}
|
||||||
@ -564,7 +565,7 @@ namespace AST {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
state.errors.push_back(CompileError("No suitable unary operator found", this->m_meta));
|
state.errors.push_back(CompileError("No suitable unary operator found for " + this->formatted(), this->m_meta));
|
||||||
return { expr_res.type, false, false };
|
return { expr_res.type, false, false };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
test.c
5
test.c
@ -52,9 +52,8 @@ int main() {
|
|||||||
printf("2d array: %d!\n", twod_array[0][0]);
|
printf("2d array: %d!\n", twod_array[0][0]);
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
printf("counter: %d\n", counter++);
|
int a = !0;
|
||||||
printf("counter: %d\n", counter++);
|
printf("a: %d\n", a);
|
||||||
printf("counter: %d\n", counter++);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user