123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- struct Ast;
- struct Scope;
- struct Type;
- struct Entity;
- struct DeclInfo;
- struct AstFile;
- struct AstPackage;
- enum AddressingMode {
- Addressing_Invalid, // invalid addressing mode
- Addressing_NoValue, // no value (void in C)
- Addressing_Value, // computed value (rvalue)
- Addressing_Context, // context value
- 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)
- Addressing_SoaVariable, // Struct-Of-Arrays indexed variable
- Addressing_AtomOpAssign, // Specialized for custom atom operations for assignments
- };
- struct TypeAndValue {
- AddressingMode mode;
- Type * type;
- ExactValue value;
- };
- enum ParseFileError {
- ParseFile_None,
- ParseFile_WrongExtension,
- ParseFile_InvalidFile,
- ParseFile_EmptyFile,
- ParseFile_Permission,
- ParseFile_NotFound,
- ParseFile_InvalidToken,
- ParseFile_GeneralError,
- ParseFile_FileTooLarge,
- ParseFile_Count,
- };
- struct CommentGroup {
- Slice<Token> list; // Token_Comment
- };
- enum PackageKind {
- Package_Normal,
- Package_Runtime,
- Package_Init,
- };
- struct ImportedPackage {
- PackageKind kind;
- String path;
- String rel_path;
- TokenPos pos; // import
- isize index;
- };
- struct ImportedFile {
- AstPackage *pkg;
- FileInfo fi;
- TokenPos pos; // import
- isize index;
- };
- struct AstFile {
- i32 id;
- AstPackage * pkg;
- Scope * scope;
- Arena arena;
- Ast * pkg_decl;
- String fullpath;
- Tokenizer tokenizer;
- Array<Token> tokens;
- isize curr_token_index;
- Token curr_token;
- Token prev_token; // previous non-comment
- Token package_token;
- String package_name;
- // >= 0: In Expression
- // < 0: In Control Clause
- // NOTE(bill): Used to prevent type literals in control clauses
- isize expr_level;
- bool allow_range; // NOTE(bill): Ranges are only allowed in certain cases
- bool allow_in_expr; // NOTE(bill): in expression are only allowed in certain cases
- bool in_foreign_block;
- bool allow_type;
- Slice<Ast *> decls;
- Array<Ast *> imports; // 'import'
- isize directive_count;
- Ast * curr_proc;
- isize error_count;
- ParseFileError last_error;
- f64 time_to_tokenize; // seconds
- f64 time_to_parse; // seconds
- bool is_private;
- bool is_test;
- CommentGroup *lead_comment; // Comment (block) before the decl
- CommentGroup *line_comment; // Comment after the semicolon
- CommentGroup *docs; // current docs
- Array<CommentGroup *> comments; // All the comments!
- #define PARSER_MAX_FIX_COUNT 6
- isize fix_count;
- TokenPos fix_prev_pos;
- struct LLVMOpaqueMetadata *llvm_metadata;
- struct LLVMOpaqueMetadata *llvm_metadata_scope;
- };
- enum AstForeignFileKind {
- AstForeignFile_Invalid,
- AstForeignFile_S, // Source,
- AstForeignFile_COUNT
- };
- struct AstForeignFile {
- AstForeignFileKind kind;
- String source;
- };
- struct AstPackage {
- PackageKind kind;
- isize id;
- String name;
- String fullpath;
- Array<AstFile *> files;
- Array<AstForeignFile> foreign_files;
- bool is_single_file;
- // NOTE(bill): Created/set in checker
- Scope * scope;
- DeclInfo *decl_info;
- bool used;
- bool is_extra;
- };
- struct Parser {
- String init_fullpath;
- StringSet imported_files; // fullpath
- StringMap<AstPackage *> package_map; // Key(package name)
- Array<AstPackage *> packages;
- Array<ImportedPackage> package_imports;
- isize file_to_process_count;
- isize total_token_count;
- isize total_line_count;
- gbMutex file_add_mutex;
- gbMutex file_decl_mutex;
- };
- gb_global ThreadPool parser_thread_pool = {};
- struct ParserWorkerData {
- Parser *parser;
- ImportedFile imported_file;
- };
- struct ForeignFileWorkerData {
- Parser *parser;
- ImportedFile imported_file;
- AstForeignFileKind foreign_kind;
- };
- enum ProcInlining {
- ProcInlining_none = 0,
- ProcInlining_inline = 1,
- ProcInlining_no_inline = 2,
- };
- enum ProcTag {
- ProcTag_bounds_check = 1<<0,
- ProcTag_no_bounds_check = 1<<1,
- ProcTag_require_results = 1<<4,
- ProcTag_optional_ok = 1<<5,
- };
- enum ProcCallingConvention {
- ProcCC_Invalid = 0,
- ProcCC_Odin = 1,
- ProcCC_Contextless = 2,
- ProcCC_CDecl = 3,
- ProcCC_StdCall = 4,
- ProcCC_FastCall = 5,
- ProcCC_None = 6,
- ProcCC_InlineAsm = 7,
- ProcCC_MAX,
- ProcCC_ForeignBlockDefault = -1,
- };
- enum StateFlag : u16 {
- StateFlag_bounds_check = 1<<0,
- StateFlag_no_bounds_check = 1<<1,
- StateFlag_no_deferred = 1<<5,
- StateFlag_BeenHandled = 1<<15,
- };
- enum ViralStateFlag : u16 {
- ViralStateFlag_ContainsDeferredProcedure = 1<<0,
- };
- enum FieldFlag {
- FieldFlag_NONE = 0,
- FieldFlag_ellipsis = 1<<0,
- FieldFlag_using = 1<<1,
- FieldFlag_no_alias = 1<<2,
- FieldFlag_c_vararg = 1<<3,
- FieldFlag_auto_cast = 1<<4,
- FieldFlag_const = 1<<5,
- FieldFlag_Tags = 1<<10,
- FieldFlag_Results = 1<<16,
- FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast|FieldFlag_const,
- FieldFlag_Struct = FieldFlag_using|FieldFlag_Tags,
- };
- enum StmtAllowFlag {
- StmtAllowFlag_None = 0,
- StmtAllowFlag_In = 1<<0,
- StmtAllowFlag_Label = 1<<1,
- };
- enum InlineAsmDialectKind : u8 {
- InlineAsmDialect_Default, // ATT is default
- InlineAsmDialect_ATT,
- InlineAsmDialect_Intel,
- InlineAsmDialect_COUNT,
- };
- char const *inline_asm_dialect_strings[InlineAsmDialect_COUNT] = {
- "",
- "att",
- "intel",
- };
- #define AST_KINDS \
- AST_KIND(Ident, "identifier", struct { \
- Token token; \
- Entity *entity; \
- }) \
- AST_KIND(Implicit, "implicit", Token) \
- AST_KIND(Undef, "undef", Token) \
- AST_KIND(BasicLit, "basic literal", struct { \
- Token token; \
- }) \
- AST_KIND(BasicDirective, "basic directive", struct { \
- Token token; \
- String name; \
- }) \
- AST_KIND(Ellipsis, "ellipsis", struct { \
- Token token; \
- Ast *expr; \
- }) \
- AST_KIND(ProcGroup, "procedure group", struct { \
- Token token; \
- Token open; \
- Token close; \
- Slice<Ast *> args; \
- }) \
- AST_KIND(ProcLit, "procedure literal", struct { \
- Ast *type; \
- Ast *body; \
- u64 tags; \
- ProcInlining inlining; \
- Token where_token; \
- Slice<Ast *> where_clauses; \
- DeclInfo *decl; \
- }) \
- AST_KIND(CompoundLit, "compound literal", struct { \
- Ast *type; \
- Slice<Ast *> elems; \
- Token open, close; \
- i64 max_count; \
- }) \
- AST_KIND(_ExprBegin, "", bool) \
- AST_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \
- AST_KIND(TagExpr, "tag expression", struct { Token token, name; Ast *expr; }) \
- AST_KIND(UnaryExpr, "unary expression", struct { Token op; Ast *expr; }) \
- AST_KIND(BinaryExpr, "binary expression", struct { Token op; Ast *left, *right; } ) \
- AST_KIND(ParenExpr, "parentheses expression", struct { Ast *expr; Token open, close; }) \
- AST_KIND(SelectorExpr, "selector expression", struct { Token token; Ast *expr, *selector; }) \
- AST_KIND(ImplicitSelectorExpr, "implicit selector expression", struct { Token token; Ast *selector; }) \
- AST_KIND(SelectorCallExpr, "selector call expression", struct { Token token; Ast *expr, *call; bool modified_call; }) \
- AST_KIND(IndexExpr, "index expression", struct { Ast *expr, *index; Token open, close; }) \
- AST_KIND(DerefExpr, "dereference expression", struct { Token op; Ast *expr; }) \
- AST_KIND(SliceExpr, "slice expression", struct { \
- Ast *expr; \
- Token open, close; \
- Token interval; \
- Ast *low, *high; \
- }) \
- AST_KIND(CallExpr, "call expression", struct { \
- Ast * proc; \
- Slice<Ast *> args; \
- Token open; \
- Token close; \
- Token ellipsis; \
- ProcInlining inlining; \
- bool optional_ok_one; \
- }) \
- AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
- AST_KIND(TernaryExpr, "ternary expression", struct { Ast *cond, *x, *y; }) \
- AST_KIND(TernaryIfExpr, "ternary if expression", struct { Ast *x, *cond, *y; }) \
- AST_KIND(TernaryWhenExpr, "ternary when expression", struct { Ast *x, *cond, *y; }) \
- AST_KIND(TypeAssertion, "type assertion", struct { Ast *expr; Token dot; Ast *type; Type *type_hint; }) \
- AST_KIND(TypeCast, "type cast", struct { Token token; Ast *type, *expr; }) \
- AST_KIND(AutoCast, "auto_cast", struct { Token token; Ast *expr; }) \
- AST_KIND(InlineAsmExpr, "inline asm expression", struct { \
- Token token; \
- Token open, close; \
- Slice<Ast *> param_types; \
- Ast *return_type; \
- Ast *asm_string; \
- Ast *constraints_string; \
- bool has_side_effects; \
- bool is_align_stack; \
- InlineAsmDialectKind dialect; \
- }) \
- AST_KIND(_ExprEnd, "", bool) \
- AST_KIND(_StmtBegin, "", bool) \
- AST_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
- AST_KIND(EmptyStmt, "empty statement", struct { Token token; }) \
- AST_KIND(ExprStmt, "expression statement", struct { Ast *expr; } ) \
- AST_KIND(TagStmt, "tag statement", struct { \
- Token token; \
- Token name; \
- Ast * stmt; \
- }) \
- AST_KIND(AssignStmt, "assign statement", struct { \
- Token op; \
- Slice<Ast *> lhs, rhs; \
- }) \
- AST_KIND(_ComplexStmtBegin, "", bool) \
- AST_KIND(BlockStmt, "block statement", struct { \
- Slice<Ast *> stmts; \
- Ast *label; \
- Token open, close; \
- }) \
- AST_KIND(IfStmt, "if statement", struct { \
- Token token; \
- Ast *label; \
- Ast * init; \
- Ast * cond; \
- Ast * body; \
- Ast * else_stmt; \
- }) \
- AST_KIND(WhenStmt, "when statement", struct { \
- Token token; \
- Ast *cond; \
- Ast *body; \
- Ast *else_stmt; \
- bool is_cond_determined; \
- bool determined_cond; \
- }) \
- AST_KIND(ReturnStmt, "return statement", struct { \
- Token token; \
- Slice<Ast *> results; \
- }) \
- AST_KIND(ForStmt, "for statement", struct { \
- Token token; \
- Ast *label; \
- Ast *init; \
- Ast *cond; \
- Ast *post; \
- Ast *body; \
- }) \
- AST_KIND(RangeStmt, "range statement", struct { \
- Token token; \
- Ast *label; \
- Ast *val0; \
- Ast *val1; \
- Token in_token; \
- Ast *expr; \
- Ast *body; \
- }) \
- AST_KIND(InlineRangeStmt, "inline range statement", struct { \
- Token inline_token; \
- Token for_token; \
- Ast *val0; \
- Ast *val1; \
- Token in_token; \
- Ast *expr; \
- Ast *body; \
- }) \
- AST_KIND(CaseClause, "case clause", struct { \
- Token token; \
- Slice<Ast *> list; \
- Slice<Ast *> stmts; \
- Entity *implicit_entity; \
- }) \
- AST_KIND(SwitchStmt, "switch statement", struct { \
- Token token; \
- Ast *label; \
- Ast *init; \
- Ast *tag; \
- Ast *body; \
- bool partial; \
- }) \
- AST_KIND(TypeSwitchStmt, "type switch statement", struct { \
- Token token; \
- Ast *label; \
- Ast *tag; \
- Ast *body; \
- bool partial; \
- }) \
- AST_KIND(DeferStmt, "defer statement", struct { Token token; Ast *stmt; }) \
- AST_KIND(BranchStmt, "branch statement", struct { Token token; Ast *label; }) \
- AST_KIND(UsingStmt, "using statement", struct { \
- Token token; \
- Slice<Ast *> list; \
- }) \
- AST_KIND(_ComplexStmtEnd, "", bool) \
- AST_KIND(_StmtEnd, "", bool) \
- AST_KIND(_DeclBegin, "", bool) \
- AST_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
- AST_KIND(ForeignBlockDecl, "foreign block declaration", struct { \
- Token token; \
- Ast *foreign_library; \
- Ast *body; \
- Array<Ast *> attributes; \
- CommentGroup *docs; \
- }) \
- AST_KIND(Label, "label", struct { \
- Token token; \
- Ast *name; \
- }) \
- AST_KIND(ValueDecl, "value declaration", struct { \
- Slice<Ast *> names; \
- Ast * type; \
- Slice<Ast *> values; \
- Array<Ast *> attributes; \
- CommentGroup *docs; \
- CommentGroup *comment; \
- bool is_using; \
- bool is_mutable; \
- }) \
- AST_KIND(PackageDecl, "package declaration", struct { \
- Token token; \
- Token name; \
- CommentGroup *docs; \
- CommentGroup *comment; \
- }) \
- AST_KIND(ImportDecl, "import declaration", struct { \
- AstPackage *package; \
- Token token; \
- Token relpath; \
- String fullpath; \
- Token import_name; \
- CommentGroup *docs; \
- CommentGroup *comment; \
- bool is_using; \
- }) \
- AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \
- Token token; \
- Slice<Token> filepaths; \
- Token library_name; \
- String collection_name; \
- Slice<String> fullpaths; \
- Array<Ast *> attributes; \
- CommentGroup *docs; \
- CommentGroup *comment; \
- }) \
- AST_KIND(_DeclEnd, "", bool) \
- AST_KIND(Attribute, "attribute", struct { \
- Token token; \
- Slice<Ast *> elems; \
- Token open, close; \
- }) \
- AST_KIND(Field, "field", struct { \
- Slice<Ast *> names; \
- Ast * type; \
- Ast * default_value; \
- Token tag; \
- u32 flags; \
- CommentGroup * docs; \
- CommentGroup * comment; \
- }) \
- AST_KIND(FieldList, "field list", struct { \
- Token token; \
- Slice<Ast *> list; \
- }) \
- AST_KIND(_TypeBegin, "", bool) \
- AST_KIND(TypeidType, "typeid", struct { \
- Token token; \
- Ast *specialization; \
- }) \
- AST_KIND(HelperType, "helper type", struct { \
- Token token; \
- Ast *type; \
- }) \
- AST_KIND(DistinctType, "distinct type", struct { \
- Token token; \
- Ast *type; \
- }) \
- AST_KIND(PolyType, "polymorphic type", struct { \
- Token token; \
- Ast * type; \
- Ast * specialization; \
- }) \
- AST_KIND(ProcType, "procedure type", struct { \
- Token token; \
- Ast *params; \
- Ast *results; \
- u64 tags; \
- ProcCallingConvention calling_convention; \
- bool generic; \
- bool diverging; \
- }) \
- AST_KIND(PointerType, "pointer type", struct { \
- Token token; \
- Ast *type; \
- }) \
- AST_KIND(RelativeType, "relative type", struct { \
- Ast *tag; \
- Ast *type; \
- }) \
- AST_KIND(ArrayType, "array type", struct { \
- Token token; \
- Ast *count; \
- Ast *elem; \
- Ast *tag; \
- }) \
- AST_KIND(DynamicArrayType, "dynamic array type", struct { \
- Token token; \
- Ast *elem; \
- Ast *tag; \
- }) \
- AST_KIND(StructType, "struct type", struct { \
- Token token; \
- Slice<Ast *> fields; \
- isize field_count; \
- Ast *polymorphic_params; \
- Ast *align; \
- Token where_token; \
- Slice<Ast *> where_clauses; \
- bool is_packed; \
- bool is_raw_union; \
- }) \
- AST_KIND(UnionType, "union type", struct { \
- Token token; \
- Slice<Ast *> variants; \
- Ast *polymorphic_params; \
- Ast * align; \
- bool maybe; \
- bool no_nil; \
- Token where_token; \
- Slice<Ast *> where_clauses; \
- }) \
- AST_KIND(EnumType, "enum type", struct { \
- Token token; \
- Ast * base_type; \
- Slice<Ast *> fields; /* FieldValue */ \
- bool is_using; \
- }) \
- AST_KIND(BitSetType, "bit set type", struct { \
- Token token; \
- Ast * elem; \
- Ast * underlying; \
- }) \
- AST_KIND(MapType, "map type", struct { \
- Token token; \
- Ast *count; \
- Ast *key; \
- Ast *value; \
- }) \
- AST_KIND(_TypeEnd, "", bool)
- enum AstKind {
- Ast_Invalid,
- #define AST_KIND(_kind_name_, ...) GB_JOIN2(Ast_, _kind_name_),
- AST_KINDS
- #undef AST_KIND
- Ast_COUNT,
- };
- String const ast_strings[] = {
- {cast(u8 *)"invalid node", gb_size_of("invalid node")},
- #define AST_KIND(_kind_name_, name, ...) {cast(u8 *)name, gb_size_of(name)-1},
- AST_KINDS
- #undef AST_KIND
- };
- #define AST_KIND(_kind_name_, name, ...) typedef __VA_ARGS__ GB_JOIN2(Ast, _kind_name_);
- AST_KINDS
- #undef AST_KIND
- isize const ast_variant_sizes[] = {
- 0,
- #define AST_KIND(_kind_name_, name, ...) gb_size_of(GB_JOIN2(Ast, _kind_name_)),
- AST_KINDS
- #undef AST_KIND
- };
- struct AstCommonStuff {
- AstKind kind;
- u16 state_flags;
- u16 viral_state_flags;
- AstFile * file;
- Scope * scope;
- TypeAndValue tav; // TODO(bill): Make this a pointer to minimize pointer size
- };
- struct Ast {
- AstKind kind;
- u16 state_flags;
- u16 viral_state_flags;
- AstFile * file;
- Scope * scope;
- TypeAndValue tav; // TODO(bill): Make this a pointer to minimize pointer size
- // IMPORTANT NOTE(bill): This must be at the end since the AST is allocated to be size of the variant
- union {
- #define AST_KIND(_kind_name_, name, ...) GB_JOIN2(Ast, _kind_name_) _kind_name_;
- AST_KINDS
- #undef AST_KIND
- };
- };
- #define ast_node(n_, Kind_, node_) GB_JOIN2(Ast, Kind_) *n_ = &(node_)->Kind_; GB_ASSERT_MSG((node_)->kind == GB_JOIN2(Ast_, Kind_), \
- "expected '%.*s' got '%.*s'", \
- LIT(ast_strings[GB_JOIN2(Ast_, Kind_)]), LIT(ast_strings[(node_)->kind]))
- #define case_ast_node(n_, Kind_, node_) case GB_JOIN2(Ast_, Kind_): { ast_node(n_, Kind_, node_);
- #ifndef case_end
- #define case_end } break;
- #endif
- gb_inline bool is_ast_expr(Ast *node) {
- return gb_is_between(node->kind, Ast__ExprBegin+1, Ast__ExprEnd-1);
- }
- gb_inline bool is_ast_stmt(Ast *node) {
- return gb_is_between(node->kind, Ast__StmtBegin+1, Ast__StmtEnd-1);
- }
- gb_inline bool is_ast_complex_stmt(Ast *node) {
- return gb_is_between(node->kind, Ast__ComplexStmtBegin+1, Ast__ComplexStmtEnd-1);
- }
- gb_inline bool is_ast_decl(Ast *node) {
- return gb_is_between(node->kind, Ast__DeclBegin+1, Ast__DeclEnd-1);
- }
- gb_inline bool is_ast_type(Ast *node) {
- return gb_is_between(node->kind, Ast__TypeBegin+1, Ast__TypeEnd-1);
- }
- gb_inline bool is_ast_when_stmt(Ast *node) {
- return node->kind == Ast_WhenStmt;
- }
- gb_global Arena global_ast_arena = {};
- gbAllocator ast_allocator(AstFile *f) {
- Arena *arena = f ? &f->arena : &global_ast_arena;
- // Arena *arena = &global_ast_arena;
- return arena_allocator(arena);
- }
- Ast *alloc_ast_node(AstFile *f, AstKind kind);
|