+RELEASE=1
+
OBJ_FILES=\
build/onyxlex.o \
build/onyxparser.o \
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)
[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.
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, \
return 1;
}
+b32 bh_file_exists(char const* filename) {
+ struct stat s;
+ return stat(filename, &s) != -1;
+}
+
#endif // ifndef BH_NO_FILE
typedef struct AstFieldAccess AstFieldAccess;
typedef struct AstSizeOf AstSizeOf;
typedef struct AstAlignOf AstAlignOf;
+typedef struct AstFileContents AstFileContents;
typedef struct AstReturn AstReturn;
typedef struct AstBreak AstBreak;
Ast_Kind_Field_Access,
Ast_Kind_Size_Of,
Ast_Kind_Align_Of,
+ Ast_Kind_File_Contents,
Ast_Kind_If,
Ast_Kind_For,
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; };
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,
AstGlobal *global;
AstTyped *expr;
AstStrLit *strlit;
+ AstFileContents *file_contents;
AstType *type_alias;
AstEnumType *enum_type;
AstMemRes *mem_res;
Msg_Type_Failed_Gen_Load,
Msg_Type_Failed_Gen_Store,
+ Msg_Type_File_Not_Found,
Msg_Type_Count,
} MsgType;
// 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
- 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:
}
proc #export "main" {
- asdf :: "staring asdfkjasd asdflkjasdflkajsdflya";
+ print(#file_contents "progs/filetest");
heap_init();
print(deferred_example());
--- /dev/null
+This is a test from a file!
\ No newline at end of file
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;
break;
case Ast_Kind_StrLit: break;
+ case Ast_Kind_File_Contents: break;
case Ast_Kind_Overloaded_Function: break;
case Ast_Kind_Enum_Value: break;
case Entity_Type_String_Literal: break;
+ case Entity_Type_File_Contents: break;
+
case Entity_Type_Global_Header: break;
case Entity_Type_Use_Package: break;
}
// 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;
"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) {
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);
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,
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) {
"FIELD_ACCESS",
"SIZE OF",
"ALIGN OF"
+ "FILE CONTENTS"
"IF",
"FOR",
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;
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;
// 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,
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);
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;
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;
}