Explorar el Código

Reimplement `immutable` with different rules.

Ginger Bill hace 8 años
padre
commit
74d15ab84b
Se han modificado 6 ficheros con 48 adiciones y 54 borrados
  1. 3 7
      code/demo.odin
  2. 21 22
      src/check_expr.c
  3. 2 6
      src/check_stmt.c
  4. 18 16
      src/checker.c
  5. 3 3
      src/parser.c
  6. 1 0
      src/tokenizer.c

+ 3 - 7
code/demo.odin

@@ -1,16 +1,12 @@
 #import "fmt.odin";
 
-x := [...]int{1, 2, 3, 4};
 
 main :: proc() {
 	{
 
-
-		foo :: proc() -> [...]int {
-			return x;
-		}
-
-		// foo()[0] = 2;
+		x := [...]int{1, 2, 3, 4};
+		immutable y := ^x;
+		fmt.println(y^[0]);
 	}
 
 /*

+ 21 - 22
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);

+ 2 - 6
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);

+ 18 - 16
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;

+ 3 - 3
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);

+ 1 - 0
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"),           \