Add Core compiler interface
This commit is contained in:
327
core_ast.cpp
327
core_ast.cpp
@@ -1,332 +1,5 @@
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AST
|
||||
//-----------------------------------------------------------------------------
|
||||
enum Ast_Kind: U32{
|
||||
AST_NONE,
|
||||
|
||||
AST_NAMESPACE,
|
||||
|
||||
AST_MODULE,
|
||||
AST_FILE,
|
||||
AST_SCOPE,
|
||||
AST_VALUE,
|
||||
AST_CAST,
|
||||
AST_IDENT,
|
||||
AST_INDEX,
|
||||
AST_UNARY,
|
||||
AST_BINARY,
|
||||
AST_CALL_ITEM,
|
||||
AST_CALL,
|
||||
|
||||
AST_CONSTANT_ASSERT,
|
||||
AST_RUNTIME_ASSERT,
|
||||
AST_SIZE_OF,
|
||||
AST_LENGTH_OF,
|
||||
AST_ALIGN_OF,
|
||||
AST_TYPE_OF,
|
||||
|
||||
AST_SWITCH,
|
||||
AST_SWITCH_CASE,
|
||||
AST_VAR_UNPACK,
|
||||
AST_BREAK,
|
||||
AST_COMPOUND,
|
||||
AST_TYPE,
|
||||
AST_VAR,
|
||||
AST_CONST,
|
||||
AST_POINTER,
|
||||
AST_ARRAY,
|
||||
AST_FOR,
|
||||
AST_IF,
|
||||
AST_IF_NODE,
|
||||
AST_RETURN,
|
||||
AST_BLOCK,
|
||||
AST_PASS,
|
||||
AST_LAMBDA,
|
||||
AST_LAMBDA_EXPR,
|
||||
AST_LAMBDA_ARG,
|
||||
AST_ENUM,
|
||||
AST_ENUM_MEMBER,
|
||||
AST_STRUCT,
|
||||
};
|
||||
|
||||
typedef U32 Ast_Flag;
|
||||
enum{
|
||||
AST_EXPR = bit_flag(1),
|
||||
AST_STMT = bit_flag(2),
|
||||
AST_STRICT = bit_flag(3),
|
||||
AST_AGGREGATE = bit_flag(4),
|
||||
AST_AGGREGATE_CHILD = bit_flag(5),
|
||||
AST_ATOM = bit_flag(7),
|
||||
AST_FOREIGN = bit_flag(8),
|
||||
AST_DECL = bit_flag(9),
|
||||
AST_GLOBAL = bit_flag(10),
|
||||
AST_FLAG = bit_flag(11),
|
||||
AST_VAR_IS_CONST = bit_flag(12),
|
||||
AST_OPERATOR_OVERLOAD = bit_flag(13),
|
||||
AST_IS_LVALUE = bit_flag(14),
|
||||
};
|
||||
|
||||
struct Ast{
|
||||
U64 di; // Debug id, shouldn't ever be used in the program
|
||||
Token *pos;
|
||||
|
||||
Ast_Kind kind;
|
||||
Ast_Scope *parent_scope;
|
||||
Ast_Flag flags;
|
||||
};
|
||||
|
||||
struct Ast_Type;
|
||||
struct Ast_Expr:Ast{
|
||||
Ast_Type *resolved_type;
|
||||
Ast_Decl *resolved_operator_overload;
|
||||
union{
|
||||
Ast_Type *index_original_type;
|
||||
Ast_Type *cast_after_type;
|
||||
Ast_Type *dot_access_step_resolution;
|
||||
};
|
||||
};
|
||||
|
||||
struct Ast_Atom: Ast_Expr{
|
||||
// We have a field type here
|
||||
// it has a different purpose from the
|
||||
// resolved_type of Ast_Expr, it describes
|
||||
// the inherent type of a value
|
||||
//
|
||||
// resolved_type is a solid type that
|
||||
// can be use during code generation
|
||||
// it cannot be untyped. (or at least thats the hope :)
|
||||
/*#import meta
|
||||
meta.inline_value_fields()
|
||||
*/
|
||||
union {
|
||||
Value value;
|
||||
struct {
|
||||
Ast_Type *type;
|
||||
Ast_Decl *resolved_decl;
|
||||
union {
|
||||
bool bool_val;
|
||||
F64 f64_val;
|
||||
Intern_String intern_val;
|
||||
BigInt big_int_val;
|
||||
Ast_Type *type_val;
|
||||
};
|
||||
};
|
||||
};
|
||||
/*END*/
|
||||
};
|
||||
|
||||
typedef U32 Ast_Call_Item_Flag;
|
||||
enum{
|
||||
CALL_INDEX = bit_flag(1),
|
||||
CALL_NAME = bit_flag(2),
|
||||
CALL_INCLUDED= bit_flag(4),
|
||||
};
|
||||
|
||||
struct Ast_Call_Item: Ast_Expr{
|
||||
Ast_Call_Item_Flag call_flags;
|
||||
S32 resolved_index;
|
||||
Ast_Expr *item;
|
||||
union {
|
||||
Ast_Atom *name;
|
||||
Ast_Expr *index;
|
||||
};
|
||||
Intern_String resolved_name;
|
||||
};
|
||||
|
||||
struct Ast_Lambda;
|
||||
struct Ast_Call: Ast_Expr{
|
||||
union{
|
||||
Ast_Expr *name;
|
||||
Ast_Expr *typespec;
|
||||
};
|
||||
Array<Ast_Call_Item *> exprs;
|
||||
Ast_Decl *resolved_decl;
|
||||
};
|
||||
|
||||
struct Ast_Var_Unpack: Ast_Expr{
|
||||
Array<Ast_Decl *> vars;
|
||||
Ast_Expr *expr;
|
||||
};
|
||||
|
||||
struct Ast_Unary: Ast_Expr{
|
||||
Token_Kind op;
|
||||
Ast_Expr *expr;
|
||||
U64 padding[2]; // For folding constants into atoms
|
||||
};
|
||||
|
||||
struct Ast_Index: Ast_Expr{
|
||||
Ast_Expr *expr;
|
||||
Ast_Expr *index;
|
||||
};
|
||||
|
||||
struct Ast_Binary: Ast_Expr{
|
||||
Token_Kind op;
|
||||
Ast_Expr *left;
|
||||
Ast_Expr *right;
|
||||
Ast_Type *before_type;
|
||||
};
|
||||
|
||||
struct Ast_Builtin: Ast_Expr{
|
||||
Ast_Expr *expr;
|
||||
Intern_String assert_message;
|
||||
U64 padding[1]; // For folding constants into atoms
|
||||
};
|
||||
|
||||
// Problem: We are parsing out of order, in the middle of parsing a function
|
||||
// we can jump down a different function, we cant therfore use global map.
|
||||
// Each scope needs to have it's checked locals list. To lookup syms we need to
|
||||
// look into global scope and to the locals list.
|
||||
//
|
||||
|
||||
struct Ast_Return: Ast{
|
||||
Ast_Type *resolved_type;
|
||||
Array<Ast_Expr *> expr;
|
||||
};
|
||||
|
||||
struct Ast_If_Node: Ast{
|
||||
Ast_Expr *expr ;
|
||||
Ast_Scope *scope;
|
||||
Ast_Binary*init;
|
||||
};
|
||||
|
||||
struct Ast_If: Ast{
|
||||
Array<Ast_If_Node *> ifs;
|
||||
};
|
||||
|
||||
struct Ast_Pass: Ast{};
|
||||
struct Ast_Break: Ast{};
|
||||
|
||||
struct Ast_For: Ast{
|
||||
Ast_Expr *init;
|
||||
Ast_Expr *cond;
|
||||
Ast_Expr *iter;
|
||||
Ast_Scope *scope;
|
||||
|
||||
Ast_Decl *array_traversal_var;
|
||||
bool is_array_traversal;
|
||||
bool is_also_slice_traversal;
|
||||
};
|
||||
|
||||
struct Ast_Lambda : Ast_Expr {
|
||||
Array<Ast_Decl *> args;
|
||||
Array<Ast_Expr *> ret;
|
||||
Ast_Scope *scope;
|
||||
};
|
||||
|
||||
struct Ast_Array: Ast_Expr{
|
||||
Ast_Expr *base;
|
||||
Ast_Expr *expr;
|
||||
U64 padding[2];
|
||||
};
|
||||
|
||||
struct Ast_Switch_Case: Ast{
|
||||
Array<Ast_Expr *> labels;
|
||||
Ast_Scope *scope;
|
||||
B32 fallthrough;
|
||||
};
|
||||
|
||||
struct Ast_Switch: Ast{
|
||||
Ast_Expr *value;
|
||||
Array<Ast_Switch_Case *> cases;
|
||||
Ast_Scope *default_scope;
|
||||
};
|
||||
|
||||
/*
|
||||
How does current declaration order resolver works:
|
||||
* First we put all the global declarations into the global scope (when parsing) all unresolved
|
||||
* All the types are declared INCOMPLETE and RESOLVED
|
||||
* We descent the tree by resolving each of the named declarations, we resolve by their name
|
||||
When we start resolving we set RESOLVING flag and when we complete RESOLVED flag
|
||||
and put into ordered list
|
||||
* When we meet a symbol (named declaration) while descending the tree,
|
||||
we resolve that symbol instead before resolving current declaration.
|
||||
* When we meet a declaration that requires size of a type - field access, var assignment,
|
||||
we need to call "complete_type", it sets COMPLETING flag.
|
||||
This call resolves all the dependencies of that type,
|
||||
sets size of type and marks it as COMPLETE and puts into ordered list.
|
||||
If it detects COMPLETING while
|
||||
resolving, we got a circular dependency. That might happen when we have
|
||||
that struct without pointer inside itself.
|
||||
|
||||
*/
|
||||
|
||||
struct Ast_Scope: Ast{
|
||||
String debug_name; // Dont use
|
||||
List<Ast_Scope *> implicit_imports;
|
||||
List<Ast_Decl *> decls;
|
||||
Array<Ast *> stmts;
|
||||
|
||||
U32 visit_id;
|
||||
U32 scope_id;
|
||||
Ast_Scope *file; // Self referential for file and module
|
||||
Ast_Module *module;
|
||||
};
|
||||
|
||||
enum Ast_Module_State{
|
||||
MODULE_REGISTERED,
|
||||
MODULE_PARSED,
|
||||
MODULE_RESOLVED,
|
||||
};
|
||||
|
||||
struct Ast_Module: Ast_Scope{
|
||||
Ast_Module_State state;
|
||||
String absolute_base_folder;
|
||||
String absolute_file_path;
|
||||
List<Ast_File *> all_loaded_files;
|
||||
};
|
||||
|
||||
struct Ast_File: Ast_Scope{
|
||||
String absolute_base_folder;
|
||||
String absolute_file_path;
|
||||
String filecontent;
|
||||
};
|
||||
|
||||
enum Ast_Decl_State{
|
||||
DECL_NOT_RESOLVED,
|
||||
DECL_RESOLVED,
|
||||
DECL_RESOLVED_TYPE,
|
||||
DECL_RESOLVING,
|
||||
};
|
||||
|
||||
struct Ast_Decl: Ast{
|
||||
Ast_Decl_State state;
|
||||
Intern_String name;
|
||||
Intern_String unique_name; // For code generation, currently only present on lambdas
|
||||
|
||||
U64 operator_overload_arguments_hash;
|
||||
Operator_Info *overload_op_info;
|
||||
|
||||
Ast_Scope *scope;
|
||||
Ast_Expr *typespec;
|
||||
union{
|
||||
Ast_Expr *expr;
|
||||
Ast_Lambda *lambda;
|
||||
};
|
||||
|
||||
/*#import meta
|
||||
meta.inline_value_fields()
|
||||
*/
|
||||
union {
|
||||
Value value;
|
||||
struct {
|
||||
Ast_Type *type;
|
||||
Ast_Decl *resolved_decl;
|
||||
union {
|
||||
bool bool_val;
|
||||
F64 f64_val;
|
||||
Intern_String intern_val;
|
||||
BigInt big_int_val;
|
||||
Ast_Type *type_val;
|
||||
};
|
||||
};
|
||||
};
|
||||
/*END*/
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AST Constructors beginning with expressions
|
||||
//-----------------------------------------------------------------------------
|
||||
#define AST_NEW(T,ikind,ipos,iflags) \
|
||||
Ast_##T *result = arena_push_type(pctx->perm, Ast_##T, AF_ZeroMemory);\
|
||||
result->flags = iflags; \
|
||||
|
||||
Reference in New Issue
Block a user