High Level Language Macros
These macros are to make it easier to write readable and maintainable PIR by preprocessing common HLL forms into their low level PIR forms. These are not actually high level constructs, but merely preprocessor directives.
Conditionals
When a conditional is labeled as a parameter,
the valid syntax is limited.
Only code snippets such as $P0
,
$I0 <= 42
,
null $P0
,
are allowed.
Groupings such as $I0 <= 42 || $I0 > 142
are not allowed,
although it is possible to write a macro that contains two parameters representing conditionals.
It's important to avoid the { } delimiter on the conditionals since a newline in the conditional renders the generated PIR invalid.
Code blocks
The macro preprocessor is very simple.
But it allows using braces to delimit code that contains commas or right parenthesis,
)
,
without causing an error.
This allows for nesting macros to near infinite depths.
And macro parameter that uses a comma or right parenthesis must be enclosed in braces.
Macros
.NL()
This is the most simple of macros.
Because PIR statements are delimited by newlines,
putting multiple statements,
no matter how simple or short,
is not allowed.
Sometimes for readability you wish to have two on the same line.
Using .If(conditional, code)
Runs the code in .Unless(conditional, code)
Runs the code in .IfElse(conditional, true, false)
Runs the code in .While(conditional, code)
Runs the code in .DoWhile(code, conditional)
Runs the code in .Loop(code)
Runs the code in .For(start, conditional, continue, code)
First .Foreach(name, array, code)
A simple foreach loop.
Given the aggregate
.NL()
in a line will insert a linebreak.
code
if conditional
is true.
code
if conditional
is false.
true
if conditional
is true,
otherwise runs the code in false
.
code
as long as conditional
is true.
code
once,
and then as long as conditional
is true.
code
forever.
start
is executed,
such as i = 0
,
and then if the conditional
is true,
runs code
,
and then the continue
code,
such as inc i
.
array
,
which must be a register,
it iterates through the array,
putting each value into name
to work with in code
.Examples
Good morning!
"Hello, world!" is so mundane, make it more fun.
.include "tm.pasm" .include "hllmacros.pir" .sub main :main $I0 = time $P0 = decodelocaltime $I0 $I0 = $P0[.TM_HOUR] .IfElse($I0 < 12,{ print "Good morning!\n" },{ .IfElse($I0 > 18,{ print "Good night!\n" },{ print "Good evening!\n" }) }) .end
Simple looping
A simple demonstration of the For loop.
.include "hllmacros.pir" .sub main :main print "For\n" .For(i = 0 , i < 5, inc i, print "\t" print i print "\n" ) .end
A simple demonstration of the Foreach loop.
.include "hllmacros.pir" .sub main :main print "Foreach\n" .local pmc array, letter array = new 'ResizablePMCArray' push array, "a" push array, "b" push array, "c" .Foreach(letter, array, { print "\t" print letter print " " .IfElse(letter == 'b', print "is b\n" , print "isn't b\n" ) }) .end
Using .NL()
.local int i, j .For({i = 0 .NL() j = 11}, i < j, {inc i .NL() dec j }, { print i print "\t" print j print "\n" })
Caveats
The .Foreach macro is not nestable within itself currently. You can use other macros inside a .Foreach loop, and the .Foreach loop can be nested inside other macros.
.Foreach(foo, bar, { .Foreach(foobar, foo, { print foobar }) })
Will not run as you would expect.