From: Brendan Hansen Date: Thu, 6 Aug 2020 22:26:42 +0000 (-0500) Subject: Added '#file_contents' directive to expression X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=8ab62803c215c8870c3493fe403e9f981cefac82;p=onyx.git Added '#file_contents' directive to expression --- diff --git a/Makefile b/Makefile index ca7a3d7f..0e514db6 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +RELEASE=1 + OBJ_FILES=\ build/onyxlex.o \ build/onyxparser.o \ @@ -13,9 +15,14 @@ OBJ_FILES=\ CC=gcc INCLUDES=-I./include LIBS= -FLAGS=-g TARGET=./onyx +ifeq ($(RELEASE), 1) + FLAGS=-O2 +else + FLAGS=-g +endif + build/%.o: src/%.c include/bh.h $(CC) $(FLAGS) -c $< -o $@ $(INCLUDES) diff --git a/docs/plan b/docs/plan index 12652ee9..25846cec 100644 --- a/docs/plan +++ b/docs/plan @@ -142,12 +142,12 @@ HOW: [X] Hex literals + [X] #file_contents + [ ] Better checking for casts [ ] All code paths return correct value - [ ] #file_contents - [ ] #initialize structs [ ] Start work on evaluating compile time known values. diff --git a/include/bh.h b/include/bh.h index 4b1b07b5..3760fda2 100644 --- a/include/bh.h +++ b/include/bh.h @@ -331,6 +331,7 @@ bh_file_error bh_file_close(bh_file* file); i32 bh_file_read(bh_file* file, void* buffer, isize buff_size); i32 bh_file_write(bh_file* file, void* buffer, isize buff_size); i64 bh_file_size(bh_file* file); +b32 bh_file_exists(char const* filename); #define bh_file_read_contents(allocator_, x) _Generic((x), \ bh_file*: bh_file_read_contents_bh_file, \ @@ -1364,6 +1365,11 @@ b32 bh_file_contents_free(bh_file_contents* contents) { return 1; } +b32 bh_file_exists(char const* filename) { + struct stat s; + return stat(filename, &s) != -1; +} + #endif // ifndef BH_NO_FILE diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 3ba79b67..3f03c4e2 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -22,6 +22,7 @@ typedef struct AstArrayAccess AstArrayAccess; typedef struct AstFieldAccess AstFieldAccess; typedef struct AstSizeOf AstSizeOf; typedef struct AstAlignOf AstAlignOf; +typedef struct AstFileContents AstFileContents; typedef struct AstReturn AstReturn; typedef struct AstBreak AstBreak; @@ -112,6 +113,7 @@ typedef enum AstKind { Ast_Kind_Field_Access, Ast_Kind_Size_Of, Ast_Kind_Align_Of, + Ast_Kind_File_Contents, Ast_Kind_If, Ast_Kind_For, @@ -269,6 +271,7 @@ struct AstArrayAccess { AstTyped_base; AstTyped *addr; AstTyped *expr; u64 ele struct AstFieldAccess { AstTyped_base; AstTyped *expr; u64 offset; }; struct AstSizeOf { AstTyped_base; AstType *so_type; u64 size; }; struct AstAlignOf { AstTyped_base; AstType *ao_type; u64 alignment; }; +struct AstFileContents { AstTyped_base; OnyxToken *filename; }; // Intruction Node struct AstReturn { AstNode_base; AstTyped* expr; }; @@ -405,6 +408,7 @@ typedef enum EntityType { Entity_Type_Unknown, Entity_Type_Use_Package, Entity_Type_String_Literal, + Entity_Type_File_Contents, Entity_Type_Enum, Entity_Type_Type_Alias, Entity_Type_Memory_Reservation, @@ -427,6 +431,7 @@ typedef struct Entity { AstGlobal *global; AstTyped *expr; AstStrLit *strlit; + AstFileContents *file_contents; AstType *type_alias; AstEnumType *enum_type; AstMemRes *mem_res; diff --git a/include/onyxmsgs.h b/include/onyxmsgs.h index 26f2b57c..1f78243b 100644 --- a/include/onyxmsgs.h +++ b/include/onyxmsgs.h @@ -36,6 +36,7 @@ typedef enum MsgType { Msg_Type_Failed_Gen_Load, Msg_Type_Failed_Gen_Store, + Msg_Type_File_Not_Found, Msg_Type_Count, } MsgType; diff --git a/include/onyxwasm.h b/include/onyxwasm.h index 3471b64f..a42d78ac 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -309,6 +309,8 @@ typedef struct OnyxWasmModule { // to the function type index if it has been created. bh_table(i32) type_map; + bh_table(u32) loaded_file_offsets; + bh_arr(u8) structured_jump_target; bh_arr(WasmFuncType*) types; // NOTE: This have to be pointers because the type is variadic in size diff --git a/misc/onyx.sublime-syntax b/misc/onyx.sublime-syntax index 4327aa60..c728bf37 100644 --- a/misc/onyx.sublime-syntax +++ b/misc/onyx.sublime-syntax @@ -39,7 +39,7 @@ contexts: - match: '\b0x[0-9A-Fa-f]+\b' scope: constant.numeric.onyx - - match: '#[a-zA-Z]+' + - match: '#[a-zA-Z_]+' scope: keyword.other.onyx double_quoted_string: diff --git a/onyx b/onyx index 2486714a..0210d24e 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/alloc_test.onyx b/progs/alloc_test.onyx index ebb8b131..c8accc5b 100644 --- a/progs/alloc_test.onyx +++ b/progs/alloc_test.onyx @@ -21,7 +21,7 @@ deferred_example :: proc -> i32 { } proc #export "main" { - asdf :: "staring asdfkjasd asdflkjasdflkajsdflya"; + print(#file_contents "progs/filetest"); heap_init(); print(deferred_example()); diff --git a/progs/filetest b/progs/filetest new file mode 100644 index 00000000..b2bc3257 --- /dev/null +++ b/progs/filetest @@ -0,0 +1 @@ +This is a test from a file! \ No newline at end of file diff --git a/src/onyx.c b/src/onyx.c index 58debdeb..ba454dda 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -223,6 +223,13 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res break; } + case Ast_Kind_File_Contents: { + ent.type = Entity_Type_File_Contents; + ent.file_contents = (AstFileContents *) node; + bh_arr_push(compiler_state->prog_info.entities, ent); + break; + } + case Ast_Kind_Type_Alias: case Ast_Kind_Struct_Type: { ent.type = Entity_Type_Type_Alias; diff --git a/src/onyxchecker.c b/src/onyxchecker.c index cfc3afd7..64390bcf 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -774,6 +774,7 @@ CHECK(expression, AstTyped** pexpr) { break; case Ast_Kind_StrLit: break; + case Ast_Kind_File_Contents: break; case Ast_Kind_Overloaded_Function: break; case Ast_Kind_Enum_Value: break; @@ -1086,6 +1087,8 @@ void onyx_type_check() { case Entity_Type_String_Literal: break; + case Entity_Type_File_Contents: break; + case Entity_Type_Global_Header: break; case Entity_Type_Use_Package: break; diff --git a/src/onyxlex.c b/src/onyxlex.c index ba69632e..f5462d56 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -234,7 +234,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { } // Hex literal - if (*tokenizer->curr == '0' && *(tokenizer->curr + 1) == 'x' && char_is_num(*(tokenizer->curr + 2))) { + if (*tokenizer->curr == '0' && *(tokenizer->curr + 1) == 'x' && charset_contains("0123456789abcdefABCDEF", *(tokenizer->curr + 2))) { INCREMENT_CURR_TOKEN(tokenizer); INCREMENT_CURR_TOKEN(tokenizer); u32 len = 3; diff --git a/src/onyxmsgs.c b/src/onyxmsgs.c index a79f4e11..c5ad22d1 100644 --- a/src/onyxmsgs.c +++ b/src/onyxmsgs.c @@ -34,6 +34,8 @@ static const char* msg_formats[] = { "failed to generate load instruction for type '%s'", "failed to generate store instruction for type '%s'", + + "file not found '%s'", }; void onyx_message_init(bh_allocator allocator, bh_table(bh_file_contents)* files) { diff --git a/src/onyxparser.c b/src/onyxparser.c index 834e76d2..e8097273 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -27,6 +27,7 @@ static AstNode* parse_statement(OnyxParser* parser); static AstType* parse_type(OnyxParser* parser); static AstStructType* parse_struct(OnyxParser* parser); static AstLocal* parse_function_params(OnyxParser* parser); +static b32 parse_possible_directive(OnyxParser* parser, const char* dir); static AstFunction* parse_function_definition(OnyxParser* parser); static AstTyped* parse_global_declaration(OnyxParser* parser); static AstEnumType* parse_enum_declaration(OnyxParser* parser); @@ -288,6 +289,29 @@ static AstTyped* parse_factor(OnyxParser* parser) { break; } + case '#': { + if (parse_possible_directive(parser, "file_contents")) { + AstPointerType* fc_type = make_node(AstPointerType, Ast_Kind_Pointer_Type); + fc_type->flags |= Basic_Flag_Pointer; + fc_type->elem = (AstType *) &basic_type_u8; + + AstFileContents* fc = make_node(AstFileContents, Ast_Kind_File_Contents); + fc->token = parser->prev - 1; + fc->filename = expect_token(parser, Token_Type_Literal_String); + fc->type_node = (AstType *) fc_type; + + add_node_to_process(parser, (AstNode *) fc); + + retval = (AstTyped *) fc; + break; + } + + onyx_message_add(Msg_Type_Literal, + parser->curr->pos, + "invalid directive in expression."); + return NULL; + } + default: onyx_message_add(Msg_Type_Unexpected_Token, parser->curr->pos, diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 275582a4..5f0a2869 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -489,6 +489,8 @@ static void symres_enum(AstEnumType* enum_node) { static void symres_memres(AstMemRes** memres) { (*memres)->type_node = symres_type((*memres)->type_node); + if ((*memres)->type_node == NULL) return; + (*memres)->type = type_build_from_ast(semstate.allocator, (*memres)->type_node); if ((*memres)->type->kind != Type_Kind_Array && (*memres)->type->kind != Type_Kind_Struct) { diff --git a/src/onyxutils.c b/src/onyxutils.c index 481e7eea..a8a4ec36 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -53,6 +53,7 @@ static const char* ast_node_names[] = { "FIELD_ACCESS", "SIZE OF", "ALIGN OF" + "FILE CONTENTS" "IF", "FOR", diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 4bd78cc9..6c24c76a 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -1055,6 +1055,17 @@ COMPILE_FUNC(expression, AstTyped* expr) { break; } + case Ast_Kind_File_Contents: { + AstFileContents* fc = (AstFileContents *) expr; + token_toggle_end(fc->filename); + + u32 offset = bh_table_get(u32, mod->loaded_file_offsets, fc->filename->text); + WID(WI_I32_CONST, offset); + + token_toggle_end(fc->filename); + break; + } + default: bh_printf("Unhandled case: %d\n", expr->kind); DEBUG_HERE; @@ -1426,6 +1437,10 @@ static void compile_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) { if (src[i] == '\\') { i++; switch (src[i]) { + case '0': *des++ = '\0'; break; + case 'a': *des++ = '\a'; break; + case 'b': *des++ = '\b'; break; + case 'f': *des++ = '\f'; break; case 'n': *des++ = '\n'; break; case 't': *des++ = '\t'; break; case 'r': *des++ = '\r'; break; @@ -1475,6 +1490,46 @@ static void compile_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) { // bh_arr_push(mod->data, datum); } +static void compile_file_contents(OnyxWasmModule* mod, AstFileContents* fc) { + token_toggle_end(fc->filename); + + if (bh_table_has(u32, mod->loaded_file_offsets, fc->filename->text)) { + token_toggle_end(fc->filename); + return; + } + + u32 offset = mod->next_datum_offset; + if (offset % 16 != 0) + offset += 16 - (offset % 16); + bh_table_put(u32, mod->loaded_file_offsets, fc->filename->text, offset); + + if (!bh_file_exists(fc->filename->text)) { + onyx_message_add(Msg_Type_File_Not_Found, + fc->filename->pos, + fc->filename->text); + + token_toggle_end(fc->filename); + return; + } + + bh_file_contents contents = bh_file_read_contents(global_heap_allocator, fc->filename->text); + u8* actual_data = bh_alloc(global_heap_allocator, contents.length + 1); + u32 length = contents.length + 1; + memcpy(actual_data, contents.data, contents.length); + actual_data[contents.length] = 0; + bh_file_contents_free(&contents); + + WasmDatum datum = { + .offset = offset, + .length = length, + .data = actual_data, + }; + + bh_arr_push(mod->data, datum); + + token_toggle_end(fc->filename); +} + OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { OnyxWasmModule module = { .allocator = alloc, @@ -1518,6 +1573,7 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { bh_table_init(global_heap_allocator, module.type_map, 61); bh_table_init(global_heap_allocator, module.exports, 61); + bh_table_init(global_heap_allocator, module.loaded_file_offsets, 7); bh_imap_init(&module.index_map, global_heap_allocator, 128); bh_imap_init(&module.local_map, global_heap_allocator, 16); @@ -1540,6 +1596,14 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program) { module->export_count++; bh_arr_each(Entity, entity, program->entities) { + + // HACK: To put this here + // NOTE: Round up to the nearest multiple of 16 + builtin_heap_start.value.i = + (module->next_datum_offset & 15) + ? ((module->next_datum_offset >> 4) + 1) << 4 + : module->next_datum_offset; + switch (entity->type) { case Entity_Type_Function_Header: { if (!should_compile_function(entity->function)) break; @@ -1567,25 +1631,16 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program) { case Entity_Type_String_Literal: { compile_string_literal(module, (AstStrLit *) entity->strlit); + break; + } - // HACK: To put this here - // NOTE: Round up to the nearest multiple of 16 - builtin_heap_start.value.i = - (module->next_datum_offset & 15) - ? ((module->next_datum_offset >> 4) + 1) << 4 - : module->next_datum_offset; + case Entity_Type_File_Contents: { + compile_file_contents(module, (AstFileContents *) entity->file_contents); break; } case Entity_Type_Memory_Reservation: { compile_memory_reservation(module, (AstMemRes *) entity->mem_res); - - // HACK: To put this here - // NOTE: Round up to the nearest multiple of 16 - builtin_heap_start.value.i = - (module->next_datum_offset & 15) - ? ((module->next_datum_offset >> 4) + 1) << 4 - : module->next_datum_offset; break; }