You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
76 lines
2.2 KiB
Lua
76 lines
2.2 KiB
Lua
--- An intelligent 'loop-unrolling' macro.
|
|
-- `do_` defines a named scoped macro `var` which is the loop iterator.
|
|
--
|
|
-- For example,
|
|
--
|
|
-- y = 0
|
|
-- do_(i,1,10
|
|
-- y = y + i
|
|
-- )
|
|
-- assert(y == 55)
|
|
--
|
|
-- `tuple` is an example of how the expansion of a macro can be
|
|
-- controlled by its context. Normally a tuple `A` expands to
|
|
-- `A_1,A_2,A_3` but inside `do_` it works element-wise:
|
|
--
|
|
-- tuple(3) A,B
|
|
-- def_ do3(stmt) do_(k,1,3,stmt)
|
|
-- do3(A = B/2)
|
|
--
|
|
-- This expands as
|
|
--
|
|
-- A_1 = B_1/2
|
|
-- A_2 = B_2/2
|
|
-- A_3 = B_3/2
|
|
--
|
|
-- @module macro.do
|
|
local M = require 'macro'
|
|
|
|
--- Expand a loop inline.
|
|
-- @p var the loop variable
|
|
-- @p start initial value of `var`
|
|
-- @p finish final value of `var`
|
|
-- @p stat the statement containing `var`
|
|
-- @macro do_
|
|
M.define('do_(v,s,f,stat)',function(var,start,finish,statements)
|
|
-- macros with specified formal args have to make their own putter,
|
|
-- and convert the actual arguments to the type they expect.
|
|
local put = M.Putter()
|
|
var,start,finish = var:get_iden(),start:get_number(),finish:get_number()
|
|
M.push_macro_stack('do_',var)
|
|
-- 'do_' works by setting the variable macro for each value
|
|
for i = start, finish do
|
|
put:name 'set_':name(var):number(i):space()
|
|
put:tokens(statements)
|
|
end
|
|
put:name 'undef_':name(var)
|
|
put:name '_DROP_':string 'do_':space()
|
|
return put
|
|
end)
|
|
|
|
--- an example of conditional expansion.
|
|
-- `tuple` takes a list of variable names, like a declaration list except that it
|
|
-- must end with a line end.
|
|
-- @macro tuple
|
|
M.define('tuple',function(get)
|
|
get:expecting '('
|
|
local N = get:number()
|
|
get:expecting ')'
|
|
local names = get:names '\n'
|
|
for _,name in ipairs(names) do
|
|
M.define(name,function(get,put)
|
|
local loop_var = M.value_of_macro_stack 'do_'
|
|
if loop_var then
|
|
local loop_idx = tonumber(M.get_macro_value(loop_var))
|
|
return put:name (name..'_'..loop_idx)
|
|
else
|
|
local out = {}
|
|
for i = 1,N do
|
|
out[i] = name..'_'..i
|
|
end
|
|
return put:names(out)
|
|
end
|
|
end)
|
|
end
|
|
end)
|