June 16, 2025
added typing rules - a way to create types with value constraints,
consider this:
(define-type ZeroOrOne)
(define-typing-rules
(Number n is ZeroOrOne <=> (or
(eq? n 0)
(eq? n 1)))
(Bool is ZeroOrOne)
(ZeroOrOne is Number))
this creates a type ZeroOrOne, which will only be able to hold a value 0 or 1. other values should result in an error thrown by the compiler,
consider this function, right after the code i showed beforehand:
(define-signature f ZeroOrOne -> Number)
(define (f x) x)
it is basically a self or I function, but it does type conversion. since every ZeroOrOne is a Number, it can be freely converted that way, but because only Numbers 0 and 1 are ZeroOrOne, all invocations of f that are not (f 0) or (f 1) will error out. (i mean - they may error out, the typechecker is nowhere near good enough to do symbex to catch every single possible errors - it's a rather uncomplicated type checker)
the typechecker is now much smarter, now it can detect invalid return types of functions based on their body vs what signature was provided.
consider this:
(define-signature f Number -> String)
(define (f x)
x)
(define (main)
(f 10))
the compiler now is able to infer that f called as (f 10) will not return a string, but a number, and will throw a compile-time error
embed
macro, that embeds files as bytes,i used quite a lot of brain power on this
- added deeper typechecking (more on that later)
- added -M to test macroexpand/optimize combo
consider this:
```
(define (g x)
(string-append x x))
(define (f x)
(g x))
(define (main)
(f 1))
```
the typechecker is now able to throw an error at compile time saying it is impossible to call string-append at 1, as the type is Number, while String is required (see the screenshot)
begin
. it's now a builtin handled by the compiler,Implemented most of the devices. I still am yet to implement File/stat, File/append, and the entirety of the Audio device. The emulator seems to be in a functional state. It seems to be unable to run left
yet, but some other big roms run fine. I've implemented smart drawing, which only re-draws the recently updated part of the screen. It outperforms uxnsdl, which was to this point the only implementation that could run on plan9.
Added more type checking, it now accepts type signatures and will yield errors on invalid args passed to functions. Still a lot of work needs to be done on that, as right now it only can detect types if they are known in the exact place a function call takes place, so for example:
(define-signature f Number -> Number)
(f abc) ; <- this will error out
(let ((v abc))
(f v)) ; <- this will not error out, yet it should
added command line arg support, which was tricky, so it works via a callback called by (call-with-command-line ...) which accepts a lambda of 1 arg which is a list of strings. i've fallen into many traps set out by myself from the past which included a shitty allocator that can be un-stable-d by writing a byte out of bounds. but hey, wcyd, at least it was fun---ish
this means the only things that are left to implement are
- [ ] the entire audio stack
- [ ] append mode for devices
for now i've migrated post listing, authentication, post deletion & used 800 megs of my vps' bandwidth, i really need to start testing locally instead of doing this so brain-dead-ly
a website i wrote eons ago for my friend. this project contains devlogs of me migrating it to a different server & a different api & a different frontend for administration
this devlog includes stuff written off-timer, during the summer of coding event (no cheating was done, go look through the commits :) ). yup i forgot about wakatime.
i decided to write a native uxn emulator for plan9 as this platform lacked one, and the one that did work (most of the time) — uxnemu, or, uxnsdl — was pretty slow on my potato laptop, as it required a MITM between the software and libdraw which was an SDL emulation. this slowed down things quite a bit to the point of unusableness. uxn9 is much faster on plan9. i cannot test it on other operating systems as it is written in specifically plan9 in mind.
is anyone reading this? if so i can later add a tldr of what plan9 and uxn are, if not, why bother?
demo:
* added uxn5 as an emulator
* sent patches to uxn5 mailing list regarding invalid obj references
compiler:
* string=?
* cond
* arity checking
* include libraries at compile-time
* 'symbols
* structs, packed structs
* fix malloc (of course; again)
* fix lambda rewriting
* show perf data when compiler is called with -V
* add bunnymark & tests to the web demo
* add thread test (https://krzysckh.org/b/Implementing-greener-threads-by-putting-uxn-in-your-uxn.html)
* add TCE on top of TCO (delete function frame on tail non-recursive calls -- _tailcall! & _tailcall-fast!)
* generate symbol tables for debuggers with -s
* add constant folding for more operations
Removed bugs in uint8t* -> wchart* buffer conversions. Include ./lib into the final library with linker black magic, so files that are not in eru source tree can include ./lib/* at runtime. I've added a syntax hack that allows an expression to be evaluated at read-time instead of when computing the output. It works like #. in common lisp.
Basically
lst ← #((cons a) b)
output ← lst
will reduce twice, once for lst', and once for
output'.
l've been learning more lambda calculus. found a fatal flaw in my reducer. i'll have to figure out some declarative reduce this first syntax as a hint to it. here are some expressions i have figured out myself:
.include lib/cons.l
.include lib/comb.l
.include lib/math.l
_rev ← λrev.λl.(((null? (cdr l)) ((cons (car l)) nil)) ((append' (rev (cdr l))) (car l)))
rev ← (Y _rev)
_riota ← λriota.λx.(((zero? x) nil) ((cons x) (riota (pred x))))
riota ← (Y _riota)
iota ← λx.(rev (riota x))
_append' ← λappend.λl.λel.(((null? l) ((cons el) nil)) ((cons (car l)) ((append (cdr l)) el)))
append' ← (Y _append') ; l is a list, el is not a list
lst ← ((cons a) ((cons b) ((cons c) nil)))
output ← (rev lst)
started not a long time ago. got beta-reduction working. i'm not quite sure how to go about wrongly choosing infinite paths. i don't know if i have to do something about the naivity of my reducer. it can achieve self-reference with the Y combinator (cool!). my pc is too slow to compute 5!. i need to do some optimizations and plumb memory leaks.
λ-calculus beta reducer. written in C. As a demo link i've attached a *compiled* static version of this for x86_64 GNU/Linux. If you don't want to compile it from source, wget it and chmod +x it to be able to run test programs from the git repo. Please also make sure that a C.UTF-8 locale is available on your system. It **DOES NOT** work on MS Windows. This is a MVP running only on unix-likes. It runs on my linux machine and my bsd machine. Please make sure you're running it on a unix-like operating system.
after fighting with clang --target=wasm32 for literal hours, writing lots of js simulating a real environment i was finally able to create a ghetto demo website demonstrating how the compiler works. i might refine it later. for now it can compile / disassemble files. It's just a web wasm frontend. If you can, please use the normal compiler.
Also i have spent a lot of time going through a weird bug just to realize my js bump malloc is not aligning pointers. big oops
added call-with-lines, uf2 font drawing routines, realloc, memcpy, strlen, varvara file IO (read-file, write-file), {key,button}-pressed, keypress vector, the compiler now alloc!s inline strings (there's no need to do that manually now), fixed dead code elimination for alloc! (it no longer deletes functions that are referenced only in _alloc! expressions). started working on a web demo
well i've worked much more than the counter shows here, just on a machine without hackatime. i've re-written the allocator because i found a fatal flaw that literally made it go boom on certain allocation sequences. i've added some utility functions, signed 16bit arithmetic emulation.
I also got heavily hackernews'd - my blog post was on the main page for some time, and my web server really struggled, as it's a tiny vps with like 300 megs of ram. in 3 hours i got twice as many requests as in the entirety of last year (only from stats from people without adblockers). feels kind of surreal.
what has been up to now:
- basic compilation phases & code generation
- some peephole optimizations
- tail call optimization
- closure generation (https://krzysckh.org/b/Homegrown-closures-for-uxn.html)
- runtime memory allocation (implemented malloc+free)
- variables as 1st class citizens (the compiler can recognise multiple label types)
An optimizing compiler for a lisp dialect targetting the uxn virtual machine. Read a blog posts: - https://krzysckh.org/b/Homegrown-closures-for-uxn.html - https://krzysckh.org/b/Implementing-greener-threads-by-putting-uxn-in-your-uxn.html The background image is called "uxn.crew.jpeg". As of my knowledge it was drawn by Rek Bell. Distributed by Devine Lu Linvega on wiki.xxiivv.com. Used under the BY-NC-SA4.0 License.
This was widely regarded as a great move by everyone.