diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-02-14 12:35:50 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-02-14 12:35:50 +0000 |
| commit | 74d15ab84b39a83285953b963f1637956f091f45 (patch) | |
| tree | 4dcee1f973197146353ec4edede418a51db432af /src | |
| parent | 763cd2649da4c87d8a9be2c2e44f8535e757a95a (diff) | |
Reimplement `immutable` with different rules.
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.c | 43 | ||||
| -rw-r--r-- | src/check_stmt.c | 8 | ||||
| -rw-r--r-- | src/checker.c | 34 | ||||
| -rw-r--r-- | src/parser.c | 6 | ||||
| -rw-r--r-- | src/tokenizer.c | 1 |
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"), \ |