Skip to content

Commit

Permalink
constants
Browse files Browse the repository at this point in the history
  • Loading branch information
vajexal committed Jun 11, 2024
1 parent 5ff6705 commit 16a9985
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 8 deletions.
3 changes: 2 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ fn types() void {
[]Foo arr = [new Foo(), new Foo()]
}
auto PI = 3.14 // globals
auto qux = 123 // globals
const auto PI = 3.14 // consts
fn flow() void {
// will print "then"
Expand Down
2 changes: 1 addition & 1 deletion src/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ yy::parser::symbol_type yylex(Driver &driver) {
"string" { return yy::parser::make_STRING_TYPE(driver.location); }
"void" { return yy::parser::make_VOID_TYPE(driver.location); }
"auto" { return yy::parser::make_AUTO_TYPE(driver.location); }
"const" { return yy::parser::make_CONST(driver.location); }
"false" { return yy::parser::make_BOOL(false, driver.location); }
"true" { return yy::parser::make_BOOL(true, driver.location); }
"fn" { return yy::parser::make_FN(driver.location); }
"var" { return yy::parser::make_VAR(driver.location); }
"case" { return yy::parser::make_CASE(driver.location); }
"default" { return yy::parser::make_DEFAULT(driver.location); }
"if" { return yy::parser::make_IF(driver.location); }
Expand Down
10 changes: 8 additions & 2 deletions src/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
%token STRING_TYPE "string"
%token VOID_TYPE "void"
%token AUTO_TYPE "auto"
%token CONST "const"
%token FN "fn"
%token VAR "var"
%token <std::string> IDENTIFIER
%token CASE "case"
%token DEFAULT "default"
Expand Down Expand Up @@ -95,6 +95,7 @@
%nterm <Type> array_type
%nterm <Type> return_type
%nterm <DeclNode *> var_decl
%nterm <DeclNode *> id_decl
%nterm <VarNode *> identifier
%nterm <std::string> static_identifier
%nterm <ScalarNode *> scalar
Expand Down Expand Up @@ -243,6 +244,11 @@ type { $$ = std::move($1); }
;

var_decl:
CONST id_decl { $2->type.makeConst(); $$ = $2; }
| id_decl { $$ = $1; }
;

id_decl:
type IDENTIFIER '=' expr { $$ = new DeclNode(std::move($1), std::move($2), $4); }
| AUTO_TYPE IDENTIFIER '=' expr { $$ = new DeclNode(Type::autoTy(), std::move($2), $4); }
| type IDENTIFIER { $$ = new DeclNode(std::move($1), std::move($2)); }
Expand Down Expand Up @@ -380,7 +386,7 @@ COMMENT { $$ = new CommentNode(std::move($1)); }
;

prop_decl:
access_modifier optional_static var_decl { $$ = new PropDeclNode($3, $1, $2); }
access_modifier optional_static id_decl { $$ = new PropDeclNode($3, $1, $2); }
;

method_def:
Expand Down
19 changes: 18 additions & 1 deletion src/pipes/type_inferrer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,14 @@ namespace X::Pipes {
}

Type TypeInferrer::infer(AssignNode *node) {
auto exprType = node->expr->infer(*this);
auto varType = getVarType(node->name);

if (varType.isConst()) {
throw ModifyConstException();
}

auto exprType = node->expr->infer(*this);

if (!canCastTo(exprType, varType)) {
throw InvalidTypeException();
}
Expand Down Expand Up @@ -609,6 +614,10 @@ namespace X::Pipes {
throw InvalidTypeException();
}

if (arrType.isConst()) {
throw ModifyConstException();
}

auto idxType = node->idx->infer(*this);
if (!idxType.is(Type::TypeID::INT)) {
throw InvalidTypeException();
Expand All @@ -628,6 +637,10 @@ namespace X::Pipes {
throw InvalidTypeException();
}

if (arrType.isConst()) {
throw ModifyConstException();
}

auto exprType = node->expr->infer(*this);
if (!canCastTo(exprType, *arrType.getSubtype())) {
throw InvalidTypeException();
Expand Down Expand Up @@ -679,6 +692,10 @@ namespace X::Pipes {

checkLvalueTypeIsValid(exprType);

if (type.isConst()) {
exprType.makeConst();
}

node->type = exprType;

return;
Expand Down
5 changes: 5 additions & 0 deletions src/pipes/type_inferrer.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,9 @@ namespace X::Pipes {
public:
InvalidTypeException() : TypeInferrerException("invalid type") {}
};

class ModifyConstException : public TypeInferrerException {
public:
ModifyConstException() : TypeInferrerException("can't modify const") {}
};
}
10 changes: 8 additions & 2 deletions src/type.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "type.h"

namespace X {
Type::Type(const Type &type) : id(type.id) {
Type::Type(const Type &type) : id(type.id), constant(type.constant) {
if (type.className) {
className = type.className.value();
}
Expand All @@ -11,14 +11,16 @@ namespace X {
}
}

Type::Type(Type &&type) : id(type.id), className(std::move(type.className)), subtype(type.subtype) {
Type::Type(Type &&type) : id(type.id), className(std::move(type.className)), subtype(type.subtype), constant(type.constant) {
type.id = TypeID::VOID;
type.className = std::nullopt;
type.subtype = nullptr;
type.constant = false;
}

Type &Type::operator=(const Type &type) {
id = type.id;
constant = type.constant;

if (type.className) {
className = type.className.value();
Expand Down Expand Up @@ -120,6 +122,10 @@ namespace X {
}

std::ostream &operator<<(std::ostream &out, const Type &type) {
if (type.isConst()) {
out << "const ";
}

switch (type.getTypeID()) {
case Type::TypeID::INT:
return out << "int";
Expand Down
3 changes: 3 additions & 0 deletions src/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace X {
TypeID id;
std::optional<std::string> className;
Type *subtype = nullptr;
bool constant;

Type(TypeID id) : id(id) {}

Expand All @@ -69,6 +70,8 @@ namespace X {
TypeID getTypeID() const { return id; }
const std::string &getClassName() const { return className.value(); }
Type *getSubtype() const { return subtype; }
void makeConst() { constant = true; }
bool isConst() const { return constant; }

bool is(TypeID typeId) const { return id == typeId; }

Expand Down
56 changes: 56 additions & 0 deletions tests/statement_test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "compiler_test_helper.h"

#include "codegen/codegen.h"
#include "pipes/type_inferrer.h"

class StatementTest : public CompilerTest {
};
Expand Down Expand Up @@ -75,3 +76,58 @@ fn main() void {
}
)code", "3");
}

TEST_F(StatementTest, consts) {
checkProgram(R"code(
const auto x = 10
fn main() void {
const int y = 20
println(x + y)
}
)code", "30");
}

TEST_P(StatementTest, modifyConst) {
auto [code, exceptionMessage] = GetParam();

try {
compiler.compile(code);
FAIL() << "expected ModifyConstException";
} catch (const Pipes::ModifyConstException &e) {
ASSERT_EQ(e.what(), exceptionMessage);
}
}

INSTANTIATE_TEST_SUITE_P(Code, StatementTest, testing::Values(
std::make_pair(
R"code(
const auto x = 10
fn main() void {
x = 20
}
)code", "can't modify const"),
std::make_pair(
R"code(
fn main() void {
const int x = 10
x = 20
}
)code", "can't modify const"),
std::make_pair(
R"code(
fn main() void {
const auto a = [1, 2, 3]
a[] = 4
}
)code", "can't modify const"),
std::make_pair(
R"code(
fn main() void {
const auto a = [1, 2, 3]
a[1] = 4
}
)code", "can't modify const")
));
3 changes: 2 additions & 1 deletion tests/tour_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ fn types() void {
[]Foo arr = [new Foo(), new Foo()]
}
auto PI = 3.14 // globals
auto qux = 123 // globals
const auto PI = 3.14 // consts
fn flow() void {
// will print "then"
Expand Down

0 comments on commit 16a9985

Please sign in to comment.