|
Spaces home Caution: Singularity Ahe...PhotosProfileFriendsMore ![]() | ![]() |
Caution: Singularity AheadJoshua Bell's Personal Blog
August 25 A nice turtle reductionI've been poking away at my Logo Interpreter for the past week. A whole bunch of changes went in - it now supports 64 built-in procedures (25 Turtle Graphics, 25 arithmetic/logical/comparisons, plus flow control, etc.), infix expressions (+-*/%^, etc.), and attempts to adhere to the UCBLogo and Apple II Logo "standards" where possible. (They are only "standards" as every Logo interpreter has its own quirks; it's a far less standardized language than BASIC.) To wrap up the tinkering today, I decided to tackle a "weird" bit of syntax - calling a procedure within parenthesis. In most programming languages, () are grouping characters around expressions. This is true in Logo as well so you can do FORWARD (1+2)*3. But Logo also supports a convention for calling functions that may consume an unlimited number of arguments - e.g. (SUM 1 2 3 4). This required adding two new bits of logic - the syntax handling, and the function handling. First, a special case for the ( operator so that if the first atom inside is an identifier, don't simply evaluate the contents but instead create a list from the following expressions. So (SUM 1 2 + 3 4) prepares a list [ 1 5 4 ] to hand off. Second, the handling. I started looking in dread at the functions - how do I make SUM handle 2 (in a non-list context) or a list of arguments? I started off special-casing the function and caller to pass in "multi" mode. That was lame, when you need to do it for some large fraction of the 64 functions (SUM, PRODUCT, AND, OR, WORD, ...). An alternative would be to specify the "arity" as metadata for each function - so the evaluator would know before calling that SUM would consume two inputs in a sequence like PRODUCT 2 SUM 3 MINUS 12 and take care of the evaluation. This scales (and is probably the standard implementation technique).... but still wasn't elegant enough. Instead, after staring at the functions, I decided to use a reduce (or fold) heuristic. So SUM only ever consumes two inputs from the input list. But when called in a parenthetical context, it keeps getting called until there are no inputs left in the list, e.g.
This is called folding or reducing over a function - in some languages, you can call reduce( myfunctions, inputs ... ) and it basically does this same thing, calling the function repeatedly until you run out. The nice thing is that for the built-in procedures like PRODUCT, SUM, WORD, AND, OR, etc. this does exactly what you'd expect. What's neat though is that this instantly - with no other changes to the code - you can apply this to user defined functions. So you can do:
That's a fairly lame example - anything better? To avoid locking up when you call a function that consumes no inputs like (HIDETURTLE) I put in a check so that if no arguments are consumed the reduction terminates. August 16 Logo Interpreter in JavascriptOthers have done it better, but I thought I'd take a stab at a Logo interpreter in Javascript. So here it is - warning, doesn't work in Internet Explorer (yet). The TODO list is pretty large. Right now it uses the "canvas" element so it only works in Firefox, Safari and Opera (i.e. not I.E.). I plan to make it optionally use VML (in IE), SVG or canvas. August 04 Product Idea I want one of these:
... but made of carbon fiber so it weighs practically nothing. Surely there's a market for that? (And I'm not going to spend $2000 on one from a company called Halliburton.) Anyone? July 19 Nebula Class ToybashThis project has been on my TODO list for many years. I finally dusted off the pieces last weekend and took it to a reasonable stopping point. At least, for a few more years. It's a conversion of a Playmates Galaxy-class U.S.S. Enterprise NCC-1701-D into a Nebula-class ship. I'd picked the ship up on eBay ages ago, and separated(poorly!) the hulls, but then it sat for a few years. The hulls are joined together by screws inside the secondary hull, so it can be disassembled for further work. The wiring and electronics are intact. The sound effects buttons are in pairs, and there wasn't room for one of them, so only two buttons/sounds remain. I swapped the button leads around so it has "photon torpedo" and "jump to warp" as the functional SFX. The nacelle lighting also still works. (Not shown in pictures.) Since this is a kitbash, it diverges from the actual Nebula-class design, and more closely resembles the Nebula-class prototypes used as background set props and graveyard ships in episodes of TNG and DS9. Specifically, the secondary hull is too pointy and the nacelles/pylons are too far back.
The junction between the primary and secondary hull has a gap - it required significant eyeballing to get the cut lines right. I'd also completely removed the "cobra head" portion of the neck from the lower half of the hull, so it was actually a matter of figuring out how much to reattach. The undercut at the bottom of the secondary hull (where the nacelle pylons used to attach) is covered with an as-yet un-detailed polystyrene plate. The TODO list for the far distant future includes:
July 12 vnIIc Update - Keyboard/Joystick supportCrossing something off my TODO list (and giving my brain a rest for a while) I dusted off some in-progress work on vnIIc and published version 1.0.0.15. Changes:
Most of this has been done for a while, but unpublished. The initial protocol was one way only. I'd bodged in handling receiving data from the client, but it was done with an asynchronous event handler and the system would behave unreliably. The server would continue to stream data to the client while it was busy reading the paddle states (which can take several milliseconds) and all hell would break loose. I reworked the protocol to be synchronous (the server sends 256 bytes of graphic data, then reads 1 byte of input state data), and then spent 2 hours tracking down a silly bug where the client would fall into an infinite loop. At that point, everything was rock solid. This probably means I can simplify the client->server transmission protocol. Right now it sends keyboard state (if changed) *or* open apple state (if changed) *or* closed apple state (if changed) *or* paddle 0 state (if changed) *or* paddle 1 state (if changed) *or* a sync byte - in other words, it sends the most relevant state change as a single byte. This is legacy from when the time the client would spend computing what to send and sending it would cause the communication to fall out of sync. Now that it is synchronous, I can probably just send everything. It also means that I can bolt on mouse support some time soon. (i.e. in 6 months when I feel like touching this again)
|
Geeky projects at various levels of completion
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|