Added '#file_contents' directive to expression
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 6 Aug 2020 22:26:42 +0000 (17:26 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 6 Aug 2020 22:26:42 +0000 (17:26 -0500)
18 files changed:
Makefile
docs/plan
include/bh.h
include/onyxastnodes.h
include/onyxmsgs.h
include/onyxwasm.h
misc/onyx.sublime-syntax
onyx
progs/alloc_test.onyx
progs/filetest [new file with mode: 0644]
src/onyx.c
src/onyxchecker.c
src/onyxlex.c
src/onyxmsgs.c
src/onyxparser.c
src/onyxsymres.c
src/onyxutils.c
src/onyxwasm.c

index ca7a3d7f1ad9a26d0fa0e65bc08f6a14410e1090..0e514db6108e81017afbacf2eac82318593c4738 100644 (file)
--- 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)
 
index 12652ee995c7ea7df8127b48b108babcc96650a0..25846cec17a548faec6c54ef0d205bdde89f30bc 100644 (file)
--- 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.
index 4b1b07b5f7af15fe0532619ba6f75fcf38f1faf3..3760fda290e57e2594dc3ed0b75354a2dd07a187 100644 (file)
@@ -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
 
 
index 3ba79b67858d187af4d9bb443d4693e98d762e7b..3f03c4e299002717cc7a60d4268228ae7c7199ac 100644 (file)
@@ -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;
index 26f2b57ce5bf0e2017f8b68277546c9cbaae8eed..1f78243bf8a96deb9d80edb16fcabc85320ccbd1 100644 (file)
@@ -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;
index 3471b64fdc7222cce72ff914e00f028283f558c5..a42d78ac61ccb85b4041483446262815b206c4a1 100644 (file)
@@ -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
index 4327aa60ca7ffb327b27f6638ec274ae60cd7716..c728bf370619ff466f29e9393ae15e40ebefd99a 100644 (file)
@@ -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 2486714a44c242bdaecc81b46c57ffb88647bbe1..0210d24e20ff7011972b018e66bfeaf1e2d7cc26 100755 (executable)
Binary files a/onyx and b/onyx differ
index ebb8b131f08db03058ddbdf7167e6b6dbf56196a..c8accc5b9c57fd3edab64cf6d0236df97dff5078 100644 (file)
@@ -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 (file)
index 0000000..b2bc325
--- /dev/null
@@ -0,0 +1 @@
+This is a test from a file!
\ No newline at end of file
index 58debdeb8322b7f4be3e5bd0d43f95dca983b59e..ba454ddae6da5ba89db6b79af92f611cf394b9cb 100644 (file)
@@ -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;
index cfc3afd7328b8f15a1402b1173ebdac3a3a55bc8..64390bcfed674be10392e8c7063467c16b3fb454 100644 (file)
@@ -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;
index ba69632e7b3df7cbae919c0b1d342098fa711ca2..f5462d56a4aadfcf880a5448f4fa8b3c3cefcc19 100644 (file)
@@ -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;
index a79f4e118c251b093211eb1e165a12e2079d719d..c5ad22d13fbc87938eae0cb20f9358e85a5c0b5e 100644 (file)
@@ -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) {
index 834e76d2de9481d22bdef5312f4ca62a8d5dd8c8..e8097273235c071faaeffef37de42df20f46799f 100644 (file)
@@ -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,
index 275582a4cbbca3e70a5c5e8d43d2378c1f20537a..5f0a28694c473ab53eb189768157771504da5a79 100644 (file)
@@ -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) {
index 481e7eea6bdc416560b973a3bcce4530e89bcfd4..a8a4ec361b41bbd5c43a6af1692372a0f6c25d36 100644 (file)
@@ -53,6 +53,7 @@ static const char* ast_node_names[] = {
     "FIELD_ACCESS",
     "SIZE OF",
     "ALIGN OF"
+    "FILE CONTENTS"
 
     "IF",
     "FOR",
index 4bd78cc91d4a0497084511ff138303d231bd9663..6c24c76a5213effc44b316b134df1d45729ab7ad 100644 (file)
@@ -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;
             }