aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-14 12:35:50 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-14 12:35:50 +0000
commit74d15ab84b39a83285953b963f1637956f091f45 (patch)
tree4dcee1f973197146353ec4edede418a51db432af /src
parent763cd2649da4c87d8a9be2c2e44f8535e757a95a (diff)
Reimplement `immutable` with different rules.
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.c43
-rw-r--r--src/check_stmt.c8
-rw-r--r--src/checker.c34
-rw-r--r--src/parser.c6
-rw-r--r--src/tokenizer.c1
5 files changed, 45 insertions, 47 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index 5b91ffd39..25576ae85 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -1030,7 +1030,7 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
}
o->mode = Addressing_Variable;
if (e->Variable.is_immutable) {
- o->mode = Addressing_Value;
+ o->mode = Addressing_Immutable;
}
break;
@@ -2714,7 +2714,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
break;
case Entity_Variable:
// TODO(bill): This is the rule I need?
- if (sel.indirect || operand->mode != Addressing_Value) {
+ if (operand->mode == Addressing_Immutable) {
+ // Okay
+ } else if (sel.indirect || operand->mode != Addressing_Value) {
operand->mode = Addressing_Variable;
} else {
operand->mode = Addressing_Value;
@@ -4097,6 +4099,16 @@ void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) {
}
}
+void check_set_mode_with_indirection(Operand *o, bool indirection) {
+ if (o->mode != Addressing_Immutable) {
+ if (indirection) {
+ o->mode = Addressing_Variable;
+ } else if (o->mode != Addressing_Variable) {
+ o->mode = Addressing_Value;
+ }
+ }
+}
+
bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_count) {
Type *t = base_type(type_deref(type));
@@ -4106,9 +4118,7 @@ bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_cou
if (o->mode == Addressing_Constant) {
*max_count = o->value.value_string.len;
}
- if (o->mode != Addressing_Variable) {
- o->mode = Addressing_Value;
- }
+ check_set_mode_with_indirection(o, indirection);
o->type = t_u8;
return true;
}
@@ -4116,22 +4126,13 @@ bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_cou
case Type_Array:
*max_count = t->Array.count;
- if (indirection) {
- o->mode = Addressing_Variable;
- } else if (o->mode != Addressing_Variable) {
- o->mode = Addressing_Value;
- }
-
+ check_set_mode_with_indirection(o, indirection);
o->type = t->Array.elem;
return true;
case Type_Vector:
*max_count = t->Vector.count;
- if (indirection) {
- o->mode = Addressing_Variable;
- } else if (o->mode != Addressing_Variable) {
- o->mode = Addressing_Value;
- }
+ check_set_mode_with_indirection(o, indirection);
o->type = t->Vector.elem;
return true;
@@ -4143,11 +4144,7 @@ bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_cou
case Type_DynamicArray:
o->type = t->DynamicArray.elem;
- if (indirection) {
- o->mode = Addressing_Variable;
- } else if (o->mode != Addressing_Variable) {
- o->mode = Addressing_Value;
- }
+ check_set_mode_with_indirection(o, indirection);
return true;
}
@@ -5183,7 +5180,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
} else {
Type *t = base_type(o->type);
if (t->kind == Type_Pointer) {
- o->mode = Addressing_Variable;
+ if (o->mode != Addressing_Immutable) {
+ o->mode = Addressing_Variable;
+ }
o->type = t->Pointer.elem;
} else {
gbString str = expr_to_string(o->expr);
diff --git a/src/check_stmt.c b/src/check_stmt.c
index 983c9f25f..6769ddb40 100644
--- a/src/check_stmt.c
+++ b/src/check_stmt.c
@@ -268,17 +268,13 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
AstNode *x = ln->IndexExpr.expr;
TypeAndValue *tav = type_and_value_of_expression(&c->info, x);
GB_ASSERT(tav != NULL);
- switch (tav->mode) {
- case Addressing_Variable:
- break;
- case Addressing_Value:
+ if (tav->mode != Addressing_Variable) {
if (!is_type_pointer(tav->type)) {
gbString str = expr_to_string(lhs.expr);
error_node(lhs.expr, "Cannot assign to the value of a map `%s`", str);
gb_string_free(str);
return NULL;
}
- break;
}
}
} break;
@@ -297,7 +293,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
}
gbString str = expr_to_string(lhs.expr);
- if (e != NULL && e->kind == Entity_Variable && e->Variable.is_immutable) {
+ if (lhs.mode == Addressing_Immutable) {
error_node(lhs.expr, "Cannot assign to an immutable: `%s`", str);
} else {
error_node(lhs.expr, "Cannot assign to `%s`", str);
diff --git a/src/checker.c b/src/checker.c
index 17af9a44a..5ae1460ad 100644
--- a/src/checker.c
+++ b/src/checker.c
@@ -6,6 +6,22 @@ typedef enum ExprKind {
Expr_Stmt,
} ExprKind;
+typedef enum AddressingMode {
+ Addressing_Invalid,
+
+ Addressing_NoValue,
+ Addressing_Value,
+ Addressing_Variable,
+ Addressing_Immutable,
+ Addressing_Constant,
+ Addressing_Type,
+ Addressing_Builtin,
+ Addressing_Overload,
+ Addressing_MapIndex,
+
+ Addressing_Count,
+} AddressingMode;
+
// Statements and Declarations
typedef enum StmtFlag {
Stmt_BreakAllowed = 1<<0,
@@ -106,22 +122,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
};
-
-typedef enum AddressingMode {
- Addressing_Invalid,
-
- Addressing_NoValue,
- Addressing_Value,
- Addressing_Variable,
- Addressing_Constant,
- Addressing_Type,
- Addressing_Builtin,
- Addressing_Overload,
- Addressing_MapIndex,
-
- Addressing_Count,
-} AddressingMode;
-
#include "types.c"
#define MAP_TYPE Entity *
@@ -149,7 +149,9 @@ bool is_operand_value(Operand o) {
switch (o.mode) {
case Addressing_Value:
case Addressing_Variable:
+ case Addressing_Immutable:
case Addressing_Constant:
+ case Addressing_MapIndex:
return true;
}
return false;
diff --git a/src/parser.c b/src/parser.c
index b5d8f442b..69ea32c48 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -2358,7 +2358,7 @@ bool is_token_field_prefix(TokenKind kind) {
switch (kind) {
case Token_using:
case Token_no_alias:
- // case Token_immutable:
+ case Token_immutable:
return true;
}
return false;
@@ -2374,7 +2374,7 @@ u32 parse_field_prefixes(AstFile *f) {
switch (f->curr_token.kind) {
case Token_using: using_count += 1; next_token(f); break;
case Token_no_alias: no_alias_count += 1; next_token(f); break;
- // case Token_immutable: immutable_count += 1; next_token(f); break;
+ case Token_immutable: immutable_count += 1; next_token(f); break;
}
}
if (using_count > 1) syntax_error(f->curr_token, "Multiple `using` in this field list");
@@ -3272,7 +3272,7 @@ AstNode *parse_stmt(AstFile *f) {
return ast_bad_stmt(f, token, f->curr_token);
} break;
-#if 0
+#if 1
case Token_immutable: {
Token token = expect_token(f, Token_immutable);
AstNode *node = parse_stmt(f);
diff --git a/src/tokenizer.c b/src/tokenizer.c
index f2cabfb02..fc85fd927 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -102,6 +102,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_map, "map"), \
TOKEN_KIND(Token_using, "using"), \
TOKEN_KIND(Token_no_alias, "no_alias"), \
+ TOKEN_KIND(Token_immutable, "immutable"), \
TOKEN_KIND(Token_cast, "cast"), \
TOKEN_KIND(Token_transmute, "transmute"), \
TOKEN_KIND(Token_down_cast, "down_cast"), \