6

Nimrodのチュートリアルの第 2 部を進めていくと、マクロについて説明する部分に到達しました。ドキュメントには、コンパイル時に実行されると書かれているので、文字列を解析してドメイン固有の言語を自分で作成できると考えました。ただし、これを行う方法の例はありません。デバッグ マクロの例には、文字列パラメーターの処理方法が表示されていません。

次のようなコードを変換したい:

instantiate("""
    height,f,132.4
    weight,f,75.0
    age,i,25
    """)

…手書きで次のように記述します。

var height: float = 132.4
var weight: float = 75.0
var age: int = 25

明らかに、この例はあまり役に立ちませんが、より複雑なものを実装するのに役立つ単純なもの (複数行/カンマ分割、変換) を見てみたいと思います。

ここでの私の問題は、マクロがどのように入力文字列を取得し、それを解析するか (コンパイル時!)、およびコンパイル時に実行できるコードの種類 (それは単なる言語のサブセットですか? 他のマクロ/コードを使用できますか?インポートされたモジュール)?

編集:答えに基づいて、質問に対する可能なコード解決策があります:

import macros, strutils

# Helper proc, macro inline lambdas don't seem to compile.
proc cleaner(x: var string) = x = x.strip()

macro declare(s: string): stmt =
  # First split all the input into separate lines.
  var
    rawLines = split(s.strVal, {char(0x0A), char(0x0D)})
    buf = ""

  for rawLine in rawLines:
    # Split the input line into three columns, stripped, and parse.
    var chunks = split(rawLine, ',')
    map(chunks, cleaner)

    if chunks.len != 3:
      error("Declare macro syntax is 3 comma separated values:\n" &
        "Got: '" & rawLine & "'")

    # Add the statement, preppending a block if the buffer is empty.
    if buf.len < 1: buf = "var\n"
    buf &= "  " & chunks[0] & ": "

    # Parse the input type, which is an abbreviation.
    case chunks[1]
    of "i": buf &= "int = "
    of "f": buf &= "float = "
    else: error("Unexpected type '" & chunks[1] & "'")
    buf &= chunks[2] & "\n"

  # Finally, check if we did add any variable!
  if buf.len > 0:
    result = parseStmt(buf)
  else:
    error("Didn't find any input values!")

declare("""
x, i, 314
y, f, 3.14
""")
echo x
echo y
4

1 に答える 1

7

マクロは、概して、同じ場所にあるプロシージャが参照できるすべての純粋な Nimrod コードを利用することもできます。たとえば、文字列をインポートstrutilsまたはpeg解析して、そこから出力を作成できます。例:

import macros, strutils

macro declare(s: string): stmt =
  var parts = split(s.strVal, {' ', ','})
  if len(parts) != 3:
    error("declare macro requires three parts")
  result = parseStmt("var $1: $2 = $3" % parts)

declare("x, int, 314")
echo x

マクロを「呼び出す」と、基本的にコンパイル時にそれがプロシージャであるかのように評価されます (ただし、マクロの引数は実際には AST になるため、s.strVal代わりに上記を使用する必要がありますs)。マクロ呼び出しの位置。

マクロ コードは、コンパイラの内部仮想マシンによって評価されます。

于 2013-11-13T14:28:53.000 に答える