Add Core compiler interface

This commit is contained in:
Krzosa Karol
2022-12-31 14:47:47 +01:00
parent 673db72e29
commit 23db7cc5c4
13 changed files with 607 additions and 2373 deletions

View File

@@ -138,6 +138,7 @@ typedef double F64;
#define JOIN(X,Y) JOIN1(X,Y) #define JOIN(X,Y) JOIN1(X,Y)
#define string_expand(x) (int)x.len, x.str #define string_expand(x) (int)x.len, x.str
#define CORE_STRINGS
struct String{ struct String{
U8 *str; U8 *str;
S64 len; S64 len;
@@ -154,78 +155,6 @@ global String string_null = {(U8 *)"null", 4};
#include "stb_sprintf.h" #include "stb_sprintf.h"
#define snprintf stbsp_snprintf #define snprintf stbsp_snprintf
union Vec2 {
struct { F32 x, y; };
struct { F32 width, height; };
F32 p[2];
};
union Vec3 {
struct{ F32 x, y, z; };
struct{ F32 r, g, b; };
struct{ Vec2 xy; F32 z_; };
struct{ F32 x_; Vec2 yz; };
F32 p[3];
};
union Vec4 {
struct{ F32 x, y, z, w; };
struct{ F32 r, g, b, a; };
struct{ Vec2 xy; Vec2 zw; };
struct{ Vec2 xy_; F32 width, height; };
struct{ Vec3 xyz; F32 w_; };
struct{ F32 x_; Vec3 yzw; };
struct{ Vec3 rgb; F32 a_; };
F32 p[4];
};
struct Mat4 {
F32 p[4][4];
};
union Vec1I {
S32 x;
S32 p[1];
};
union Vec2I {
struct { S32 x, y; };
struct { S32 width, height; };
S32 p[2];
};
union Vec3I {
struct { S32 x, y, z; };
struct { S32 r, g, b; };
struct { Vec2I xy; S32 z_; };
struct { S32 x_; Vec2I yz; };
S32 p[3];
};
union Vec4I {
struct { S32 x, y, z, w; };
struct { S32 r, g, b, a; };
struct { Vec2I xy; Vec2I zw; };
struct { Vec2I xy_; S32 width, height; };
struct { Vec3I xyz; S32 w_; };
struct { S32 x_; Vec3I yzw; };
struct { Vec3I rgb; S32 a_; };
S32 p[4];
};
union Rect2 {
struct {F32 min_x, min_y, max_x, max_y;};
struct { Vec2 min; Vec2 max; };
F32 p[4];
};
union Rect2I {
struct { S32 min_x, min_y, max_x, max_y;};
struct { Vec2I min; Vec2I max; };
S32 p[4];
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Utilities // Utilities
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ rem cl main.cpp -I.. user32.lib
clang core_main.cpp -O0 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib clang core_main.cpp -O0 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib
rem ubuntu run clang core_main.cpp -O0 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o core.out rem ubuntu run clang core_main.cpp -O0 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o core.out
main.exe -testing rem main.exe -testing
rem echo Building arms race rem echo Building arms race
rem call examples/arms_race/build_arms_race.bat rem call examples/arms_race/build_arms_race.bat

View File

@@ -1,13 +1,4 @@
struct Token; struct Token;
struct BigInt
{
unsigned digit_count;
bool is_negative;
union {
uint64_t digit;
uint64_t *digits;
};
};
#include <inttypes.h> #include <inttypes.h>
enum CmpRes enum CmpRes

View File

@@ -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) \ #define AST_NEW(T,ikind,ipos,iflags) \
Ast_##T *result = arena_push_type(pctx->perm, Ast_##T, AF_ZeroMemory);\ Ast_##T *result = arena_push_type(pctx->perm, Ast_##T, AF_ZeroMemory);\
result->flags = iflags; \ result->flags = iflags; \

View File

@@ -1,127 +1,5 @@
struct Ast_Scope;
struct Ast_Decl;
struct Ast_File_Namespace;
struct Ast_File;
struct Ast_Module;
struct Ast_Type;
struct Ast;
struct Ast_Expr;
enum Token_Kind{
TK_End,
/*#
import meta
for i in meta.token_kinds:
print(" TK_" + i[0] + ",")
*/
TK_Mul,
TK_Div,
TK_Mod,
TK_LeftShift,
TK_RightShift,
TK_FirstMul = TK_Mul,
TK_LastMul = TK_RightShift,
TK_Add,
TK_Sub,
TK_FirstAdd = TK_Add,
TK_LastAdd = TK_Sub,
TK_Equals,
TK_LesserThenOrEqual,
TK_GreaterThenOrEqual,
TK_LesserThen,
TK_GreaterThen,
TK_NotEquals,
TK_FirstCompare = TK_Equals,
TK_LastCompare = TK_NotEquals,
TK_BitAnd,
TK_BitOr,
TK_BitXor,
TK_And,
TK_Or,
TK_FirstLogical = TK_BitAnd,
TK_LastLogical = TK_Or,
TK_Neg,
TK_Not,
TK_Decrement,
TK_Increment,
TK_PostDecrement,
TK_PostIncrement,
TK_Assign,
TK_ColonAssign,
TK_DivAssign,
TK_MulAssign,
TK_ModAssign,
TK_SubAssign,
TK_AddAssign,
TK_AndAssign,
TK_OrAssign,
TK_XorAssign,
TK_LeftShiftAssign,
TK_RightShiftAssign,
TK_FirstAssign = TK_Assign,
TK_LastAssign = TK_RightShiftAssign,
TK_OpenParen,
TK_CloseParen,
TK_OpenBrace,
TK_CloseBrace,
TK_OpenBracket,
TK_CloseBracket,
TK_Comma,
TK_Pound,
TK_Question,
TK_ThreeDots,
TK_Semicolon,
TK_Dot,
TK_TwoDots,
TK_NewLine,
TK_Colon,
TK_DoubleColon,
TK_At,
TK_Arrow,
TK_ExprSizeof,
TK_DocComment,
TK_Comment,
TK_Identifier,
TK_UnicodeLit,
TK_StringLit,
TK_Error,
TK_Float,
TK_Integer,
TK_Keyword,
/*END*/
TK_Pointer = TK_Mul,
TK_Dereference = TK_BitAnd,
OPEN_SCOPE = 128,
CLOSE_SCOPE,
SAME_SCOPE,
};
struct Token{
Token_Kind kind;
U32 di; // debug_id
union{
String string;
struct{U8 *str; S64 len;};
};
union {
U32 unicode;
BigInt int_val;
F64 f64_val;
String error_val;
Intern_String intern_val;
S64 indent;
};
Intern_String file;
S32 line;
U8 *line_begin;
};
struct Lex_Stream{ struct Lex_Stream{
String stream; String stream;
S64 iter; S64 iter;

597
core_compiler_interface.hpp Normal file
View File

@@ -0,0 +1,597 @@
#pragma once
#include <stdint.h>
struct Ast;
struct Ast_Scope;
struct Ast_Decl;
struct Ast_File_Namespace;
struct Ast_File;
struct Ast_Module;
struct Ast_Lambda;
struct Ast_Type;
struct Ast_Expr;
#ifndef CORE_STRINGS
#define CORE_STRINGS
struct String{
uint8_t *str;
int64_t len;
};
union Intern_String{ // Basically just String
String s;
struct{
uint8_t *str;
int64_t len;
};
};
#endif
enum Token_Kind{
TK_End,
/*#
import meta
for i in meta.token_kinds:
print(" TK_" + i[0] + ",")
*/
TK_Mul,
TK_Div,
TK_Mod,
TK_LeftShift,
TK_RightShift,
TK_FirstMul = TK_Mul,
TK_LastMul = TK_RightShift,
TK_Add,
TK_Sub,
TK_FirstAdd = TK_Add,
TK_LastAdd = TK_Sub,
TK_Equals,
TK_LesserThenOrEqual,
TK_GreaterThenOrEqual,
TK_LesserThen,
TK_GreaterThen,
TK_NotEquals,
TK_FirstCompare = TK_Equals,
TK_LastCompare = TK_NotEquals,
TK_BitAnd,
TK_BitOr,
TK_BitXor,
TK_And,
TK_Or,
TK_FirstLogical = TK_BitAnd,
TK_LastLogical = TK_Or,
TK_Neg,
TK_Not,
TK_Decrement,
TK_Increment,
TK_PostDecrement,
TK_PostIncrement,
TK_Assign,
TK_ColonAssign,
TK_DivAssign,
TK_MulAssign,
TK_ModAssign,
TK_SubAssign,
TK_AddAssign,
TK_AndAssign,
TK_OrAssign,
TK_XorAssign,
TK_LeftShiftAssign,
TK_RightShiftAssign,
TK_FirstAssign = TK_Assign,
TK_LastAssign = TK_RightShiftAssign,
TK_OpenParen,
TK_CloseParen,
TK_OpenBrace,
TK_CloseBrace,
TK_OpenBracket,
TK_CloseBracket,
TK_Comma,
TK_Pound,
TK_Question,
TK_ThreeDots,
TK_Semicolon,
TK_Dot,
TK_TwoDots,
TK_NewLine,
TK_Colon,
TK_DoubleColon,
TK_At,
TK_Arrow,
TK_ExprSizeof,
TK_DocComment,
TK_Comment,
TK_Identifier,
TK_UnicodeLit,
TK_StringLit,
TK_Error,
TK_Float,
TK_Integer,
TK_Keyword,
/*END*/
TK_Pointer = TK_Mul,
TK_Dereference = TK_BitAnd,
OPEN_SCOPE = 128,
CLOSE_SCOPE,
SAME_SCOPE,
};
struct BigInt {
unsigned digit_count;
bool is_negative;
union {
uint64_t digit;
uint64_t *digits;
};
};
struct Token{
Token_Kind kind;
uint32_t di; // debug_id
union{
String string;
struct{
uint8_t *str;
int64_t len;
};
};
union {
uint32_t unicode;
BigInt int_val;
double f64_val;
String error_val;
Intern_String intern_val;
int64_t indent;
};
Intern_String file;
int32_t line;
uint8_t *line_begin;
};
enum Ast_Type_Kind{
TYPE_NONE,
TYPE_S64, // FIRST_NUMERIC
TYPE_S32,
TYPE_S16,
TYPE_S8 ,
TYPE_INT,
TYPE_CHAR,
TYPE_U64,
TYPE_U32,
TYPE_U16,
TYPE_U8 ,
TYPE_F32,
TYPE_F64,
TYPE_POINTER,
TYPE_BOOL, // LAST_NUMERIC
TYPE_STRING,
TYPE_VOID,
TYPE_ARRAY,
TYPE_LAMBDA,
TYPE_STRUCT,
TYPE_UNION,
TYPE_ENUM,
TYPE_TYPE,
TYPE_SLICE,
TYPE_TUPLE,
TYPE_COMPLETING,
TYPE_INCOMPLETE,
TYPE_UNTYPED_BOOL, // FIRST_TYPED_NUMERIC, FIRST_NUMERIC
TYPE_UNTYPED_INT,
TYPE_UNTYPED_FLOAT, // LAST_TYPED_NUMERIC
TYPE_UNTYPED_STRING,
TYPE_UNTYPED_FIRST = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST = TYPE_UNTYPED_STRING,
TYPE_UNTYPED_FIRST_NUMERIC = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST_NUMERIC = TYPE_UNTYPED_FLOAT,
TYPE_FIRST_NUMERIC = TYPE_S64,
TYPE_LAST_NUMERIC = TYPE_BOOL,
};
struct Value {
/*#import meta
print(meta.value_struct_content)
*/
Ast_Type *type;
Ast_Decl *resolved_decl;
union {
bool bool_val;
double f64_val;
Intern_String intern_val;
BigInt big_int_val;
Ast_Type *type_val;
};
/*END*/
};
struct Ast_Resolved_Member{
Intern_String name;
int32_t offset;
bool visited;
/*#import meta
meta.inline_value_fields()
*/
union {
Value value;
struct {
Ast_Type *type;
Ast_Decl *resolved_decl;
union {
bool bool_val;
double f64_val;
Intern_String intern_val;
BigInt big_int_val;
Ast_Type *type_val;
};
};
};
/*END*/
};
struct Ast_Type{
Ast_Type_Kind kind;
int32_t size;
int32_t align;
int32_t is_unsigned;
int32_t type_id;
int32_t padding;
Ast *ast;
union{
Ast_Type *base;
struct{
Ast_Type *base;
int32_t size;
// @note: if you have array with size "[32]"
// you still want to pass that array into
// a function that expects an array of size "[]"
// so we want also should check this
uint64_t slice_hash;
}arr;
struct{
Array<Ast_Resolved_Member> members;
}agg;
struct{
Ast_Type * ret;
Array<Ast_Type *> args;
uint64_t hash_without_ret;
}func;
};
};
enum Ast_Kind: uint32_t{
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 uint32_t Ast_Flag;
enum{
AST_EXPR = 1ull << 1,
AST_STMT = 1ull << 2,
AST_STRICT = 1ull << 3,
AST_AGGREGATE = 1ull << 4,
AST_AGGREGATE_CHILD = 1ull << 5,
AST_ATOM = 1ull << 7,
AST_FOREIGN = 1ull << 8,
AST_DECL = 1ull << 9,
AST_GLOBAL = 1ull << 10,
AST_FLAG = 1ull << 11,
AST_VAR_IS_CONST = 1ull << 12,
AST_OPERATOR_OVERLOAD = 1ull << 13,
AST_IS_LVALUE = 1ull << 14,
};
struct Ast{
uint64_t 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_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;
double f64_val;
Intern_String intern_val;
BigInt big_int_val;
Ast_Type *type_val;
};
};
};
/*END*/
};
typedef uint32_t Ast_Call_Item_Flag;
enum{
CALL_INDEX = 1ull << 1,
CALL_NAME = 1ull << 2,
CALL_INCLUDED= 1ull << 4,
};
struct Ast_Call_Item: Ast_Expr{
Ast_Call_Item_Flag call_flags;
int32_t resolved_index;
Ast_Expr *item;
union {
Ast_Atom *name;
Ast_Expr *index;
};
Intern_String resolved_name;
};
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;
uint64_t 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;
uint64_t 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;
uint64_t padding[2];
};
struct Ast_Switch_Case: Ast{
Array<Ast_Expr *> labels;
Ast_Scope *scope;
bool 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;
uint32_t visit_id;
uint32_t 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_Operator_Info{
Intern_String op;
String name;
Token_Kind op_kind;
bool valid_binary_expr;
bool valid_unary_expr;
};
struct Ast_Decl: Ast{
Ast_Decl_State state;
Intern_String name;
Intern_String unique_name; // For code generation, currently only present on lambdas
uint64_t operator_overload_arguments_hash;
Ast_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;
double f64_val;
Intern_String intern_val;
BigInt big_int_val;
Ast_Type *type_val;
};
};
};
/*END*/
};

