Last active
December 14, 2015 07:29
-
-
Save tangentstorm/5050753 to your computer and use it in GitHub Desktop.
Work in progress : macros for b4a.js ... These are actually more like mini-compilers. Basically the idea is that when you see a word like `.if` , it's going to define `.then` and `.else` on the fly... This way if you encounter an `.else` that is not inside an `.if`, it will be a syntax error. The assembly code should wind up looking a lot more l…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// when asm( ) encounters a word that starts with punctuation, | |
// it will not try to compile a call to that word, but will instead | |
// look up the word's definition in the "macro" vocabulary, and | |
// execute the macro immediately. | |
// | |
// The macros are written in javascript. | |
// semicolon. in forth this would issue a 'return' instruction, | |
// but in b4, it's used as punctuation. In the default context, | |
// it doesn't do anything, but it can be used to break long | |
// strings of words down into easier to understand chunks. | |
def( ';', function( ) { | |
}); | |
// REPEAT ... UNTIL ... ; loop, as in pascal or oberon. | |
def( '.repeat', function { | |
// repeat-loop ::= REPEAT <code> UNTIL <condition> ";" | |
// so define what UNTIL means in this context. | |
pushdef( '.until', function( ) { | |
// ... and inside UNTIL, redefine ";" | |
pushdef( ';', function( ) { | |
// when we encounter the ';' emit code to conditionally jump back to the REPEAT. | |
// That is, "UNTIL x;" compiles down to "IF x NOT THEN JUMP: <top-of-loop> END" | |
// so by the time we're here, we will have already compiled | |
// 'IF x', and we can continue with: | |
asm( "not .then" ); | |
// REPEAT will have put the <top-of-loop> label on the stack. | |
// ".emit" will take it off the stack and compile it: | |
asm( "JUMP: .emit" ); | |
// close the IF statement, so it can clean up after itself: | |
asm( ".end" ); | |
// and then step out of the REPEAT context: | |
popdefs( ";", ".until" ); | |
}); | |
// with the plan for ";" in place, UNTIL now compiles the IF | |
asm( ".if" ); | |
}); | |
// and with the plan for "UNTIL" in place, REPEAT now records <top-of-loop>. | |
asm( ".here" ); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment