summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-08-05 04:58:40 -0400
committerWormHeamer2025-08-05 04:58:40 -0400
commit457d70acda9b9c02ddb297fcb36ed1fa5b57f92a (patch)
treea9254683bb8ffd1076821eb9cfdd2128dfcfda41
parent98bf590247c281137fdc62478699c66bb35ff29f (diff)
write some stuff about language goals
-rw-r--r--doc/generics.txt33
-rw-r--r--doc/goals.txt62
-rw-r--r--doc/macros.txt25
-rw-r--r--test.lang12
4 files changed, 128 insertions, 4 deletions
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
}