From 5d15aa1c57f5665dc8b252b3d96703287d69a574 Mon Sep 17 00:00:00 2001 From: zongor Date: Sun, 8 Jun 2025 00:30:52 -0400 Subject: [PATCH] fix minor things, add inital opcode, add mem2mem test --- README.org | 20 +- docs/MACHINE.org | 35 ++++ docs/SPECIFICATION.org | 114 +++++------ docs/dis-like-mem2mem/udis_vm.c | 69 +++++++ docs/dis-like-mem2mem/udis_vm_q16-16.c | 210 +++++++++++++++++++++ docs/project-syntax-example/src/client.ztl | 8 +- docs/project-syntax-example/src/common.ztl | 10 +- docs/project-syntax-example/src/server.ztl | 2 +- 8 files changed, 393 insertions(+), 75 deletions(-) create mode 100644 docs/dis-like-mem2mem/udis_vm.c create mode 100644 docs/dis-like-mem2mem/udis_vm_q16-16.c diff --git a/README.org b/README.org index 6844485..472b933 100644 --- a/README.org +++ b/README.org @@ -1,13 +1,13 @@ #+OPTIONS: toc:nil -* Zongor's Universe Machine +* Zongor's Reality Engine :PROPERTIES: :CUSTOM_ID: zongors-universe-machine :END: * Overview - ZTL is a lightweight, portable programming language for permacomputing, game preservation, and indie game development. - Built in **C99** for cross-platform compatibility (desktop, microcontrollers, and web via Emscripten). + ZRE is a lightweight, portable programming language for permacomputing, game preservation, and indie game development. + Built in **C89** for cross-platform compatibility (desktop, microcontrollers, and web via Emscripten). Designed for simplicity, performance, and creative exploration. It is inspired by [[https://wiki.xxiivv.com/site/uxn.html][uxn]], [[http://duskos.org/][Dusk OS]], [[https://lua.org][Lua]], [[https://en.wikipedia.org/wiki/Lisp_(programming_language)][Lisp]], [[https://en.wikipedia.org/wiki/C_(programming_language)][C]], and [[https://ziglang.org/][Zig]]. @@ -30,30 +30,32 @@ - Emacs major mode included; Vim, VSCode, and Lite XL support planned. ** Language Design - - Dynamically typed with optional type hints in function signatures. - - Unified =real= type (=f64= by default) with =byte= for interop (u8, i32, f32, etc.). + - Strongly typed with optional type hints in function signatures. + - Unified =real= type (=f64= by default) for floating point/fixed point numbers with =byte= for integer numbers (u8, i32, etc.). - 3D math primitives: =vec=, =mat=, =quat=, and more. - Strings with interpolation, =split=, =replace=, =trim=, etc. - Error handling: - Go-style explicit errors. - Null coalescing (=??=) and null checks (=?.=). - Lightweight coroutines with event-loop-driven multitasking. - - FFI via C-defined "native functions" (examples provided in VM). + - FFI via C-defined "system calls" (examples provided in VM). ** Modularity & Ecosystem - Unified table type (like Lua) for lists, maps, and tuples. + - Higher performance array type. - Standard library: math, networking, 3D rendering, minimal GUI. - =use= keyword for modular code organization via file-based namespaces. * Technical Details ** VM Architecture - - Stack-based bytecode interpreter written in C99. + - Stack-based bytecode interpreter written in C89. - Portable to new systems, microcontrollers, and web via Emscripten. ** Memory Management - Reference counting for globally scoped objects. - =weak= keyword to avoid cyclical references. + - garbage collection as a system call (choose when to free memory) - Arena allocators for short-lived, scoped memory (e.g., function-local objects). ** Rendering & I/O @@ -84,9 +86,9 @@ * Motivation -ZTL bridges retro-inspired creativity with modern portability for: +ZRE bridges retro-inspired creativity with modern portability for: - Game jams (rapid prototyping + 3D engine). - Indie games (5th/6th-gen aesthetics). - Permacomputing (low-resource, sustainable code). -- Education (simple VM/language design). +- Education (simple VM/language design), a language which scales to the developers level. diff --git a/docs/MACHINE.org b/docs/MACHINE.org index 02701f0..5dc8fae 100644 --- a/docs/MACHINE.org +++ b/docs/MACHINE.org @@ -91,3 +91,38 @@ be something like the backend dac for ORCA. 9p filesystem/network by default. Have an easy way to network. + +*** opcodes + +|---------------------------------------------------------------------------------------+------------------------------------------------------------------| +| opcode | description | +|---------------------------------------------------------------------------------------+------------------------------------------------------------------| +| nil | noop/nil/eos | +| *bbbb call | calls the address as a function | +| b syscall | calls a system call based on the opcode | +| bbbb pushReal - | allocates Q16.16 bits on the stack | +| - popReal bbbb | deallocates Q16.16 bits from the stack | +| b *bbbb storeByte - | stores 8 bits from the stack to the address | +| bbbb *bbbb storeReal - | stores 64 bits from the stack to the address | +| *bbbb loadByte b | loads 8 bits from the address to the stack | +| *bbbb loadReal bbbb | loads 64 bits from the address to the stack | +| bbbb bbbb addReal bbbb | adds 64 bits from the stack | +| bbbb bbbb subReal bbbb | subtracts 64 bits from the stack | +| bbbb bbbb mulReal bbbb | multiplies 64 bits from the stack | +| bbbb bbbb divReal bbbb | divides 64 bits from the stack | +| bbbb [bbbb bbbb bbbb] scalevec3 [bbbb bbbb bbbb] | scales the vec3 by the f64 on the stack | +| [bbbb bbbb bbbb] [bbbb bbbb bbbb] addvec3 [bbbb bbbb bbbb] | adds 2 vec3 together from the stack | +| [bbbb bbbb bbbb] [bbbb bbbb bbbb] subvec3 [bbbb bbbb bbbb] | subtracts 2 vec3 together from the stack | +| [bbbb bbbb bbbb] [bbbb bbbb bbbb] mulvec3 [bbbb bbbb bbbb] | multiplies 2 vec3 together from the stack | +| [bbbb bbbb bbbb] [bbbb bbbb bbbb] dotvec3 bbbb | dot product of 2 vec3 together from the stack | +| [bbbb bbbb bbbb] [bbbb bbbb bbbb] crossvec3 [bbbb bbbb bbbb] | cross product of 2 vec3 together from the stack | +| [bbbb bbbb bbbb] normvec3 [bbbb bbbb bbbb] | normalizes a vec3 | +| [[bbbb bbbb bbbb bbbb]*4] invmat4 [[bbbb bbbb bbbb bbbb]*4] | inverts a mat4 from the stack | +| [[bbbb bbbb bbbb bbbb]*4] [[bbbb bbbb bbbb bbbb]*4] mulmat4 [[bbbb bbbb bbbb bbbb]*4] | multiplies 2 mat4's from the stack | +| *triangle-array-ptr nnnn drawtriangles - | drawn 'n' many triangles using a array of vertices and its color | +| *str1 *str2 streq b | checks 2 strings returns a bool of if they are the same | +| *str1 *str2 strcat *str3 | concatinates 2 strings and returns the address of the new string | +| *str strlen bbbb | pushes the length of the string onto the stack | +| | | +| | | +|---------------------------------------------------------------------------------------+------------------------------------------------------------------| diff --git a/docs/SPECIFICATION.org b/docs/SPECIFICATION.org index 48dce7f..7dd9d56 100644 --- a/docs/SPECIFICATION.org +++ b/docs/SPECIFICATION.org @@ -1,18 +1,18 @@ -* /ZTL/ (Zongors Transpiler Language) Design parameters +* /ZRE/ (Zongors Reality Engine) Design parameters :PROPERTIES: -:CUSTOM_ID: ztl-zongors-transpiler-language-design-parameters +:CUSTOM_ID: zre-zongors-transpiler-language-design-parameters :END: -** What is /ztl/? +** What is /zre/? :PROPERTIES: -:CUSTOM_ID: what-is-ztl +:CUSTOM_ID: what-is-zre :END: -/ztl/ is an domain specific language for 3d games with C/Lua style syntax. +/zre/ is an domain specific language for 3d games with C/Lua style syntax. The compiler is written in C which should make it easy to port to other systems. -* /ZTL/ Grammar and Specification +* /ZRE/ Grammar and Specification :PROPERTIES: -:CUSTOM_ID: ztl-grammar-and-specification +:CUSTOM_ID: zre-grammar-and-specification :END: ** Types :PROPERTIES: @@ -23,13 +23,13 @@ systems. are coming from object oriented languages you can think of self as "primitive types" -#+begin_src ztl +#+begin_src zre type «token» { init() { // values } } -#+end_src ztl +#+end_src zre * Basic Types :PROPERTIES: @@ -40,10 +40,12 @@ type «token» { :CUSTOM_ID: numeric :END: - =real= - - 64 bit floating point (Double) - - Is it slow and takes up a lot of space? yeah it does, - but because it is the only numeric type it makes it so that you do not have to worry about type casting which actually ends up speeding up processing - This is also how Lua, Lox, and Wren programming language handles numbers. Also because ZTL is intended to be used for Games, floats are used more for + - 64 bit floating point (Double) by default for modern CPUs that have a FPU + - 32 bit 16.16 for microcontrollers/hardware without a FPU like a raspberry pi pico, retro hardware like a Mac 68k + - 16 bit 12.4 for older retro hardware like PS1 or UXN. + - Is it slow and takes up a lot of space? yeah, kinda, maybe, + the nice part of a unified numeric type is that makes it so that you do not have to worry about type casting which actually ends up speeding up processing + This is also how Lua, Lox, and Wren programming language handles numbers. Also because ZRE is intended to be used for Games, floats are used more for 3D graphics than other numeric types. ** string @@ -66,7 +68,7 @@ string interpolation :CUSTOM_ID: binary :END: - =byte= - - same as uint8 or c char, used for interop + - same as uint8 or c char, also used for interop ** logical :PROPERTIES: @@ -85,11 +87,11 @@ monad above and is unwrapped in a similar way. You could also think of it as every variable being able to have "the type" and also "error" as a possible value. -#+begin_src ztl +#+begin_src zre let rr = err("something borked"); let var = rr ?? 0; // value is 0 let other_var = rr ?? panic(rr); // will panic -#+end_src ztl +#+end_src zre ** datastructure :PROPERTIES: @@ -108,13 +110,13 @@ Types that can be indexes are numbers and strings (no objects); syntax (yes I was nice and kept the syntax the same as most C like langs) -#+begin_src ztl +#+begin_src zre /* array same as a map of int to «type» */ let «variable» = [val1, val2, ...]; /* or as a map */ let «variable» = {key1: val1, key2: val2, ...}; -#+end_src ztl +#+end_src zre *** tunnel :PROPERTIES: @@ -202,19 +204,19 @@ The following is a list of global operators and their effect: let operator -#+begin_src ztl +#+begin_src zre let «token» = true; -#+end_src ztl +#+end_src zre =is= checks if a object is of that type -#+begin_src ztl +#+begin_src zre if («token» is real) { print("hello yes self is a real?"); } -#+end_src ztl +#+end_src zre also used for letting constants @@ -222,26 +224,26 @@ also used for letting constants coerces a type as another type if possible -#+begin_src ztl +#+begin_src zre let «token» = 0; /* default is real */ some_functon(«token» as byte); /* needs an byte */ -#+end_src ztl +#+end_src zre =in= checks if a object's type, or a type impls another type -#+begin_src ztl +#+begin_src zre if («token» in Tunnel) { print("im tunnel-able"); } -#+end_src ztl +#+end_src zre also used inside of the for loops -#+begin_src ztl +#+begin_src zre for («token» in «collection») { «body» } -#+end_src ztl +#+end_src zre ** Object :PROPERTIES: @@ -249,9 +251,9 @@ for («token» in «collection») { «body» } :END: An object is an invoked type. -#+begin_src ztl +#+begin_src zre let «variable» = «type»(«fields», …); -#+end_src ztl +#+end_src zre ** Tunnel :PROPERTIES: @@ -305,7 +307,7 @@ connected tunnel =success? : tunnel_object.walk(path_or_endpoint)= -> moves around the filesystem or through the graph -#+begin_src ztl +#+begin_src zre /* client */ let endpoint = `protocol://path/to/source`; let tunnel = endpoint.attach(user, auth); @@ -320,7 +322,7 @@ s.bind("/some/resource", fn () str { return "hello world"; }) server.start(); -#+end_src ztl +#+end_src zre ** Functions :PROPERTIES: @@ -331,11 +333,11 @@ always have a "default type" for all constant values or a developer can use the =as= keyword we do not have to define all values like in C, while keeping the same type safety as a more strongly typed language. -#+begin_src ztl +#+begin_src zre fn «token» («parameter» «type», ...) «return_type» { «body» } -#+end_src ztl +#+end_src zre - Built in transtypes - sort @@ -352,27 +354,27 @@ fn «token» («parameter» «type», ...) «return_type» { :PROPERTIES: :CUSTOM_ID: loops :END: -#+begin_src ztl +#+begin_src zre for («token» in «collection») { «body» } -#+end_src ztl +#+end_src zre iterates through each object in the collection setting it to token -#+begin_src ztl +#+begin_src zre while («boolean expression») { «body» } -#+end_src ztl +#+end_src zre loops until the expression is false -#+begin_src ztl +#+begin_src zre loop { «body» } -#+end_src ztl +#+end_src zre loops infinitely until break or return -#+begin_src ztl +#+begin_src zre do («variable» = initial_value, end_value, increment) { «body» } -#+end_src ztl +#+end_src zre loops from initial value to end value by increment value @@ -380,7 +382,7 @@ loops from initial value to end value by increment value :PROPERTIES: :CUSTOM_ID: branching :END: -#+begin_src ztl +#+begin_src zre if («boolean expression») { } else if («boolean expression») { @@ -388,7 +390,7 @@ if («boolean expression») { } else { } -#+end_src ztl +#+end_src zre *** exceptions :PROPERTIES: @@ -396,11 +398,11 @@ if («boolean expression») { :END: take a look at error's, but you can panic on an error like self: -#+begin_src ztl +#+begin_src zre panic(err("error message")); panic(err(3)); panic(«some_error_token»); -#+end_src ztl +#+end_src zre ** Localization :PROPERTIES: @@ -408,9 +410,9 @@ panic(«some_error_token»); :END: will look up the text of «token» in the linked localization.json file -#+begin_src ztl +#+begin_src zre #«token» -#+end_src ztl +#+end_src zre #+begin_src json { @@ -436,13 +438,13 @@ can even use localization tokens to create config files. Since everything is lazily compiled jit anyways it (in theory) doesn't hurt pertypeance much -#+begin_src ztl -use `https://example.com/some_library/some_file.ztl` -#+end_src ztl +#+begin_src zre +use `https://example.com/some_library/some_file.zre` +#+end_src zre -#+begin_src ztl -use `./some_local_file.ztl` -#+end_src ztl +#+begin_src zre +use `./some_local_file.zre` +#+end_src zre ** Testing :PROPERTIES: @@ -452,9 +454,9 @@ use `./some_local_file.ztl` :PROPERTIES: :CUSTOM_ID: assertion :END: -#+begin_src ztl +#+begin_src zre assert(«expression», «expected output») /* returns «error or none» */ -#+end_src ztl +#+end_src zre ** Measurements :PROPERTIES: diff --git a/docs/dis-like-mem2mem/udis_vm.c b/docs/dis-like-mem2mem/udis_vm.c new file mode 100644 index 0000000..da221d5 --- /dev/null +++ b/docs/dis-like-mem2mem/udis_vm.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include + +#define MEMORY_SIZE 65536 // 64KB memory (adjustable) +uint32_t memory[MEMORY_SIZE]; // Memory array + +typedef enum { + OP_ADD, // dest = src1 + src2 + OP_MOV, // dest = src1 + OP_JMP, // jump to address + OP_HALT // terminate execution +} Opcode; + +void run_vm() { + uint32_t pc = 0; // Program counter + while (1) { + // Fetch instruction + Opcode opcode = memory[pc]; + uint32_t src1_addr = memory[pc + 1]; + uint32_t src2_addr = memory[pc + 2]; + uint32_t dest_addr = memory[pc + 3]; + pc += 4; // Advance to next instruction + + // Validate addresses (safety check) + if (src1_addr >= MEMORY_SIZE || src2_addr >= MEMORY_SIZE || dest_addr >= MEMORY_SIZE) { + printf("Invalid memory address!\n"); + exit(1); + } + + // Execute instruction + switch (opcode) { + case OP_ADD: + memory[dest_addr] = memory[src1_addr] + memory[src2_addr]; + break; + case OP_MOV: + memory[dest_addr] = memory[src1_addr]; + break; + case OP_JMP: + pc = src1_addr; // Jump to address + break; + case OP_HALT: + return; + default: + printf("Unknown opcode: %d\n", opcode); + exit(1); + } + } +} + +int main() { + // Initialize memory + memory[0] = OP_ADD; // Opcode + memory[1] = 100; // A (src1) + memory[2] = 101; // B (src2) + memory[3] = 102; // C (dest) + memory[100] = 5; // Value of A + memory[101] = 7; // Value of B + memory[4] = OP_HALT; // Terminate after ADD + + run_vm(); + + printf("Result at address 102: %u\n", memory[102]); // Output: 12 + return 0; +} diff --git a/docs/dis-like-mem2mem/udis_vm_q16-16.c b/docs/dis-like-mem2mem/udis_vm_q16-16.c new file mode 100644 index 0000000..010e2c7 --- /dev/null +++ b/docs/dis-like-mem2mem/udis_vm_q16-16.c @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include + +// Q16.16 fixed-point macros +#define Q16_16_SCALE 16 +#define Q16_16_FRACTION_MASK 0x0000FFFF +#define TO_Q16_16(x) \ + ((int32_t)((x) << Q16_16_SCALE)) // Convert integer to Q16.16 +#define FROM_Q16_16(x) \ + ((int32_t)((x) >> Q16_16_SCALE)) // Convert Q16.16 to integer + +#define MEMORY_SIZE 65536 +int32_t memory[MEMORY_SIZE]; // Changed to signed for fixed-point support + +typedef enum { OP_ADD, OP_MOV, OP_JMP, OP_HALT } Opcode; + + +// Convert string to Q16.16 fixed-point +int32_t string_to_q16_16(const char *str) { + int32_t result = 0; + int sign = 1; + + // Handle sign + if (*str == '-') { + sign = -1; + str++; + } + + // Parse integer part + int32_t integer_part = 0; + while (*str != '.' && *str != '\0') { + if (*str < '0' || *str > '9') { + return 0; // Invalid character + } + integer_part = integer_part * 10 + (*str - '0'); + str++; + } + + // Clamp integer part to 16-bit range + if (integer_part > 32767) { + integer_part = 32767; // Overflow clamp + } + + // Parse fractional part + uint32_t frac_digits = 0; + int frac_count = 0; + + if (*str == '.') { + str++; // Skip decimal point + while (*str != '\0' && frac_count < 6) { + if (*str < '0' || *str > '9') { + break; + } + frac_digits = frac_digits * 10 + (*str - '0'); + frac_count++; + str++; + } + } + + // Scale fractional part to Q16.16 + // frac_q16 = (frac_digits * 65536 + 500000) / 1000000 + // This avoids floating-point by using integer arithmetic + uint32_t scaled_frac = 0; + if (frac_count > 0) { + // Pad with zeros if less than 6 digits + while (frac_count < 6) { + frac_digits *= 10; + frac_count++; + } + // Compute scaled fractional part with rounding + scaled_frac = (frac_digits * 65536 + 500000) / 1000000; + if (scaled_frac > 0xFFFF) { + scaled_frac = 0xFFFF; // Clamp to 16-bit range + } + } + + // Combine integer and fractional parts + result = (integer_part << Q16_16_SCALE) | (scaled_frac & Q16_16_FRACTION_MASK); + return result * sign; +} + +// Convert Q16.16 to string using integer-only arithmetic +int q16_16_to_string(int32_t value, char *buffer, size_t size) { + if (size < 13) { // Minimum buffer size for "-32768.000000\0" + if (size > 0) + buffer[0] = '\0'; + return -1; // Buffer too small + } + + char *buf = buffer; + size_t remaining = size; + + // Handle sign + if (value < 0) { + *buf++ = '-'; + value = -value; + remaining--; + } + + // Extract integer and fractional parts + int32_t integer_part = value >> Q16_16_SCALE; + uint32_t frac = value & Q16_16_FRACTION_MASK; + + // Convert integer part to string + char int_buf[11]; // Max 10 digits for 32-bit int + char *int_end = int_buf + sizeof(int_buf); + char *int_ptr = int_end; + + // Special case for zero + if (integer_part == 0) { + *--int_ptr = '0'; + } else { + while (integer_part > 0 && int_ptr > int_buf) { + *--int_ptr = '0' + (integer_part % 10); + integer_part /= 10; + } + } + + // Copy integer part to output buffer + while (int_ptr < int_end && remaining > 1) { + *buf++ = *int_ptr++; + remaining--; + } + + // Add decimal point + if (remaining > 7) { // Need space for .000000 + *buf++ = '.'; + remaining--; + } else { + if (remaining > 0) + *buf = '\0'; + return size - remaining; // Truncate if insufficient space + } + + // Convert fractional part to 6 digits + for (int i = 0; i < 6 && remaining > 1; i++) { + frac *= 10; + uint32_t digit = frac >> 16; + frac &= 0xFFFF; + *buf++ = '0' + digit; + remaining--; + } + + // Null-terminate + *buf = '\0'; + return buf - buffer; // Return length written +} + +void run_vm() { + uint32_t pc = 0; + while (1) { + Opcode opcode = memory[pc]; + uint32_t src1_addr = memory[pc + 1]; + uint32_t src2_addr = memory[pc + 2]; + uint32_t dest_addr = memory[pc + 3]; + pc += 4; + + if (src1_addr >= MEMORY_SIZE || src2_addr >= MEMORY_SIZE || + dest_addr >= MEMORY_SIZE) { + printf("Invalid memory address!\n"); + exit(1); + } + + switch (opcode) { + case OP_ADD: + // Q16.16 addition requires no scaling adjustment + memory[dest_addr] = memory[src1_addr] + memory[src2_addr]; + break; + case OP_MOV: + // Direct copy preserves fixed-point representation + memory[dest_addr] = memory[src1_addr]; + break; + case OP_JMP: + pc = src1_addr; + break; + case OP_HALT: + return; + default: + printf("Unknown opcode: %d\n", opcode); + exit(1); + } + } +} + +int main() { + // Initialize memory with Q16.16 values + memory[0] = OP_ADD; + memory[1] = 100; + memory[2] = 101; + memory[3] = 102; + const char *input = "-5.0"; + memory[100] = string_to_q16_16(input); // Convert "-5.0" to Q16.16 + const char *input2 = "10.0"; + memory[101] = string_to_q16_16(input2); // Convert "10.0" to Q16.16 + memory[4] = OP_HALT; + + run_vm(); + + char buffer[13]; // Sufficient for Q16.16 format + + // Convert result back to integer + q16_16_to_string(memory[102], buffer, sizeof(buffer)); + printf("Result at address 102: %s\n", buffer); // Output: 5.0 + return 0; +} diff --git a/docs/project-syntax-example/src/client.ztl b/docs/project-syntax-example/src/client.ztl index 3a738d6..e77be3f 100644 --- a/docs/project-syntax-example/src/client.ztl +++ b/docs/project-syntax-example/src/client.ztl @@ -7,7 +7,7 @@ fn main(argc real, argv str[]) { let username = argv[0]; let password = argv[1]; - let me = Player(username, (0.0, 1.0, 2.0), PURPLE); + let me = Player(username, Vec3(0.0, 1.0, 2.0), PURPLE); let running = true; while (running) { @@ -22,12 +22,12 @@ fn main(argc real, argv str[]) { } splitbox(parent.size * 0.75) { canvas("3D") { - model(Floor((0, 0, 0), 30)); + model(Floor(Vec3(0, 0, 0), 30)); me.update(); - model(Cube(me.pos, (0.5, 0.5, 0.5), me.appearance)); + model(Cube(me.pos, Vec3(0.5, 0.5, 0.5), me.appearance)); if (let players = me.server.read("players")) { for (p in players) { - model(Cube(p.pos, (0.5, 0.5, 0.5), p.apperance)); + model(Cube(p.pos, Vec3(0.5, 0.5, 0.5), p.apperance)); } } } diff --git a/docs/project-syntax-example/src/common.ztl b/docs/project-syntax-example/src/common.ztl index 48da3c1..f8d288c 100644 --- a/docs/project-syntax-example/src/common.ztl +++ b/docs/project-syntax-example/src/common.ztl @@ -5,7 +5,7 @@ type Camera { init(pos Vec3, look Vec3) { this.setting = "CAMERA_PERSPECTIVE"; this.pov = 45.0; - this.up = (0.0, 1.0, 0.0); + this.up = Vec3(0.0, 1.0, 0.0); this.pos = pos; this.look = look; } @@ -24,7 +24,7 @@ type Player { Camera((this.pos.x + 10.0, this.pos.y + 10.0, this.pos.z), this.pos); } - login(password str) Player[] { + login(str password) Player[] { this.server.attach(this.username, password); this.players = server.open("players"); return players.read(); @@ -59,6 +59,6 @@ type Player { } } -const RED is[255, 0, 0]; -const WHITE is[0, 0, 0]; -const PURPLE is[255, 255, 0]; +const RED is [255, 0, 0]; +const WHITE is [0, 0, 0]; +const PURPLE is [255, 255, 0]; diff --git a/docs/project-syntax-example/src/server.ztl b/docs/project-syntax-example/src/server.ztl index 2d07a0d..4488dc5 100644 --- a/docs/project-syntax-example/src/server.ztl +++ b/docs/project-syntax-example/src/server.ztl @@ -3,7 +3,7 @@ use "common.ztl"; fn main(argc real, argv str[]) { let s = Server("tcp://0.0.0.0:25565"); let running = true; - let players = [Player("user", (0, 0, 0), RED)]; + let players = [Player("user", [0, 0, 0], RED)]; while (running) { if (let client = s.accept("players")) { if (let message = client.get()) {