Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

64 Bit Integers #44

Merged
merged 2 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion grammar/Fusion.g4
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ expr
qualifier: CONST | LET;

type
: I32
: I32
| I64
| CHAR
| BOOL
;
Expand Down Expand Up @@ -88,6 +89,7 @@ COMMENT: '/*' .*? '*/' -> skip;

// types
I32: 'i32';
I64: 'i64';
CHAR: 'ch';
BOOL: 'bool';

Expand Down
6 changes: 3 additions & 3 deletions include/ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ class Expression : public Node {

class IntegerLiteral : public Expression {
private:
int value;
long long value;

public:
explicit IntegerLiteral(int value, Token* token);
int get_value() const;
explicit IntegerLiteral(long long value, TypePtr type, Token* token);
long long get_value() const;

void xml(int level) override;
};
Expand Down
1 change: 1 addition & 0 deletions include/backend/types/integer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

namespace integer {
mlir::Value create_i32(int value);
mlir::Value create_i64(long long value);
} // namespace integer
3 changes: 2 additions & 1 deletion include/shared/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ extern mlir::MLIRContext context;
extern TypePtr ch;
extern TypePtr any;
extern TypePtr i32;
extern TypePtr i64;
extern TypePtr f32;
extern TypePtr none;
extern TypePtr t_bool;
extern TypePtr bool_;

extern std::vector<TypePtr> primitives;

Expand Down
8 changes: 8 additions & 0 deletions include/shared/type/integer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@ class I32 : public Type {
mlir::Type get_mlir() const override;
bool is_numeric() const override;
};

class I64 : public Type {
public:
I64();
std::string get_specifier() const override;
mlir::Type get_mlir() const override;
bool is_numeric() const override;
};
15 changes: 8 additions & 7 deletions src/ast/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ TypePtr ast::Expression::get_type() const {
}

ast::BooleanLiteral::BooleanLiteral(bool value, Token* token)
: Expression(ctx::t_bool, token) {
: Expression(ctx::bool_, token) {
this->value = value;
}

Expand All @@ -135,22 +135,23 @@ char ast::CharacterLiteral::get_value() const {
}

void ast::CharacterLiteral::xml(int level) {
std::cout << std::string(level * 4, ' ') << "<ch value=\"" << this->value
std::cout << std::string(level * 4, ' ') << "<ch value=\"" << value
<< "\"/>\n";
}

ast::IntegerLiteral::IntegerLiteral(int value, Token* token)
: Expression(ctx::i32, token) {
ast::IntegerLiteral::IntegerLiteral(long long value, TypePtr type, Token* token)
: Expression(type, token) {
assert(*type == *ctx::i32 || *type == *ctx::i64);
this->value = value;
}

int ast::IntegerLiteral::get_value() const {
long long ast::IntegerLiteral::get_value() const {
return this->value;
}

void ast::IntegerLiteral::xml(int level) {
std::cout << std::string(level * 4, ' ') << "<i32 value=\"" << this->value
<< "\"/>\n";
std::cout << std::string(level * 4, ' ')
<< "<" + type->get_name() + " value=\"" << value << "\"/>\n";
}

ast::Variable::Variable(Qualifier qualifier,
Expand Down
20 changes: 14 additions & 6 deletions src/ast/builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "FusionParser.h"
#include "ast/ast.h"
#include "ast/builder.h"
#include "errors/errors.h"
#include "shared/context.h"
#include "shared/type/type.h"

Expand Down Expand Up @@ -99,16 +100,23 @@ std::any Builder::visitQualifier(FusionParser::QualifierContext* ctx) {

std::any Builder::visitLiteralInt(FusionParser::LiteralIntContext* ctx) {
Token* token = ctx->INT()->getSymbol();
int value = 0;
std::string str = ctx->INT()->getText();

try {
value = std::stoi(ctx->INT()->getText());
} catch (const std::out_of_range& oor) {
std::runtime_error(oor.what());
int num = std::stoi(str);
auto node = make_shared<ast::IntegerLiteral>(num, ctx::i32, token);
return to_node(node);
} catch (const std::out_of_range&) {
try {
long long num = std::stoll(str);
auto node = make_shared<ast::IntegerLiteral>(num, ctx::i64, token);
return to_node(node);
} catch (const std::out_of_range&) {
throw SyntaxError(token->getLine(), "number overflowed 64 bits");
}
}

auto node = make_shared<ast::IntegerLiteral>(value, token);
return to_node(node);
throw std::runtime_error("failed to parse integer");
}

std::any Builder::visitLiteralBool(FusionParser::LiteralBoolContext* ctx) {
Expand Down
33 changes: 19 additions & 14 deletions src/ast/passes/type_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ void TypeCheck::visit_declaration(shared_ptr<ast::Declaration> node) {
visit(node->var);
visit(node->expr);

Type var = *node->var->get_type();
Type expr = *node->expr->get_type();
if (var != expr) {
TypePtr var = node->var->get_type();
TypePtr expr = node->expr->get_type();
if (*var == *ctx::i64 && *expr == *ctx::i32) {
node->expr->set_type(ctx::i64);
return;
}

if (*var != *expr) {
throw TypeError(node->token->getLine(),
"mismatched lhs(" + var.get_name() + ") and rhs(" +
expr.get_name() + ") types on declaration");
"mismatched lhs(" + var->get_name() + ") and rhs(" +
expr->get_name() + ") types on declaration");
}
}

Expand Down Expand Up @@ -96,7 +101,7 @@ void TypeCheck::visit_binary_operator(shared_ptr<ast::BinaryOperator> node) {
case ast::BinaryOpType::GTE:
check_numeric(lhs, line);
check_numeric(rhs, line);
node->set_type(ctx::t_bool);
node->set_type(ctx::bool_);
break;
case ast::BinaryOpType::ADD:
case ast::BinaryOpType::SUB:
Expand All @@ -112,11 +117,11 @@ void TypeCheck::visit_binary_operator(shared_ptr<ast::BinaryOperator> node) {
case ast::BinaryOpType::OR:
check_bool(lhs, line);
check_bool(rhs, line);
node->set_type(ctx::t_bool);
node->set_type(ctx::bool_);
break;
case ast::BinaryOpType::EQ:
case ast::BinaryOpType::NE:
node->set_type(ctx::t_bool);
node->set_type(ctx::bool_);
break;
}
}
Expand All @@ -125,17 +130,17 @@ void TypeCheck::visit_unary_operator(shared_ptr<ast::UnaryOperator> node) {
visit(node->rhs);

size_t line = node->token->getLine();
Type rhs = *node->get_type();
if (node->type == ast::UnaryOpType::MINUS && rhs != *ctx::i32) {
TypePtr rhs = node->get_type();
if (node->type == ast::UnaryOpType::MINUS && !rhs->is_numeric()) {
throw TypeError(
line, "unary minus only works on numeric types, found type: " +
rhs.get_name());
rhs->get_name());
}

if (node->type == ast::UnaryOpType::NOT && rhs != *ctx::t_bool) {
if (node->type == ast::UnaryOpType::NOT && *rhs != *ctx::bool_) {
throw TypeError(line,
"unary minus only works on booleans, found type: " +
rhs.get_name());
rhs->get_name());
}
}

Expand All @@ -146,7 +151,7 @@ void TypeCheck::check_numeric(TypePtr type, size_t line) {
}

void TypeCheck::check_bool(TypePtr type, size_t line) {
if (*type != *ctx::t_bool) {
if (*type != *ctx::bool_) {
throw TypeError(line, "type(" + type->get_name() + ") is not boolean");
}
}
2 changes: 1 addition & 1 deletion src/backend/builtin/print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void setupPrintf() {

void newline_type_str(TypePtr type) {
std::string ty = type->get_specifier() + "\n";
auto gvalue = mlir::StringRef(ty.c_str(), 4);
auto gvalue = mlir::StringRef(ty.c_str(), ty.size() + 1);

auto gtype =
mlir::LLVM::LLVMArrayType::get(ctx::ch->get_mlir(), gvalue.size());
Expand Down
8 changes: 4 additions & 4 deletions src/backend/expressions/arithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ mlir::Value arithmetic::mod(mlir::Value lhs, mlir::Value rhs, TypePtr type) {
}

mlir::Value arithmetic::and_(mlir::Value lhs, mlir::Value rhs, TypePtr type) {
return binop<mlir::LLVM::AndOp>(lhs, rhs, ctx::t_bool);
return binop<mlir::LLVM::AndOp>(lhs, rhs, ctx::bool_);
}

mlir::Value arithmetic::or_(mlir::Value lhs, mlir::Value rhs, TypePtr type) {
return binop<mlir::LLVM::OrOp>(lhs, rhs, ctx::t_bool);
return binop<mlir::LLVM::OrOp>(lhs, rhs, ctx::bool_);
}

mlir::Value arithmetic::pow(mlir::Value lhs, mlir::Value rhs, TypePtr type) {
Expand Down Expand Up @@ -79,7 +79,7 @@ mlir::Value arithmetic::lte(mlir::Value lhs, mlir::Value rhs, TypePtr type) {

mlir::Value arithmetic::not_(mlir::Value value) {
mlir::Value f = boolean::create_bool(false);
return eq(f, value, ctx::t_bool);
return eq(f, value, ctx::bool_);
}

mlir::Value arithmetic::negate(mlir::Value value, TypePtr type) {
Expand All @@ -92,7 +92,7 @@ mlir::Value arithmetic::binary_equality(mlir::Value lhs,
TypePtr type,
mlir::LLVM::ICmpPredicate predicate) {
mlir::Value value = ctx::builder->create<mlir::LLVM::ICmpOp>(
*ctx::loc, ctx::t_bool->get_mlir(), predicate, lhs, rhs);
*ctx::loc, ctx::bool_->get_mlir(), predicate, lhs, rhs);

return value;
}
Expand Down
2 changes: 1 addition & 1 deletion src/backend/types/boolean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

mlir::Value boolean::create_bool(bool value) {
mlir::Value val = ctx::builder->create<mlir::LLVM::ConstantOp>(
*ctx::loc, ctx::t_bool->get_mlir(), value);
*ctx::loc, ctx::bool_->get_mlir(), value);

return val;
}
7 changes: 7 additions & 0 deletions src/backend/types/integer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ mlir::Value integer::create_i32(int value) {

return val;
}

mlir::Value integer::create_i64(long long value) {
mlir::Value val = ctx::builder->create<mlir::LLVM::ConstantOp>(
*ctx::loc, ctx::i64->get_mlir(), value);

return val;
}
6 changes: 5 additions & 1 deletion src/backend/visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ mlir::Value Backend::visit_block(shared_ptr<ast::Block> node) {

mlir::Value Backend::visit_integer_literal(
shared_ptr<ast::IntegerLiteral> node) {
return integer::create_i32(node->get_value());
if (*node->get_type() == *ctx::i32) {
return integer::create_i32(node->get_value());
}

return integer::create_i64(node->get_value());
}

mlir::Value Backend::visit_character_literal(
Expand Down
11 changes: 5 additions & 6 deletions src/shared/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ std::unique_ptr<mlir::ModuleOp> ctx::module;
TypePtr ctx::ch;
TypePtr ctx::any;
TypePtr ctx::i32;
TypePtr ctx::i64;
TypePtr ctx::f32;
TypePtr ctx::none;
TypePtr ctx::t_bool;
TypePtr ctx::bool_;

std::vector<TypePtr> ctx::primitives;

Expand All @@ -26,16 +27,14 @@ void ctx::initialize_context() {

ctx::any = make_shared<Any>();
ctx::i32 = make_shared<I32>();
ctx::i64 = make_shared<I64>();
ctx::f32 = make_shared<F32>();
ctx::none = make_shared<None>();
ctx::ch = make_shared<Character>();
ctx::t_bool = make_shared<Boolean>();
ctx::bool_ = make_shared<Boolean>();

ctx::primitives = {
ctx::ch,
ctx::i32,
ctx::f32,
ctx::t_bool,
ctx::ch, ctx::i32, ctx::i64, ctx::f32, ctx::bool_,
};

module = std::make_unique<mlir::ModuleOp>(
Expand Down
14 changes: 14 additions & 0 deletions src/shared/type/integer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,17 @@ mlir::Type I32::get_mlir() const {
bool I32::is_numeric() const {
return true;
}

I64::I64() : Type("i64") {}

std::string I64::get_specifier() const {
return "%ld";
}

mlir::Type I64::get_mlir() const {
return ctx::builder->getI64Type();
}

bool I64::is_numeric() const {
return true;
}
3 changes: 3 additions & 0 deletions tests/input/declaration/basic.in
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ fn main(): i32 {
println(t);
println(f);

let r: i64 = 10000000000000;
println(r);

return 0;
}
4 changes: 4 additions & 0 deletions tests/input/errors/syntax/int_overflow.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main(): i32 {
let x: i64 = 100000000000000000000000000000000000;
return 0;
}
4 changes: 4 additions & 0 deletions tests/input/errors/type/int_sizes.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main(): i32 {
let x: i32 = 10000000000000;
return 0;
}
1 change: 1 addition & 0 deletions tests/output/declaration/basic.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
55a
1
0
10000000000000
1 change: 1 addition & 0 deletions tests/output/errors/syntax/int_overflow.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SyntaxError on Line 2
1 change: 1 addition & 0 deletions tests/output/errors/type/int_sizes.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TypeError on Line 2
Loading