| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- // checker.hpp
- struct Type;
- struct Entity;
- struct Scope;
- struct DeclInfo;
- struct AstFile;
- struct Checker;
- struct CheckerInfo;
- struct CheckerContext;
- enum AddressingMode;
- struct TypeAndValue;
- // ExprInfo stores information used for "untyped" expressions
- struct ExprInfo {
- AddressingMode mode;
- Type * type;
- ExactValue value;
- bool is_lhs; // Debug info
- };
- gb_inline ExprInfo make_expr_info(AddressingMode mode, Type *type, ExactValue value, bool is_lhs) {
- ExprInfo ei = {};
- ei.mode = mode;
- ei.type = type;
- ei.value = value;
- ei.is_lhs = is_lhs;
- return ei;
- }
- enum ExprKind {
- Expr_Expr,
- Expr_Stmt,
- };
- // Statements and Declarations
- enum StmtFlag {
- Stmt_BreakAllowed = 1<<0,
- Stmt_ContinueAllowed = 1<<1,
- Stmt_FallthroughAllowed = 1<<2,
- Stmt_TypeSwitch = 1<<4,
- Stmt_CheckScopeDecls = 1<<5,
- };
- enum BuiltinProcPkg {
- BuiltinProcPkg_builtin,
- BuiltinProcPkg_intrinsics,
- };
- struct BuiltinProc {
- String name;
- isize arg_count;
- bool variadic;
- ExprKind kind;
- BuiltinProcPkg pkg;
- bool diverging;
- };
- #include "checker_builtin_procs.hpp"
- // 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;
- Ast * expr;
- BuiltinProcId builtin_id;
- Entity * proc_group;
- };
- struct BlockLabel {
- String name;
- Ast *label; // Ast_Label;
- };
- enum DeferredProcedureKind {
- DeferredProcedure_none,
- DeferredProcedure_in,
- DeferredProcedure_out,
- DeferredProcedure_in_out,
- };
- struct DeferredProcedure {
- DeferredProcedureKind kind;
- Entity *entity;
- };
- struct AttributeContext {
- bool is_export;
- bool is_static;
- bool require_results;
- bool require_declaration;
- bool has_disabled_proc;
- bool disabled_proc;
- bool test;
- bool set_cold;
- String link_name;
- String link_prefix;
- isize init_expr_list_count;
- String thread_local_model;
- String deprecated_message;
- DeferredProcedure deferred_procedure;
- u32 optimization_mode; // ProcedureOptimizationMode
- struct TypeAtomOpTable *atom_op_table;
- };
- AttributeContext make_attribute_context(String link_prefix) {
- AttributeContext ac = {};
- ac.link_prefix = link_prefix;
- return ac;
- }
- #define DECL_ATTRIBUTE_PROC(_name) bool _name(CheckerContext *c, Ast *elem, String name, Ast *value, AttributeContext *ac)
- typedef DECL_ATTRIBUTE_PROC(DeclAttributeProc);
- void check_decl_attributes(CheckerContext *c, Array<Ast *> const &attributes, DeclAttributeProc *proc, AttributeContext *ac);
- // 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 *entity;
- Ast * decl_node;
- Ast * type_expr;
- Ast * init_expr;
- Array<Ast *> attributes;
- Ast * proc_lit; // Ast_ProcLit
- Type * gen_proc_type; // Precalculated
- bool is_using;
- bool where_clauses_evaluated;
- CommentGroup *comment;
- CommentGroup *docs;
- PtrSet<Entity *> deps;
- PtrSet<Type *> type_info_deps;
- Array<BlockLabel> labels;
- };
- // ProcInfo stores the information needed for checking a procedure
- struct ProcInfo {
- AstFile * file;
- Token token;
- DeclInfo *decl;
- Type * type; // Type_Procedure
- Ast * body; // Ast_BlockStmt
- u64 tags;
- bool generated_from_polymorphic;
- Ast * poly_def_node;
- };
- enum ScopeFlag : i32 {
- ScopeFlag_Pkg = 1<<1,
- ScopeFlag_Builtin = 1<<2,
- ScopeFlag_Global = 1<<3,
- ScopeFlag_File = 1<<4,
- ScopeFlag_Init = 1<<5,
- ScopeFlag_Proc = 1<<6,
- ScopeFlag_Type = 1<<7,
- ScopeFlag_HasBeenImported = 1<<10, // This is only applicable to file scopes
- ScopeFlag_ContextDefined = 1<<16,
- };
- enum { DEFAULT_SCOPE_CAPACITY = 29 };
- struct Scope {
- Ast * node;
- Scope * parent;
- Scope * prev;
- Scope * next;
- Scope * first_child;
- Scope * last_child;
- StringMap<Entity *> elements;
- Array<Ast *> delayed_directives;
- Array<Ast *> delayed_imports;
- PtrSet<Scope *> imported;
- i32 flags; // ScopeFlag
- union {
- AstPackage *pkg;
- AstFile * file;
- Entity * procedure_entity;
- };
- };
- 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;
- };
- struct ImportGraphNode;
- typedef PtrSet<ImportGraphNode *> ImportGraphNodeSet;
- struct ImportGraphNode {
- AstPackage * pkg;
- Scope * scope;
- ImportGraphNodeSet pred;
- ImportGraphNodeSet succ;
- isize index; // Index in array/queue
- isize dep_count;
- };
- enum EntityVisiblityKind {
- EntityVisiblity_Public,
- EntityVisiblity_PrivateToPackage,
- EntityVisiblity_PrivateToFile,
- };
- struct ForeignContext {
- Ast * curr_library;
- ProcCallingConvention default_cc;
- String link_prefix;
- EntityVisiblityKind visibility_kind;
- };
- typedef Array<Entity *> CheckerTypePath;
- typedef Array<Type *> CheckerPolyPath;
- struct AtomOpMapEntry {
- u32 kind;
- Ast *node;
- };
- struct CheckerContext;
- // CheckerInfo stores all the symbol information for a type-checked program
- struct CheckerInfo {
- Checker *checker;
- Map<ExprInfo> untyped; // Key: Ast * | Expression -> ExprInfo
- // NOTE(bill): This needs to be a map and not on the Ast
- // as it needs to be iterated across
- StringMap<AstFile *> files; // Key (full path)
- StringMap<AstPackage *> packages; // Key (full path)
- StringMap<Entity *> foreigns;
- Array<Entity *> definitions;
- Array<Entity *> entities;
- Array<DeclInfo *> variable_init_order;
- Map<Array<Entity *> > gen_procs; // Key: Ast * | Identifier -> Entity
- Map<Array<Entity *> > gen_types; // Key: Type *
- Array<Type *> type_info_types;
- Map<isize> type_info_map; // Key: Type *
- AstPackage * builtin_package;
- AstPackage * runtime_package;
- AstPackage * init_package;
- Scope * init_scope;
- Entity * entry_point;
- PtrSet<Entity *> minimum_dependency_set;
- PtrSet<isize> minimum_dependency_type_info_set;
- Array<Entity *> required_foreign_imports_through_force;
- Array<Entity *> required_global_variables;
- Map<AtomOpMapEntry> atom_op_map; // Key: Ast *
- Array<Entity *> testing_procedures;
- bool allow_identifier_uses;
- Array<Ast *> identifier_uses; // only used by 'odin query'
- };
- struct CheckerContext {
- Checker * checker;
- CheckerInfo * info;
- AstPackage * pkg;
- AstFile * file;
- Scope * scope;
- DeclInfo * decl;
- u32 state_flags;
- bool in_defer; // TODO(bill): Actually handle correctly
- Type * type_hint;
- String proc_name;
- DeclInfo * curr_proc_decl;
- Type * curr_proc_sig;
- ProcCallingConvention curr_proc_calling_convention;
- bool in_proc_sig;
- ForeignContext foreign_context;
- CheckerTypePath *type_path;
- isize type_level; // TODO(bill): Actually handle correctly
- CheckerPolyPath *poly_path;
- isize poly_level; // TODO(bill): Actually handle correctly
- #define MAX_INLINE_FOR_DEPTH 1024ll
- i64 inline_for_depth;
- bool in_enum_type;
- bool collect_delayed_decls;
- bool allow_polymorphic_types;
- bool no_polymorphic_errors;
- bool hide_polymorphic_errors;
- bool in_polymorphic_specialization;
- bool allow_arrow_right_selector_expr;
- Scope * polymorphic_scope;
- Ast *assignment_lhs_hint;
- Ast *unary_address_hint;
- };
- struct Checker {
- Parser * parser;
- CheckerInfo info;
- Array<ProcInfo> procs_to_check;
- Array<Entity *> procs_with_deferred_to_check;
- CheckerContext *curr_ctx;
- CheckerContext init_ctx;
- };
- gb_global AstPackage *builtin_pkg = nullptr;
- gb_global AstPackage *intrinsics_pkg = nullptr;
- gb_global AstPackage *config_pkg = nullptr;
- HashKey hash_node (Ast *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 (Ast *expr);
- Type * type_of_expr (Ast *expr);
- Entity * implicit_entity_of_node(Ast *clause);
- Scope * scope_of_node (Ast *node);
- DeclInfo * decl_info_of_ident (Ast *ident);
- DeclInfo * decl_info_of_entity (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);
- // Will return nullptr if not found
- Entity *entity_of_node(Ast *expr);
- Entity *scope_lookup_current(Scope *s, String const &name);
- Entity *scope_lookup (Scope *s, String const &name);
- void scope_lookup_parent (Scope *s, String const &name, Scope **scope_, Entity **entity_);
- Entity *scope_insert (Scope *s, Entity *entity);
- ExprInfo *check_get_expr_info (CheckerInfo *i, Ast *expr);
- void check_set_expr_info (CheckerInfo *i, Ast *expr, ExprInfo info);
- void check_remove_expr_info (CheckerInfo *i, Ast *expr);
- void add_untyped (CheckerInfo *i, Ast *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
- void add_type_and_value (CheckerInfo *i, Ast *expression, AddressingMode mode, Type *type, ExactValue value);
- void add_entity_use (CheckerContext *c, Ast *identifier, Entity *entity);
- void add_implicit_entity (CheckerContext *c, Ast *node, Entity *e);
- void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, DeclInfo *d, bool is_exported=true);
- void add_type_info_type (CheckerContext *c, Type *t);
- void check_add_import_decl(CheckerContext *c, Ast *decl);
- void check_add_foreign_import_decl(CheckerContext *c, Ast *decl);
- void check_entity_decl(CheckerContext *c, Entity *e, DeclInfo *d, Type *named_type);
- void check_const_decl(CheckerContext *c, Entity *e, Ast *type_expr, Ast *init_expr, Type *named_type);
- void check_type_decl(CheckerContext *c, Entity *e, Ast *type_expr, Type *def);
- bool check_arity_match(CheckerContext *c, AstValueDecl *vd, bool is_global = false);
- void check_collect_entities(CheckerContext *c, Slice<Ast *> const &nodes);
- void check_collect_entities_from_when_stmt(CheckerContext *c, AstWhenStmt *ws);
- void check_delayed_file_import_entity(CheckerContext *c, Ast *decl);
- CheckerTypePath *new_checker_type_path();
- void destroy_checker_type_path(CheckerTypePath *tp);
- void check_type_path_push(CheckerContext *c, Entity *e);
- Entity *check_type_path_pop (CheckerContext *c);
- CheckerPolyPath *new_checker_poly_path();
- void destroy_checker_poly_path(CheckerPolyPath *);
- void check_poly_path_push(CheckerContext *c, Type *t);
- Type *check_poly_path_pop (CheckerContext *c);
- void init_core_context(Checker *c);
|