mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Unicode file loading; push_allocator & push_context
This commit is contained in:
@@ -24,7 +24,7 @@ set compiler_warnings= ^
|
||||
-wd4505 -wd4512 -wd4550
|
||||
|
||||
set compiler_includes=
|
||||
set libs= kernel32.lib user32.lib gdi32.lib opengl32.lib
|
||||
set libs= kernel32.lib
|
||||
|
||||
set linker_flags= -incremental:no -opt:ref -subsystem:console
|
||||
|
||||
|
||||
+14
-2
@@ -1,19 +1,31 @@
|
||||
#import "fmt.odin"
|
||||
#import "os.odin"
|
||||
#import "mem.odin"
|
||||
// #import "http_test.odin" as ht
|
||||
// #import "game.odin" as game
|
||||
// #import "punity.odin" as pn
|
||||
|
||||
|
||||
main :: proc() {
|
||||
|
||||
arena: mem.Arena
|
||||
mem.init_arena_from_context(^arena, 1000)
|
||||
defer mem.free_arena(^arena)
|
||||
|
||||
push_allocator mem.arena_allocator(^arena) {
|
||||
x := new(int)
|
||||
x^ = 1337
|
||||
fmt.println(x^)
|
||||
}
|
||||
|
||||
|
||||
// struct_padding()
|
||||
// bounds_checking()
|
||||
// type_introspection()
|
||||
// any_type()
|
||||
// crazy_introspection()
|
||||
namespaces_and_files()
|
||||
// namespaces_and_files()
|
||||
// miscellany()
|
||||
|
||||
// ht.run()
|
||||
// game.run()
|
||||
// {
|
||||
|
||||
@@ -33,4 +33,3 @@ thing :: proc() {
|
||||
thing :: proc() {
|
||||
println("Hello5!")
|
||||
}*/
|
||||
|
||||
|
||||
+5
-4
@@ -130,6 +130,7 @@ memory_compare :: proc(dst, src: rawptr, len: int) -> int {
|
||||
}
|
||||
|
||||
memory_copy :: proc(dst, src: rawptr, len: int) #inline {
|
||||
// NOTE(bill): This _must_ implemented like C's memmove
|
||||
llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memmove.p0i8.p0i8.i64"
|
||||
llvm_memmove_64bit(dst, src, len, 1, false)
|
||||
}
|
||||
@@ -142,7 +143,7 @@ memory_copy :: proc(dst, src: rawptr, len: int) #inline {
|
||||
|
||||
|
||||
|
||||
Allocator :: struct {
|
||||
Allocator :: struct #ordered {
|
||||
Mode :: enum {
|
||||
ALLOC,
|
||||
FREE,
|
||||
@@ -159,7 +160,7 @@ Allocator :: struct {
|
||||
}
|
||||
|
||||
|
||||
Context :: struct {
|
||||
Context :: struct #ordered {
|
||||
thread_id: int
|
||||
|
||||
allocator: Allocator
|
||||
@@ -279,8 +280,6 @@ __default_allocator :: proc() -> Allocator {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__string_eq :: proc(a, b: string) -> bool {
|
||||
if a.count != b.count {
|
||||
return false
|
||||
@@ -382,3 +381,5 @@ __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@echo off
|
||||
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
|
||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
|
||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
|
||||
set _NO_DEBUG_HEAP=1
|
||||
|
||||
|
||||
+22
-4
@@ -839,10 +839,9 @@ void check_type_name_cycles(Checker *c, CycleCheck *cc, Entity *e) {
|
||||
// }
|
||||
}
|
||||
|
||||
void init_type_info_types(Checker *c) {
|
||||
void init_runtime_types(Checker *c) {
|
||||
if (t_type_info == NULL) {
|
||||
String type_info_str = make_string("Type_Info");
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str);
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Type_Info`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
@@ -875,6 +874,25 @@ void init_type_info_types(Checker *c) {
|
||||
t_type_info_enum = record->fields[15]->type;
|
||||
}
|
||||
|
||||
if (t_allocator == NULL) {
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Allocator"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Allocator`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
}
|
||||
t_allocator = e->type;
|
||||
t_allocator_ptr = make_type_pointer(c->allocator, t_allocator);
|
||||
}
|
||||
|
||||
if (t_context == NULL) {
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Context"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Context`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
}
|
||||
t_context = e->type;
|
||||
t_context_ptr = make_type_pointer(c->allocator, t_context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1131,7 +1149,7 @@ void check_parsed_files(Checker *c) {
|
||||
|
||||
check_global_entity(c, Entity_TypeName);
|
||||
|
||||
init_type_info_types(c);
|
||||
init_runtime_types(c);
|
||||
#if 1
|
||||
check_global_entity(c, Entity_Constant);
|
||||
check_global_entity(c, Entity_Procedure);
|
||||
|
||||
+39
-23
@@ -266,15 +266,19 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
AstNode *name = cd->names[i];
|
||||
Entity *e = entities[i];
|
||||
Token name_token = name->Ident;
|
||||
HashKey key = hash_string(name_token.string);
|
||||
if (map_get(&entity_map, key) != NULL) {
|
||||
// TODO(bill): Scope checking already checks the declaration
|
||||
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
|
||||
} else {
|
||||
map_set(&entity_map, key, e);
|
||||
if (name_token.string == make_string("_")) {
|
||||
other_fields[other_field_index++] = e;
|
||||
} else {
|
||||
HashKey key = hash_string(name_token.string);
|
||||
if (map_get(&entity_map, key) != NULL) {
|
||||
// TODO(bill): Scope checking already checks the declaration
|
||||
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
|
||||
} else {
|
||||
map_set(&entity_map, key, e);
|
||||
other_fields[other_field_index++] = e;
|
||||
}
|
||||
add_entity(c, c->context.scope, name, e);
|
||||
}
|
||||
add_entity(c, c->context.scope, name, e);
|
||||
}
|
||||
} else if (decl->kind == AstNode_TypeDecl) {
|
||||
ast_node(td, TypeDecl, decl);
|
||||
@@ -284,15 +288,19 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
add_entity(c, c->context.scope, td->name, e);
|
||||
check_type_decl(c, e, td->type, NULL, NULL);
|
||||
|
||||
HashKey key = hash_string(name_token.string);
|
||||
if (map_get(&entity_map, key) != NULL) {
|
||||
// TODO(bill): Scope checking already checks the declaration
|
||||
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
|
||||
} else {
|
||||
map_set(&entity_map, key, e);
|
||||
if (name_token.string == make_string("_")) {
|
||||
other_fields[other_field_index++] = e;
|
||||
} else {
|
||||
HashKey key = hash_string(name_token.string);
|
||||
if (map_get(&entity_map, key) != NULL) {
|
||||
// TODO(bill): Scope checking already checks the declaration
|
||||
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
|
||||
} else {
|
||||
map_set(&entity_map, key, e);
|
||||
other_fields[other_field_index++] = e;
|
||||
}
|
||||
add_entity_use(&c->info, td->name, e);
|
||||
}
|
||||
add_entity_use(&c->info, td->name, e);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -318,6 +326,11 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
type->Named.type_name = e;
|
||||
add_entity(c, c->context.scope, name, e);
|
||||
|
||||
if (name_token.string == make_string("_")) {
|
||||
error(name_token, "`_` cannot be used a union subtype");
|
||||
continue;
|
||||
}
|
||||
|
||||
HashKey key = hash_string(name_token.string);
|
||||
if (map_get(&entity_map, key) != NULL) {
|
||||
// TODO(bill): Scope checking already checks the declaration
|
||||
@@ -352,17 +365,20 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
Token name_token = name->Ident;
|
||||
|
||||
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index);
|
||||
HashKey key = hash_string(name_token.string);
|
||||
if (map_get(&entity_map, key) != NULL) {
|
||||
// TODO(bill): Scope checking already checks the declaration
|
||||
error(name_token, "`%.*s` is already declared in this type", LIT(name_token.string));
|
||||
if (name_token.string == make_string("_")) {
|
||||
fields[field_index++] = e;
|
||||
} else {
|
||||
map_set(&entity_map, key, e);
|
||||
fields[field_index] = e;
|
||||
field_index++;
|
||||
add_entity(c, c->context.scope, name, e);
|
||||
HashKey key = hash_string(name_token.string);
|
||||
if (map_get(&entity_map, key) != NULL) {
|
||||
// TODO(bill): Scope checking already checks the declaration
|
||||
error(name_token, "`%.*s` is already declared in this type", LIT(name_token.string));
|
||||
} else {
|
||||
map_set(&entity_map, key, e);
|
||||
fields[field_index++] = e;
|
||||
add_entity(c, c->context.scope, name, e);
|
||||
}
|
||||
add_entity_use(&c->info, name, e);
|
||||
}
|
||||
add_entity_use(&c->info, name, e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1483,6 +1483,23 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
|
||||
|
||||
case_ast_node(pa, PushAllocator, node);
|
||||
Operand op = {};
|
||||
check_expr(c, &op, pa->expr);
|
||||
check_assignment(c, &op, t_allocator, make_string("argument to push_allocator"));
|
||||
check_stmt(c, pa->body, mod_flags);
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(pa, PushContext, node);
|
||||
Operand op = {};
|
||||
check_expr(c, &op, pa->expr);
|
||||
check_assignment(c, &op, t_context, make_string("argument to push_context"));
|
||||
check_stmt(c, pa->body, mod_flags);
|
||||
case_end;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+17
-13
@@ -4,21 +4,20 @@ enum BasicKind {
|
||||
Basic_Invalid,
|
||||
Basic_bool,
|
||||
Basic_i8,
|
||||
Basic_i16,
|
||||
Basic_i32,
|
||||
Basic_i64,
|
||||
Basic_u8,
|
||||
Basic_i16,
|
||||
Basic_u16,
|
||||
Basic_i32,
|
||||
Basic_u32,
|
||||
Basic_i64,
|
||||
Basic_u64,
|
||||
Basic_f32,
|
||||
Basic_f64,
|
||||
Basic_int,
|
||||
Basic_uint,
|
||||
Basic_rawptr,
|
||||
Basic_string,
|
||||
|
||||
Basic_any,
|
||||
Basic_string, // ^u8 + int
|
||||
Basic_any, // ^Type_Info + rawptr
|
||||
|
||||
Basic_UntypedBool,
|
||||
Basic_UntypedInteger,
|
||||
@@ -27,7 +26,6 @@ enum BasicKind {
|
||||
Basic_UntypedString,
|
||||
Basic_UntypedRune,
|
||||
|
||||
|
||||
Basic_Count,
|
||||
|
||||
Basic_byte = Basic_u8,
|
||||
@@ -294,12 +292,12 @@ gb_global Type basic_types[] = {
|
||||
{0, Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}},
|
||||
{0, Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
|
||||
{0, Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
|
||||
{0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
||||
{0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
||||
{0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
||||
{0, Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
|
||||
{0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
||||
{0, Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
|
||||
{0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
||||
{0, Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
|
||||
{0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
||||
{0, Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
||||
{0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
||||
{0, Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
||||
@@ -370,6 +368,12 @@ gb_global Type *t_type_info_raw_union = NULL;
|
||||
gb_global Type *t_type_info_enum = NULL;
|
||||
gb_global Type *t_type_info_any = NULL;
|
||||
|
||||
gb_global Type *t_allocator = NULL;
|
||||
gb_global Type *t_allocator_ptr = NULL;
|
||||
gb_global Type *t_context = NULL;
|
||||
gb_global Type *t_context_ptr = NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
b32 is_type_named(Type *t) {
|
||||
@@ -674,12 +678,12 @@ gb_global i64 basic_type_sizes[] = {
|
||||
0, // Basic_Invalid
|
||||
1, // Basic_bool
|
||||
1, // Basic_i8
|
||||
2, // Basic_i16
|
||||
4, // Basic_i32
|
||||
8, // Basic_i64
|
||||
1, // Basic_u8
|
||||
2, // Basic_i16
|
||||
2, // Basic_u16
|
||||
4, // Basic_i32
|
||||
4, // Basic_u32
|
||||
8, // Basic_i64
|
||||
8, // Basic_u64
|
||||
4, // Basic_f32
|
||||
8, // Basic_f64
|
||||
|
||||
@@ -48,7 +48,6 @@ String ssa_mangle_name(ssaGen *s, String path, String name) {
|
||||
if (str[i] == '\\') {
|
||||
str[i] = '/';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
char const *base = gb_path_base_name(str);
|
||||
|
||||
@@ -84,8 +84,11 @@ void ssa_print_escape_string(ssaFileBuffer *f, String name, b32 print_quotes) {
|
||||
|
||||
char hex_table[] = "0123456789ABCDEF";
|
||||
isize buf_len = name.len + extra + 2;
|
||||
u8 *buf = gb_alloc_array(gb_heap_allocator(), u8, buf_len);
|
||||
defer (gb_free(gb_heap_allocator(), buf));
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
u8 *buf = gb_alloc_array(string_buffer_allocator, u8, buf_len);
|
||||
|
||||
isize j = 0;
|
||||
|
||||
@@ -809,9 +812,11 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
|
||||
|
||||
|
||||
if (proc->module->generate_debug_info && proc->entity != NULL) {
|
||||
ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity));
|
||||
GB_ASSERT(di->kind == ssaDebugInfo_Proc);
|
||||
ssa_fprintf(f, "!dbg !%d ", di->id);
|
||||
if (proc->body != NULL) {
|
||||
ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity));
|
||||
GB_ASSERT(di->kind == ssaDebugInfo_Proc);
|
||||
ssa_fprintf(f, "!dbg !%d ", di->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+45
-5
@@ -2200,10 +2200,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
ssaValue *elem_size = ssa_make_const_int(allocator, s);
|
||||
ssaValue *elem_align = ssa_make_const_int(allocator, a);
|
||||
|
||||
ssaValue *len = ssa_build_expr(proc, ce->args[1]);
|
||||
ssaValue *len =ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[1]), t_int);
|
||||
ssaValue *cap = len;
|
||||
if (gb_array_count(ce->args) == 3) {
|
||||
cap = ssa_build_expr(proc, ce->args[2]);
|
||||
cap = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[2]), t_int);
|
||||
}
|
||||
|
||||
ssa_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, cap, false);
|
||||
@@ -2218,9 +2218,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
|
||||
ssaValue *ptr = ssa_emit_conv(proc, call, ptr_type, true);
|
||||
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_zero32, ptr_type), ptr);
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_one32, t_int), len);
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), cap);
|
||||
|
||||
ssaValue *gep0 = ssa_emit_struct_gep(proc, slice, v_zero32, ptr_type);
|
||||
ssaValue *gep1 = ssa_emit_struct_gep(proc, slice, v_one32, t_int);
|
||||
ssaValue *gep2 = ssa_emit_struct_gep(proc, slice, v_two32, t_int);
|
||||
ssa_emit_store(proc, gep0, ptr);
|
||||
ssa_emit_store(proc, gep1, len);
|
||||
ssa_emit_store(proc, gep2, cap);
|
||||
return ssa_emit_load(proc, slice);
|
||||
} break;
|
||||
|
||||
@@ -3678,6 +3682,42 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
ssa_emit_unreachable(proc);
|
||||
case_end;
|
||||
|
||||
|
||||
|
||||
case_ast_node(pa, PushAllocator, node);
|
||||
ssa_emit_comment(proc, make_string("PushAllocator"));
|
||||
|
||||
ssaValue *context_ptr = *map_get(&proc->module->members, hash_string(make_string("__context")));
|
||||
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
|
||||
ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
|
||||
defer (ssa_emit_store(proc, context_ptr, ssa_emit_load(proc, prev_context)));
|
||||
|
||||
ssaValue *gep = ssa_emit_struct_gep(proc, context_ptr, 1, t_allocator_ptr);
|
||||
ssa_emit_store(proc, gep, ssa_build_expr(proc, pa->expr));
|
||||
|
||||
proc->scope_index++;
|
||||
ssa_build_stmt(proc, pa->body);
|
||||
proc->scope_index--;
|
||||
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(pa, PushContext, node);
|
||||
ssa_emit_comment(proc, make_string("PushContext"));
|
||||
|
||||
ssaValue *context_ptr = *map_get(&proc->module->members, hash_string(make_string("__context")));
|
||||
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
|
||||
ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
|
||||
defer (ssa_emit_store(proc, context_ptr, ssa_emit_load(proc, prev_context)));
|
||||
|
||||
ssa_emit_store(proc, context_ptr, ssa_build_expr(proc, pa->expr));
|
||||
|
||||
proc->scope_index++;
|
||||
ssa_build_stmt(proc, pa->body);
|
||||
proc->scope_index--;
|
||||
case_end;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,47 @@
|
||||
|
||||
#include "string.cpp"
|
||||
|
||||
String get_module_dir(gbAllocator a) {
|
||||
isize len = GetModuleFileNameW(NULL, NULL, 0);
|
||||
if (len == 0) {
|
||||
return make_string(NULL, 0);
|
||||
}
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
|
||||
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
||||
|
||||
String16 str = {text, len};
|
||||
GetModuleFileNameW(NULL, text, len);
|
||||
String path = string16_to_string(a, str);
|
||||
for (isize i = path.len-1; i >= 0; i--) {
|
||||
u8 c = path.text[i];
|
||||
if (c == '/' || c == '\\') {
|
||||
break;
|
||||
}
|
||||
path.len--;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
String path_to_fullpath(gbAllocator a, String s) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
String16 string16 = string_to_string16(string_buffer_allocator, s);
|
||||
|
||||
DWORD len = GetFullPathNameW(string16.text, 0, NULL, NULL);
|
||||
if (len == 0) {
|
||||
return make_string(NULL, 0);
|
||||
}
|
||||
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
||||
GetFullPathNameW(string16.text, len, text, NULL);
|
||||
text[len] = 0;
|
||||
|
||||
return string16_to_string(a, make_string16(text, len));
|
||||
}
|
||||
|
||||
struct BlockTimer {
|
||||
u64 start;
|
||||
|
||||
+2
-2
@@ -190,7 +190,7 @@ ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
|
||||
}
|
||||
|
||||
failure:
|
||||
compiler_error("Invalid unary operation, %.*s", LIT(token_strings[op.kind]));
|
||||
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op.kind]));
|
||||
|
||||
ExactValue error_value = {};
|
||||
return error_value;
|
||||
@@ -212,7 +212,7 @@ i32 exact_value_order(ExactValue v) {
|
||||
return 4;
|
||||
|
||||
default:
|
||||
compiler_error("How'd you get here? Invalid Value.kind");
|
||||
GB_PANIC("How'd you get here? Invalid Value.kind");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -3948,7 +3948,7 @@ void const *gb_memrchr(void const *data, u8 c, isize n) {
|
||||
|
||||
gb_inline void *gb_alloc_align (gbAllocator a, isize size, isize alignment) { return a.proc(a.data, gbAllocation_Alloc, size, alignment, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
||||
gb_inline void *gb_alloc (gbAllocator a, isize size) { return gb_alloc_align(a, size, GB_DEFAULT_MEMORY_ALIGNMENT); }
|
||||
gb_inline void gb_free (gbAllocator a, void *ptr) { a.proc(a.data, gbAllocation_Free, 0, 0, ptr, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
||||
gb_inline void gb_free (gbAllocator a, void *ptr) { if (ptr != NULL) a.proc(a.data, gbAllocation_Free, 0, 0, ptr, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
||||
gb_inline void gb_free_all (gbAllocator a) { a.proc(a.data, gbAllocation_FreeAll, 0, 0, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
||||
gb_inline void *gb_resize (gbAllocator a, void *ptr, isize old_size, isize new_size) { return gb_resize_align(a, ptr, old_size, new_size, GB_DEFAULT_MEMORY_ALIGNMENT); }
|
||||
gb_inline void *gb_resize_align(gbAllocator a, void *ptr, isize old_size, isize new_size, isize alignment) { return a.proc(a.data, gbAllocation_Resize, new_size, alignment, ptr, old_size, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
||||
@@ -4698,7 +4698,7 @@ void gb_thread_set_name(gbThread *t, char const *name) {
|
||||
tn.flags = 0;
|
||||
|
||||
__try {
|
||||
RaiseException(0x406d1388, 0, gb_size_of(tn)/4, cast(usize *)&tn);
|
||||
RaiseException(0x406d1388, 0, gb_size_of(tn)/4, cast(ULONG_PTR *)&tn);
|
||||
} __except(1 /*EXCEPTION_EXECUTE_HANDLER*/) {
|
||||
}
|
||||
|
||||
|
||||
+72
-39
@@ -7,26 +7,35 @@
|
||||
#include "codegen/codegen.cpp"
|
||||
|
||||
i32 win32_exec_command_line_app(char *fmt, ...) {
|
||||
STARTUPINFOA start_info = {gb_size_of(STARTUPINFOA)};
|
||||
STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)};
|
||||
PROCESS_INFORMATION pi = {};
|
||||
char cmd_line[2048] = {};
|
||||
isize cmd_len;
|
||||
va_list va;
|
||||
gbTempArenaMemory tmp;
|
||||
String16 cmd;
|
||||
|
||||
start_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||
start_info.wShowWindow = SW_SHOW;
|
||||
start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
char cmd_line[2048] = {};
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va);
|
||||
cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va);
|
||||
va_end(va);
|
||||
|
||||
if (CreateProcessA(NULL, cmd_line,
|
||||
NULL, NULL, true, 0, NULL, NULL,
|
||||
&start_info, &pi)) {
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
cmd = string_to_string16(string_buffer_allocator, make_string(cast(u8 *)cmd_line, cmd_len-1));
|
||||
|
||||
if (CreateProcessW(NULL, cmd.text,
|
||||
NULL, NULL, true, 0, NULL, NULL,
|
||||
&start_info, &pi)) {
|
||||
DWORD exit_code = 0;
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
GetExitCodeProcess(pi.hProcess, &exit_code);
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
@@ -40,7 +49,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
// #define DISPLAY_TIMING
|
||||
#define DISPLAY_TIMING
|
||||
#if defined(DISPLAY_TIMING)
|
||||
#define INIT_TIMER() f64 start_time = gb_time_now(), end_time = 0, total_time = 0
|
||||
#define PRINT_TIMER(section) do { \
|
||||
@@ -62,23 +71,50 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
|
||||
#endif
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
gb_printf_err("Please specify a .odin file\n");
|
||||
return 1;
|
||||
}
|
||||
char module_path_buf[300] = {};
|
||||
String module_path = {};
|
||||
module_path.text = cast(u8 *)module_path_buf;
|
||||
module_path.len = GetModuleFileNameA(NULL, module_path_buf, gb_size_of(module_path_buf));
|
||||
for (isize i = module_path.len-1; i >= 0; i--) {
|
||||
u8 c = module_path.text[i];
|
||||
if (c == '/' || c == '\\') {
|
||||
break;
|
||||
}
|
||||
module_path.len--;
|
||||
enum ArchKind {
|
||||
ArchKind_x64,
|
||||
ArchKind_x86,
|
||||
};
|
||||
|
||||
struct ArchData {
|
||||
BaseTypeSizes sizes;
|
||||
String llc_flags;
|
||||
String link_flags;
|
||||
};
|
||||
|
||||
ArchData make_arch_data(ArchKind kind) {
|
||||
ArchData data = {};
|
||||
|
||||
switch (kind) {
|
||||
case ArchKind_x64:
|
||||
default:
|
||||
data.sizes.word_size = 8;
|
||||
data.sizes.max_align = 16;
|
||||
data.llc_flags = make_string("-march=x86-64 ");
|
||||
data.link_flags = make_string("/machine:x64 /defaultlib:libcmt ");
|
||||
break;
|
||||
|
||||
case ArchKind_x86:
|
||||
data.sizes.word_size = 4;
|
||||
data.sizes.max_align = 8;
|
||||
data.llc_flags = make_string("-march=x86 ");
|
||||
data.link_flags = make_string("/machine:x86 /defaultlib:libcmt ");
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
gb_printf_err("using: %s [run] <filename> \n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
init_string_buffer_memory();
|
||||
|
||||
String module_dir = get_module_dir(gb_heap_allocator());
|
||||
// defer (gb_free(gb_heap_allocator(), module_dir.text));
|
||||
|
||||
INIT_TIMER();
|
||||
|
||||
@@ -104,16 +140,11 @@ int main(int argc, char **argv) {
|
||||
|
||||
PRINT_TIMER("Syntax Parser");
|
||||
|
||||
// print_ast(parser.files[0].decls, 0);
|
||||
|
||||
#if 1
|
||||
Checker checker = {};
|
||||
BaseTypeSizes sizes = {};
|
||||
// NOTE(bill): x64
|
||||
sizes.word_size = 8;
|
||||
sizes.max_align = 16;
|
||||
ArchData arch_data = make_arch_data(ArchKind_x64);
|
||||
|
||||
init_checker(&checker, &parser, sizes);
|
||||
init_checker(&checker, &parser, arch_data.sizes);
|
||||
// defer (destroy_checker(&checker));
|
||||
|
||||
check_parsed_files(&checker);
|
||||
@@ -146,14 +177,14 @@ int main(int argc, char **argv) {
|
||||
// For more passes arguments: http://llvm.org/docs/Passes.html
|
||||
exit_code = win32_exec_command_line_app(
|
||||
"%.*sbin/opt %s -o %.*s.bc "
|
||||
"-memcpyopt "
|
||||
"-mem2reg "
|
||||
"-memcpyopt "
|
||||
"-die -dse "
|
||||
"-dce "
|
||||
// "-S "
|
||||
// "-debug-pass=Arguments "
|
||||
"",
|
||||
LIT(module_path),
|
||||
LIT(module_dir),
|
||||
output_name, LIT(output));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
@@ -164,10 +195,11 @@ int main(int argc, char **argv) {
|
||||
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
|
||||
exit_code = win32_exec_command_line_app(
|
||||
"%.*sbin/llc %.*s.bc -filetype=obj -O0 "
|
||||
"-march=x86-64 "
|
||||
"%.*s "
|
||||
"",
|
||||
LIT(module_path),
|
||||
LIT(output));
|
||||
LIT(module_dir),
|
||||
LIT(output),
|
||||
LIT(arch_data.llc_flags));
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
@@ -183,13 +215,14 @@ int main(int argc, char **argv) {
|
||||
" %.*s.lib", LIT(lib));
|
||||
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
||||
}
|
||||
char *linker_flags = "-nologo -DEFAULTLIB:libcmt -machine:x64 -incremental:no -opt:ref -subsystem:console";
|
||||
char *linker_flags =
|
||||
"/nologo /incremental:no /opt:ref /subsystem:console";
|
||||
|
||||
exit_code = win32_exec_command_line_app(
|
||||
"link %.*s.obj -OUT:%.*s.exe %s %s "
|
||||
"link %.*s.obj -OUT:%.*s.exe %s %.*s %s"
|
||||
"",
|
||||
LIT(output), LIT(output),
|
||||
lib_str, linker_flags);
|
||||
lib_str, LIT(arch_data.link_flags), linker_flags);
|
||||
if (exit_code != 0) {
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
+80
-46
@@ -214,6 +214,16 @@ AST_NODE_KIND(_ComplexStmtBegin, "", struct{}) \
|
||||
AstNode *clobber_list; \
|
||||
isize output_count, input_count, clobber_count; \
|
||||
}) \
|
||||
AST_NODE_KIND(PushAllocator, "push_allocator statement", struct { \
|
||||
Token token; \
|
||||
AstNode *expr; \
|
||||
AstNode *body; \
|
||||
}) \
|
||||
AST_NODE_KIND(PushContext, "push_context statement", struct { \
|
||||
Token token; \
|
||||
AstNode *expr; \
|
||||
AstNode *body; \
|
||||
}) \
|
||||
\
|
||||
AST_NODE_KIND(_ComplexStmtEnd, "", struct{}) \
|
||||
AST_NODE_KIND(_StmtEnd, "", struct{}) \
|
||||
@@ -414,6 +424,10 @@ Token ast_node_token(AstNode *node) {
|
||||
return node->UsingStmt.token;
|
||||
case AstNode_AsmStmt:
|
||||
return node->AsmStmt.token;
|
||||
case AstNode_PushAllocator:
|
||||
return node->PushAllocator.token;
|
||||
case AstNode_PushContext:
|
||||
return node->PushContext.token;
|
||||
case AstNode_BadDecl:
|
||||
return node->BadDecl.begin;
|
||||
case AstNode_VarDecl:
|
||||
@@ -765,6 +779,21 @@ gb_inline AstNode *make_asm_stmt(AstFile *f, Token token, b32 is_volatile, Token
|
||||
return result;
|
||||
}
|
||||
|
||||
gb_inline AstNode *make_push_allocator(AstFile *f, Token token, AstNode *expr, AstNode *body) {
|
||||
AstNode *result = make_node(f, AstNode_PushAllocator);
|
||||
result->PushAllocator.token = token;
|
||||
result->PushAllocator.expr = expr;
|
||||
result->PushAllocator.body = body;
|
||||
return result;
|
||||
}
|
||||
|
||||
gb_inline AstNode *make_push_context(AstFile *f, Token token, AstNode *expr, AstNode *body) {
|
||||
AstNode *result = make_node(f, AstNode_PushContext);
|
||||
result->PushContext.token = token;
|
||||
result->PushContext.expr = expr;
|
||||
result->PushContext.body = body;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -996,34 +1025,24 @@ void fix_advance_to_next_stmt(AstFile *f) {
|
||||
}
|
||||
|
||||
b32 expect_semicolon_after_stmt(AstFile *f, AstNode *s) {
|
||||
// if (s != NULL) {
|
||||
// switch (s->kind) {
|
||||
// case AstNode_ProcDecl:
|
||||
// return true;
|
||||
// case AstNode_TypeDecl: {
|
||||
// switch (s->TypeDecl.type->kind) {
|
||||
// case AstNode_StructType:
|
||||
// case AstNode_UnionType:
|
||||
// case AstNode_EnumType:
|
||||
// case AstNode_ProcType:
|
||||
// return true;
|
||||
// }
|
||||
// } break;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!allow_token(f, Token_Semicolon)) {
|
||||
if (f->cursor[0].pos.line == f->cursor[-1].pos.line) {
|
||||
if (f->cursor[0].kind != Token_CloseBrace) {
|
||||
// CLEANUP(bill): Semicolon handling in parser
|
||||
syntax_error(f->cursor[0],
|
||||
"Expected `;` after %.*s, got `%.*s`",
|
||||
LIT(ast_node_strings[s->kind]), LIT(token_strings[f->cursor[0].kind]));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (allow_token(f, Token_Semicolon)) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
if (f->cursor[0].pos.line != f->cursor[-1].pos.line) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (f->cursor[0].kind) {
|
||||
case Token_EOF:
|
||||
case Token_CloseBrace:
|
||||
return true;
|
||||
}
|
||||
|
||||
syntax_error(f->cursor[0],
|
||||
"Expected `;` after %.*s, got `%.*s`",
|
||||
LIT(ast_node_strings[s->kind]), LIT(token_strings[f->cursor[0].kind]));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2593,6 +2612,28 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
return make_using_stmt(f, token, node);
|
||||
} break;
|
||||
|
||||
case Token_push_allocator: {
|
||||
next_token(f);
|
||||
isize prev_level = f->expr_level;
|
||||
f->expr_level = -1;
|
||||
AstNode *expr = parse_expr(f, false);
|
||||
f->expr_level = prev_level;
|
||||
|
||||
AstNode *body = parse_block_stmt(f);
|
||||
return make_push_allocator(f, token, expr, body);
|
||||
} break;
|
||||
|
||||
case Token_push_context: {
|
||||
next_token(f);
|
||||
isize prev_level = f->expr_level;
|
||||
f->expr_level = -1;
|
||||
AstNode *expr = parse_expr(f, false);
|
||||
f->expr_level = prev_level;
|
||||
|
||||
AstNode *body = parse_block_stmt(f);
|
||||
return make_push_context(f, token, expr, body);
|
||||
} break;
|
||||
|
||||
case Token_Hash: {
|
||||
s = parse_tag_stmt(f, NULL);
|
||||
String tag = s->TagStmt.name.string;
|
||||
@@ -2706,10 +2747,8 @@ AstNodeArray parse_stmt_list(AstFile *f) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParseFileError init_ast_file(AstFile *f, String fullpath) {
|
||||
if (!string_has_extension(fullpath, make_string("odin"))) {
|
||||
// gb_printf_err("Only `.odin` files are allowed\n");
|
||||
return ParseFile_WrongExtension;
|
||||
}
|
||||
TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath);
|
||||
@@ -2809,34 +2848,29 @@ String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
|
||||
gb_memcopy(str+i, base_dir.text, base_dir.len); i += base_dir.len;
|
||||
gb_memcopy(str+i, path.text, path.len);
|
||||
str[str_len] = '\0';
|
||||
char *path_str = gb_path_get_full_name(a, cast(char *)str);
|
||||
return make_string(path_str);
|
||||
return path_to_fullpath(a, make_string(str, str_len));
|
||||
}
|
||||
|
||||
String get_fullpath_core(gbAllocator a, String path) {
|
||||
char buf[300] = {};
|
||||
u32 buf_len = GetModuleFileNameA(GetModuleHandleA(NULL), buf, gb_size_of(buf));
|
||||
for (isize i = buf_len-1; i >= 0; i--) {
|
||||
if (buf[i] == '\\' ||
|
||||
buf[i] == '/') {
|
||||
break;
|
||||
}
|
||||
buf_len--;
|
||||
}
|
||||
String module_dir = get_module_dir(gb_heap_allocator());
|
||||
defer (if (module_dir.len > 0) {
|
||||
gb_free(gb_heap_allocator(), module_dir.text);
|
||||
});
|
||||
|
||||
char core[] = "core/";
|
||||
isize core_len = gb_size_of(core)-1;
|
||||
|
||||
isize str_len = buf_len + core_len + path.len;
|
||||
isize str_len = module_dir.len + core_len + path.len;
|
||||
u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
|
||||
defer (gb_free(gb_heap_allocator(), str));
|
||||
|
||||
gb_memcopy(str, buf, buf_len);
|
||||
gb_memcopy(str+buf_len, core, core_len);
|
||||
gb_memcopy(str+buf_len+core_len, path.text, path.len);
|
||||
gb_memcopy(str, module_dir.text, module_dir.len);
|
||||
gb_memcopy(str+module_dir.len, core, core_len);
|
||||
gb_memcopy(str+module_dir.len+core_len, path.text, path.len);
|
||||
str[str_len] = '\0';
|
||||
char *path_str = gb_path_get_full_name(a, cast(char *)str);
|
||||
return make_string(path_str);}
|
||||
|
||||
return path_to_fullpath(a, make_string(str, str_len));
|
||||
}
|
||||
|
||||
// NOTE(bill): Returns true if it's added
|
||||
b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
|
||||
|
||||
+91
-1
@@ -1,13 +1,26 @@
|
||||
gb_global gbArena string_buffer_arena = {};
|
||||
gb_global gbAllocator string_buffer_allocator = {};
|
||||
|
||||
void init_string_buffer_memory() {
|
||||
// NOTE(bill): This should be enough memory for file systems
|
||||
gb_arena_init_from_allocator(&string_buffer_arena, gb_heap_allocator(), gb_megabytes(1));
|
||||
string_buffer_allocator = gb_arena_allocator(&string_buffer_arena);
|
||||
}
|
||||
|
||||
|
||||
// NOTE(bill): Used for UTF-8 strings
|
||||
typedef struct String {
|
||||
u8 *text;
|
||||
u8 * text;
|
||||
isize len;
|
||||
} String;
|
||||
// NOTE(bill): used for printf style arguments
|
||||
#define LIT(x) (x).len, (x).text
|
||||
|
||||
|
||||
typedef struct String16 {
|
||||
wchar_t *text;
|
||||
isize len;
|
||||
} String16;
|
||||
|
||||
|
||||
gb_inline String make_string(u8 *text, isize len) {
|
||||
@@ -20,6 +33,15 @@ gb_inline String make_string(u8 *text, isize len) {
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
gb_inline String16 make_string16(wchar_t *text, isize len) {
|
||||
String16 s;
|
||||
s.text = text;
|
||||
s.len = len;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
gb_inline String make_string(char *text) {
|
||||
return make_string(cast(u8 *)cast(void *)text, gb_strlen(text));
|
||||
}
|
||||
@@ -133,6 +155,74 @@ b32 string_contains_char(String s, u8 c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(bill): Make this non-windows specific
|
||||
String16 string_to_string16(gbAllocator a, String s) {
|
||||
if (s.len < 1) {
|
||||
return make_string16(NULL, 0);
|
||||
}
|
||||
|
||||
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
cast(char *)s.text, s.len, NULL, 0);
|
||||
if (len == 0) {
|
||||
return make_string16(NULL, 0);
|
||||
}
|
||||
|
||||
wchar_t *text = gb_alloc_array(a, wchar_t, len+1);
|
||||
|
||||
int len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
cast(char *)s.text, s.len, text, len);
|
||||
if (len1 == 0) {
|
||||
gb_free(a, text);
|
||||
return make_string16(NULL, 0);
|
||||
}
|
||||
text[len] = 0;
|
||||
|
||||
return make_string16(text, len-1);
|
||||
}
|
||||
|
||||
String string16_to_string(gbAllocator a, String16 s) {
|
||||
if (s.len < 1) {
|
||||
return make_string(NULL, 0);
|
||||
}
|
||||
|
||||
int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||
s.text, s.len, NULL, 0,
|
||||
NULL, NULL);
|
||||
if (len == 0) {
|
||||
return make_string(NULL, 0);
|
||||
}
|
||||
|
||||
u8 *text = gb_alloc_array(a, u8, len+1);
|
||||
|
||||
int len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||
s.text, s.len, cast(char *)text, len,
|
||||
NULL, NULL);
|
||||
if (len1 == 0) {
|
||||
gb_free(a, text);
|
||||
return make_string(NULL, 0);
|
||||
}
|
||||
text[len] = 0;
|
||||
|
||||
return make_string(text, len-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
b32 unquote_char(String s, u8 quote, Rune *rune, b32 *multiple_bytes, String *tail_string) {
|
||||
if (s.text[0] == quote &&
|
||||
(quote == '$' || quote == '"')) {
|
||||
|
||||
+25
-23
@@ -82,29 +82,31 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
|
||||
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
||||
\
|
||||
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_type, "type"), \
|
||||
TOKEN_KIND(Token_proc, "proc"), \
|
||||
TOKEN_KIND(Token_match, "match"), \
|
||||
TOKEN_KIND(Token_break, "break"), \
|
||||
TOKEN_KIND(Token_continue, "continue"), \
|
||||
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
|
||||
TOKEN_KIND(Token_case, "case"), \
|
||||
TOKEN_KIND(Token_default, "default"), \
|
||||
TOKEN_KIND(Token_then, "then"), \
|
||||
TOKEN_KIND(Token_if, "if"), \
|
||||
TOKEN_KIND(Token_else, "else"), \
|
||||
TOKEN_KIND(Token_for, "for"), \
|
||||
TOKEN_KIND(Token_range, "range"), \
|
||||
TOKEN_KIND(Token_defer, "defer"), \
|
||||
TOKEN_KIND(Token_return, "return"), \
|
||||
TOKEN_KIND(Token_struct, "struct"), \
|
||||
TOKEN_KIND(Token_union, "union"), \
|
||||
TOKEN_KIND(Token_raw_union, "raw_union"), \
|
||||
TOKEN_KIND(Token_enum, "enum"), \
|
||||
TOKEN_KIND(Token_using, "using"), \
|
||||
TOKEN_KIND(Token_asm, "asm"), \
|
||||
TOKEN_KIND(Token_volatile, "volatile"), \
|
||||
TOKEN_KIND(Token_atomic, "atomic"), \
|
||||
TOKEN_KIND(Token_type, "type"), \
|
||||
TOKEN_KIND(Token_proc, "proc"), \
|
||||
TOKEN_KIND(Token_match, "match"), \
|
||||
TOKEN_KIND(Token_break, "break"), \
|
||||
TOKEN_KIND(Token_continue, "continue"), \
|
||||
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
|
||||
TOKEN_KIND(Token_case, "case"), \
|
||||
TOKEN_KIND(Token_default, "default"), \
|
||||
TOKEN_KIND(Token_then, "then"), \
|
||||
TOKEN_KIND(Token_if, "if"), \
|
||||
TOKEN_KIND(Token_else, "else"), \
|
||||
TOKEN_KIND(Token_for, "for"), \
|
||||
TOKEN_KIND(Token_range, "range"), \
|
||||
TOKEN_KIND(Token_defer, "defer"), \
|
||||
TOKEN_KIND(Token_return, "return"), \
|
||||
TOKEN_KIND(Token_struct, "struct"), \
|
||||
TOKEN_KIND(Token_union, "union"), \
|
||||
TOKEN_KIND(Token_raw_union, "raw_union"), \
|
||||
TOKEN_KIND(Token_enum, "enum"), \
|
||||
TOKEN_KIND(Token_using, "using"), \
|
||||
TOKEN_KIND(Token_asm, "asm"), \
|
||||
TOKEN_KIND(Token_volatile, "volatile"), \
|
||||
TOKEN_KIND(Token_atomic, "atomic"), \
|
||||
TOKEN_KIND(Token_push_allocator, "push_allocator"), \
|
||||
TOKEN_KIND(Token_push_context, "push_context"), \
|
||||
TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \
|
||||
TOKEN_KIND(Token_Count, "")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user