diff options
Diffstat (limited to 'src/checker.cpp')
| -rw-r--r-- | src/checker.cpp | 380 |
1 files changed, 4 insertions, 376 deletions
diff --git a/src/checker.cpp b/src/checker.cpp index 06b65c1ec..55df36fb4 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1,150 +1,6 @@ #include "entity.cpp" - -enum ExprKind { - Expr_Expr, - Expr_Stmt, -}; - -// Statements and Declarations -enum StmtFlag { - Stmt_BreakAllowed = 1<<0, - Stmt_ContinueAllowed = 1<<1, - Stmt_FallthroughAllowed = 1<<2, - - Stmt_CheckScopeDecls = 1<<5, -}; - -struct BuiltinProc { - String name; - isize arg_count; - bool variadic; - ExprKind kind; -}; -enum BuiltinProcId { - BuiltinProc_Invalid, - - BuiltinProc_len, - BuiltinProc_cap, - - // BuiltinProc_new, - BuiltinProc_make, - // BuiltinProc_free, - - // BuiltinProc_reserve, - // BuiltinProc_clear, - // BuiltinProc_append, - // BuiltinProc_delete, - - BuiltinProc_size_of, - BuiltinProc_align_of, - BuiltinProc_offset_of, - BuiltinProc_type_of, - BuiltinProc_type_info_of, - - BuiltinProc_compile_assert, - - BuiltinProc_swizzle, - - BuiltinProc_complex, - BuiltinProc_real, - BuiltinProc_imag, - BuiltinProc_conj, - - // BuiltinProc_slice_ptr, - // BuiltinProc_slice_to_bytes, - - BuiltinProc_expand_to_tuple, - - BuiltinProc_min, - BuiltinProc_max, - BuiltinProc_abs, - BuiltinProc_clamp, - - BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures - - BuiltinProc_COUNT, -}; -gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { - {STR_LIT(""), 0, false, Expr_Stmt}, - - {STR_LIT("len"), 1, false, Expr_Expr}, - {STR_LIT("cap"), 1, false, Expr_Expr}, - - // {STR_LIT("new"), 1, false, Expr_Expr}, - {STR_LIT("make"), 1, true, Expr_Expr}, - // {STR_LIT("free"), 1, false, Expr_Stmt}, - - // {STR_LIT("reserve"), 2, false, Expr_Stmt}, - // {STR_LIT("clear"), 1, false, Expr_Stmt}, - // {STR_LIT("append"), 1, true, Expr_Expr}, - // {STR_LIT("delete"), 2, false, Expr_Stmt}, - - {STR_LIT("size_of"), 1, false, Expr_Expr}, - {STR_LIT("align_of"), 1, false, Expr_Expr}, - {STR_LIT("offset_of"), 2, false, Expr_Expr}, - {STR_LIT("type_of"), 1, false, Expr_Expr}, - {STR_LIT("type_info_of"), 1, false, Expr_Expr}, - - {STR_LIT("compile_assert"), 1, false, Expr_Expr}, - - {STR_LIT("swizzle"), 1, true, Expr_Expr}, - - {STR_LIT("complex"), 2, false, Expr_Expr}, - {STR_LIT("real"), 1, false, Expr_Expr}, - {STR_LIT("imag"), 1, false, Expr_Expr}, - {STR_LIT("conj"), 1, false, Expr_Expr}, - - // {STR_LIT("slice_ptr"), 2, true, Expr_Expr}, - // {STR_LIT("slice_to_bytes"), 1, false, Expr_Expr}, - - {STR_LIT("expand_to_tuple"), 1, false, Expr_Expr}, - - {STR_LIT("min"), 2, false, Expr_Expr}, - {STR_LIT("max"), 2, false, Expr_Expr}, - {STR_LIT("abs"), 1, false, Expr_Expr}, - {STR_LIT("clamp"), 3, false, Expr_Expr}, - - {STR_LIT(""), 0, true, Expr_Expr}, // DIRECTIVE -}; - - #include "types.cpp" -enum AddressingMode { - Addressing_Invalid, // invalid addressing mode - Addressing_NoValue, // no value (void in C) - Addressing_Value, // computed value (rvalue) - Addressing_Immutable, // immutable computed value (const rvalue) - Addressing_Variable, // addressable variable (lvalue) - Addressing_Constant, // constant - Addressing_Type, // type - Addressing_Builtin, // built-in procedure - Addressing_ProcGroup, // procedure group (overloaded procedure) - Addressing_MapIndex, // map index expression - - // lhs: acts like a Variable - // rhs: acts like OptionalOk - Addressing_OptionalOk, // rhs: acts like a value with an optional boolean part (for existence check) -}; - -// Operand is used as an intermediate value whilst checking -// Operands store an addressing mode, the expression being evaluated, -// its type and node, and other specific information for certain -// addressing modes -// Its zero-value is a valid "invalid operand" -struct Operand { - AddressingMode mode; - Type * type; - ExactValue value; - AstNode * expr; - BuiltinProcId builtin_id; - Entity * proc_group; -}; - -struct TypeAndValue { - AddressingMode mode; - Type * type; - ExactValue value; -}; bool is_operand_value(Operand o) { switch (o.mode) { @@ -166,79 +22,6 @@ bool is_operand_undef(Operand o) { -struct BlockLabel { - String name; - AstNode *label; // AstNode_Label; -}; - -// 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; - - Entity ** entities; - isize entity_count; - - AstNode * type_expr; - AstNode * init_expr; - Array<AstNode *> init_expr_list; - Array<AstNode *> attributes; - AstNode * proc_lit; // AstNode_ProcLit - Type * gen_proc_type; // Precalculated - - PtrSet<Entity *> deps; - Array<BlockLabel> labels; -}; - -// ProcedureInfo stores the information needed for checking a procedure - - -struct ProcedureInfo { - AstFile * file; - Token token; - DeclInfo * decl; - Type * type; // Type_Procedure - AstNode * body; // AstNode_BlockStmt - u64 tags; - bool generated_from_polymorphic; -}; - -// ExprInfo stores information used for "untyped" expressions -struct ExprInfo { - bool is_lhs; // Debug info - AddressingMode mode; - Type * type; // Type_Basic - ExactValue value; -}; - -ExprInfo make_expr_info(bool is_lhs, AddressingMode mode, Type *type, ExactValue value) { - ExprInfo ei = {is_lhs, mode, type, value}; - return ei; -} - - - -struct Scope { - AstNode * node; - Scope * parent; - Scope * prev, *next; - Scope * first_child; - Scope * last_child; - Map<Entity *> elements; // Key: String - PtrSet<Entity *> implicit; - - Array<Scope *> shared; - Array<AstNode *> delayed_file_decls; - PtrSet<Scope *> imported; - PtrSet<Scope *> exported; // NOTE(bhall): Contains 'using import' too - bool is_proc; - bool is_global; - bool is_file; - bool is_init; - bool is_struct; - bool has_been_imported; // This is only applicable to file scopes - AstFile * file; -}; gb_global Scope *universal_scope = nullptr; void scope_reset(Scope *scope) { @@ -257,7 +40,7 @@ i32 is_scope_an_ancestor(Scope *parent, Scope *child) { isize i = 0; while (child != nullptr) { if (parent == child) { - return true; + return i; } child = child->parent; i++; @@ -265,18 +48,6 @@ i32 is_scope_an_ancestor(Scope *parent, Scope *child) { return -1; } - -struct EntityGraphNode; -typedef PtrSet<EntityGraphNode *> EntityGraphNodeSet; - -struct EntityGraphNode { - Entity * entity; // Procedure, Variable, Constant - EntityGraphNodeSet pred; - EntityGraphNodeSet succ; - isize index; // Index in array/queue - isize dep_count; -}; - void entity_graph_node_set_destroy(EntityGraphNodeSet *s) { if (s->hashes.data != nullptr) { ptr_set_destroy(s); @@ -326,9 +97,6 @@ void entity_graph_node_swap(EntityGraphNode **data, isize i, isize j) { -struct ImportGraphNode; -typedef PtrSet<ImportGraphNode *> ImportGraphNodeSet; - void import_graph_node_set_destroy(ImportGraphNodeSet *s) { if (s->hashes.data != nullptr) { ptr_set_destroy(s); @@ -350,16 +118,6 @@ void import_graph_node_set_remove(ImportGraphNodeSet *s, ImportGraphNode *n) { ptr_set_remove(s, n); } -struct ImportGraphNode { - Scope * scope; - String path; - isize file_id; - ImportGraphNodeSet pred; - ImportGraphNodeSet succ; - isize index; // Index in array/queue - isize dep_count; -}; - ImportGraphNode *import_graph_node_create(gbAllocator a, Scope *scope) { ImportGraphNode *n = gb_alloc_item(a, ImportGraphNode); n->scope = scope; @@ -368,7 +126,6 @@ ImportGraphNode *import_graph_node_create(gbAllocator a, Scope *scope) { return n; } - void import_graph_node_destroy(ImportGraphNode *n, gbAllocator a) { import_graph_node_set_destroy(&n->pred); import_graph_node_set_destroy(&n->succ); @@ -409,118 +166,10 @@ GB_COMPARE_PROC(ast_node_cmp) { return token_pos_cmp(i.pos, j.pos); } -struct ForeignContext { - AstNode * curr_library; - ProcCallingConvention default_cc; - String link_prefix; - bool in_export; -}; - -struct CheckerContext { - Scope * file_scope; - Scope * scope; - DeclInfo * decl; - u32 stmt_state_flags; - bool in_defer; // TODO(bill): Actually handle correctly - String proc_name; - Type * type_hint; - DeclInfo * curr_proc_decl; - ForeignContext foreign_context; - - bool collect_delayed_decls; - bool allow_polymorphic_types; - bool no_polymorphic_errors; - Scope * polymorphic_scope; -}; - - -// CheckerInfo stores all the symbol information for a type-checked program -struct CheckerInfo { - Map<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value) - Map<ExprInfo> untyped; // Key: AstNode * | Expression -> ExprInfo - Map<AstFile *> files; // Key: String (full path) - Map<Entity *> foreigns; // Key: String - Array<Entity *> definitions; - Array<Entity *> entities; - Array<DeclInfo *> variable_init_order; - - Map<Array<Entity *> > gen_procs; // Key: AstNode * | Identifier -> Entity - Map<Array<Entity *> > gen_types; // Key: Type * - - Map<isize> type_info_map; // Key: Type * - isize type_info_count; - - Scope * init_scope; - Entity * entry_point; - PtrSet<Entity *> minimum_dependency_set; -}; - -struct Checker { - Parser * parser; - CheckerInfo info; - gbMutex mutex; - - AstFile * curr_ast_file; - Scope * global_scope; - // NOTE(bill): Procedures to check - Array<ProcedureInfo> procs; - Map<Scope *> file_scopes; // Key: String (fullpath) - Array<ImportGraphNode *> file_order; - - gbAllocator allocator; - gbArena arena; - gbArena tmp_arena; - gbAllocator tmp_allocator; - - CheckerContext context; - - Array<Type *> proc_stack; - bool done_preload; - - PtrSet<AstFile *> checked_files; - -}; - - - -HashKey hash_node (AstNode *node) { return hash_pointer(node); } -HashKey hash_ast_file (AstFile *file) { return hash_pointer(file); } -HashKey hash_entity (Entity *e) { return hash_pointer(e); } -HashKey hash_type (Type *t) { return hash_pointer(t); } -HashKey hash_decl_info(DeclInfo *decl) { return hash_pointer(decl); } - -// CheckerInfo API -TypeAndValue type_and_value_of_expr (CheckerInfo *i, AstNode *expr); -Type * type_of_expr (CheckerInfo *i, AstNode *expr); -Entity * entity_of_ident (CheckerInfo *i, AstNode *identifier); -Entity * implicit_entity_of_node(CheckerInfo *i, AstNode *clause); -Scope * scope_of_node (CheckerInfo *i, AstNode *node); -DeclInfo * decl_info_of_ident (CheckerInfo *i, AstNode *ident); -DeclInfo * decl_info_of_entity (CheckerInfo *i, Entity * e); -AstFile * ast_file_of_filename (CheckerInfo *i, String filename); -// IMPORTANT: Only to use once checking is done -isize type_info_index (CheckerInfo *i, Type * type, bool error_on_failure = true); -Entity *current_scope_lookup_entity(Scope *s, String name); -Entity *scope_lookup_entity (Scope *s, String name); -void scope_lookup_parent_entity (Scope *s, String name, Scope **scope_, Entity **entity_); -Entity *scope_insert_entity (Scope *s, Entity *entity); -ExprInfo *check_get_expr_info (CheckerInfo *i, AstNode *expr); -void check_set_expr_info (CheckerInfo *i, AstNode *expr, ExprInfo info); -void check_remove_expr_info (CheckerInfo *i, AstNode *expr); -void add_untyped (CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value); -void add_type_and_value (CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value); -void add_entity_use (Checker *c, AstNode *identifier, Entity *entity); -void add_implicit_entity (Checker *c, AstNode *node, Entity *e); -void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d); - -void check_add_import_decl(Checker *c, AstNodeImportDecl *id); -void check_add_export_decl(Checker *c, AstNodeExportDecl *ed); -void check_add_foreign_import_decl(Checker *c, AstNode *decl); - void init_declaration_info(DeclInfo *d, Scope *scope, DeclInfo *parent) { d->parent = parent; @@ -771,6 +420,9 @@ Entity *scope_lookup_entity(Scope *s, String name) { Entity *scope_insert_entity(Scope *s, Entity *entity) { String name = entity->token.string; + if (name == "") { + return nullptr; + } HashKey key = hash_string(name); Entity **found = map_get(&s->elements, key); @@ -1742,30 +1394,6 @@ void init_preload(Checker *c) { -bool check_arity_match(Checker *c, AstNodeValueDecl *vd, bool is_global = false); -void check_collect_entities(Checker *c, Array<AstNode *> nodes); -void check_collect_entities_from_when_stmt(Checker *c, AstNodeWhenStmt *ws); -void check_delayed_file_import_entity(Checker *c, AstNode *decl); - -struct AttributeContext { - String link_name; - String link_prefix; - isize init_expr_list_count; - String thread_local_model; -}; - -AttributeContext make_attribute_context(String link_prefix) { - AttributeContext ac = {}; - ac.link_prefix = link_prefix; - return ac; -} - -#define DECL_ATTRIBUTE_PROC(_name) bool _name(Checker *c, AstNode *elem, String name, ExactValue value, AttributeContext *ac) -typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc); - - -void check_decl_attributes(Checker *c, Array<AstNode *> attributes, DeclAttributeProc *proc, AttributeContext *ac); - DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) { if (name == "default_calling_convention") { if (value.kind == ExactValue_String) { |