FolkComputer / folk

🎁 Physical computing system.
https://folk.computer
Apache License 2.0
75 stars 4 forks source link

folk.js library for consuming from JS #156

Closed s-ol closed 2 months ago

s-ol commented 2 months ago

WS message are executed in the context of a match that is tied to the websocket lifetime. An emit prefix msg proc is provided, and the JS code dispatches messages based on the prefix value.

Utilities for encoding and decoding Tcl strings are provided, including a tagged template literal:

const complicatedString = 'This string {contains} some {} odd "stuff"';
tcl`We ${'embed'} ${complicatedString} here`
// 'We embed {This string {contains} some {} odd "stuff"} here' 

const json = [ { name: "Sol", age: 27 }, { name: "folk", age: "-1" } ];
ws.send(tcl`Assert the entities are ${json}`);
// 'Assert the entities are {{name Sol age 27} {name folk age -1}}'

const tclVal = '{name Sol age 27} {name folk age -1}';
loadList(tclVal).map(loadDict);
// [ { "name": "Sol", "age": "27" }, { "name": "folk", "age": "-1" } ]
s-ol commented 2 months ago

There's something subtly wrong with Commit but I don't understand why - when re-committing statements that had been committed in the past nothing happens. This can be reproduced using /new:

osnr commented 2 months ago

There's something subtly wrong with Commit but I don't understand why - when re-committing statements that had been committed in the past nothing happens. This can be reproduced using /new:

  • create an error (Wash $this is outlined blue) and save

    • the error is shown
  • fix the error (Wish $this is outlined blue) and save

    • the error is cleared
  • trigger the same error (Wash $this is outlined blue) and save

    • no error is shown
  • trigger a different error (Wash $this is outlined red) and save

    • the error is shown

Yes, I see this too -- can't go back to previous program source code, the Commit just doesn't work. I'll look into this a bit more over the next couple days.

Otherwise looks good, this is really clean and feel like we'll use it a lot

osnr commented 2 months ago

There's something subtly wrong with Commit but I don't understand why - when re-committing statements that had been committed in the past nothing happens. This can be reproduced using /new:

  • create an error (Wash $this is outlined blue) and save

    • the error is shown
  • fix the error (Wish $this is outlined blue) and save

    • the error is cleared
  • trigger the same error (Wash $this is outlined blue) and save

    • no error is shown
  • trigger a different error (Wash $this is outlined red) and save

    • the error is shown

Yes, I see this too -- can't go back to previous program source code, the Commit just doesn't work. I'll look into this a bit more over the next couple days.

Otherwise looks good, this is really clean and feel like we'll use it a lot

I think the problem might be that the Assert when websocket $chan is connected [subst {{this} {$msg}}] with environment [list $chan] is exactly the same statement, so it just gets rolled into the existing Assert that's already in the db and doesn't trigger any new evaluation. You could generate a random number or sequence number in handleWS, probably.

s-ol commented 2 months ago

I think the problem might be that the Assert when websocket $chan is connected [subst {{this} {$msg}}] with environment [list $chan] is exactly the same statement, so it just gets rolled into the existing Assert that's already in the db and doesn't trigger any new evaluation. You could generate a random number or sequence number in handleWS, probably.

Adding a timestamp to the when's environment seems to have done the trick :+1:

osnr commented 2 months ago
image

Hmm, I don't like the leak here when you drag the region around -- maybe we should think about a different approach, or add a layer where you can commit so that it knows that it can replace the prev commit?

(I also wonder if the millisecond counter is not precise enough if you send a bunch of stuff in a row)

s-ol commented 2 months ago

maybe we should think about a different approach, or add a layer where you can commit so that it knows that it can replace the prev commit?

hm, you mean use something like Commit $chan { ... } so that only the last snippet is ever in the DB? That could work, and it should solve the above problem without using the timestamp as well.

Feels like really #76 should be solved first tho, and whatever comes out of that used here

s-ol commented 2 months ago

Ah, right, just putting the message into a Commit doesn't really work because then each new message undoes the previous messages (apart from stateful Tcl/OS interactions). So maybe there needs to be a js ws.Commit(...) function that uses a "top-level Commit" to make sure previous statements are fully retracted, and a ws.Eval(...) that executes code with a connection-length lifetime.

There's still the case for a different logic for triggering events, the main example currently being printing. A possibility would be an ws.AssertTemp(...) that does an Assert followed by Retract.

osnr commented 2 months ago

This is all set from my point of view. I'll merge it later today if you think the changes are OK @s-ol

s-ol commented 2 months ago

Just noticed the Tcl parsing still has bugs; typing an } while viewing web-keyboards.folk throws an exception. looking into that Edit: I'm not 100% I got the JS part right but this is actually a mistake on the Tcl side, the websocket sends this string, which is not a well-formed Tcl list:

channel-0 {add {kb /dev/input/by-path/platform-i8042-serio-0-event-kbd p \}} m15579:198}

Edit again: didn't realize backslashes do have some special meaning in brace-strings

s-ol commented 2 months ago

Okay that particular escaping thing is solved, I finally found the authoritative source on the topic: https://www.tcl.tk/man/tcl8.7/TclCmd/Tcl.html#M10

The parsing is definitely not 100% compliant yet, in particular it doesn't properly implement escaped newlines as described there

osnr commented 2 months ago

@s-ol how are you feeling about this? do you want me to do another pass or are you working on it?

(we could also just merge it as is if it works)

osnr commented 2 months ago

(I'm leaving ws.commit as is on the argument that at least it behaves the same way as Folk Commit, which also doesn't automatically uncommit on parent program removal. Probably both need to be replaced with something better eventually.)