From 457d70acda9b9c02ddb297fcb36ed1fa5b57f92a Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Tue, 5 Aug 2025 04:58:40 -0400 Subject: write some stuff about language goals --- doc/generics.txt | 33 ++++++++++++++++++++++++++++++ doc/goals.txt | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/macros.txt | 25 +++++++++++++++++++++++ test.lang | 12 +++++++---- 4 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 doc/generics.txt create mode 100644 doc/goals.txt create mode 100644 doc/macros.txt diff --git a/doc/generics.txt b/doc/generics.txt new file mode 100644 index 0000000..22745c1 --- /dev/null +++ b/doc/generics.txt @@ -0,0 +1,33 @@ +struct DynArr(T) { + data ^T, + len, cap i64 +} + +proc da_fit(da ^DynArr(T), n i64, a ^Arena) { + let c = da^.cap + if c <= n { + if c = 0 { c := 1 } + while c <= n { + c := c << 1 + } + da^.data := arena_realloc(a, da^.data, da^.cap * sizeof(T), alignof(T)) + da^.cap := c + } +} + +proc da_push(da ^DynArr(T), v T, a ^Arena) { + da_fit(da, da^.len + 1, a) + da^.data[da^.len] := v + da^.len := da^.len + 1 +} + +proc main { + let a = Arena {} + let v = DynArr(i32) {} + da_push(&v, 1, &a) + da_push(&v, 2, &a) + da_push(&v, 3, &a) + da_push(&v, 4, &a) + da_push(&v, 5, &a) + da_push(&v, 6, &a) +} diff --git a/doc/goals.txt b/doc/goals.txt new file mode 100644 index 0000000..620438c --- /dev/null +++ b/doc/goals.txt @@ -0,0 +1,62 @@ +a loose collection of goals and ideas for this as-yet-unnamed language + +* fast compilation + + grammar must be very easy to parse + + more important than high performance + + more important than minor ergonomic sacrifices + + possibly built-in hot code reloading somewhere down the line + + in general: + - the most important thing for coding to be fun is a tight feedback loop + +* very small, self-contained executables + + hello world should ideally be on the order of a couple kilobytes + + only functions which get referenced from main (and so on recursively) + get any code generated, even for the stdlib + + favor size over performance where reasonable + +* explicit + + procedures that allocate should have an arena parameter + + no operator overloading, but builtin vector/matrix types (eventually) + +* aesthetically minimalist + + not too many keywords or features + + no semicolons + + no significant whitespace + + no parentheses around conditions + + type inference wherever possible + +* more modern type system than c + + distinction between pointers and arrays + + slice types (ptr, len) + - strings are slices, like rust &str or c++ str_view + + dynamic arrays (ptr, len, cap) + - manipulation of dynamic arrays is handled by normal functions + + type-safe generics + + parametric polymorphism (at compile time) + + built-in types for vector and matrix math + + scalar types have explicit bit sizes + - u8, i32, u64, f32, f64 + + bit set support! + + type inference + - let x = y + - can do like .ENUM_NAME when expecting an enum value, even though + otherwise it's `let x = EnumType.ENUM_NAME` + +* c interop + + ability to specify different calling conventions on: + - functions imported from outside + - functions exported + +* types and procedures in any order + + this goal can be thrown out if it turns out to slow down the compiler + - but finding these first allows to hand all procedures to a thread pool + for parsing and optimization + + removes the need for function prototypes, opaque structs, etc. + + like in odin, all files in a directory are compiled together and have + the same toplevel scope; to isolate things in a package, put them in + a different directory + +* portable + + should be as easy as possible (like that's saying much...) to port to new platforms + + at minimum support amd64 and wasm + + consider having a version of the compiler which uses LLVM for release builds diff --git a/doc/macros.txt b/doc/macros.txt new file mode 100644 index 0000000..f39a30b --- /dev/null +++ b/doc/macros.txt @@ -0,0 +1,25 @@ +/* + * dollar sign identifiers are only valid within a macro body (what i believe + * scheme folk call "hygienic") + */ + +macro SWAP($a, $b) { + let $tmp = $a + $a := b + $b := $tmp +} + +proc foo(n ^Node) { + SWAP(&n^.in.data[0], &n^.in.data[1]) +} + +/* + * note that the macro body between the braces isn't a new scope, so you can + * still e.g. have a macro that defines a variable. or, perhaps, a function: + */ + +macro V2OP($name, $op) { + func $name(a, b vec2) vec2 { + return vec2 { a.x $op b.x, a.y $op b.y } + } +} diff --git a/test.lang b/test.lang index 05efc47..94869c8 100644 --- a/test.lang +++ b/test.lang @@ -8,9 +8,13 @@ // also single-line now +proc fib(x i64) { + return x & 1023 +} + proc main(a, b i64) { - //let x = (a + -b) = (a xor b) - //let y = (a + b) = (b * 2) - //return (x & y & (a = a) & (a = ~b)) | ((a + a) = (a / 2)) - return (a <= b) = ~(a > b) + // let x = (a + -a) = (a xor a) + // let y = (a + a) = (a * 2) + // return (x & y & (a = a) & (a = ~a)) | ((a + a) = (a + 2)) + return a - (b + b) - a } -- cgit v1.2.3