Browse Source

Fix illegal type declaration error

Ginger Bill 8 years ago
parent
commit
ab2ca7cf59
6 changed files with 46 additions and 33 deletions
  1. 20 19
      src/checker/checker.c
  2. 1 1
      src/checker/decl.c
  3. 9 3
      src/checker/expr.c
  4. 3 0
      src/checker/types.c
  5. 7 6
      src/parser.c
  6. 6 4
      src/tokenizer.c

+ 20 - 19
src/checker/checker.c

@@ -724,7 +724,7 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
 				return false;
 			} else {
 				TokenPos pos = insert_entity->token.pos;
-				if (token_pos_are_equal(pos, entity->token.pos)) {
+				if (token_pos_eq(pos, entity->token.pos)) {
 					// NOTE(bill): Error should have been handled already
 					return false;
 				}
@@ -1048,27 +1048,29 @@ void check_global_entities_by_kind(Checker *c, EntityKind kind) {
 	for_array(i, c->info.entities.entries) {
 		MapDeclInfoEntry *entry = &c->info.entities.entries.e[i];
 		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
-		if (e->kind == kind) {
-			DeclInfo *d = entry->value;
-			if (d->scope != e->scope) {
-				continue;
-			}
+		DeclInfo *d = entry->value;
 
-			add_curr_ast_file(c, d->scope->file);
-			if (kind != Entity_Procedure && str_eq(e->token.string, str_lit("main"))) {
-				if (e->scope->is_init) {
-					error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
-					continue;
-				}
-			} else if (e->scope->is_global && str_eq(e->token.string, str_lit("main"))) {
+		if (e->kind != kind) {
+			continue;
+		}
+		if (d->scope != e->scope) {
+			continue;
+		}
+
+		add_curr_ast_file(c, d->scope->file);
+		if (e->kind != Entity_Procedure && str_eq(e->token.string, str_lit("main"))) {
+			if (e->scope->is_init) {
 				error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
 				continue;
 			}
-
-			Scope *prev_scope = c->context.scope;
-			c->context.scope = d->scope;
-			check_entity_decl(c, e, d, NULL, NULL);
+		} else if (e->scope->is_global && str_eq(e->token.string, str_lit("main"))) {
+			error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
+			continue;
 		}
+
+		Scope *prev_scope = c->context.scope;
+		c->context.scope = d->scope;
+		check_entity_decl(c, e, d, NULL, NULL);
 	}
 }
 
@@ -1383,14 +1385,13 @@ void check_parsed_files(Checker *c) {
 	}
 
 	check_global_entities_by_kind(c, Entity_TypeName);
-
 	init_preload_types(c);
 	add_implicit_value(c, ImplicitValue_context, str_lit("context"), str_lit("__context"), t_context);
-
 	check_global_entities_by_kind(c, Entity_Constant);
 	check_global_entities_by_kind(c, Entity_Procedure);
 	check_global_entities_by_kind(c, Entity_Variable);
 
+
 	for (isize i = 1; i < ImplicitValue_Count; i++) {
 		// NOTE(bill): First is invalid
 		Entity *e = c->info.implicit_values[i];

+ 1 - 1
src/checker/decl.c

@@ -305,7 +305,7 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
 	named->Named.base = bt;
 	named->Named.base = base_type(named->Named.base);
 	if (named->Named.base == t_invalid) {
-		gb_printf("check_type_decl: %s\n", type_to_string(named));
+		// gb_printf("check_type_decl: %s\n", type_to_string(named));
 	}
 
 	cycle_checker_destroy(&local_cycle_checker);

+ 9 - 3
src/checker/expr.c

@@ -1329,14 +1329,19 @@ end:
 
 	if (is_type_named(type)) {
 		if (type->Named.base == NULL) {
+			error_node(e, "Invalid type definition");
 			type->Named.base = t_invalid;
 		}
 	}
 
+	if (is_type_typed(type)) {
+		add_type_and_value(&c->info, e, Addressing_Type, type, null_value);
+	} else {
+		error_node(e, "Invalid type definition");
+		type = t_invalid;
+	}
 	set_base_type(named_type, type);
-	GB_ASSERT(is_type_typed(type));
 
-	add_type_and_value(&c->info, e, Addressing_Type, type, null_value);
 
 
 	return type;
@@ -3755,7 +3760,8 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
 	}
 
 	Type *proc_type = base_type(operand->type);
-	if (proc_type == NULL || proc_type->kind != Type_Proc) {
+	if (proc_type == NULL || proc_type->kind != Type_Proc ||
+	    !(operand->mode == Addressing_Value || operand->mode == Addressing_Variable)) {
 		AstNode *e = operand->expr;
 		gbString str = expr_to_string(e);
 		error_node(e, "Cannot call a non-procedure: `%s`", str);

+ 3 - 0
src/checker/types.c

@@ -490,6 +490,9 @@ bool is_type_string(Type *t) {
 }
 bool is_type_typed(Type *t) {
 	t = base_type(t);
+	if (t == NULL) {
+		return false;
+	}
 	if (t->kind == Type_Basic) {
 		return (t->Basic.flags & BasicFlag_Untyped) == 0;
 	}

+ 7 - 6
src/parser.c

@@ -1133,7 +1133,7 @@ void fix_advance_to_next_stmt(AstFile *f) {
 
 		case Token_Hash:
 		{
-			if (token_pos_are_equal(t.pos, f->fix_prev_pos) &&
+			if (token_pos_eq(t.pos, f->fix_prev_pos) &&
 			    f->fix_count < PARSER_MAX_FIX_COUNT) {
 				f->fix_count++;
 				return;
@@ -2304,9 +2304,11 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
 
 	if (f->curr_token.kind == Token_OpenBrace) {
 		if ((tags & ProcTag_foreign) != 0) {
-			syntax_error(f->curr_token, "A procedure tagged as `#foreign` cannot have a body");
+			syntax_error_node(name, "A procedure tagged as `#foreign` cannot have a body");
 		}
 		body = parse_body(f);
+	} else if ((tags & ProcTag_foreign) == 0) {
+		syntax_error_node(name, "Only a procedure tagged as `#foreign` cannot have a body");
 	}
 
 	f->curr_proc = curr_proc;
@@ -2339,8 +2341,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
 
 	bool is_mutable = true;
 
-	if (f->curr_token.kind == Token_Eq ||
-	    f->curr_token.kind == Token_Colon) {
+	if (f->curr_token.kind == Token_Eq || f->curr_token.kind == Token_Colon) {
 		if (f->curr_token.kind == Token_Colon) {
 			is_mutable = false;
 		}
@@ -2903,7 +2904,7 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 
 			return make_import_decl(f, s->TagStmt.token, file_path, import_name, os, arch, false);
-		} else if (str_eq(tag, str_lit("load"))) {
+		} else if (str_eq(tag, str_lit("include"))) {
 			String os = {0};
 			String arch = {0};
 			// TODO(bill): better error messages
@@ -2914,7 +2915,7 @@ AstNode *parse_stmt(AstFile *f) {
 			if (f->curr_proc == NULL) {
 				return make_import_decl(f, s->TagStmt.token, file_path, import_name, os, arch, true);
 			}
-			syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
+			syntax_error(token, "You cannot use #include within a procedure. This must be done at the file scope");
 			return make_bad_decl(f, token, file_path);
 		} else {
 

+ 6 - 4
src/tokenizer.c

@@ -83,6 +83,8 @@ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
 \
 TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_type,           "type"), \
+	/* TOKEN_KIND(Token_import,         "import"), */ \
+	/* TOKEN_KIND(Token_include,         "include"), */ \
 	TOKEN_KIND(Token_proc,           "proc"), \
 	TOKEN_KIND(Token_match,          "match"), \
 	TOKEN_KIND(Token_break,          "break"), \
@@ -143,7 +145,7 @@ i32 token_pos_cmp(TokenPos a, TokenPos b) {
 	return (a.line < b.line) ? -1 : +1;
 }
 
-bool token_pos_are_equal(TokenPos a, TokenPos b) {
+bool token_pos_eq(TokenPos a, TokenPos b) {
 	return token_pos_cmp(a, b) == 0;
 }
 
@@ -182,7 +184,7 @@ void warning_va(Token token, char *fmt, va_list va) {
 
 	global_error_collector.warning_count++;
 	// NOTE(bill): Duplicate error, skip it
-	if (!token_pos_are_equal(global_error_collector.prev, token.pos)) {
+	if (!token_pos_eq(global_error_collector.prev, token.pos)) {
 		global_error_collector.prev = token.pos;
 		gb_printf_err("%.*s(%td:%td) Warning: %s\n",
 		              LIT(token.pos.file), token.pos.line, token.pos.column,
@@ -197,7 +199,7 @@ void error_va(Token token, char *fmt, va_list va) {
 
 	global_error_collector.count++;
 	// NOTE(bill): Duplicate error, skip it
-	if (!token_pos_are_equal(global_error_collector.prev, token.pos)) {
+	if (!token_pos_eq(global_error_collector.prev, token.pos)) {
 		global_error_collector.prev = token.pos;
 		gb_printf_err("%.*s(%td:%td) %s\n",
 		              LIT(token.pos.file), token.pos.line, token.pos.column,
@@ -212,7 +214,7 @@ void syntax_error_va(Token token, char *fmt, va_list va) {
 
 	global_error_collector.count++;
 	// NOTE(bill): Duplicate error, skip it
-	if (!token_pos_are_equal(global_error_collector.prev, token.pos)) {
+	if (!token_pos_eq(global_error_collector.prev, token.pos)) {
 		global_error_collector.prev = token.pos;
 		gb_printf_err("%.*s(%td:%td) Syntax Error: %s\n",
 		              LIT(token.pos.file), token.pos.line, token.pos.column,