Skip to content

Instantly share code, notes, and snippets.

@crcx
Forked from tangentstorm/FORLOOP.rx
Last active December 11, 2015 13:49
Show Gist options
  • Save crcx/4610280 to your computer and use it in GitHub Desktop.
Save crcx/4610280 to your computer and use it in GitHub Desktop.
## OBERON SYNTAX TO COMPILE:
FOR x := start TO goal BY step DO
block
END;
## StringTemplate ( generating retro code ):
for_stmt(id, beg, end, step, block) ::= <<
( FOR ) <id>
( := ) <beg>
( TO ) <end>
( BY ) <step>
( DO
[
<block>
]
( END ) FOR
>>
## Retro helper macro
{{
( Helper functions )
: relop dup 2 + @ 0 > [ &<= ] [ &>= ] if ;
: start dup 4 + 1 , , ;
: goal dup 3 + 1 , , ;
: by dup 2 + 1 , , ;
: quote dup 1 + 1 , , ;
---reveal---
: for ( start goal step quote - )
ahead [ 5 allot ] dip here over !
quote ` ! by ` ! goal ` ! start ` !
` repeat [
start ` @ goal ` @ relop , 0; ` drop
start ` @ by ` @ ` + start ` !
quote ` @ ` do
] dip ` again
drop ; immediate
}}
( Test )
: foo 10 0 -2 [ 1 ] for ;
@crcx
Copy link
Author

crcx commented Jan 23, 2013

ahead [ 5 allot ] dip here over !

This creates a private structure in the code using the for macro. We have helper functions for accessing each of these fields: start, goal, by, and quote. The helper functions add the appropriate offsets and compile VM_LIT instructions into the target definition. Helper functions leave the struct pointer on the stack.

quote ` ! by ` ! goal ` ! start ` !

Using the helpers, store values (from the stack) into the new structure.

` repeat [

Starts an unconditional loop. Since repeat leaves a pointer on the stack, we use a quote and dip combinator to move the loop pointer away until we finish filling in the body of the loop.

start ` @  goal  ` @  relop ,  0;  ` drop

Compile code to fetch the start and goal values from the struct. relop is a helper which compiles the appropriate conditional into the loop. If it maches, we exit the loop via the 0; drop sequence. Otherwise we go on to modify start for the next cycle through the loop:

start ` @ by ` @ ` + start ` !

Pretty cut and dry. This would probably be better done using +!, but that's an optimization for later consideration.

quote ` @ ` do

Invoke the quote. This has some overhead and could be handled much more efficiently. (E.g., by changing quote to compile an implied call rather than a literal pointer to the stored quote address)

] dip ` again

Finish off the repeat / again loop.

drop ; immediate

Discard the struct pointer and finish the macro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment