From: Brendan Hansen Date: Tue, 15 Dec 2020 19:40:20 +0000 (-0600) Subject: lots of code refactoring; added #context_scope; struct literals are even better X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=d3b0e3eb327818209281f4ff6c993e8e6d20ffb7;p=onyx.git lots of code refactoring; added #context_scope; struct literals are even better --- diff --git a/core/builtin.onyx b/core/builtin.onyx index 6ac95cb6..de79b973 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -3,9 +3,6 @@ package builtin str :: #type []u8; cstr :: #type ^u8; -// CLEANUP: Remove the buffer type from builtin -Buffer :: #type []void; - // NOTE: Because of many implementation details, all fields of this // struct are required to be i32's. range :: struct { @@ -68,6 +65,6 @@ cmp_asc :: proc (a: $T, b: T) -> i32 do return cast(i32) (a - b); cmp_dec :: proc (a: $T, b: T) -> i32 do return cast(i32) (b - a); context : struct { - allocator : Allocator; - temp_allocator : Allocator; + allocator : Allocator; + temp_allocator : Allocator; } diff --git a/core/conv.onyx b/core/conv.onyx new file mode 100644 index 00000000..3402baae --- /dev/null +++ b/core/conv.onyx @@ -0,0 +1,190 @@ +package core.conv + +i64_to_str :: proc (n_: i64, base: u64, buf: [] u8) -> str { + n := cast(u64) n_; + + is_neg := false; + if n_ < 0 && base == 10 { + is_neg = true; + n = cast(u64) -n_; + } + + c := ^buf[buf.count - 1]; + len := 0; + + s :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; + + while n > 0 { + m :: n % base; + + *c = s[cast(u32) m]; + len += 1; + c -= 1; + + n /= base; + + } else { + *c = #char "0"; + len += 1; + c -= 1; + } + + if base == 16 { + *c = #char "x"; + len += 1; + c -= 1; + *c = #char "0"; + len += 1; + c -= 1; + } + + if base == 2 { + *c = #char "b"; + len += 1; + c -= 1; + *c = #char "0"; + len += 1; + c -= 1; + } + + if is_neg { + *c = #char "-"; + len += 1; + c -= 1; + } + + return str.{ data = c + 1, count = len }; +} + +// NOTE: This is a big hack but it will work for now +f64_to_str :: proc (f: f64, buf: [] u8) -> str { + a := f; + a *= 10000.0; + v := cast(i64) a; + + len := 0; + + s1 := i64_to_str(v / 10000, 10, buf); + for i: 0 .. s1.count do buf.data[i] = s1.data[i]; + buf.data[s1.count] = #char "."; + len = s1.count + 1; + + if v < ~~0 do v = -v; + s2 := i64_to_str(v % 10000, 10, buf); + for i: 0 .. s2.count do buf.data[s1.count + 1 + i] = s2.data[i]; + len += s2.count; + + return str.{ buf.data, len }; +} + +str_format :: proc (format: str, buffer: [] u8, va: ...) -> str { + return str_format_va(format, buffer, va); +} + +str_format_va :: proc (format: str, buffer: [] u8, va: vararg) -> str { + len := 0; + state := 0; + + for ch: format do switch (state) { + case 0 { + if ch == #char "%" do state = 1; + else { + buffer[len] = ch; + len += 1; + } + } + + case #default { + switch (ch) { + case #char "%" { buffer[len] = ch; len += 1; } + + case #char "i" { + n : i32; + if !vararg_get(va, ^n) do return; + + ibuf : [128] u8; + istr := i64_to_str(~~n, 10, ibuf[0 .. 128]); + + for a: istr { + buffer[len] = a; + len += 1; + } + } + + case #char "l" { + n : i64; + if !vararg_get(va, ^n) do return; + + ibuf : [128] u8; + istr := i64_to_str(n, 10, ibuf[0 .. 128]); + + for a: istr { + buffer[len] = a; + len += 1; + } + } + + case #char "f" { + n : f32; + if !vararg_get(va, ^n) do return; + + fbuf : [128] u8; + fstr := f64_to_str(~~n, fbuf[0 .. 128]); + + for a: fstr { + buffer[len] = a; + len += 1; + } + } + + case #char "d" { + n : f64; + if !vararg_get(va, ^n) do return; + + fbuf : [128] u8; + fstr := f64_to_str(n, fbuf[0 .. 128]); + + for a: fstr { + buffer[len] = a; + len += 1; + } + } + + case #char "s" { + s : str; + if !vararg_get(va, ^s) do return; + + for a: s { + buffer[len] = a; + len += 1; + } + } + + case #char "p" { + n : rawptr; + if !vararg_get(va, ^n) do return; + + ibuf : [128] u8; + istr := i64_to_str(~~n, 16, ibuf[0 .. 128]); + + for a: istr { + buffer[len] = a; + len += 1; + } + } + + case #char "c" { + c : u8; + if !vararg_get(va, ^c) do return; + + buffer[len] = c; + len += 1; + } + } + + state = 0; + } + } + + return str.{ ~~buffer.data, len }; +} diff --git a/core/js/webgl.onyx b/core/js/webgl.onyx index e89a9761..39d9a4cc 100644 --- a/core/js/webgl.onyx +++ b/core/js/webgl.onyx @@ -736,10 +736,10 @@ blendEquationSeparate :: proc (modeRGB: GLenum, modeAlpha: GLenum) #for blendFunc :: proc (sfactor: GLenum, dfactor: GLenum) #foreign "gl" "blendFunc" --- blendFuncSeparate :: proc (srcRGB: GLenum, dstRGB: GLenum, srcAlpha: GLenum, dstAlpha: GLenum) #foreign "gl" "blendFuncSeparate" --- blitFramebuffer :: proc (sx0: GLint, sy0: GLint, sx1: GLint, sy1: GLint, dx0: GLint, dy0: GLint, dx1: GLint, dy1: GLint, mask: GLbitfield, filter: GLenum) #foreign "gl" "blitFramebuffer" --- -bufferDataWithData :: proc (target: GLenum, buffer: Buffer, usage: GLenum) #foreign "gl" "bufferDataWithData" --- +bufferDataWithData :: proc (target: GLenum, buffer: [] void, usage: GLenum) #foreign "gl" "bufferDataWithData" --- bufferDataNoData :: proc (target: GLenum, size: GLsizeiptr, usage: GLenum) #foreign "gl" "bufferDataNoData" --- bufferData :: proc { bufferDataWithData, bufferDataNoData } -bufferSubData :: proc (target: GLenum, offset: GLsizei, data: Buffer) #foreign "gl" "bufferSubData" --- +bufferSubData :: proc (target: GLenum, offset: GLsizei, data: [] void) #foreign "gl" "bufferSubData" --- canvasSize :: proc (width: GLsizei, height: GLsizei) #foreign "gl" "canvasSize" --- checkFrameBufferStatus :: proc (target: GLenum) -> GLenum #foreign "gl" "checkFrameBufferStatus" --- clear :: proc (mask: GLbitfield) #foreign "gl" "clear" --- diff --git a/core/std/js.onyx b/core/std/js.onyx index 5efe76ba..459ea86b 100644 --- a/core/std/js.onyx +++ b/core/std/js.onyx @@ -4,6 +4,7 @@ package core #include_file "core/alloc" #include_file "core/array" +#include_file "core/conv" #include_file "core/intrinsics" #include_file "core/map" #include_file "core/math" @@ -11,6 +12,7 @@ package core #include_file "core/random" #include_file "core/stdio" #include_file "core/string" +#include_file "core/string/builder" #include_file "core/string/reader" #include_file "core/sys/js" diff --git a/core/std/wasi.onyx b/core/std/wasi.onyx index 28c50274..2a19f1d9 100644 --- a/core/std/wasi.onyx +++ b/core/std/wasi.onyx @@ -4,6 +4,7 @@ package core #include_file "core/alloc" #include_file "core/array" +#include_file "core/conv" #include_file "core/file" #include_file "core/intrinsics" #include_file "core/map" @@ -12,6 +13,7 @@ package core #include_file "core/random" #include_file "core/stdio" #include_file "core/string" +#include_file "core/string/builder" #include_file "core/string/reader" #include_file "core/wasi" diff --git a/core/stdio.onyx b/core/stdio.onyx index 54d7863a..c48ffb2f 100644 --- a/core/stdio.onyx +++ b/core/stdio.onyx @@ -4,24 +4,24 @@ package core // of the system package use package system as system -#private_file print_buffer : string.StringBuilder; +#private_file print_buffer : string.builder.Builder; stdio_init :: proc () { - print_buffer = string.builder_make(2048); + print_buffer = string.builder.make(2048); } print_str :: proc (s: str) { - string.builder_append(^print_buffer, s); + string.builder.append(^print_buffer, s); if s.data[s.count - 1] == #char "\n" do print_buffer_flush(); } -print_cstr :: proc (s: cstr) do string.builder_append(^print_buffer, s); -print_i64 :: proc (n: i64, base: u64 = 10) do string.builder_append(^print_buffer, n, base); -print_i32 :: proc (n: i32, base: u32 = 10) do string.builder_append(^print_buffer, cast(i64) n, cast(u64) base); -print_f64 :: proc (n: f64) do string.builder_append(^print_buffer, n); -print_f32 :: proc (n: f32) do string.builder_append(^print_buffer, cast(f64) n); -print_bool :: proc (b: bool) do string.builder_append(^print_buffer, b); -print_ptr :: proc (p: ^void) do string.builder_append(^print_buffer, cast(i64) p, cast(u64) 16); +print_cstr :: proc (s: cstr) do string.builder.append(^print_buffer, s); +print_i64 :: proc (n: i64, base: u64 = 10) do string.builder.append(^print_buffer, n, base); +print_i32 :: proc (n: i32, base: u32 = 10) do string.builder.append(^print_buffer, cast(i64) n, cast(u64) base); +print_f64 :: proc (n: f64) do string.builder.append(^print_buffer, n); +print_f32 :: proc (n: f32) do string.builder.append(^print_buffer, cast(f64) n); +print_bool :: proc (b: bool) do string.builder.append(^print_buffer, b); +print_ptr :: proc (p: ^void) do string.builder.append(^print_buffer, cast(i64) p, cast(u64) 16); print_range :: proc (r: range, sep := " ") { for i: r { @@ -46,111 +46,7 @@ println :: proc (x: $T) { printf :: proc (format: str, va: ...) { buffer: [2048] u8; - len := 0; - - state := 0; - for ch: format do switch (state) { - case 0 { - if ch == #char "%" do state = 1; - else { - buffer[len] = ch; - len += 1; - } - } - - case #default { - switch (ch) { - case #char "%" { buffer[len] = ch; len += 1; } - - case #char "i" { - n : i32; - if !vararg_get(va, ^n) do return; - - ibuf : [128] u8; - istr := string.i64_to_str(~~n, 10, Buffer.{ ~~ibuf, 128 }); - - for a: istr { - buffer[len] = a; - len += 1; - } - } - - case #char "l" { - n : i64; - if !vararg_get(va, ^n) do return; - - ibuf : [128] u8; - istr := string.i64_to_str(n, 10, Buffer.{ ~~ibuf, 128 }); - - for a: istr { - buffer[len] = a; - len += 1; - } - } - - case #char "f" { - n : f32; - if !vararg_get(va, ^n) do return; - - fbuf : [128] u8; - fstr := string.f64_to_str(~~n, fbuf[0 .. 128]); - - for a: fstr { - buffer[len] = a; - len += 1; - } - } - - case #char "d" { - n : f64; - if !vararg_get(va, ^n) do return; - - fbuf : [128] u8; - fstr := string.f64_to_str(n, fbuf[0 .. 128]); - - for a: fstr { - buffer[len] = a; - len += 1; - } - } - - case #char "s" { - s : str; - if !vararg_get(va, ^s) do return; - - for a: s { - buffer[len] = a; - len += 1; - } - } - - case #char "p" { - n : rawptr; - if !vararg_get(va, ^n) do return; - - ibuf : [128] u8; - istr := string.i64_to_str(~~n, 16, Buffer.{ ~~ibuf, 128 }); - - for a: istr { - buffer[len] = a; - len += 1; - } - } - - case #char "c" { - c : u8; - if !vararg_get(va, ^c) do return; - - buffer[len] = c; - len += 1; - } - } - - state = 0; - } - } - - print(str.{ ~~buffer, len }); + print(conv.str_format_va(format, buffer[0 .. 2048], va)); } // This works on both slices and arrays @@ -164,12 +60,12 @@ print_array :: proc (arr: $T, sep := " ") { } print_buffer_flush :: proc () { - if print_buffer.len == 0 do return; + if print_buffer.data.count == 0 do return; ^print_buffer - |> string.builder_to_str() + |> string.builder.to_str() |> system.output_str(); - ^print_buffer |> string.builder_clear(); + ^print_buffer |> string.builder.clear(); } diff --git a/core/string.onyx b/core/string.onyx index 571725f9..9acd2163 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -143,178 +143,6 @@ strip_trailing_whitespace :: proc (s: ^str) { } - - -// -// String Builder -// -StringBuilder :: struct { - alloc : Allocator; - - data : ^u8 = null; - len : u32 = 0; - cap : u32 = 0; -} - -builder_make :: proc (initial_cap: u32) -> StringBuilder { - data: ^u8 = null; - - if initial_cap > 0 { - data = cast(^u8) calloc(initial_cap); - } - - return StringBuilder.{ - alloc = context.allocator, - data = data, - cap = initial_cap, - }; -} - -builder_add_str :: proc (use sb: ^StringBuilder, s: str) -> ^StringBuilder { - len_total :: len + s.count; - - if cap >= len_total { - for i: 0 .. s.count do data[len + i] = s[i]; - len += s.count; - return sb; - } - - new_cap := cap; - while new_cap < len_total do new_cap <<= 1; - - new_data := cast(^u8) resize(alloc, data, new_cap); - if new_data == null do return sb; - - data = new_data; - cap = new_cap; - - for i: 0 .. s.count do data[len + i] = s[i]; - len += s.count; - return sb; -} - -builder_add_cstr :: proc (use sb: ^StringBuilder, cstring: cstr) -> ^StringBuilder { - s := make(cstring); - return builder_add_str(sb, s); -} - -i64_to_str :: proc (n_: i64, base: u64, buf: Buffer) -> str { - n := cast(u64) n_; - - is_neg := false; - if n_ < 0 && base == 10 { - is_neg = true; - n = cast(u64) -n_; - } - - c := ^(cast(^u8) buf.data)[buf.count - 1]; - len := 0; - - s :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; - - while n > 0 { - m :: n % base; - - *c = s[cast(u32) m]; - len += 1; - c -= 1; - - n /= base; - - } else { - *c = #char "0"; - len += 1; - c -= 1; - } - - if base == 16 { - *c = #char "x"; - len += 1; - c -= 1; - *c = #char "0"; - len += 1; - c -= 1; - } - - if base == 2 { - *c = #char "b"; - len += 1; - c -= 1; - *c = #char "0"; - len += 1; - c -= 1; - } - - if is_neg { - *c = #char "-"; - len += 1; - c -= 1; - } - - return str.{ data = c + 1, count = len }; -} - -// NOTE: This is a big hack but it will work for now -f64_to_str :: proc (f: f64, buf: [] u8) -> str { - a := f; - a *= 10000.0; - v := cast(i64) a; - - b := Buffer.{ cast(^void) buf.data, buf.count }; - len := 0; - - s1 := i64_to_str(v / 10000, 10, b); - for i: 0 .. s1.count do buf.data[i] = s1.data[i]; - buf.data[s1.count] = #char "."; - len = s1.count + 1; - - if v < ~~0 do v = -v; - s2 := i64_to_str(v % 10000, 10, b); - for i: 0 .. s2.count do buf.data[s1.count + 1 + i] = s2.data[i]; - len += s2.count; - - return str.{ buf.data, len }; -} - -builder_add_i64 :: proc (use sb: ^StringBuilder, n: i64, base: u64 = 10) -> ^StringBuilder { - buf : [256] u8; - s := i64_to_str(n, base, Buffer.{ cast(^void) buf, 256 }); - return builder_add_str(sb, s); -} - -builder_add_f64 :: proc (use sb: ^StringBuilder, f: f64) -> ^StringBuilder { - buf : [256] u8; - s := f64_to_str(f, buf[0 .. 256]); - return builder_add_str(sb, s); -} - -builder_add_bool :: proc (use sb: ^StringBuilder, b: bool) -> ^StringBuilder { - if b { - return builder_add_str(sb, "true"); - } else { - return builder_add_str(sb, "false"); - } - - return null; -} - -builder_append :: proc { - builder_add_str, - builder_add_cstr, - builder_add_i64, - builder_add_f64, - builder_add_bool, -} - -builder_to_str :: proc (use sb: ^StringBuilder) -> str { - return str.{ data, len }; -} - -builder_clear :: proc (use sb: ^StringBuilder) -> ^StringBuilder { - len = 0; - return sb; -} - read_u32 :: proc (s: ^str, out: ^u32) { n := 0; diff --git a/core/string/builder.onyx b/core/string/builder.onyx new file mode 100644 index 00000000..37372e1a --- /dev/null +++ b/core/string/builder.onyx @@ -0,0 +1,77 @@ +package core.string.builder + +use package core.array as array +use package core.string as string +use package core.conv as conv + +Builder :: struct { + alloc : Allocator; + data : [..] u8; +} + +make :: proc (initial_cap := 4, alloc := context.allocator) -> Builder { + builder : Builder; + builder.alloc = alloc; + + #context_scope { + context.allocator = alloc; + array.init(^builder.data, initial_cap); + } + + return builder; +} + +clear :: proc (use sb: ^Builder) -> ^Builder { + data.count = 0; + return sb; +} + +add_str :: proc (use sb: ^Builder, s: str) -> ^Builder { + len_total :: data.count + s.count; + + if data.capacity < len_total do #context_scope { + context.allocator = alloc; + array.ensure_capacity(^data, len_total); + } + + for i: 0 .. s.count do data[data.count + i] = s[i]; + data.count += s.count; + return sb; +} + +add_cstr :: proc (use sb: ^Builder, cstring: cstr) -> ^Builder { + s := string.make(cstring); + return add_str(sb, s); +} + +add_i64 :: proc (use sb: ^Builder, n: i64, base: u64 = 10) -> ^Builder { + buf : [256] u8; + s := conv.i64_to_str(n, base, buf[0 .. 256]); + return add_str(sb, s); +} + +add_f64 :: proc (use sb: ^Builder, f: f64) -> ^Builder { + buf : [256] u8; + s := conv.f64_to_str(f, buf[0 .. 256]); + return add_str(sb, s); +} + +add_bool :: proc (use sb: ^Builder, b: bool) -> ^Builder { + if b do return add_str(sb, "true"); + else do return add_str(sb, "false"); + + return sb; +} + +append :: proc { + add_str, + add_cstr, + add_i64, + add_f64, + add_bool, +} + +to_str :: proc (use sb: ^Builder) -> str { + return str.{ data.data, data.count }; +} + diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index a4418ca0..ae3c5bf6 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -818,6 +818,7 @@ extern AstType *builtin_range_type; extern Type *builtin_range_type_type; extern AstType *builtin_vararg_type; extern Type *builtin_vararg_type_type; +extern AstTyped *builtin_context_variable; typedef struct BuiltinSymbol { char* package; diff --git a/onyx b/onyx index a58312a8..94c832ab 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyxbuiltins.c b/src/onyxbuiltins.c index a47a330e..54b2553f 100644 --- a/src/onyxbuiltins.c +++ b/src/onyxbuiltins.c @@ -43,6 +43,7 @@ AstType *builtin_range_type; Type *builtin_range_type_type; AstType *builtin_vararg_type; Type *builtin_vararg_type_type; +AstTyped *builtin_context_variable; const BuiltinSymbol builtin_symbols[] = { { NULL, "void", (AstNode *) &basic_type_void }, @@ -357,6 +358,11 @@ void initialize_builtins(bh_allocator a, ProgramInfo* prog) { return; } + builtin_context_variable = (AstTyped *) symbol_raw_resolve(p->scope, "context"); + if (builtin_context_variable == NULL) { + onyx_report_error((OnyxFilePos) { 0 }, "'context' variable not found in builtin package."); + return; + } bh_table_init(global_heap_allocator, intrinsic_table, 128); diff --git a/src/onyxparser.c b/src/onyxparser.c index 35857d95..e347af27 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -24,7 +24,7 @@ static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type); static AstNumLit* parse_int_literal(OnyxParser* parser); static AstNumLit* parse_float_literal(OnyxParser* parser); -static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret); +static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret); static AstTyped* parse_factor(OnyxParser* parser); static AstTyped* parse_expression(OnyxParser* parser); static AstIfWhile* parse_if_stmt(OnyxParser* parser); @@ -187,48 +187,13 @@ static AstNumLit* parse_float_literal(OnyxParser* parser) { return float_node; } -static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret) { - if (parser->curr->type != Token_Type_Symbol) return 0; - - STORE_PARSER_STATE; - - bh_arr(OnyxToken *) syms = NULL; - bh_arr_new(global_heap_allocator, syms, 4); - - b32 success = 1; - while (parser->curr->type == Token_Type_Symbol) { - if (parser->hit_unexpected_token) break; - - OnyxToken* symbol = soft_expect_token(parser, Token_Type_Symbol); - bh_arr_push(syms, symbol); - - if (!soft_expect_token(parser, '.')) { - success = 0; - break; - } - } - - if (parser->curr->type != '{') success = 0; - - if (!success) { - bh_arr_free(syms); - RESTORE_PARSER_STATE; - return 0; - } +static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret) { + if (parser->curr->type != '.' + || (parser->curr + 1)->type != '{') return 0; AstStructLiteral* sl = make_node(AstStructLiteral, Ast_Kind_Struct_Literal); sl->token = parser->curr; - - sl->stnode = make_node(AstTyped, Ast_Kind_Symbol); - sl->stnode->token = syms[0]; - - for (i32 i = 1; i < bh_arr_length(syms); i++) { - AstFieldAccess* fa = make_node(AstFieldAccess, Ast_Kind_Field_Access); - fa->token = syms[i]; - fa->expr = sl->stnode; - sl->stnode = (AstTyped *) fa; - } - bh_arr_free(syms); + sl->stnode = left; bh_arr_new(global_heap_allocator, sl->values, 4); bh_arr_new(global_heap_allocator, sl->named_values, 4); @@ -237,6 +202,7 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret) { sl->named_values[i] = NULL; } + expect_token(parser, '.'); expect_token(parser, '{'); b32 is_named = ((parser->curr + 1)->type == '='); @@ -389,8 +355,6 @@ static AstTyped* parse_factor(OnyxParser* parser) { } case Token_Type_Symbol: { - if (parse_possible_struct_literal(parser, &retval)) return retval; - OnyxToken* sym_token = expect_token(parser, Token_Type_Symbol); AstTyped* sym_node = make_node(AstTyped, Ast_Kind_Symbol); sym_node->token = sym_token; @@ -532,6 +496,12 @@ static AstTyped* parse_factor(OnyxParser* parser) { retval = (AstTyped *) char_lit; break; } + else if (parse_possible_directive(parser, "type")) { + AstTypeAlias* alias = make_node(AstTypeAlias, Ast_Kind_Type_Alias); + alias->to = parse_type(parser); + retval = (AstTyped *) alias; + break; + } onyx_report_error(parser->curr->pos, "invalid directive in expression."); return NULL; @@ -563,6 +533,8 @@ static AstTyped* parse_factor(OnyxParser* parser) { } case '.': { + if (parse_possible_struct_literal(parser, retval, &retval)) return retval; + consume_token(parser); AstFieldAccess* field = make_node(AstFieldAccess, Ast_Kind_Field_Access); field->token = expect_token(parser, Token_Type_Symbol); @@ -1238,6 +1210,32 @@ static AstNode* parse_statement(OnyxParser* parser) { break; } + case '#': { + if (parse_possible_directive(parser, "context_scope")) { + AstLocal* context_tmp = make_node(AstLocal, Ast_Kind_Local); + context_tmp->type_node = builtin_context_variable->type_node; + + AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op); + assignment->operation = Binary_Op_Assign; + assignment->left = (AstTyped *) context_tmp; + assignment->right = builtin_context_variable; + context_tmp->next = (AstNode *) assignment; + + AstBlock* context_block = parse_block(parser); + needs_semicolon = 0; + assignment->next = (AstNode *) context_block; + + AstBinaryOp* assignment2 = make_node(AstBinaryOp, Ast_Kind_Binary_Op); + assignment2->operation = Binary_Op_Assign; + assignment2->left = builtin_context_variable; + assignment2->right = (AstTyped *) context_tmp; + context_block->next = (AstNode *) assignment2; + + retval = (AstNode *) context_tmp; + break; + } + } + default: break; } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 832e3de5..8c952926 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -201,7 +201,8 @@ static void symres_local(AstLocal** local) { bh_arr_push(bh_arr_last(semstate.block_stack)->locals, *local); bh_arr_push(semstate.curr_function->locals, *local); - symbol_introduce(semstate.curr_scope, (*local)->token, (AstNode *) *local); + if ((*local)->token != NULL) + symbol_introduce(semstate.curr_scope, (*local)->token, (AstNode *) *local); } static void symres_call(AstCall* call) {