I can create the @start and @rule macros but I’m not sure how to pass the model variable around. The @start macro generates a random variable name for model and likewise for @rule macro.
See LSystem.jl repo for the current implementation. I am open to suggestions including tweaking the DSL itself to make it easier. Thanks
Do I understand correctly, that the main questions are:
How to capture the name of the model variable created by var = LModel(name) expression?
How to pass this name to add_rule() calls?
If so, here’s one simple way to implement @lsys which does the trick:
# let's say, @start and `rule` generated the following expression which is passed to @lsys
ex = quote
# say, @start generated name `model_123`
model_123 = LModel("A")
# initially using dummy name __model_var__
add_rule(__model_var__, "A", split("AB", ""))
add_rule(__model_var__, "B", split("A", ""))
end
using Espresso
# Espresso.findex() traverses AST and finds all subexpressions
# matching the pattern "_var = LModel(_)"
# (any symbol starting with underscore is considered a placeholder)
model_subexs = findex(:(_var = LModel(_)), ex)
# ==> 1-element Array{Any,1}:
# ==> :(model_123 = LModel("A"))
# model variable is in
model_var = model_subexs[1].args[1]
# ==> :model_123
# now we can substitute all occurrences of `__model_var__` with actual model var name
subs(ex, Dict(:__model_var__ => model_var))
# ==> quote
# ==> model_123 = LModel("A")
# ==> add_rule(model_123, "A", split("AB", ""))
# ==> add_rule(model_123, "B", split("A", ""))
# ==> end
Another approach would be to mimic how it’s done in @sync and @async (i.e., create a binding with special gensym’ed variable sync_varname in @sync using let).
It would be something like
const model_varname = gensym(:model)
macro lsys(block)
var = esc(sync_varname)
quote
let $var
$(esc(block))
end
end
end
macro start(name)
var = esc(model_varname)
quote
$var = LModel($(esc(name)))
end
end
and so on (untested). You can also use @isdefined macro in @start to throw a user-friendly error when it’s used outside @lsys.