|
|
|
@@ -272,6 +272,15 @@ add_module(Token *pos, Intern_String filename, B32 command_line_module, bool str
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CORE_Static Ast_File *
|
|
|
|
|
|
|
|
custom_parse_string(String string) {
|
|
|
|
|
|
|
|
Ast_Module *module = pctx->custom_module;
|
|
|
|
|
|
|
|
Ast_File *file = get(&module->all_loaded_files, 0);
|
|
|
|
|
|
|
|
file->filecontent = string;
|
|
|
|
|
|
|
|
parse_file(file);
|
|
|
|
|
|
|
|
return file;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CORE_Static void
|
|
|
|
CORE_Static void
|
|
|
|
resolve_everything_in_module(Ast_Module *module) {
|
|
|
|
resolve_everything_in_module(Ast_Module *module) {
|
|
|
|
if (module->state == MODULE_RESOLVED)
|
|
|
|
if (module->state == MODULE_RESOLVED)
|
|
|
|
@@ -292,10 +301,12 @@ resolve_everything_in_module(Ast_Module *module) {
|
|
|
|
|
|
|
|
|
|
|
|
CORE_Static void
|
|
|
|
CORE_Static void
|
|
|
|
init_language_core() {
|
|
|
|
init_language_core() {
|
|
|
|
{
|
|
|
|
pctx->custom_module = add_module(0, pctx->intern("Custom.core"_s), false, true);
|
|
|
|
Ast_Module *module = add_module(0, pctx->intern("Language.core"_s), false, true);
|
|
|
|
pctx->custom_module->state = MODULE_RESOLVED;
|
|
|
|
get(&module->all_loaded_files, 0)->filecontent =
|
|
|
|
|
|
|
|
R"(
|
|
|
|
Ast_Module *module = add_module(0, pctx->intern("Language.core"_s), false, true);
|
|
|
|
|
|
|
|
get(&module->all_loaded_files, 0)->filecontent =
|
|
|
|
|
|
|
|
R"(
|
|
|
|
Any :: struct
|
|
|
|
Any :: struct
|
|
|
|
data: *void
|
|
|
|
data: *void
|
|
|
|
type: Type
|
|
|
|
type: Type
|
|
|
|
@@ -360,62 +371,229 @@ GetTypeInfo :: (type: Type): *Type_Info
|
|
|
|
return type_infos + id
|
|
|
|
return type_infos + id
|
|
|
|
)"_s;
|
|
|
|
)"_s;
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
insert_builtin_type_into_scope(module, "S64"_s, pctx->type_s64);
|
|
|
|
insert_builtin_type_into_scope(module, "S64"_s, pctx->type_s64);
|
|
|
|
insert_builtin_type_into_scope(module, "S32"_s, pctx->type_s32);
|
|
|
|
insert_builtin_type_into_scope(module, "S32"_s, pctx->type_s32);
|
|
|
|
insert_builtin_type_into_scope(module, "S16"_s, pctx->type_s16);
|
|
|
|
insert_builtin_type_into_scope(module, "S16"_s, pctx->type_s16);
|
|
|
|
insert_builtin_type_into_scope(module, "S8"_s, pctx->type_s8);
|
|
|
|
insert_builtin_type_into_scope(module, "S8"_s, pctx->type_s8);
|
|
|
|
insert_builtin_type_into_scope(module, "int"_s, pctx->type_int);
|
|
|
|
insert_builtin_type_into_scope(module, "int"_s, pctx->type_int);
|
|
|
|
insert_builtin_type_into_scope(module, "char"_s, pctx->type_char);
|
|
|
|
insert_builtin_type_into_scope(module, "char"_s, pctx->type_char);
|
|
|
|
insert_builtin_type_into_scope(module, "U64"_s, pctx->type_u64);
|
|
|
|
insert_builtin_type_into_scope(module, "U64"_s, pctx->type_u64);
|
|
|
|
insert_builtin_type_into_scope(module, "U32"_s, pctx->type_u32);
|
|
|
|
insert_builtin_type_into_scope(module, "U32"_s, pctx->type_u32);
|
|
|
|
insert_builtin_type_into_scope(module, "U16"_s, pctx->type_u16);
|
|
|
|
insert_builtin_type_into_scope(module, "U16"_s, pctx->type_u16);
|
|
|
|
insert_builtin_type_into_scope(module, "U8"_s, pctx->type_u8);
|
|
|
|
insert_builtin_type_into_scope(module, "U8"_s, pctx->type_u8);
|
|
|
|
insert_builtin_type_into_scope(module, "F64"_s, pctx->type_f64);
|
|
|
|
insert_builtin_type_into_scope(module, "F64"_s, pctx->type_f64);
|
|
|
|
insert_builtin_type_into_scope(module, "F32"_s, pctx->type_f32);
|
|
|
|
insert_builtin_type_into_scope(module, "F32"_s, pctx->type_f32);
|
|
|
|
insert_builtin_type_into_scope(module, "void"_s, pctx->type_void);
|
|
|
|
insert_builtin_type_into_scope(module, "void"_s, pctx->type_void);
|
|
|
|
insert_builtin_type_into_scope(module, "Bool"_s, pctx->type_bool);
|
|
|
|
insert_builtin_type_into_scope(module, "Bool"_s, pctx->type_bool);
|
|
|
|
// insert_builtin_type_into_scope(module, "String"_s, pctx->type_string);
|
|
|
|
// insert_builtin_type_into_scope(module, "String"_s, pctx->type_string);
|
|
|
|
insert_builtin_type_into_scope(module, "Type"_s, pctx->type_type);
|
|
|
|
insert_builtin_type_into_scope(module, "Type"_s, pctx->type_type);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Ast_Scope *scope = ast_decl_scope(&pctx->null_token, pctx->perm, get(&module->all_loaded_files, 0));
|
|
|
|
|
|
|
|
Ast_Decl * decl = ast_namespace(&pctx->null_token, scope, pctx->intern("Const"_s));
|
|
|
|
|
|
|
|
decl->state = DECL_RESOLVED;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value v1 = {};
|
|
|
|
|
|
|
|
v1.type = pctx->untyped_string;
|
|
|
|
|
|
|
|
v1.intern_val = pctx->intern(OS_NAME);
|
|
|
|
|
|
|
|
Ast_Decl *const_os1 = ast_const(&pctx->null_token, pctx->intern("OSName"_s), v1);
|
|
|
|
|
|
|
|
const_os1->state = DECL_RESOLVED;
|
|
|
|
|
|
|
|
insert_into_scope(scope, const_os1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value v2 = {};
|
|
|
|
|
|
|
|
v1.type = pctx->untyped_string;
|
|
|
|
|
|
|
|
v1.intern_val = pctx->intern(OS_NAME_LOWER);
|
|
|
|
|
|
|
|
Ast_Decl *const_os2 = ast_const(&pctx->null_token, pctx->intern("OSNameLower"_s), v2);
|
|
|
|
|
|
|
|
const_os2->state = DECL_RESOLVED;
|
|
|
|
|
|
|
|
insert_into_scope(scope, const_os2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
insert_into_scope(module, decl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pctx->language_base_module = module;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parse_all_modules();
|
|
|
|
|
|
|
|
resolve_everything_in_module(module);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// @note: language stuff needs to be declared before type_info data
|
|
|
|
|
|
|
|
// so we mark where it ends
|
|
|
|
|
|
|
|
pctx->base_language_ordered_decl_len = length(&pctx->ordered_decls);
|
|
|
|
|
|
|
|
Ast_Decl *any_decl = search_for_single_decl(module, pctx->intern("Any"_s));
|
|
|
|
|
|
|
|
assert(any_decl->type == pctx->type_type);
|
|
|
|
|
|
|
|
pctx->type_any = any_decl->type_val;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ast_Decl *string_decl = search_for_single_decl(module, pctx->intern("String"_s));
|
|
|
|
|
|
|
|
assert(string_decl->type == pctx->type_type);
|
|
|
|
|
|
|
|
pctx->type_string = string_decl->type_val;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef void Ast_Visit_Callback(Ast *ast);
|
|
|
|
|
|
|
|
// @todo: We are traversing the modules multiple times cause they can have multiple connections, need to add visit id
|
|
|
|
|
|
|
|
void ast_list_rewrite_callback(Ast *ast) {
|
|
|
|
|
|
|
|
switch(ast->kind) {
|
|
|
|
|
|
|
|
CASE(CALL, Call) {
|
|
|
|
|
|
|
|
if (node->name->kind == AST_IDENT) {
|
|
|
|
|
|
|
|
Ast_Atom *ident = (Ast_Atom *)node->name;
|
|
|
|
|
|
|
|
if (pctx->intern("List_Insert"_s) == ident->intern_val) {
|
|
|
|
|
|
|
|
Ast_Decl *list_insert = search_for_single_decl(pctx->custom_module, pctx->intern("List_Insert"_s), false);
|
|
|
|
|
|
|
|
if (!list_insert) {
|
|
|
|
|
|
|
|
custom_parse_string(R"(
|
|
|
|
|
|
|
|
List_Insert :: (list: List, node: Node)
|
|
|
|
|
|
|
|
if list.first == 0
|
|
|
|
|
|
|
|
list.first = node
|
|
|
|
|
|
|
|
list.last = node
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
list.last.next = node
|
|
|
|
|
|
|
|
list.last = node
|
|
|
|
|
|
|
|
)"_s);
|
|
|
|
|
|
|
|
list_insert = search_for_single_decl(pctx->custom_module, pctx->intern("List_Insert"_s), false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(list_insert);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
void ast_visit(uint32_t visit_id, Ast_Visit_Callback *callback, Ast *ast) {
|
|
|
|
Ast_Scope *scope = ast_decl_scope(&pctx->null_token, pctx->perm, get(&module->all_loaded_files, 0));
|
|
|
|
if (!ast) return;
|
|
|
|
Ast_Decl * decl = ast_namespace(&pctx->null_token, scope, pctx->intern("Const"_s));
|
|
|
|
|
|
|
|
decl->state = DECL_RESOLVED;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value v1 = {};
|
|
|
|
callback(ast);
|
|
|
|
v1.type = pctx->untyped_string;
|
|
|
|
switch(ast->kind) {
|
|
|
|
v1.intern_val = pctx->intern(OS_NAME);
|
|
|
|
CASE(MODULE, Module) {
|
|
|
|
Ast_Decl *const_os1 = ast_const(&pctx->null_token, pctx->intern("OSName"_s), v1);
|
|
|
|
if (node->visit_id == visit_id) return;
|
|
|
|
const_os1->state = DECL_RESOLVED;
|
|
|
|
node->visit_id = visit_id;
|
|
|
|
insert_into_scope(scope, const_os1);
|
|
|
|
For(node->decls) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
For(node->implicit_imports) ast_visit(visit_id, callback, it);
|
|
|
|
Value v2 = {};
|
|
|
|
For(node->stmts) ast_visit(visit_id, callback, it);
|
|
|
|
v1.type = pctx->untyped_string;
|
|
|
|
For(node->all_loaded_files) ast_visit(visit_id, callback, it);
|
|
|
|
v1.intern_val = pctx->intern(OS_NAME_LOWER);
|
|
|
|
BREAK();
|
|
|
|
Ast_Decl *const_os2 = ast_const(&pctx->null_token, pctx->intern("OSNameLower"_s), v2);
|
|
|
|
|
|
|
|
const_os2->state = DECL_RESOLVED;
|
|
|
|
|
|
|
|
insert_into_scope(scope, const_os2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
insert_into_scope(module, decl);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(FILE, File) {
|
|
|
|
pctx->language_base_module = module;
|
|
|
|
if (node->visit_id == visit_id) return;
|
|
|
|
|
|
|
|
node->visit_id = visit_id;
|
|
|
|
parse_all_modules();
|
|
|
|
For(node->decls) ast_visit(visit_id, callback, it);
|
|
|
|
resolve_everything_in_module(module);
|
|
|
|
For(node->implicit_imports) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
For(node->stmts) ast_visit(visit_id, callback, it);
|
|
|
|
// @note: language stuff needs to be declared before type_info data
|
|
|
|
BREAK();
|
|
|
|
// so we mark where it ends
|
|
|
|
}
|
|
|
|
pctx->base_language_ordered_decl_len = length(&pctx->ordered_decls);
|
|
|
|
CASE(SCOPE, Scope) {
|
|
|
|
Ast_Decl *any_decl = search_for_single_decl(module, pctx->intern("Any"_s));
|
|
|
|
if (node->visit_id == visit_id) return;
|
|
|
|
assert(any_decl->type == pctx->type_type);
|
|
|
|
node->visit_id = visit_id;
|
|
|
|
pctx->type_any = any_decl->type_val;
|
|
|
|
For(node->decls) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
For(node->implicit_imports) ast_visit(visit_id, callback, it);
|
|
|
|
Ast_Decl *string_decl = search_for_single_decl(module, pctx->intern("String"_s));
|
|
|
|
For(node->stmts) ast_visit(visit_id, callback, it);
|
|
|
|
assert(string_decl->type == pctx->type_type);
|
|
|
|
BREAK();
|
|
|
|
pctx->type_string = string_decl->type_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(LAMBDA, Decl){
|
|
|
|
|
|
|
|
Ast_Lambda *lambda = node->lambda;
|
|
|
|
|
|
|
|
For(lambda->ret) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
For(lambda->args) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->typespec);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->scope);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, lambda->scope);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(CONST, Decl){
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->expr);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->typespec);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->scope);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(VAR, Decl){
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->expr);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->typespec);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->scope);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case AST_NAMESPACE:
|
|
|
|
|
|
|
|
CASE(ENUM, Decl){
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->typespec);
|
|
|
|
|
|
|
|
For(node->scope->decls) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(INDEX, Index) {
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->expr);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->index);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(STRUCT, Decl) {
|
|
|
|
|
|
|
|
// @todo
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(ARRAY, Array) {
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->base);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->expr);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(BINARY, Binary) {
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->left);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->right);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(VAR_UNPACK, Var_Unpack) {
|
|
|
|
|
|
|
|
For(node->vars) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->expr);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(UNARY, Unary) {
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->expr);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case AST_COMPOUND:
|
|
|
|
|
|
|
|
CASE(CALL, Call){
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->name); // @union
|
|
|
|
|
|
|
|
For(node->exprs) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(CALL_ITEM, Call_Item){
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->item);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->name); // @union
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case AST_CONSTANT_ASSERT:
|
|
|
|
|
|
|
|
CASE(RUNTIME_ASSERT, Builtin){
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->expr);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(RETURN, Return){
|
|
|
|
|
|
|
|
For(node->expr) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(FOR, For) {
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->init);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->cond);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->iter);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->scope);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->array_traversal_var);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(IF, If) {
|
|
|
|
|
|
|
|
For(node->ifs) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(IF_NODE, If_Node) {
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->expr);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->scope);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->init);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(SWITCH_CASE, Switch_Case) {
|
|
|
|
|
|
|
|
For(node->labels) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->scope);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CASE(SWITCH, Switch) {
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->value);
|
|
|
|
|
|
|
|
For(node->cases) ast_visit(visit_id, callback, it);
|
|
|
|
|
|
|
|
ast_visit(visit_id, callback, node->default_scope);
|
|
|
|
|
|
|
|
BREAK();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
case AST_VALUE: case AST_IDENT: case AST_PASS: case AST_BREAK: break;
|
|
|
|
|
|
|
|
invalid_default_case;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -430,10 +608,9 @@ compile_file_to_string(Allocator *allocator, String filename) {
|
|
|
|
Ast_Module *module = add_module(0, pctx->intern(filename), true);
|
|
|
|
Ast_Module *module = add_module(0, pctx->intern(filename), true);
|
|
|
|
parse_all_modules();
|
|
|
|
parse_all_modules();
|
|
|
|
assert(module);
|
|
|
|
assert(module);
|
|
|
|
|
|
|
|
|
|
|
|
resolve_everything_in_module(module);
|
|
|
|
resolve_everything_in_module(module);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pctx->stage_arena->len = 0;
|
|
|
|
|
|
|
|
String result = compile_to_c_code();
|
|
|
|
String result = compile_to_c_code();
|
|
|
|
|
|
|
|
|
|
|
|
pctx->time.total = os_time() - pctx->time.total;
|
|
|
|
pctx->time.total = os_time() - pctx->time.total;
|
|
|
|
|