Thursday, December 1, 2011

Indexed stack shufflers

Some 12 hours ago a guest on #concatenative shared this idea for a new syntax for stack shuffling:
"world" ", " "hello" "!" <1 2 3 0> 4append ! => "hello, world!"

I decided that would be a great challenge and an opportunity to level up my macro skills. Here it is:
USING: fry grouping kernel lexer locals locals.parser
locals.types make math math.order math.parser multiline
namespaces parser quotations sequences vocabs.parser words ;
IN: shortlocals

! 4 -> { "arg-3" "arg-2" "arg-1" "arg-0" }
: >params-0 ( n -- vec )
1 + iota reverse [ number>string "arg-" prepend ] map ;

! 3 -> { "arg-1" "arg-2" "arg-3" }
: >params-n ( n -- vec )
1 + iota unclip drop [ number>string "arg-" prepend ] map ;

! like \ supremum but for seqs with non-numbers intermixed
: max-num ( seq -- n )
[ number? ] filter supremum ;

SYNTAX: [0>
[let 0 :> largest!
"]"
[
! = modded parse-datum
dup string>number [ dup string>number largest max largest! "arg-" prepend ] [ ] if
] map-tokens
largest
] >params-0 ! -- words params
'[ [ _ [ make-local ] map ] H{ } make-assoc ] dip
'[ _ [ dup search [ ] [ dup string>number [ ] [ no-word ] ?if ] ?if ] map >quotation ]
((parse-lambda))
<lambda> ?rewrite-closures append! ;
! final version of 0[

SYNTAX: [n>
[let 0 :> largest!
"]"
[
! = modded parse-datum
dup string>number [ dup string>number largest max largest! "arg-" prepend ] [ ] if
] map-tokens
largest
] >params-n ! -- words params
'[ [ _ [ make-local ] map ] H{ } make-assoc ] dip
'[ _ [ dup search [ ] [ dup string>number [ ] [ no-word ] ?if ] ?if ] map >quotation ]
((parse-lambda))
<lambda> ?rewrite-closures append! ;



! top-of-stack is 0, below that is 1, and so forth
"world" ", " "hello" "!" [0> 1 2 3 0 3append append ] call . ! => "hello, world!"

! natural order: "world" is 1, the comma is 2, "hello" is 3 and "!" is 4:
"world" ", " "hello" "!" [n> 3 2 1 4 3append append ] call . ! => "hello, world!"

It's a bit of a mess still as I haven't refactored it yet, and as there's some code that I copied from other words' definitions instead of calling the word (because I was changing some bits but ended up mostly leaving the way it was and not undoing the mess).
I'll explain the code and what I learned from the experience tomorrow.

No comments:

Post a Comment