You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a template, macro or const does not require arguments to be substituted, It is done instantly. This makes it impossible to pass this symbol to a typed macro as a symbol.
Example
import macros
# Here are just a bunch of definitions to test if it is possible to pass their # symbol to a macro as an ``nnkSym``.templateargsTemplate(arg1, arg2: untyped): untyped=echo"something"templatenoArgsTemplate(): untyped=echo"something"templatedefaultArgsTemplate(arg1: int=123, arg2: string="abc"): untyped=echo"something"macroargsMacro(arg1, arg2: untyped): untyped=result=quotedo:
echo"something"macronoArgsMacro(): untyped=result=quotedo:
echo"something"macrodefaultArgsMacro(arg1: int=123, arg2: string="abc"): untyped=result=quotedo:
echo"something"procargsProc(arg1, arg2: int) =echo"something"procnoArgsProc() =echo"something"procdefaultArgsProc(arg1: int=123, arg2: string="abc") =echo"something"const myConst =123iteratorargsIterator(a,b: int): int=yield a+b
iteratornoArgsIterator(): int=yield123iteratordefaultArgsIterator(a: int=12; b: int=23): int=yield a+b
macroprocessSymbol(arg: typed): untyped=echo arg.lispRepr
# Here starts the test to pass all the symbols to the `processSymbol` macro.# pass template symbolprocessSymbol(argsTemplate) # (Sym "argsTemplate") -> OKprocessSymbol(noArgsTemplate) # (Command (Sym "echo") ...) -> not okprocessSymbol(defaultArgsTemplate) # (Command (Sym "echo") ...) -> not ok# pass macros symbolprocessSymbol(argsMacro) # (Sym "argsMacro") -> OKprocessSymbol(noArgsMacro) # (Command (Sym "echo") ...) -> not OK# Error: in call 'defaultArgsMacro' got -1, but expected 2 argument(s)# processSymbol(defaultArgsMacro) # -> not ok# pass proc symbol (works)processSymbol(argsProc) # (Sym "argsProc") -> OKprocessSymbol(noArgsProc) # (Sym "noArgsProc") -> OKprocessSymbol(defaultArgsProc) # (Sym "defaultArgsProc") -> OK# pass module symbolprocessSymbol(macros) # (Sym "macros") -> OKprocessSymbol(macros.newLit) # (ClosedSymChoice (Sym "newLit") ...) -> OK# pass const symbol #processSymbol(myConst) # (IntLit 123) -> not OK# pass iterator symbolprocessSymbol(argsIterator) # (Sym "argsIterator") -> OKprocessSymbol(noArgsIterator) # (Sym "noArgsIterator") -> OKprocessSymbol(defaultArgsIterator) # (Sym "defaultArgsIterator") -> OK
Possible Solution
resolve symbol at callsite
If there would be a proc in Macros to convert an identifier into a symbol by looking the symbol up in the context of the callsite, this problem could be avoided.
macrosetSymAlias(newName, oldName: untyped) =let oldSym =resolveAtCallsite(oldName)
case oldSym.symKind
...
distinct between myTempl() and myTempl (no args)
when a template that is declared with () in the declaration cannot be called without (), there is much less of a problem.
templatefoo() =discardlet x = foo # <-- error `()` required
Provide a syntax that prevents symbol substitution
In Scala methods can be call without braces. Since the this parameter for local methodes also doesn't need to be provided, function calls can be nothing more than the function name on it's own. But in some contexts, when you want to pass the function symbol as a function object, there is a syntax for it that prevents function execution:
processCallback(argumentLessMethod _)
Remove Feature that the () for argument less templates are optional.
To call a procedure, the () are required to distinguish it from the expression where just the function symbol as a value should be used. I don't know who thought that for templates and macros we don't need this distinction, but if we din't have it, this problem would not exist. This breaks a lot. I don't think it is feasible. I just add this as a reminder that careless addition of features and rules in the compiler really can break things and cause problems in the long run.
Additional Information
This issue came up when I tried to implement symbol aliasing as a pure macro implementation. My approach looks promising, but it does require that I can pass all sorts of symbol types to a macro which I currently don't know how to do it:
import macros
procforwardParams(call, params: NimNode): NimNode=case params.kind
of nnkFormalParams:
for i in1..< params.len:
discardforwardParams(call, params[i])
of nnkIdentDefs:
for i in0..< params.len -2:
call.add params[i]
else:
discardresult= call
macrosetSymAlias(newName: untyped; oldName: typed) =echo"set sym alias: ", newName.repr, " = ", oldName.repr
## Sets a symbol alias for symbol `oldName` to `newName`.echo newName.lispRepr
echo oldName.lispRepr
oldName.expectKind nnkSym
case oldName.symKind
of nskProc, nskTemplate, nskMacro, nskMethod:
let params = oldName.getImpl[3]
result= nnkTemplateDef.newTree(
newName,
newEmptyNode(),
newEmptyNode(),
params,
newEmptyNode(),
newEmptyNode(),
forwardParams(newCall(oldName), params)
)
of nskLet, nskVar, nskParam, nskConst, nskResult:
result= nnkTemplateDef.newTree(
newName,
newEmptyNode(),
newEmptyNode(),
nnkFormalParams.newTree(
newIdentNode("untyped")
),
newEmptyNode(),
newEmptyNode(),
oldName
)
else:
error("incompatible symbol kind "&$oldName.symKind, oldName)
whenisMainModule:
echoresult.repr
Here is a usage example of that symbol alias implementation:
proct(arg: int=123): int=42+ arg
setSymAlias(ta,t)
let value =ta()
setSymAlias(valuea,value)
echo valuea
echota(arg =337)
macrofun2(a =1,b=2): untyped=quotedo: (`a`,`b`)
setSymAlias(fun2a, fun2) # error with fun2
The text was updated successfully, but these errors were encountered:
When a template, macro or const does not require arguments to be substituted, It is done instantly. This makes it impossible to pass this symbol to a typed macro as a symbol.
Example
Possible Solution
resolve symbol at callsite
If there would be a proc in Macros to convert an identifier into a symbol by looking the symbol up in the context of the callsite, this problem could be avoided.
distinct between myTempl() and myTempl (no args)
when a template that is declared with () in the declaration cannot be called without (), there is much less of a problem.
Provide a syntax that prevents symbol substitution
In Scala methods can be call without braces. Since the this parameter for local methodes also doesn't need to be provided, function calls can be nothing more than the function name on it's own. But in some contexts, when you want to pass the function symbol as a function object, there is a syntax for it that prevents function execution:
Remove Feature that the
()
for argument less templates are optional.To call a procedure, the
()
are required to distinguish it from the expression where just the function symbol as a value should be used. I don't know who thought that for templates and macros we don't need this distinction, but if we din't have it, this problem would not exist. This breaks a lot. I don't think it is feasible. I just add this as a reminder that careless addition of features and rules in the compiler really can break things and cause problems in the long run.Additional Information
This issue came up when I tried to implement symbol aliasing as a pure macro implementation. My approach looks promising, but it does require that I can pass all sorts of symbol types to a macro which I currently don't know how to do it:
Here is a usage example of that symbol alias implementation:
The text was updated successfully, but these errors were encountered: