cleanup, add more stringops
This commit is contained in:
parent
d5479d1b7e
commit
7634bbe1c9
|
@ -1 +1,2 @@
|
|||
*.ul linguist-language=fortran
|
||||
*.zl linguist-language=zig
|
60
README.org
60
README.org
|
@ -1,4 +1,4 @@
|
|||
#+TITLE: A Language for Enduring Realities
|
||||
#+TITLE: The Reality Engine
|
||||
#+AUTHOR: Zongor
|
||||
#+EMAIL: archive@undar-lang.org
|
||||
#+DATE: [2025-04-05]
|
||||
|
@ -15,8 +15,6 @@
|
|||
· · · ᚾ]
|
||||
#+END_SRC
|
||||
|
||||
* The Reality Engine
|
||||
|
||||
The =Reality Engine= is a register-based virtual machine designed to render not just graphics, but persistent, inspectable, reproducible computational worlds.
|
||||
|
||||
It is:
|
||||
|
@ -55,16 +53,16 @@ Undâr is a permacomputing oriented, statically-typed language with **first-clas
|
|||
|
||||
It runs on the =Reality Engine=, a minimal C89 VM inspired by Uxn, Plan 9, and Forth - but built for =spatial software=, =deterministic execution=, and =software that lasts=.
|
||||
|
||||
Sċieppan is a bytecode assembler that is inspired by Webassemblys WAT format.
|
||||
Sċieppan is a minimal lisp inpsired by sectorlisp.
|
||||
You can view some examples in the =.lisp= files in =/test=
|
||||
|
||||
**Core Types**
|
||||
|
||||
| Type | Description |
|
||||
|------+-------------------------------------------|
|
||||
| Type | Description |
|
||||
|--------+-------------------------------------------|
|
||||
| =int= | 32-bit signed integer |
|
||||
| =nat= | 32-bit natural number |
|
||||
| =real= | Q16.16 fixed-point real number |
|
||||
| =real= | Float/Q16.16 fixed-point real number |
|
||||
| =str= | 4-byte packed string or fat pointer |
|
||||
| =bool= | Compile-time flag |
|
||||
| =ref= | Reference prefix for passing by reference |
|
||||
|
@ -105,7 +103,6 @@ A =plex= is a **Platonic form** - a structured definition of a kind of being in
|
|||
|
||||
#+BEGIN_SRC ul
|
||||
plex Player {
|
||||
version 1;
|
||||
str name;
|
||||
real[3] pos;
|
||||
|
||||
|
@ -120,36 +117,8 @@ plex Player {
|
|||
|
||||
- Not a class: no inheritance, no vtables
|
||||
- Methods are functions with implicit =this= argument
|
||||
- Instances are **atoms** - persistent, versioned, serializable
|
||||
- Stored in the internal graph
|
||||
|
||||
> *"A plex defines what a thing is. An atom is its instance in that reality."*
|
||||
|
||||
* Versioning & Shadowing (Forth-Inspired)
|
||||
|
||||
When you redefine a =plex=, the old version is **shadowed but preserved** - unless explicitly discarded.
|
||||
|
||||
#+BEGIN_SRC ul
|
||||
plex Counter { version 1; nat value; inc() { value += 1; } }
|
||||
plex Counter { version 2; nat value; inc() { value += 2; } } ! shadows v1
|
||||
|
||||
Counter c1 = Counter(); ! uses v2 (latest)
|
||||
Counter c2 = Counter.v1(); ! uses v1 - still available
|
||||
|
||||
discard Counter.v1; ! optional: free memory
|
||||
#+END_SRC
|
||||
|
||||
Internally, plex versions form a **linked version chain**:
|
||||
- =head= -> latest version
|
||||
- =tail= -> oldest retained version
|
||||
- =migrate(obj, Counter)= -> converts data layout
|
||||
- =versions(Counter)= -> list available versions
|
||||
|
||||
This enables:
|
||||
- Non-destructive evolution
|
||||
- Safe refactoring
|
||||
- Historical reproducibility
|
||||
- Code archaeology
|
||||
- Instances are **atoms**
|
||||
- A plex defines what a thing is. An atom is its instance.
|
||||
|
||||
* Graphics & Devices
|
||||
|
||||
|
@ -213,23 +182,8 @@ if (server.attach(auth)) {
|
|||
|
||||
Tunnels make I/O **uniform, composable, and archival**.
|
||||
|
||||
* Development Environment
|
||||
|
||||
supports **live coding** and **temporal development**:
|
||||
|
||||
**Live Coding Features**
|
||||
- Hot module reloading: inject code while VM runs
|
||||
- REPL-style interaction: inspect memory, call functions, test logic
|
||||
- Shadowing: redefine =plex=es without restarting
|
||||
- Symbol table manipulation: runtime introspection and patching
|
||||
|
||||
**Final Binaries**
|
||||
- Are **snapshots** of:
|
||||
- Memory state
|
||||
- Symbol table
|
||||
- Version chains
|
||||
- Can be saved, restored, or archived as =.zbin= files
|
||||
- Are fully deterministic and reproducible
|
||||
|
||||
* Getting Started
|
||||
|
||||
|
|
|
@ -71,9 +71,6 @@ typedef enum {
|
|||
#define OP(opcode, dest, src1, src2) \
|
||||
((opcode << 24) | (dest << 16) | (src1 << 8) | (src2))
|
||||
|
||||
#define OP_SYSCALL_OPCODE(syscall_id, arg_count, src) \
|
||||
((OP_SYSCALL << 24) | ((syscall_id & 0xFF) << 16) | (arg_count & 0xFF) | src)
|
||||
|
||||
typedef union value_u {
|
||||
int32_t i; /* Integers */
|
||||
float f; /* Float */
|
||||
|
|
30
src/vm.c
30
src/vm.c
|
@ -190,6 +190,10 @@ bool step_vm(VM *vm) {
|
|||
vm->frames[vm->fp].registers[dest].u = vm->pc;
|
||||
return true;
|
||||
}
|
||||
case OP_JMP: {
|
||||
vm->pc = vm->frames[vm->fp].registers[dest].u; /* Jump to address */
|
||||
return true;
|
||||
}
|
||||
case OP_SYSCALL: {
|
||||
uint32_t syscall_id = dest;
|
||||
uint32_t arg_count = src2;
|
||||
|
@ -385,10 +389,6 @@ bool step_vm(VM *vm) {
|
|||
(float)(vm->frames[vm->fp].registers[src1].u);
|
||||
return true;
|
||||
}
|
||||
case OP_JMP: {
|
||||
vm->pc = vm->frames[vm->fp].registers[dest].u; /* Jump to address */
|
||||
return true;
|
||||
}
|
||||
case OP_JEQ_UINT: {
|
||||
COMPARE_AND_JUMP(uint32_t, u, ==);
|
||||
}
|
||||
|
@ -458,6 +458,28 @@ bool step_vm(VM *vm) {
|
|||
vm->frames[vm->fp].registers[dest].u = ptr;
|
||||
return true;
|
||||
}
|
||||
case OP_STRING_TO_INT: {
|
||||
uint32_t src_addr = (uint32_t)vm->frames[vm->fp].registers[src1].u;
|
||||
uint32_t dest_addr = (uint32_t)vm->frames[vm->fp].registers[dest].u;
|
||||
char *endptr;
|
||||
int32_t value = (int32_t)strtol((char*)&vm->memory[src_addr], &endptr, 10);
|
||||
vm->memory[dest_addr].i = value;
|
||||
return true;
|
||||
}
|
||||
case OP_STRING_TO_UINT: {
|
||||
uint32_t src_addr = (uint32_t)vm->frames[vm->fp].registers[src1].u;
|
||||
uint32_t dest_addr = (uint32_t)vm->frames[vm->fp].registers[dest].u;
|
||||
long value = atol((char*)&vm->memory[src_addr]);
|
||||
vm->memory[dest_addr].u = value;
|
||||
return true;
|
||||
}
|
||||
case OP_STRING_TO_REAL: {
|
||||
uint32_t src_addr = (uint32_t)vm->frames[vm->fp].registers[src1].u;
|
||||
uint32_t dest_addr = (uint32_t)vm->frames[vm->fp].registers[dest].u;
|
||||
float value = atof((char*)&vm->memory[src_addr]);
|
||||
vm->memory[dest_addr].u = value;
|
||||
return true;
|
||||
}
|
||||
case OP_DBG_READ_STRING: {
|
||||
uint32_t str_addr = vm->mp++;
|
||||
uint32_t length = 0;
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
(puts "nuqneH 'u'?")
|
||||
hello:
|
||||
"nuqneH 'u'?"
|
||||
puts &hello
|
||||
halt
|
||||
|
Loading…
Reference in New Issue