save work
This commit is contained in:
parent
f710beff46
commit
4dd47dd56c
|
@ -142,12 +142,12 @@ A few thoughts:
|
|||
* That will get me a lot of the way there. What's left after that which might be challenging?
|
||||
- [x] string interpolation
|
||||
- [x] splats
|
||||
- [ ] splatterns
|
||||
- [x] splatterns
|
||||
- [x] string patterns
|
||||
- [x] partial application
|
||||
- [ ] tail calls
|
||||
- [ ] stack traces in panics
|
||||
- [ ] actually good lexing, parsing, and validation errors. I got some of the way there in the fall, but everything needs to be "good enough."
|
||||
- [x] tail calls
|
||||
- [-] stack traces in panics
|
||||
- [-] actually good lexing, parsing, and validation errors. I got some of the way there in the fall, but everything needs to be "good enough."
|
||||
* After that, we're in integration hell: taking this thing and putting it together for Computer Class 1. Other things that I want (e.g., `test` forms) are for later on.
|
||||
* There's then a whole host of things I'll need to get done for CC2:
|
||||
- some kind of actual parsing strategy (that's good enough for "Dissociated Press"/Markov chains)
|
||||
|
@ -243,41 +243,41 @@ To reiterate the punch list that *I would have needed for Computer Class 1*:
|
|||
* [x] jump instructions need 16 bits of operand
|
||||
- Whew, that took longer than I expected
|
||||
* [x] splatterns
|
||||
- [ ] validator should ensure splatterns are the longest patterns in a form
|
||||
* [ ] improve validator
|
||||
- [ ] Tuples may not be longer than n members
|
||||
- [ ] Loops may not have splatterns
|
||||
- [ ] Identify others
|
||||
- [-] validator should ensure splatterns are the longest patterns in a form
|
||||
* [-] improve validator
|
||||
- [-] Tuples may not be longer than n members
|
||||
- [-] Loops may not have splatterns
|
||||
- [-] Identify others
|
||||
* [x] add guards to loop forms
|
||||
* [x] check loop forms against function calls: do they still work the way we want them to?
|
||||
* [x] tail call elimination
|
||||
* [x] stack traces in panics
|
||||
|
||||
* [ ] actually good error messages
|
||||
- [ ] parsing
|
||||
- [ ] my memory is that validator messages are already good?
|
||||
- [ ] panics, esp. no match panics
|
||||
* [ ] getting to prelude
|
||||
- [ ] `base` should load into Prelude
|
||||
- [ ] prelude should run properly
|
||||
- [ ] prelude should be loaded into every context
|
||||
* [ ] packaging things up
|
||||
- [ ] add a `to_json` method for values
|
||||
- [ ] teach Rudus to speak our protocols (stdout and turtle graphics)
|
||||
- [ ] there should be a Rust function that takes Ludus source and returns valid Ludus status json
|
||||
- [ ] compile Rust to WASM
|
||||
- [ ] wire Rust-based WASM into JS
|
||||
- [ ] FINALLY, test Rudus against Ludus test cases
|
||||
* [-] actually good error messages
|
||||
- [-] parsing
|
||||
- [-] my memory is that validator messages are already good?
|
||||
- [-] panics, esp. no match panics
|
||||
* [-] getting to prelude
|
||||
- [-] `base` should load into Prelude
|
||||
- [-] prelude should run properly
|
||||
- [-] prelude should be loaded into every context
|
||||
* [-] packaging things up
|
||||
- [-] add a `to_json` method for values
|
||||
- [-] teach Rudus to speak our protocols (stdout and turtle graphics)
|
||||
- [-] there should be a Rust function that takes Ludus source and returns valid Ludus status json
|
||||
- [-] compile Rust to WASM
|
||||
- [-] wire Rust-based WASM into JS
|
||||
- [-] FINALLY, test Rudus against Ludus test cases
|
||||
|
||||
So this is the work of the week of June 16, maybe?
|
||||
|
||||
Just trying to get a sense of what needs to happen for CC2:
|
||||
* [ ] Actor model (objects, Spacewar!)
|
||||
* [ ] Animation hooked into the web frontend (Spacewar!)
|
||||
* [ ] Text input (Spacewar!)
|
||||
- [ ] Makey makey for alternate input?
|
||||
* [ ] Saving and loading data into Ludus (perceptrons, dissociated press)
|
||||
* [ ] Finding corpuses for Dissociated Press
|
||||
* [x] Actor model (objects, Spacewar!)
|
||||
* [-] Animation hooked into the web frontend (Spacewar!)
|
||||
* [-] Text input (Spacewar!)
|
||||
- [-] Makey makey for alternate input?
|
||||
* [-] Saving and loading data into Ludus (perceptrons, dissociated press)
|
||||
* [-] Finding corpuses for Dissociated Press
|
||||
|
||||
### Final touches on semantics, or lots of bugs
|
||||
#### 2025-06-19
|
||||
|
@ -309,32 +309,32 @@ So this is my near-term TODO:
|
|||
- [x] `base` should load into Prelude
|
||||
- [x] write a mock prelude with a few key functions from real prelude
|
||||
- [x] a prelude should be loaded into every context
|
||||
- [ ] the full prelude should run properly
|
||||
* [ ] packaging things up
|
||||
- [ ] add a `to_json` method for values
|
||||
- [ ] teach Rudus to speak our protocols (stdout and turtle graphics)
|
||||
- [ ] there should be a Rust function that takes Ludus source and returns valid Ludus status json
|
||||
- [ ] compile Rust to WASM
|
||||
- [ ] wire Rust-based WASM into JS
|
||||
- [ ] FINALLY, test Rudus against Ludus test cases
|
||||
- [?] the full prelude should run properly
|
||||
* [x] packaging things up
|
||||
- [x] add a `to_json` method for values
|
||||
- [x] teach Rudus to speak our protocols (stdout and turtle graphics)
|
||||
- [x] there should be a Rust function that takes Ludus source and returns valid Ludus status json
|
||||
- [x] compile Rust to WASM
|
||||
- [x] wire Rust-based WASM into JS
|
||||
- [-] FINALLY, test Rudus against Ludus test cases
|
||||
|
||||
And then: quality of life improvements:
|
||||
* [ ] refactor messes
|
||||
- [ ] The compiler should abstract over some of the very titchy bytecode instruction code
|
||||
- [ ] Pull apart some gargantuan modules into smaller chunks: e.g., `Op` and `Chunk` should be their own modules
|
||||
- [ ] Identify code smells
|
||||
- [ ] Fix some of them
|
||||
* [ ] improve validator
|
||||
- [ ] Tuples may not be longer than n members
|
||||
- [ ] Loops may not have splatterns
|
||||
- [ ] Identify others
|
||||
- [ ] Splats in functions must be the same arity, and greater than any explicit arity
|
||||
* [ ] actually good error messages
|
||||
- [ ] parsing
|
||||
- [ ] my memory is that validator messages are already good?
|
||||
- [ ] panics, esp. no match panics
|
||||
* [ ] panics should be able to refernce the line number where they fail
|
||||
* [ ] that suggests that we need a mapping from bytecodes to AST nodes
|
||||
* [-] refactor messes
|
||||
- [x] The compiler should abstract over some of the very titchy bytecode instruction code
|
||||
- [x] Pull apart some gargantuan modules into smaller chunks: e.g., `Op` and `Chunk` should be their own modules
|
||||
- [x] Identify code smells
|
||||
- [x] Fix some of them
|
||||
* [-] improve validator
|
||||
- [-] Tuples may not be longer than n members
|
||||
- [-] Loops may not have splatterns
|
||||
- [-] Identify others
|
||||
- [-] Splats in functions must be the same arity, and greater than any explicit arity
|
||||
* [-] actually good error messages
|
||||
- [-] parsing
|
||||
- [-] my memory is that validator messages are already good?
|
||||
- [-] panics, esp. no match panics
|
||||
* [-] panics should be able to refernce the line number where they fail
|
||||
* [-] that suggests that we need a mapping from bytecodes to AST nodes
|
||||
* The way I had been planning on doing this is having a vec that moves in lockstep with bytecode that's just references to ast nodes, which are `'static`, so that shouldn't be too bad. But this is per-chunk, which means we need a reference to that vec in the VM. My sense is that what we want is actually a separate data structure that holds the AST nodes--we'll only need them in the sad path, which can be slow.
|
||||
|
||||
### Bugs discovered while trying to compile prelude
|
||||
|
@ -381,15 +381,15 @@ So here's a short punch list of things to do in that register:
|
|||
* [x] Hook validator back in to both source AND prelude code
|
||||
- [x] Validator should know about the environment for global/prelude function
|
||||
- [x] Run validator on current prelude to fix current known errors
|
||||
* [ ] Do what it takes to compile this interpreter into Ludus's JS environment
|
||||
- [ ] JSONify Ludus values
|
||||
- [ ] Write a function that's source code to JSON result
|
||||
- [ ] Expose this to a WASM compiler
|
||||
- [ ] Patch this into a JS file
|
||||
- [ ] Automate this build process
|
||||
* [ ] Start testing against the cases in `ludus-test`
|
||||
* [ ] Systematically debug prelude
|
||||
- [ ] Bring it in function by function, testing each in turn
|
||||
* [x] Do what it takes to compile this interpreter into Ludus's JS environment
|
||||
- [x] JSONify Ludus values
|
||||
- [x] Write a function that's source code to JSON result
|
||||
- [x] Expose this to a WASM compiler
|
||||
- [x] Patch this into a JS file
|
||||
- [-] Automate this build process
|
||||
* [-] Start testing against the cases in `ludus-test`
|
||||
* [-] Systematically debug prelude
|
||||
- [-] Bring it in function by function, testing each in turn
|
||||
|
||||
***
|
||||
I've started working on systematically going through the Prelude.
|
||||
|
@ -486,19 +486,19 @@ I may be surprised, though.
|
|||
|
||||
Currently fixing little bugs in prelude.
|
||||
Here's a list of things that need doing:
|
||||
* [ ] Escape characters in strings: \n, \t, and \{, \}.
|
||||
* [ ] `doc!` needs to print the patterns of a function.
|
||||
* [ ] I need to return to the question of whether/how strings are ordered; do we use `at`, or do we want `char_at`? etc.
|
||||
* [ ] Original implementation of `butlast` is breaking stack discipline; I don't know why. It ends up returning from evaluating one of the arguments straight into a `load` instruction. Something about tail calls and ternary synthetic expressions and base functions. (For now, I can call `slice` instead of `base :slice` and it works.)
|
||||
* [-] Escape characters in strings: \n, \t, and \{, \}.
|
||||
* [-] `doc!` needs to print the patterns of a function.
|
||||
* [-] I need to return to the question of whether/how strings are ordered; do we use `at`, or do we want `char_at`? etc.
|
||||
* [-] Original implementation of `butlast` is breaking stack discipline; I don't know why. It ends up returning from evaluating one of the arguments straight into a `load` instruction. Something about tail calls and ternary synthetic expressions and base functions. (For now, I can call `slice` instead of `base :slice` and it works.)
|
||||
- Original version of `update` also had this same problem with `assoc`; fixed it by calling the Ludus, rather than Rust, function.
|
||||
- I need this fixed for optimization reasons.
|
||||
- I _think_ I just fixed this by fixing tail position tracking in collections
|
||||
- [ ] test this
|
||||
- [-] test this
|
||||
- I did not fix it.
|
||||
* [x] Dict patterns are giving me stack discipline grief. Why is stack discipline so hard?
|
||||
* [ ] This is in the service of getting turtle graphics working
|
||||
* [x] This is in the service of getting turtle graphics working
|
||||
* Other forms in the language need help:
|
||||
* [ ] repeat needs its stack discipline updated, it currently crashes the compiler
|
||||
* xx] repeat needs its stack discipline updated, it currently crashes the compiler
|
||||
|
||||
### More closure problems
|
||||
#### 2025-06-23
|
||||
|
@ -738,13 +738,13 @@ println!("line {line_no}: {}", lines[line_no - 1]);
|
|||
#### 2025-06-25
|
||||
* Web workers
|
||||
* My javascript wrapper needs to execute WASM in its own thread (ugh)
|
||||
- [ ] is this a thing that can be done easily in a platform-independent way (node vs. bun vs. browser)?
|
||||
- [-] is this a thing that can be done easily in a platform-independent way (node vs. bun vs. browser)?
|
||||
* Top priorities:
|
||||
- [ ] Get a node package out
|
||||
- [ ] Stand up actors + threads, etc.
|
||||
- [ ] How to model keyboard input from p5?
|
||||
* [ ] Model after the p5 keyboard input API
|
||||
* [ ] ludus keyboard API: `key_is_down(), key_pressed(), key_released()`, key code values (use a dict)
|
||||
- [-] Get a node package out
|
||||
- [-] Stand up actors + threads, etc.
|
||||
- [-] How to model keyboard input from p5?
|
||||
* [-] Model after the p5 keyboard input API
|
||||
* [-] ludus keyboard API: `key_is_down(), key_pressed(), key_released()`, key code values (use a dict)
|
||||
- Assets:
|
||||
* We don't (for now) need to worry about serialization formats, since we're not doing perceptrons
|
||||
* We do need to read from URLs, which need in a *.ludus.dev.
|
||||
|
@ -827,11 +827,11 @@ But everything else? Seems pretty straightforward.
|
|||
I've implemented what I decribe above. It works! I'm low-key astonished.
|
||||
It perfectly handles an infinitely recurring process! What the fuck.
|
||||
Anyway, things left to do:
|
||||
* [ ] `receive` forms are the big one: they require threading through the whole interpreter
|
||||
* [x] `receive` forms are the big one: they require threading through the whole interpreter
|
||||
* [x] implement the missing process functions at the end of prelude
|
||||
* [ ] research how Elixir/Erlang's abstractions over processes work (I'm especially interested in how to make synchronous-looking calls); take a look especially at https://medium.com/qixxit-development/build-your-own-genserver-in-49-lines-of-code-1a9db07b6f13
|
||||
* [ ] write some examples just using these simple tools (not even GenServer, etc.) to see how they work, and to start building curriculum
|
||||
* [ ] develop a design for how to deal with asynchronous io with js
|
||||
* [-] research how Elixir/Erlang's abstractions over processes work (I'm especially interested in how to make synchronous-looking calls); take a look especially at https://medium.com/qixxit-development/build-your-own-genserver-in-49-lines-of-code-1a9db07b6f13
|
||||
* [-] write some examples just using these simple tools (not even GenServer, etc.) to see how they work, and to start building curriculum
|
||||
* [-] develop a design for how to deal with asynchronous io with js
|
||||
|
||||
```ludus
|
||||
fn agent/get (pid) -> {
|
||||
|
@ -870,7 +870,7 @@ Two things that pop out to me:
|
|||
|
||||
### Rethinking reception
|
||||
#### 2025-06-27
|
||||
So one thing that's stuck with me is that in Elixir, `receive` isn't a special form: it's a function that takes a block.
|
||||
So one thing that's stuck with me is that in Elixir, ~`receive` isn't a special form: it's a function that takes a block~ (**EDIT**: it is indeed a special form in Elixir, and it has to be on in Ludus.).
|
||||
It may be a macro, but it's still mostly normalish, and doesn't invovle compiler shenanigans.
|
||||
|
||||
So, this is what I want to write:
|
||||
|
@ -955,7 +955,7 @@ So the flushing would need to happen in the receiver.
|
|||
|
||||
|
||||
A few things that are wrong right now:
|
||||
* [ ] `loop`/`recur` is still giving me a very headache. It breaks stack discipline to avoid packing tuples into a heap-allocated vec. There may be a way to fix this in the current compiler scheme around how I do and don't handle arguments--make recur stupider and don't bother loading anything. A different solution would be to desugar loop into an anonymous function call. A final solution would be just to use a heap-allocated tuple.
|
||||
* [-] `loop`/`recur` is still giving me a very headache. It breaks stack discipline to avoid packing tuples into a heap-allocated vec. There may be a way to fix this in the current compiler scheme around how I do and don't handle arguments--make recur stupider and don't bother loading anything. A different solution would be to desugar loop into an anonymous function call. A final solution would be just to use a heap-allocated tuple.
|
||||
|
||||
Minimal failing case:
|
||||
```ludus
|
||||
|
@ -965,16 +965,19 @@ match (nil) with {
|
|||
}
|
||||
}
|
||||
```
|
||||
* [ ] The amount of sugar needed to get to `receive` without making a special form is too great.
|
||||
* [x] The amount of sugar needed to get to `receive` without making a special form is too great.
|
||||
|
||||
In particular, function arities need to be changed, flushes need to be inserted, anonymous lambdas need to be created (which can't be multi-clause), etc.
|
||||
|
||||
~* [ ] There was another bug that I was going to write down and fix, but I forgot what it was. Something with processes.~
|
||||
* [ ] I remembered: I got some weird behaviour when `MAX_REDUCTIONS` was set to 100; I've increased it to 1000, but now need to test what happens when we yield because of reductions.
|
||||
_This is now implemented._
|
||||
|
||||
* [ ] Also: the `butlast` bug is still outstanding: `base :slice` causes a panic in that function, but not the call to the Ludus function. Still have to investigate that one.
|
||||
~* [-] There was another bug that I was going to write down and fix, but I forgot what it was. Something with processes.~
|
||||
* [-] I remembered: I got some weird behaviour when `MAX_REDUCTIONS` was set to 100; I've increased it to 1000, but now need to test what happens when we yield because of reductions.
|
||||
|
||||
* [ ] In testing this, it's looking like `match` is misbehaving; none of the matches that *should* happen in my fully sugarless `receive` testing are matching how they ought.
|
||||
* [-] Also: the `butlast` bug is still outstanding: `base :slice` causes a panic in that function, but not the call to the Ludus function. Still have to investigate that one.
|
||||
|
||||
* [x] In testing this, it's looking like `match` is misbehaving; none of the matches that *should* happen in my fully sugarless `receive` testing are matching how they ought.
|
||||
- That is not what was happening. The mailbox
|
||||
|
||||
I haven't got to a minimal case, but here's what's not working:
|
||||
```ludus
|
||||
|
@ -1098,3 +1101,47 @@ Here's some pseudobytecode to get us to where we need to be:
|
|||
090 jump to 025 (not really in bytecode; this will be unrolled)
|
||||
100 receive end
|
||||
|
||||
#### a short time later
|
||||
Well, that worked! The real issue was the jump back if we're out of messages.
|
||||
|
||||
That leaves the following list:
|
||||
* [a] research how Elixir/Erlang's abstractions over processes work (I'm especially interested in how to make synchronous-looking calls); take a look especially at https://medium.com/qixxit-development/build-your-own-genserver-in-49-lines-of-code-1a9db07b6f13
|
||||
* [ ] write some examples just using these simple tools (not even GenServer, etc.) to see how they work, and to start building curriculum
|
||||
* [a] develop a design for how to deal with asynchronous io with js
|
||||
* [a] I got some weird behaviour when `MAX_REDUCTIONS` was set to 100; I've increased it to 1000, but now need to test what happens when we yield because of reductions.
|
||||
* [a] Also: the `butlast` bug is still outstanding: `base :slice` causes a panic in that function, but not the call to the Ludus function. Still have to investigate that one.
|
||||
- Original version of `update` also had this same problem with `assoc`; fixed it by calling the Ludus, rather than Rust, function.
|
||||
* [a] `loop`/`recur` is still giving me a very headache. It breaks stack discipline to avoid packing tuples into a heap-allocated vec. There may be a way to fix this in the current compiler scheme around how I do and don't handle arguments--make recur stupider and don't bother loading anything. A different solution would be to desugar loop into an anonymous function call. A final solution would be just to use a heap-allocated tuple.
|
||||
* My javascript wrapper needs to execute WASM in its own thread (ugh)
|
||||
- [ ] is this a thing that can be done easily in a platform-independent way (node vs. bun vs. browser)?
|
||||
* Top priorities:
|
||||
- [-] Get a node package out
|
||||
- [x] Stand up actors + threads, etc.
|
||||
- [ ] How to model keyboard input from p5?
|
||||
* [ ] Model after the p5 keyboard input API
|
||||
* [ ] ludus keyboard API: `key_is_down(), key_pressed(), key_released()`, key code values (use a dict)
|
||||
* [a] Escape characters in strings: \n, \t, and \{, \}.
|
||||
* [ ] `doc!` needs to print the patterns of a function.
|
||||
* [ ] I need to return to the question of whether/how strings are ordered; do we use `at`, or do we want `char_at`? etc.
|
||||
* [ ] Automate this build process
|
||||
* [ ] Start testing against the cases in `ludus-test`
|
||||
* [ ] Systematically debug prelude
|
||||
- [ ] Bring it in function by function, testing each in turn
|
||||
* [ ] Animation hooked into the web frontend (Spacewar!)
|
||||
* [ ] Text input (Spacewar!)
|
||||
- [ ] Makey makey for alternate input?
|
||||
* [ ] Saving and loading data into Ludus (perceptrons, dissociated press)
|
||||
* [ ] Finding corpuses for Dissociated Press
|
||||
* [ ] improve validator
|
||||
- [ ] Tuples may not be longer than n members
|
||||
- [ ] Loops may not have splatterns
|
||||
- [ ] Identify others
|
||||
- [ ] Splats in functions must be the same arity, and greater than any explicit arity
|
||||
* [ ] actually good error messages
|
||||
- [ ] parsing
|
||||
- [ ] my memory is that validator messages are already good?
|
||||
- [ ] panics, esp. no match panics
|
||||
* [ ] panics should be able to refernce the line number where they fail
|
||||
* [ ] that suggests that we need a mapping from bytecodes to AST nodes
|
||||
* The way I had been planning on doing this is having a vec that moves in lockstep with bytecode that's just references to ast nodes, which are `'static`, so that shouldn't be too bad. But this is per-chunk, which means we need a reference to that vec in the VM. My sense is that what we want is actually a separate data structure that holds the AST nodes--we'll only need them in the sad path, which can be slow.
|
||||
|
||||
|
|
18
src/vm.rs
18
src/vm.rs
|
@ -1222,30 +1222,18 @@ impl Creature {
|
|||
NextMessage => {
|
||||
self.msg_idx += 1;
|
||||
}
|
||||
LoadMessage => {
|
||||
println!("loading message {} in {}", self.msg_idx, self.pid);
|
||||
match self.mbx.get(self.msg_idx) {
|
||||
Some(msg) => {
|
||||
println!("loaded message: {msg}");
|
||||
self.push(msg.clone())
|
||||
}
|
||||
LoadMessage => match self.mbx.get(self.msg_idx) {
|
||||
Some(msg) => self.push(msg.clone()),
|
||||
None => {
|
||||
println!("no more messages in {}", self.pid);
|
||||
self.msg_idx = 0;
|
||||
self.r#yield = true;
|
||||
self.ip -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
MatchMessage => {
|
||||
let matched = self.mbx.remove(self.msg_idx).unwrap();
|
||||
println!(
|
||||
"matched in {}: @idx {}, msg {matched}",
|
||||
self.pid, self.msg_idx
|
||||
);
|
||||
}
|
||||
ClearMessage => {
|
||||
println!("clearing messages in {}", self.pid);
|
||||
self.msg_idx = 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user