lots of code refactoring; added #context_scope; struct literals are even better
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 15 Dec 2020 19:40:20 +0000 (13:40 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 15 Dec 2020 19:40:20 +0000 (13:40 -0600)
13 files changed:
core/builtin.onyx
core/conv.onyx [new file with mode: 0644]
core/js/webgl.onyx
core/std/js.onyx
core/std/wasi.onyx
core/stdio.onyx
core/string.onyx
core/string/builder.onyx [new file with mode: 0644]
include/onyxastnodes.h
onyx
src/onyxbuiltins.c
src/onyxparser.c
src/onyxsymres.c

index 6ac95cb6b226eac315ed3965f3a0b979e6960dfb..de79b9734005ebbc03dfd3ea588939b0c9f17f90 100644 (file)
@@ -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 (file)
index 0000000..3402baa
--- /dev/null
@@ -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 };
+}
index e89a9761e403f36759e3e86375e37bd276bc7d58..39d9a4cc8d8f040fa016ddc892553cf862ccd6ba 100644 (file)
@@ -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" ---
index 5efe76ba81064f3c6188e15ee3085bf211419474..459ea86b03bc87ab25573718bd3db165c08b3ea7 100644 (file)
@@ -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"
index 28c5027435520da39851f11e2904c653ad76a8ca..2a19f1d9af4149a02b2c4d251542a1b3a4543084 100644 (file)
@@ -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"
 
index 54d7863a2fff8ba04cc3bbe1d8be97f4a2fac279..c48ffb2fb26eb8b31d5c2d092fc4e53cd2c7f679 100644 (file)
@@ -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();
 }
 
index 571725f9540dd63ceb39b2014c0ebe58f4b531a3..9acd216383e973a71de4fada49f93b28e5416944 100644 (file)
@@ -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 (file)
index 0000000..37372e1
--- /dev/null
@@ -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 };
+}
+
index a4418ca0f1e53befe6a784f2a7e3464eb6252d06..ae3c5bf642b1a2e95b07d2398ba34cbd17b57464 100644 (file)
@@ -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 a58312a8a47ec515e1b61b5916f6802868a0c7fe..94c832ab05734d7bc5c97efd80903e7982e9517c 100755 (executable)
Binary files a/onyx and b/onyx differ
index a47a330edf035a4f5dc411dd9db694a2423a9dea..54b2553f5387287631b2651fad2b4ff51dfb0504 100644 (file)
@@ -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);
index 35857d95af2c127937c2e76180e1c6abd7533d61..e347af2786b4d3544ca402965e2ec369b72ccc26 100644 (file)
@@ -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;
     }
index 832e3de50af5b6c4fa507a8a122cf8c3d4ec6cf7..8c952926b0cebc898b4b3249cdb36c4d63c803db 100644 (file)
@@ -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) {