给出: Token 和语法的序列
地点:
令牌 := 元组[名称:字符串, 值:字符串, 父项:令牌]
语法 := Table[system.string, proc(x:Token):string]
返回:通过语法传递的标记值字符串
当实现我的翻译器时,我得出的结论是我需要根据令牌执行一些操作,我知道使用条件分支实现此功能会更正确 ,但我对一种不同的方法感兴趣,在这种方法中,在收到代币的名称后,我会与其进行一些交互。
实现这一点的最简单方法是
Table[system.string, proc(x:Token):string]
但是,我不满意,因为无法在编译期间生成它。或者我可以,但是我不知道如何。
因为我对 php 有一点经验,所以我知道我可以使用 字符串作为函数
function a(int $num){
return $num + 3;
}
echo "a"(1); // 4
基于此,Nim 有没有一种方法可以允许提前声明一组函数以这种方式访问它们?
或者也许您可以建议如何采取更正确的方法来解决这个问题。
也许这就是您想要的(但这是一个快速实现)
import tables
import macros, macrocache
const procs = CacheTable"procs"
macro addToProcs(def: untyped): untyped =
procs[def.name.strVal] = def.name
result = def
macro genTable(t: untyped): untyped =
result = newNimNode(nnkTableConstr)
for name, ident in procs.pairs:
let expr = newNimNode(nnkExprColonExpr)
expr.add newLit(name)
expr.add quote do:
`t`(`ident`)
# https://internet-of-tomohiro.pages.dev/nim/faq.en#procedures-how-to-get-a-pointer-to-a-overloaded-procedureqmark
# use a type conversion to avoid ambiguous name `add`
result.add expr
proc add(a: int, b: int): int {.addToProcs.} =
a + b
proc sub(a: int, b: int): int {.addToProcs.} =
a - b
const table = toTable genTable(typeof(sub)) # here I don't use `add` because the name `add` has many overloads in the stdlib
echo table["add"](1, 2)
这是我的第一次尝试,甚至更加严厉。
import tables
import macros
macro genTable(names: static seq[string]): untyped =
result = newNimNode(nnkTableConstr)
for name in names:
let expr = newNimNode(nnkExprColonExpr)
expr.add newLit(name)
expr.add ident(name)
result.add expr
proc add_uniq(a: int, b: int): int =
a + b
proc sub_uniq(a: int, b: int): int =
a - b
let table = toTable genTable(@["add_uniq", "sub_uniq"])
echo table["add_uniq"](1, 2) # 3