In MyDef, all macros live in a series of nested scopes. On the very top is the global scope. Macros that are defined under "macros:" block lives in global scope. Next is the page scope. Page attributes live in page scope. Followed is the chain of scopes defined by each subcode starting at "subcode: main".
We can also dynamically create macros with the scope.
subcode: A $(set:name=Hui) Hello, $(name)!
The set macros are effective throughout the remainder of the subcode as well as all the subcodes being called with in.
subcode: A $(set:name=Hui) Hello, $(name)! $call B subcode: B Bye, $(name)!
In addition to explicit subcode scope, preprocessing directive "$(for:...)" will also create new scope implicitly. However, "$(if:...)" does not create new scopes. So:
subcode: A(name) $(if:name=Hui) $(set:greeting=Hi) $(else) $(set:greeting=Hello) $(greeting), $(name)! page: t $call A, Hui
will output "Hi, Hui!". However,
page: t $(for:i in 1-3) $(set:name=Hui_$(i)) Set $(name). $(if:name) Hi, $(name)! $(else) No name here!
will compile to
Set Hui_1. Set Hui_2. Set Hui_3. No name here!
An interesting question is: what scope should the block under "&call" be?
subcode: A $(set:name=A) BLOCK in subcode A: name = $(name) page: t &call A in BLOCK: name=$(name) $(set:name=page t)
And if we compile, we get:
in BLOCK: name=A in subcode A: name = page t
Apparently, the block under "&call" is the same as the subcode itself.
In addition to "$(set:...)" to create or reset macros at current scope, if we want to set/reset macros at one scope higher, we could use "$(export:...)":
subcode: A $(export:name=A) page: t $call A Hello, $(name)!
This will compile into:
if we want export a macro in the current scope to a higher scope, we can simply use "$(export:name)".
subcode: A $(set:name=A) $(export:name) page: t $call A Hello, $(name)!
If we want to directly set macros at global scope, we could use "$(setmacro:...)".
subcode: AA $(setmacro:name=A) subcode: A $call AA page: t $call A Hello, $(name)!