Text-based Snap using metaprogramming


Since some cool metaprogramming features were added in Snap! 8, I tried to create a text interface to Snap. I've seen a couple of these posted on the forum previously but as far as I can tell they're all just using an alist of command names and corresponding blocks to run (or worse, a giant if/else tree!), whereas this project looks up the block to run "simply" by using

[scratchblocks]my [blocks v] :: sensing reporter [/scratchblocks]

to find all the available blocks, mapping

[scratchblocks][label v] of block ({...} @addInput :: grey ring) :: control reporter [/scratchblocks]

over that, and returning the first block whose label matches the pattern constructed by the parser. I tried to add more comments to my code than I usually do, so hopefully you can figure out what's going on in the parser if you want to look at how it does that.

Speaking of the parser, it isn't very good (this is just a proof-of-concept after all) so you will almost certainly run into expressions that ought to work but don't - I might fix this in the future but no guarantees - as well as problems like the + block, which is variadic, so its label is just _ rather than _ + _ making it impossible to use. The general syntax is described in the project notes. Here are some examples of things you can try (press your Insert key to paste them in):

  • map {length of text ()} over (split (help) by 'word') (returns a list of word lengths from the help message)
  • ask 'some question' and wait, followed by answer
  • map {pick random (1) to (1000)} over (numbers from (1) to (10)) (returns 10 random numbers)
  • split ('definition' of block {parse ()}) by 'blocks' (returns a somewhat lacking representation of the implementation of the parser)
  • join (all but first of (split (help) by 'letter'))
  • map {join ['/', (), 'ə/']} over ['p','t','k','b','d','g'] (shows strange behaviour of JOIN due to variadic input - the consonants should only appear once per item, but they get appended as well)

As stated in the project notes, I'm planning on supporting semicolon-delimited scripts and improving textual representation of rings (currently just shown as <!>) but once again, no guarantees!

this is nice! i like this!

Beautiful! I love programming languages inside of Snap!


Instead of FIND FIRST, you might find all the blocks matching the label and then use other features of the block to disambiguate. That would solve your + problem while also solving the _ OF _ problem.

Yeah, that sounds good. I was thinking of using the input slot types as well as dropdown-menu options to do that (so it would choose the sensing OF if the first argument was 'costume #' but the lists OF if it was 'length' for example)

Yeah exactly.

Ok, I've implemented the type-checking, which works great (it can tell the difference between OFs now), but I'm not sure how to check menu options - when trying to see the list of options for blocks with dynamic menus, including the sensing OF, it just returns "attributesMenu" or similar, which I can't really do anything with

Also, this doesn't solve the "+ problem" as its label is literally just "_" so (e.g.) writing "(1) + (2)" looks for a block called "_ + _" which doesn't exist
Edit: escaped underscores

Fixed italicization.

Yeah why does it do that?

_<text>_ in Markdown indicates italicization, as well as *<text>*.

I was thinking that once you know which block you're talking about, you build the options into your code. There aren't all that many such blocks.

About + and friends, I guess you have to equality-test the actual blocks, not just the labels.

i feel like +, *, min, max, should just have sum, product, minimum, maximum as their labels since that's what they're called when given an input list