View File

@@ -1,11 +1,5 @@
struct Operator_Info{
Intern_String op;
String name;
Token_Kind op_kind;
bool valid_binary_expr;
bool valid_unary_expr;
};
/*#import meta /*#import meta
@@ -40,7 +34,7 @@ print(" return 0;\n}")
*/ */
Operator_Info op_info_table[] = { Ast_Operator_Info op_info_table[] = {
{{}, "MUL"_s, TK_Mul, 1, 0}, {{}, "MUL"_s, TK_Mul, 1, 0},
{{}, "DIV"_s, TK_Div, 1, 0}, {{}, "DIV"_s, TK_Div, 1, 0},
{{}, "MOD"_s, TK_Mod, 1, 0}, {{}, "MOD"_s, TK_Mod, 1, 0},
@@ -62,7 +56,7 @@ Operator_Info op_info_table[] = {
{{}, "NEG"_s, TK_Neg, 0, 1}, {{}, "NEG"_s, TK_Neg, 0, 1},
{{}, "NOT"_s, TK_Not, 0, 1}, {{}, "NOT"_s, TK_Not, 0, 1},
}; };
CORE_Static Operator_Info * CORE_Static Ast_Operator_Info *
get_operator_info(Token_Kind op){ get_operator_info(Token_Kind op){
switch(op){ switch(op){
case TK_Mul: return op_info_table + 0; case TK_Mul: return op_info_table + 0;
@@ -89,7 +83,7 @@ get_operator_info(Token_Kind op){
} }
return 0; return 0;
} }
CORE_Static Operator_Info * CORE_Static Ast_Operator_Info *
get_operator_info(Intern_String op){ get_operator_info(Intern_String op){
if(0){} if(0){}
else if(op_info_table[0].op.str == op.str) return op_info_table + 0; else if(op_info_table[0].op.str == op.str) return op_info_table + 0;

View File

@@ -268,6 +268,7 @@ For modules it's a bit different cause they should be distributed as valid.
#error Couldnt figure out OS using macros #error Couldnt figure out OS using macros
#endif #endif
#include "core_compiler_interface.hpp"
#include "c3_big_int.h" #include "c3_big_int.h"
#include "core_compiler.h" #include "core_compiler.h"
#include "core_types.h" #include "core_types.h"

View File

@@ -864,7 +864,7 @@ parse_decl(B32 is_global){
if(!expr->scope){ if(!expr->scope){
compiler_error(tname, "Operator overload doesn't have body"); compiler_error(tname, "Operator overload doesn't have body");
} }
Operator_Info *op_info = get_operator_info(tname->intern_val); Ast_Operator_Info *op_info = get_operator_info(tname->intern_val);
if(!op_info){ if(!op_info){
compiler_error(tname, "This operator cannot be overloaded"); compiler_error(tname, "This operator cannot be overloaded");
} }

View File

@@ -546,7 +546,7 @@ resolve_name(Ast_Scope *scope, Token *pos, Intern_String name, Search_Flag searc
CORE_Static Ast_Decl * CORE_Static Ast_Decl *
resolve_operator_overload(Ast_Scope *scope, Ast_Type *left, Ast_Type *right, Token *pos, Token_Kind op, U64 argument_hash){ resolve_operator_overload(Ast_Scope *scope, Ast_Type *left, Ast_Type *right, Token *pos, Token_Kind op, U64 argument_hash){
Operator_Info *op_info = get_operator_info(op); Ast_Operator_Info *op_info = get_operator_info(op);
if(op_info == 0) return 0; if(op_info == 0) return 0;
// Search for all possible candidates in three scopes // Search for all possible candidates in three scopes

View File

@@ -1,49 +1,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Resolved Types // Resolved Types
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
enum Ast_Type_Kind{
TYPE_NONE,
TYPE_S64, // FIRST_NUMERIC
TYPE_S32,
TYPE_S16,
TYPE_S8 ,
TYPE_INT,
TYPE_CHAR,
TYPE_U64,
TYPE_U32,
TYPE_U16,
TYPE_U8 ,
TYPE_F32,
TYPE_F64,
TYPE_POINTER,
TYPE_BOOL, // LAST_NUMERIC
TYPE_STRING,
TYPE_VOID,
TYPE_ARRAY,
TYPE_LAMBDA,
TYPE_STRUCT,
TYPE_UNION,
TYPE_ENUM,
TYPE_TYPE,
TYPE_SLICE,
TYPE_TUPLE,
TYPE_COMPLETING,
TYPE_INCOMPLETE,
TYPE_UNTYPED_BOOL, // FIRST_TYPED_NUMERIC, FIRST_NUMERIC
TYPE_UNTYPED_INT,
TYPE_UNTYPED_FLOAT, // LAST_TYPED_NUMERIC
TYPE_UNTYPED_STRING,
TYPE_UNTYPED_FIRST = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST = TYPE_UNTYPED_STRING,
TYPE_UNTYPED_FIRST_NUMERIC = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST_NUMERIC = TYPE_UNTYPED_FLOAT,
TYPE_FIRST_NUMERIC = TYPE_S64,
TYPE_LAST_NUMERIC = TYPE_BOOL,
};
#define CASE_SINT case TYPE_S8:case TYPE_S16:case TYPE_S32:case TYPE_S64: case TYPE_CHAR: case TYPE_INT #define CASE_SINT case TYPE_S8:case TYPE_S16:case TYPE_S32:case TYPE_S64: case TYPE_CHAR: case TYPE_INT
#define CASE_UINT case TYPE_U8:case TYPE_U16:case TYPE_U32:case TYPE_U64 #define CASE_UINT case TYPE_U8:case TYPE_U16:case TYPE_U32:case TYPE_U64
@@ -53,76 +11,3 @@ enum Ast_Type_Kind{
#define CASE_STRING case TYPE_UNTYPED_STRING: case TYPE_STRING: case TYPE_POINTER #define CASE_STRING case TYPE_UNTYPED_STRING: case TYPE_STRING: case TYPE_POINTER
#define CASE_UNTYPED case TYPE_UNTYPED_INT: case TYPE_UNTYPED_BOOL: case TYPE_UNTYPED_FLOAT: case TYPE_UNTYPED_STRING #define CASE_UNTYPED case TYPE_UNTYPED_INT: case TYPE_UNTYPED_BOOL: case TYPE_UNTYPED_FLOAT: case TYPE_UNTYPED_STRING
#define ARRAY_SIZE_SLICE (-1) #define ARRAY_SIZE_SLICE (-1)
struct Value {
/*#import meta
print(meta.value_struct_content)
*/
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*/
};
struct Ast;
struct Ast_Type;
struct Ast_Resolved_Member{
Intern_String name;
S32 offset;
B32 visited;
/*#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*/
};
struct Ast_Type{
Ast_Type_Kind kind;
S32 size;
S32 align;
S32 is_unsigned;
S32 type_id;
S32 padding;
Ast *ast;
union{
Ast_Type *base;
struct{
Ast_Type *base;
S32 size;
// @note: if you have array with size "[32]"
// you still want to pass that array into
// a function that expects an array of size "[]"
// so we want also should check this
U64 slice_hash;
}arr;
struct{
Array<Ast_Resolved_Member> members;
}agg;
struct{
Ast_Type * ret;
Array<Ast_Type *> args;
U64 hash_without_ret;
}func;
};
};

View File

@@ -136,7 +136,7 @@ Ast_Type *type;
Ast_Decl *resolved_decl; Ast_Decl *resolved_decl;
union { union {
bool bool_val; bool bool_val;
F64 f64_val; double f64_val;
Intern_String intern_val; Intern_String intern_val;
BigInt big_int_val; BigInt big_int_val;
Ast_Type *type_val; Ast_Type *type_val;