From 1ec9f7a2d1a0ffd4d5b9b340bc3945b92118d658 Mon Sep 17 00:00:00 2001 From: zongor Date: Sun, 21 Jun 2026 13:10:30 -0700 Subject: [PATCH] wip more array defs --- common.h | 4 +- compiler.c | 113 ++++++++++++++++++++++++++--------------- docs/SPECIFICATION.org | 81 +++++++++++++++-------------- libc.c | 78 ++++++++++++++++++++++++++++ libc.h | 6 ++- test/array.ul | 15 +++--- test/mat-search.ul | 8 +-- test/paint.ul | 2 +- 8 files changed, 209 insertions(+), 98 deletions(-) diff --git a/common.h b/common.h index 29fea62..a730416 100644 --- a/common.h +++ b/common.h @@ -38,8 +38,8 @@ struct symbol_s { u32 ref; /* either constant value or pointer to other thing */ u32 size; /* either size of the plex or length of the array/list/etc. */ u32 scope; /* scope ref */ - List *args; /* function params or plex constructor args */ - List *fields; /* either plex variable fields, or method signatures */ + List *args; /* function params or plex constructor args or array dimensions */ + List *fields; /* either plex variable fields, or method signatures or array strides */ }; void *node_value(Node *n); diff --git a/compiler.c b/compiler.c index 3f768e6..e66e3b3 100644 --- a/compiler.c +++ b/compiler.c @@ -2,6 +2,7 @@ #include "common.h" #include "emit.h" #include "lexer.h" +#include "libc.h" #include "list.h" Emitter emitter = {0}; @@ -257,6 +258,67 @@ define_function() fn->size = size; } +void +calculate_strides(List *dims, List *strides) +{ + u32 *num; + u32 i; + u32 num_dims = dims->count; + u32 current_stride = 1; + + if (num_dims == 1) { + List_push(arena, strides, ¤t_stride, sizeof(u32)); + return; + } + + for(i = num_dims - 1; i > 0; i--) { + List_push(arena, strides, ¤t_stride, sizeof(u32)); + + /* this is very slow but for small numbers of dimensions its fine */ + num = (u32*)List_get(dims, i); + if (num){ + current_stride *= (*num); + } else { + emitter.error("Tried to get a dimension that did not exist", 43, parser.previous.line); + } + } +} + +void +define_array() +{ + i32 size = 0, n = 0, flat_array_length = 1; + TokenType tt = parser.previous.type; + SymbolType st = token_type_to_sym_type(tt); + Symbol *array; + + List *dims = List_init(arena); + List *strides = List_init(arena); + advance(); + + while(!match(TOKEN_RBRACKET)) { + if(parser.current.type == TOKEN_LITERAL_INT) { + n = ston(parser.current.start, parser.current.length); + flat_array_length *= n; + List_push(arena, dims, &n, sizeof(u32)); + } + advance(); + if(check(TOKEN_LBRACKET)) break; + if(check(TOKEN_COMMA)) { + /* it is a multidimensional array */ + } + } + + size = emitter.get_size(st) * flat_array_length; + + array = scope_add_symbol(parser.current.start, parser.current.length, + SYMBOL_ARRAY, size); + array->secondary_type = st; + calculate_strides(dims, strides); + array->args = dims; + array->fields = strides; +} + void build_symbol_table(char *source) { @@ -276,6 +338,12 @@ build_symbol_table(char *source) define_plex(); } else if(match(TOKEN_KEYWORD_TRAIT)) { define_trait(); + } else if (parser.current.type >= TOKEN_TYPE_I8 && + parser.current.type <= TOKEN_TYPE_PTR) { + advance(); + if (check(TOKEN_LBRACKET)) { + define_array(); + } } else { /* in binary bytecode output mode we need to count the bytes here */ /* otherwise ignore everything */ @@ -291,29 +359,6 @@ ParseRule *get_rule(TokenType type); void parse_precedence(Precedence precedence); -void -calculate_strides(i32 *dims, i32 num_dims, i32 *out_strides) -{ - i32 i; - i32 current_stride = 1; - - for(i = num_dims - 1; i >= 0; i--) { - out_strides[i] = current_stride; - current_stride *= dims[i]; - } -} - -void -define_array() -{ - /* example - i32 dims[3] = {3, 3, 3}; - i32 strides[3]; - - calculate_strides(dims, 3, strides); - */ -} - u32 variable_declaration(Symbol *def) { @@ -322,33 +367,17 @@ variable_declaration(Symbol *def) SymbolType st = token_type_to_sym_type(tt); Symbol *variable; - bool is_array = false; - i32 current_stride = 1; - List *strides; - - if(parser.current.type == TOKEN_LBRACE) { - is_array = true; - strides = List_init(arena); - + if (parser.current.type == TOKEN_LBRACE) { while(!check(TOKEN_RBRACKET)) { - if(parser.previous.type == TOKEN_LITERAL_NAT) { - /* consume dimension if exists */ - } advance(); - if(check(TOKEN_LBRACKET)) break; - advance(); - if(check(TOKEN_COMMA)) { - /* it is a multidimensional array */ - } } } - USED(is_array); if(st != SYMBOL_UNDEFINED) { size = emitter.get_size(st); - variable = - scope_add_symbol(parser.current.start, parser.current.length, st, size); + variable = scope_add_symbol(parser.current.start, parser.current.length, st, size); + if(!def && (parser.pass == 0)) return size; if(def) { diff --git a/docs/SPECIFICATION.org b/docs/SPECIFICATION.org index 8cc31db..990300a 100644 --- a/docs/SPECIFICATION.org +++ b/docs/SPECIFICATION.org @@ -16,34 +16,10 @@ It is short for "Undarsċieppan" The name comes from the Proto-West-Germanic wor :PROPERTIES: :CUSTOM_ID: undar-grammar-and-specification :END: -** Plexs + +** Primitive Types :PROPERTIES: -:CUSTOM_ID: plexs -:END: -- A =plex= is a container for primitive types. -- Not a class: no inheritance, no vtables -- Methods are functions with implicit =this= argument - -#+begin_src ul -plex «token» { - init() { - // values - } -} - -// example -plex Vec3 { - init(real x, real y, real z) { - this.x = x; - this.y = z; - this.y = z; - } -} -#+end_src ul - -*** Substantial Plexs -:PROPERTIES: -:CUSTOM_ID: substantial-plexs +:CUSTOM_ID: primitive-types :END: | Type | Description | @@ -127,7 +103,13 @@ if («token» is real) { } #+end_src ul -also used for letting constants +checks if a atom's plex contains the fields inside of a trait + +#+begin_src ul +if («token» is [Tunnel, Drawable]) { + print("im tunnel-able and draw-able"); +} +#+end_src ul =as= @@ -140,18 +122,10 @@ some_functon(«token» as real); // needs a real =in= -checks if a atom's plex contains the fields inside of a trait +used inside of the for loops #+begin_src ul -if («token» in Tunnel, Drawable) { - print("im tunnel-able and draw-able"); -} -#+end_src ul - -also used inside of the for loops - -#+begin_src ul -for («token» in «collection») { «body» } +for («type» «token» in «collection») { «body» } #+end_src ul ** Control flow @@ -170,7 +144,7 @@ for («variable» in «collection») { «body» } iterates through each atom in the collection setting it to variable #+begin_src ul -for («variable» = initial_value; end_value; increment) { «body» } +for («type» «variable» = initial_value; «boolean expression»; «increment») { «body» } #+end_src ul loops from initial value to end value by increment value (like a for loop in other languages) @@ -248,6 +222,35 @@ Array of a specific plex «plex»[«length»] «variable» = [val1, val2, ...]; #+end_src ul +** Plexs +:PROPERTIES: +:CUSTOM_ID: plexs +:END: +- A =plex= is a container for primitive types. +- Not a class: no inheritance, no vtables +- Methods are functions with implicit =this= argument + +#+begin_src ul +plex «token» { + init() { + // values + } +} + +// example +plex Vec3 { + real x; + real y; + real z; + + init(real x, real y, real z) { + this.x = x; + this.y = y; + this.z = z; + } +} +#+end_src ul + ** Tunnel :WIP: :PROPERTIES: :CUSTOM_ID: tunnel-1 diff --git a/libc.c b/libc.c index 5452b20..24ced35 100644 --- a/libc.c +++ b/libc.c @@ -328,3 +328,81 @@ real_to_string(Arena *a, r32 q) return ascpy(a, buffer + i, MAX_LEN_REAL32 - i); } +bool +is_digit(char c) +{ + return c >= '0' && c <= '9'; +} + +bool +is_space(char c) +{ + switch(c) { + case ' ': + case '\r': + case '\t': + case '\v': + case '\f': + case '\n': + return true; + } + return false; +} + +i32 +stoi(const char *str, u32 length) +{ + bool neg = false; + i32 n = 0; + + while (is_space(*str)) { + if (length-- == 0) return n; + str++; + } + + if (*str == '-') { + neg = true; + if (length-- == 0) return n; + str++; + } + + while (is_digit(*str) && length-- > 0) { + int digit = *str++ - '0'; + + if (neg) { + if (n < (I32_MIN / 10) || (n == (I32_MIN / 10) && digit > -(I32_MIN % 10))) { + return I32_MIN; + } + n = n * 10 - digit; + } else { + if (n > (I32_MAX / 10) || (n == (I32_MAX / 10) && digit > (I32_MAX % 10))) { + return I32_MAX; + } + n = n * 10 + digit; + } + } + + return neg ? -n : n; +} + +u32 +ston(const char *str, u32 length) +{ + u32 n = 0; + + while (is_space(*str)) { + if (length-- == 0) return n; + str++; + } + + while (is_digit(*str) && length-- > 0) { + int digit = *str++ - '0'; + + if (n > (U32_MAX / 10) || (n == (U32_MAX / 10) && digit > (U32_MAX % 10))) { + return U32_MAX; + } + n = n * 10 + digit; + } + + return n; +} diff --git a/libc.h b/libc.h index e5a13b2..aa10841 100644 --- a/libc.h +++ b/libc.h @@ -57,7 +57,7 @@ typedef u8 bool; #define I16_MAX 32767 #define U16_MAX 65535 -#define I32_MIN -2147483648 +#define I32_MIN -2147483647 #define I32_MAX 2147483647 #define U32_MAX 4294967295 @@ -66,7 +66,7 @@ typedef u8 bool; #define AS_INT(v) ((i32)(v)) #define AS_NAT(v) ((u32)(v)) #define AS_REAL(v) ((i32)(v)) -#define FLOAT_TO_REAL(v) (((i32)(v)) * FIXED_CONST) +#define FLOAT_TO_REAL(v) ((i32)((v) * FIXED_CONST)) #define REAL_TO_FLOAT(v) (((f32)(v)) / FIXED_CONST) #define USED(x) ((void)(x)) @@ -132,5 +132,7 @@ r32 real_abs(r32 f); char *int_to_string(Arena *a, i32 v); char *nat_to_string(Arena *a, u32 v); char *real_to_string(Arena *a, r32 q); +i32 stoi(const char *str, u32 len); +u32 ston(const char *str, u32 len); #endif diff --git a/test/array.ul b/test/array.ul index bd58f5c..325e1c2 100644 --- a/test/array.ul +++ b/test/array.ul @@ -2,17 +2,16 @@ nat[6] fixed_size = [1, 2, 3, 4, 5, 6]; nat i = 0; -nat len = array.length; -while (i < len) { - print(array[i] as str); - print("\n"); +while (i < fixed_size.length) { + print(fixed_size[i] as str); + print(" "); i = i + 1; } print("\n"); -for (i in array) { - print(i as str); - print("\n"); -} +// for (i in fixed_size) { +// print(i as str); +// print("\n"); +// } halt; diff --git a/test/mat-search.ul b/test/mat-search.ul index f01e14a..7c17c8d 100644 --- a/test/mat-search.ul +++ b/test/mat-search.ul @@ -17,12 +17,12 @@ bool found = false; for (nat x = 0; x < xSize; x++) { for (nat y = 0; y < ySize; y++) { for (nat z = 0; z < zSize; z++) { - if (matrix[x][y][z] == 0) { - print("found: ["); + if (matrix[x, y, z] == 0) { + print("found '0' at ["); print(x as str); - print(","); + print(", "); print(y as str); - print(","); + print(", "); print(z as str); print("]\n"); found = true; diff --git a/test/paint.ul b/test/paint.ul index cb66f25..c97313f 100755 --- a/test/paint.ul +++ b/test/paint.ul @@ -47,7 +47,7 @@ System system = devmap(0x00, System); Screen screen = devmap(0x20, Screen); screen.vector = ref render_screen; Mouse mouse = devmap(0x90, Mouse); -mouse.vector = ref render_screen; +mouse.vector = ref on_mouse_down; halt; function on_mouse_down() {