Ioke では、リテラルのオーバーライドは許可されていますが、新しいリテラルの定義は許可されていません。これが機能する方法は、リテラルが単純にメッセージ送信に変換され、対応するメソッドを他のメソッドと同じようにオーバーライドできることです。
たとえば、これはDict
2 つのエントリを持つ a の「リテラル構文」です。1 つは aSymbol
を aにマッピングし、もう 1 つは a を aText
にマッピングSymbol
しNumber
ます。
{ :name => "Jörg", :age => 31 }
これは、実際には、という名前のメッセージのメッセージ送信に変換されます{}
(ところで: リストは同じように機能し、対応するメッセージは です[]
)。これは、次のものとまったく同じです (必要に応じて、このように書くこともできます)。
{}(:name => "Jörg", :age => 31)
現在、実際には、ほとんどすべてのオブジェクトに対して定義されている演算子であり、キー(最初の要素)がレシーバーであり、値が引数である=>
a を返すだけです。Pair
現在、オペレーターは単なるメッセージ送信でもあるため、これは次と同等です。
{}(:name =>("Jörg"), :age =>(31))
:
リテラル記号を表すシジルも、メッセージ送信に変換されます。
{}(:("name") =>("Jörg"), :("age") =>(31))
internal:createText
テキスト リテラルは、メッセージの送信に変換されます。
{}(:("name") =>(internal:createText("Jörg")), :("age") =>(31))
[注: 明らかに、ここに書かれている方法は無限再帰につながります。実のところ、 への引数internal:createText
は明らかに IokeText
ではなく、プラットフォーム文字列です。つまり、 Iokeikj
の JVM 実装の場合は実際には でjava.lang.String
ありikc
、CIL 実装の場合はSystem.String
です。ここでは三重引用符を使用してこれを表現しました。]
{}(:("name") =>(internal:createText("""Jörg""")), :("age") =>(31))
これにより、番号が残ります。これは、ご想像のとおり、送信されたメッセージでもあります。
{}(:("name") =>(internal:createText("""Jörg""")),
:("age") =>(internal:createNumber("""31""")))
すべてがメッセージ送信であるため、対応するメソッドを実装するだけで、リテラルの動作を自由にカスタマイズできます。iik
以下は、インタラクティブな Ioke REPLからの短いトランスクリプトです。
iik> "Hello"
+> "Hello"
iik> internal:createText = method(raw, super(raw) upper)
iik> "Hello"
+> "HELLO"
Converge は、 DSL ブロックと呼ばれる機能を含む、強力なコンパイル時のメタプログラミングを可能にします。DSL ブロックは、Converge 構文を使用しないコードのブロックです。DSL ブロックは次のようになります。
$<<xml>>:
<xml>
<literal>here</literal>
</xml>
$<<
これが機能する方法は、との間の文字列は、コンパイル時>>
に呼び出され、DSL ブロック全体を文字列として渡される関数の名前です (行番号、ファイル名などの一部のソース コード メタデータも同様です)。 .) そして、Converge 抽象構文ツリーのフラグメントを返します。したがって、この特定のケースでは、次のような関数があります。
func xml(dsl_block, src_infos):
// implement an XML parser here ...
return ast
Factor では、同じスコープ内の他の単語が解析される方法に影響を与える単語である解析単語の定義が可能です。実際には、Factor にはXML ライブラリの実装があり、解析語を使用して Scala の XML リテラルに非常によく似た構文を取得しますが、通常の Factor コードです。
: feed>xml ( feed -- xml )
[ title>> ]
[ url>> present ]
[ entries>> [ entry>xml ] map ] tri
<XML
<feed xmlns="http://www.w3.org/2005/Atom">
<title><-></title>
<link href=<-> />
<->
</feed>
XML> ;
[Factor の簡単な紹介::
新しい単語を定義します。つまり、最初の行では、 feed>xml
1 つの引数を取り、1 つの結果を生成するという名前の単語を定義します。単語の最初の 3 行は、フィード オブジェクトからタイトル、URI、およびエントリを抽出し、それらをスタックに配置します。は、XML モードをオンにして再びオフに<XML
する構文解析語です。XML>
XML コード内で<->
、スタックから値を取得し、それを XML に挿入します。]
Common Lisp
Common Lisp Reader Macrosを使用すると、読み取りステージ、つまり、文字列を取得してネストされたリストを生成し、それらをコンパイラ/評価器に渡すステージにフックできます。一意の 1 文字または 2 文字のプレフィックスを選択する必要があり、それらはグローバルです。最初のものはそれほど問題ではありません。<
文字をプレフィックスとして選択するだけで、自然に見えるようにすることができるからです。
Perl 6 では、プログラムの実行中に構文を変更できるはずです。Perl 6 には動的可変文法があります。つまり、コードは実行中に解析され、文法を変更して、ファイル内の他のコードが新しい文法を使用して解析されるようにすることができます。
OMeta/COLA
Ian Piumarta の COLA システム上で動作するAlessandro Warth の OMeta 言語は、彼らが「気分固有の言語」と呼ぶものを可能にします。つまり、仕様と実装が非常に軽量であるため、プログラムの途中で 1 行だけ使用して、別の構文に再び切り替えることができる言語です。
これは、Alan Kay's Viewpoint Research InstituteのInventing Fundamental New Computing Technologiesで使用されています。使用例の 1 つは、IETF RfC で使用される ASCII アート図と同じ構文を持つ言語と、ネットワーク プロトコルのステート マシンを記述するための別の言語を設計することにより、わずか 200 行のコードで TCP/IP ネットワーク スタック全体を実装することです。次に、ネットワーク スタックの実装は、RfC から ASCII ダイアグラムをコピー & ペーストし、RfC から英語のステート マシン記述をステート マシン言語に変換するだけです。
(ご参考までに、200 行は ASCII ダイアグラムとステート マシンだけではありません。2 つの言語のパーサーとコンパイラも含まれています。)
π プログラミング言語もおそらく興味深いものです。