2013-12-18 197 views
0

我想將配置參數傳遞給宏。我已經有一個基於這些參數(一個序列元組)產生一串Nimrod代碼的過程。 我知道我可以傳遞一個字符串並將其轉換爲strVal(如回答https://stackoverflow.com/a/19956317/334703所示)。我能對更復雜的數據做同樣的事嗎?將複雜參數傳遞給Nimrod宏

或者我可以使用的尼姆羅德代​​碼這個字符串編譯時程序通過調用作爲parseStmt這樣的程序?

編輯: Nimrod代碼的生成有助於測試我的想法我同意我應該直接生成AST。

這是我正在考慮的結構的一個例子。

type 
    Tconfig = tuple 
    letters: seq[string] 
    numbers:seq[int] 

var 
    data = (@("aa", "bb"), @(11, 22)) 

macro mymacro(data: Tconfig): stmt = 
    ... 

回答

1

如果您需要或想要要遍歷宏中的數據結構,首先需要將變量a constvar是運行的,所以宏將只是得到一個nnkSym節點。一旦你做出一個const你會得到相同的輸入,如果你輸入了自己的價值手動那裏。我將使用treeRepr宏和大量的echo來告訴你,你得到了什麼樣的AST,你會如何走它:

import macros 

type 
    Tconfig = tuple 
    letters: seq[string] 
    numbers:seq[int] 

const data: Tconfig = (@["aa", "bb"], @[11, 22]) 

macro mymacro(data: Tconfig): stmt = 
    echo "AST being passed in:\n", treeRepr(data) 
    echo "root type is ", data.kind 
    echo "number of children ", len(data) 
    let n1 = data[0] 
    echo "first child is ", n1.kind 
    echo "first child children ", len(n1) 
    let e2 = n1[1] 
    echo "second exp child is ", e2.kind 
    echo "second exp child children ", len(e2) 
    let v1 = e2[0] 
    echo "first seq value is ", v1.kind 
    echo "first seq value children ", len(v1) 
    echo "Final literal is ", v1.strVal 

when isMainModule: 
    mymacro(data) 

當我編譯的例子,我得到以下輸出:

AST being passed in: 
Par 
    ExprColonExpr 
    Sym "letters" 
    Bracket 
     StrLit aa 
     StrLit bb 
    ExprColonExpr 
    Sym "numbers" 
    Bracket 
     IntLit 11 
     IntLit 22 
root type is nnkPar 
number of children 2 
first child is nnkExprColonExpr 
first child children 2 
second exp child is nnkBracket 
second exp child children 2 
first seq value is nnkStrLit 
first seq value children 0 
Final literal is aa 
+0

非常感謝。這個例子非常有用。 –

1

我不是100%肯定你的意思,但是從上下文,它看起來好像你需要的功能是,macros.toStrLit,產生從AST字符串文本節點。例如:

import macros, strutils 

macro showExpr(x: expr): stmt = 
    parseStmt("echo(" & x.toStrLit.strVal.escape & ")") 

showExpr("x" & "y") 

考慮直接轉化AST,不過,因爲生成和重新分析代碼串可導致意外使用引號(注意上面的.escape),壓痕等

+0

感謝您對這些第一信息。我編輯了這個問題,試圖更清晰。 –

2

如果您的宏需要處理傳遞給它的實際恆定的數據,推薦的方法是使用靜態PARAMS:

type 
    TConfig = tuple 
    letters: seq[string] 
    numbers:seq[int] 

const data = (@["aa", "bb"], @[11, 22]) 

macro mymacro(cfg: static[TConfig]): stmt = 
    echo "letters" 
    for s in cfg.letters: 
    echo s 

    echo "numbers" 
    for n in cfg.numbers: 
    echo n 

mymacro(data) 

這種方法有多種好處:

1)代替獲取原始AST,輸入參數cfg在宏體內將有TConfig類型,因此您可以更輕鬆地訪問其成員,如示例中所示。

2)編譯器將自動評估產生TConfig值,當它們與宏(例如mymacro(mergeConfigs(userConfig, systemConfig))使用複雜的表達式,假定mergeConfigs是一些PROC可能在編譯時進行評估)。

有關靜態PARAMS的更多信息,請參閱手冊:
http://nim-lang.org/manual.html#static-t