54 lines
1.8 KiB
Plaintext
Executable File
54 lines
1.8 KiB
Plaintext
Executable File
--------------------------------------------------------------------------------
|
|
--
|
|
-- Anaphoric macros.
|
|
--
|
|
-- This extension turns 'it' into a special variable, that's bound to
|
|
-- an often used value:
|
|
--
|
|
-- * in an 'if' statement, 'it' is bound, in a block, to the condition
|
|
-- that triggered the block's execution:
|
|
-- > if 1234 then y=it end; assert (y == 1234)
|
|
--
|
|
-- * in a while loop, it's bound to the test:
|
|
-- > while file:read "*a" do table.insert (lines, it) end
|
|
--
|
|
-- 'it' is bound the the most closely surrounding structure. If you wanted to
|
|
-- use its content at a deeper position in the AST, you would have to save it
|
|
-- in a temporary variable. But what you should really do in such a case is
|
|
-- avoiding to use anaphoric macros: they're fine for one-liner, but they
|
|
-- reduce readability for bigger functions.
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- TODO: 'and' operator could, and maybe should, be anaphoric as well
|
|
-- TODO: anaphoric functions would be cool for recursive functions, but
|
|
-- recursive calls are always in an 'if' statement, so the pronoun
|
|
-- used for functions must not be the same as for 'if'.
|
|
|
|
require 'freevars'
|
|
|
|
local function anaphoric_if(ast)
|
|
local it_found = false
|
|
for i=2, #ast do
|
|
if freevars.block(ast[i])['it'] then
|
|
it_found = true
|
|
break
|
|
end
|
|
end
|
|
if it_found then
|
|
local cond = ast[1]
|
|
ast[1] = +{it}
|
|
return +{stat: do local it = -{cond}; -{ast} end }
|
|
end
|
|
end
|
|
|
|
local function anaphoric_while(ast)
|
|
local it_found = false
|
|
if freevars.block(ast[2])['it'] then
|
|
local cond = ast[1]
|
|
ast[1] = +{it}
|
|
return +{stat: do local it = -{cond}; -{ast} end }
|
|
end
|
|
end
|
|
|
|
mlp.stat:get'if'.transformers:add(anaphoric_if)
|
|
mlp.stat:get'while'.transformers:add(anaphoric_while) |