Browse Source

Allow importation of `core:builtin` to get built-in entities

gingerBill 7 years ago
parent
commit
5fe4c33d0e
8 changed files with 132 additions and 135 deletions
  1. 8 12
      src/check_decl.cpp
  2. 5 3
      src/check_expr.cpp
  3. 46 62
      src/checker.cpp
  4. 9 9
      src/checker.hpp
  5. 42 44
      src/ir.cpp
  6. 1 1
      src/main.cpp
  7. 20 4
      src/parser.cpp
  8. 1 0
      src/parser.hpp

+ 8 - 12
src/check_decl.cpp

@@ -640,7 +640,7 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
 	}
 }
 
-void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize entity_count, Ast *type_expr, Array<Ast *> const &init_expr_list) {
+void check_var_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init_expr) {
 	GB_ASSERT(e->type == nullptr);
 	GB_ASSERT(e->kind == Entity_Variable);
 
@@ -651,7 +651,7 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize ent
 	e->flags |= EntityFlag_Visited;
 
 	AttributeContext ac = make_attribute_context(e->Variable.link_prefix);
-	ac.init_expr_list_count = init_expr_list.count;
+	ac.init_expr_list_count = init_expr != nullptr ? 1 : 0;
 
 	DeclInfo *decl = decl_info_of_entity(e);
 	if (decl != nullptr) {
@@ -682,7 +682,7 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize ent
 
 
 	if (e->Variable.is_foreign) {
-		if (init_expr_list.count > 0) {
+		if (init_expr != nullptr) {
 			error(e->token, "A foreign variable declaration cannot have a default value");
 		}
 		init_entity_foreign_library(ctx, e);
@@ -716,20 +716,16 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Entity **entities, isize ent
 		}
 	}
 
-	if (init_expr_list.count == 0) {
+	if (init_expr == nullptr) {
 		if (type_expr == nullptr) {
 			e->type = t_invalid;
 		}
 		return;
 	}
 
-	if (type_expr != nullptr) {
-		for (isize i = 0; i < entity_count; i++) {
-			entities[i]->type = e->type;
-		}
-	}
-
-	check_init_variables(ctx, entities, entity_count, init_expr_list, context_name);
+	Operand o = {};
+	check_expr(ctx, &o, init_expr);
+	check_init_variable(ctx, e, &o, str_lit("variable declaration"));
 }
 
 void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, DeclInfo *d) {
@@ -895,7 +891,7 @@ void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, Type *named_
 
 	switch (e->kind) {
 	case Entity_Variable:
-		check_var_decl(&c, e, d->entities, d->entity_count, d->type_expr, d->init_expr_list);
+		check_var_decl(&c, e, d->type_expr, d->init_expr);
 		break;
 	case Entity_Constant:
 		check_const_decl(&c, e, d->type_expr, d->init_expr, named_type);

+ 5 - 3
src/check_expr.cpp

@@ -44,7 +44,6 @@ int valid_index_and_score_cmp(void const *a, void const *b) {
 
 
 
-
 #define CALL_ARGUMENT_CHECKER(name) CallArgumentError name(CheckerContext *c, Ast *call, Type *proc_type, Entity *entity, Array<Operand> operands, CallArgumentErrorMode show_error_mode, CallArgumentData *data)
 typedef CALL_ARGUMENT_CHECKER(CallArgumentCheckerType);
 
@@ -5206,6 +5205,10 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 
 
 	case_ast_node(bl, BasicLit, node);
+		// NOTE(bill, 2018-06-17): Placing this in the parser is slower than
+		// placing it here for some reason. So don't move it to the parsing
+		// stage if you _think_ it will be faster, only do it if you _know_ it
+		// will be faster.
 		Type *t = t_invalid;
 		switch (bl->token.kind) {
 		case Token_Integer: t = t_untyped_integer; break;
@@ -5231,6 +5234,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 	case_end;
 
 	case_ast_node(bd, BasicDirective, node);
+		o->mode = Addressing_Constant;
 		if (bd->name == "file") {
 			o->type = t_untyped_string;
 			o->value = exact_value_string(bd->token.pos.file);
@@ -5254,7 +5258,6 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 		} else {
 			GB_PANIC("Unknown basic directive");
 		}
-		o->mode = Addressing_Constant;
 	case_end;
 
 	case_ast_node(pg, ProcGroup, node);
@@ -5296,7 +5299,6 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 		}
 		check_close_scope(&ctx);
 
-
 		o->mode = Addressing_Value;
 		o->type = type;
 	case_end;

+ 46 - 62
src/checker.cpp

@@ -25,6 +25,7 @@ bool is_operand_undef(Operand o) {
 
 
 gb_global Scope *universal_scope = nullptr;
+gb_global AstPackage *builtin_package = nullptr;
 
 void scope_reset(Scope *scope) {
 	if (scope == nullptr) return;
@@ -531,13 +532,22 @@ void add_global_type_entity(String name, Type *type) {
 
 
 
-void init_universal_scope(void) {
+void init_universal(void) {
 	BuildContext *bc = &build_context;
 	// NOTE(bill): No need to free these
 	gbAllocator a = heap_allocator();
 	universal_scope = create_scope(nullptr, a);
 	universal_scope->is_package = true;
 
+
+	builtin_package = gb_alloc_item(a, AstPackage);
+	builtin_package->name = str_lit("builtin");
+	builtin_package->kind = Package_Normal;
+	builtin_package->scope = universal_scope;
+	universal_scope->package = builtin_package;
+
+
+
 // Types
 	for (isize i = 0; i < gb_count_of(basic_types); i++) {
 		add_global_type_entity(basic_types[i].Basic.name, &basic_types[i]);
@@ -2009,19 +2019,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
 			return;
 		}
 
-		// NOTE(bill): You need to store the entity information here unline a constant declaration
-		isize entity_cap = vd->names.count;
-		isize entity_count = 0;
-		Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_cap);
-		DeclInfo *di = nullptr;
-		if (vd->values.count > 0) {
-			di = make_decl_info(heap_allocator(), c->scope, c->decl);
-			di->entities = entities;
-			di->type_expr = vd->type;
-			di->init_expr = vd->values[0];
-			di->init_expr_list = vd->values;
-		}
-
 		for_array(i, vd->names) {
 			Ast *name = vd->names[i];
 			Ast *value = nullptr;
@@ -2052,24 +2049,15 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) {
 				e->Variable.is_export = true;
 			}
 
-			entities[entity_count++] = e;
-
-			DeclInfo *d = di;
-			if (d == nullptr || i > 0) {
-				Ast *init_expr = value;
-				d = make_decl_info(heap_allocator(), e->scope, c->decl);
-				d->type_expr = vd->type;
-				d->init_expr = init_expr;
-			}
+			Ast *init_expr = value;
+			DeclInfo *d = make_decl_info(heap_allocator(), c->scope, c->decl);
+			d->type_expr = vd->type;
+			d->init_expr = init_expr;
 			d->attributes = vd->attributes;
 
 			add_entity_and_decl_info(c, name, e, d);
 		}
 
-		if (di != nullptr) {
-			di->entity_count = entity_count;
-		}
-
 		check_arity_match(c, vd, true);
 	} else {
 		for_array(i, vd->names) {
@@ -2380,6 +2368,9 @@ void add_import_dependency_node(Checker *c, Ast *decl, Map<ImportGraphNode *> *M
 	switch (decl->kind) {
 	case_ast_node(id, ImportDecl, decl);
 		String path = id->fullpath;
+		if (path == "builtin") {
+			return;
+		}
 		HashKey key = hash_string(path);
 		AstPackage **found = map_get(&c->info.packages, key);
 		if (found == nullptr) {
@@ -2538,32 +2529,35 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
 	decl->been_handled = true;
 
 	ast_node(id, ImportDecl, decl);
+	Token token = id->relpath;
 
 	Scope *parent_scope = ctx->scope;
 	GB_ASSERT(parent_scope->is_file);
 
 	auto *pkgs = &ctx->checker->info.packages;
 
-	Token token = id->relpath;
-	HashKey key = hash_string(id->fullpath);
-	AstPackage **found = map_get(pkgs, key);
-	if (found == nullptr) {
-		for_array(pkg_index, pkgs->entries) {
-			AstPackage *pkg = pkgs->entries[pkg_index].value;
-			gb_printf_err("%.*s\n", LIT(pkg->fullpath));
-		}
-		gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
-		GB_PANIC("Unable to find scope for package: %.*s", LIT(id->fullpath));
-	}
-	AstPackage *pkg = *found;
-	Scope *scope = pkg->scope;
+	Scope *scope = nullptr;
+
+	if (id->fullpath == "builtin") {
+		scope = universal_scope;
+	} else {
+		HashKey key = hash_string(id->fullpath);
+		AstPackage **found = map_get(pkgs, key);
+		if (found == nullptr) {
+			for_array(pkg_index, pkgs->entries) {
+				AstPackage *pkg = pkgs->entries[pkg_index].value;
+				gb_printf_err("%.*s\n", LIT(pkg->fullpath));
+			}
+			gb_printf_err("%.*s(%td:%td)\n", LIT(token.pos.file), token.pos.line, token.pos.column);
+			GB_PANIC("Unable to find scope for package: %.*s", LIT(id->fullpath));
+		} else {
+			AstPackage *pkg = *found;
+			ptr_set_add(&ctx->checker->checked_packages, pkg);
+			scope = pkg->scope;
+		}
+	}
 	GB_ASSERT(scope->is_package);
 
-	// TODO(bill): Should this be allowed or not?
-	// if (scope->is_global) {
-	// 	error(token, "Importing a runtime package is disallowed and unnecessary");
-	// 	return;
-	// }
 
 	if (ptr_set_exists(&parent_scope->imported, scope)) {
 		// error(token, "Multiple import of the same file within this scope");
@@ -2615,7 +2609,6 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) {
 		}
 	}
 
-	ptr_set_add(&ctx->checker->checked_packages, pkg);
 	scope->has_been_imported = true;
 }
 
@@ -3093,11 +3086,7 @@ void calculate_global_init_order(Checker *c) {
 		}
 		ptr_set_add(&emitted, d);
 
-		if (d->entities == nullptr) {
-			d->entities = gb_alloc_array(c->allocator, Entity *, 1);
-			d->entities[0] = e;
-			d->entity_count = 1;
-		}
+		d->entity = e;
 		array_add(&info->variable_init_order, d);
 	}
 
@@ -3105,13 +3094,8 @@ void calculate_global_init_order(Checker *c) {
 		gb_printf("Variable Initialization Order:\n");
 		for_array(i, info->variable_init_order) {
 			DeclInfo *d = info->variable_init_order[i];
-			for (isize j = 0; j < d->entity_count; j++) {
-				Entity *e = d->entities[j];
-				if (j == 0) gb_printf("\t");
-				if (j > 0) gb_printf(", ");
-				gb_printf("'%.*s' %td", LIT(e->token.string), e->order_in_src);
-			}
-			gb_printf("\n");
+			Entity *e = d->entity;
+			gb_printf("\t'%.*s' %td\n", LIT(e->token.string), e->order_in_src);
 		}
 		gb_printf("\n");
 	}
@@ -3200,15 +3184,15 @@ void check_parsed_files(Checker *c) {
 	TIME_SECTION("collect entities");
 	// Collect Entities
 	for_array(i, c->parser->packages) {
-		AstPackage *p = c->parser->packages[i];
+		AstPackage *pkg = c->parser->packages[i];
 
 		CheckerContext ctx = make_checker_context(c);
 		defer (destroy_checker_context(&ctx));
-		ctx.pkg = p;
+		ctx.pkg = pkg;
 		ctx.collect_delayed_decls = false;
 
-		for_array(j, p->files) {
-			AstFile *f = p->files[j];
+		for_array(j, pkg->files) {
+			AstFile *f = pkg->files[j];
 			create_scope_from_file(&ctx, f);
 			HashKey key = hash_string(f->fullpath);
 			map_set(&c->info.files, key, f);

+ 9 - 9
src/checker.hpp

@@ -180,18 +180,17 @@ void check_decl_attributes(CheckerContext *c, Array<Ast *> const &attributes, De
 
 // DeclInfo is used to store information of certain declarations to allow for "any order" usage
 struct DeclInfo {
-	DeclInfo *        parent; // NOTE(bill): only used for procedure literals at the moment
-	Scope *           scope;
+	DeclInfo *    parent; // NOTE(bill): only used for procedure literals at the moment
+	Scope *       scope;
 
-	Entity **         entities;
-	isize             entity_count;
+	Entity *entity;
 
 	Ast *         type_expr;
 	Ast *         init_expr;
-	Array<Ast *>  init_expr_list;
+	// Array<Ast *>  init_expr_list;
 	Array<Ast *>  attributes;
 	Ast *         proc_lit;      // Ast_ProcLit
-	Type *            gen_proc_type; // Precalculated
+	Type *        gen_proc_type; // Precalculated
 
 	PtrSet<Entity *>  deps;
 	PtrSet<Type *>    type_info_deps;
@@ -204,16 +203,16 @@ struct ProcInfo {
 	Token     token;
 	DeclInfo *decl;
 	Type *    type; // Type_Procedure
-	Ast * body; // Ast_BlockStmt
+	Ast *     body; // Ast_BlockStmt
 	u64       tags;
 	bool      generated_from_polymorphic;
-	Ast * poly_def_node;
+	Ast *     poly_def_node;
 };
 
 
 
 struct Scope {
-	Ast *        node;
+	Ast *            node;
 	Scope *          parent;
 	Scope *          prev, *next;
 	Scope *          first_child;
@@ -298,6 +297,7 @@ struct CheckerInfo {
 	Map<isize>            type_info_map;   // Key: Type *
 
 
+	AstPackage *          builtin_package;
 	AstPackage *          runtime_package;
 	Scope *               init_scope;
 	Entity *              entry_point;

+ 42 - 44
src/ir.cpp

@@ -4188,8 +4188,8 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 			Entity *e = entity_of_ident(ident);
 			GB_ASSERT(e != nullptr);
 
-			if (e->parent_proc_decl != nullptr && e->parent_proc_decl->entity_count > 0) {
-				procedure = e->parent_proc_decl->entities[0]->token.string;
+			if (e->parent_proc_decl != nullptr && e->parent_proc_decl->entity != nullptr) {
+				procedure = e->parent_proc_decl->entity->token.string;
 			} else {
 				procedure = str_lit("");
 			}
@@ -8343,57 +8343,55 @@ void ir_gen_tree(irGen *s) {
 	for_array(i, info->variable_init_order) {
 		DeclInfo *d = info->variable_init_order[i];
 
-		for (isize j = 0; j < d->entity_count; j++) {
-			Entity *e = d->entities[j];
+		Entity *e = d->entity;
 
-			if (!e->scope->is_file) {
-				continue;
-			}
+		if (!e->scope->is_file) {
+			continue;
+		}
 
-			if (!ir_min_dep_entity(m, e)) {
-				continue;
-			}
-			DeclInfo *decl = decl_info_of_entity(e);
-			if (decl == nullptr) {
-				continue;
-			}
-			GB_ASSERT(e->kind == Entity_Variable);
+		if (!ir_min_dep_entity(m, e)) {
+			continue;
+		}
+		DeclInfo *decl = decl_info_of_entity(e);
+		if (decl == nullptr) {
+			continue;
+		}
+		GB_ASSERT(e->kind == Entity_Variable);
 
-			bool is_foreign = e->Variable.is_foreign;
-			bool is_export  = e->Variable.is_export;
-			bool no_name_mangle = e->Variable.link_name.len > 0 || is_foreign || is_export;
+		bool is_foreign = e->Variable.is_foreign;
+		bool is_export  = e->Variable.is_export;
+		bool no_name_mangle = e->Variable.link_name.len > 0 || is_foreign || is_export;
 
-			String name = e->token.string;
-			if (!no_name_mangle) {
-				name = ir_mangle_name(s, e);
-			}
-			ir_add_entity_name(m, e, name);
+		String name = e->token.string;
+		if (!no_name_mangle) {
+			name = ir_mangle_name(s, e);
+		}
+		ir_add_entity_name(m, e, name);
 
-			irValue *g = ir_value_global(a, e, nullptr);
-			g->Global.name = name;
-			g->Global.thread_local_model = e->Variable.thread_local_model;
-			g->Global.is_foreign = is_foreign;
-			g->Global.is_export  = is_export;
-
-			irGlobalVariable var = {};
-			var.var = g;
-			var.decl = decl;
-
-			if (decl->init_expr != nullptr && !is_type_any(e->type)) {
-				TypeAndValue tav = type_and_value_of_expr(decl->init_expr);
-				if (tav.mode != Addressing_Invalid) {
-					if (tav.value.kind != ExactValue_Invalid) {
-						ExactValue v = tav.value;
-						g->Global.value = ir_add_module_constant(m, tav.type, v);
-					}
+		irValue *g = ir_value_global(a, e, nullptr);
+		g->Global.name = name;
+		g->Global.thread_local_model = e->Variable.thread_local_model;
+		g->Global.is_foreign = is_foreign;
+		g->Global.is_export  = is_export;
+
+		irGlobalVariable var = {};
+		var.var = g;
+		var.decl = decl;
+
+		if (decl->init_expr != nullptr && !is_type_any(e->type)) {
+			TypeAndValue tav = type_and_value_of_expr(decl->init_expr);
+			if (tav.mode != Addressing_Invalid) {
+				if (tav.value.kind != ExactValue_Invalid) {
+					ExactValue v = tav.value;
+					g->Global.value = ir_add_module_constant(m, tav.type, v);
 				}
 			}
+		}
 
-			array_add(&global_variables, var);
+		array_add(&global_variables, var);
 
-			ir_module_add_value(m, e, g);
-			map_set(&m->members, hash_string(name), g);
-		}
+		ir_module_add_value(m, e, g);
+		map_set(&m->members, hash_string(name), g);
 	}
 
 	for_array(i, info->entities) {

+ 1 - 1
src/main.cpp

@@ -791,7 +791,7 @@ int main(int arg_count, char **arg_ptr) {
 		return 1;
 	}
 
-	init_universal_scope();
+	init_universal();
 	// TODO(bill): prevent compiling without a linker
 
 	timings_start_section(&timings, str_lit("parse files"));

+ 20 - 4
src/parser.cpp

@@ -2446,7 +2446,7 @@ Ast *parse_value_decl(AstFile *f, Array<Ast *> names, CommentGroup *docs) {
 	}
 
 	if (values.data == nullptr) {
-		values = array_make<Ast *>(heap_allocator());
+		values.allocator = heap_allocator();
 	}
 
 	if (f->expr_level >= 0) {
@@ -2462,6 +2462,12 @@ Ast *parse_value_decl(AstFile *f, Array<Ast *> names, CommentGroup *docs) {
 		}
 	}
 
+	if (f->curr_proc == nullptr) {
+		if (values.count > 0 && names.count != values.count) {
+			syntax_error(values[0], "Expected %td expressions on the right hand side, got %td", names.count, values.count);
+		}
+	}
+
 	return ast_value_decl(f, names, type, values, is_mutable, docs, f->line_comment);
 }
 
@@ -4094,8 +4100,13 @@ bool determine_path_from_string(Parser *p, Ast *node, String base_dir, String or
 #endif
 	}
 
-	String fullpath = string_trim_whitespace(get_fullpath_relative(a, base_dir, file_str));
-	*path = fullpath;
+
+	if (file_str == "builtin") {
+		*path = str_lit("builtin");
+	} else {
+		String fullpath = string_trim_whitespace(get_fullpath_relative(a, base_dir, file_str));
+		*path = fullpath;
+	}
 
 	return true;
 }
@@ -4155,6 +4166,9 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<Ast *>
 			import_path = string_trim_whitespace(import_path);
 
 			id->fullpath = import_path;
+			if (import_path == "builtin") {
+				continue;
+			}
 			try_add_import_path(p, import_path, original_string, ast_token(node).pos);
 		} else if (node->kind == Ast_ForeignImportDecl) {
 			ast_node(fl, ForeignImportDecl, node);
@@ -4284,6 +4298,8 @@ bool parse_file(Parser *p, AstFile *f) {
 			error(package_name, "Invalid package name '_'");
 		} else if (f->pkg->kind != Package_Runtime && package_name.string == "runtime") {
 			error(package_name, "Use of reserved package name '%.*s'", LIT(package_name.string));
+		} else if (package_name.string == "builtin") {
+			error(package_name, "Use of reserved package name '%.*s'", LIT(package_name.string));
 		}
 	}
 	f->package_name = package_name.string;
@@ -4418,8 +4434,8 @@ ParseFileError parse_packages(Parser *p, String init_filename) {
 		}
 	}
 
-	TokenPos init_pos = {};
 
+	TokenPos init_pos = {};
 	if (!build_context.generate_docs) {
 		String s = get_fullpath_core(heap_allocator(), str_lit("runtime"));
 		try_add_import_path(p, s, s, init_pos, Package_Runtime);

+ 1 - 0
src/parser.hpp

@@ -573,3 +573,4 @@ gbAllocator ast_allocator(void) {
 }
 
 Ast *alloc_ast_node(AstFile *f, AstKind kind);
+