.. 4-language .. _label4: OMake言語の概要と構文 ================================== .. Projects are specified to omake with OMakefiles. The OMakefile has a format similar to a Makefile. An OMakefile has three main kinds of syntactic objects: variable definitions, function definitions, and rule definitions. プロジェクトは ``OMakefile`` を用いてomakeにどのようにビルドするのか指定しており、構文は ``Makefile`` と似ています。 ``OMakefile`` は3つの構文規則『変数の定義』『関数の定義』『ルールの定義』を持ち合わせています。 .. index:: single: 変数 .. _label4.1: 変数 ------------- .. Variables are defined with the following syntax. The name is any sequence of alphanumeric characters, underscore _, and hyphen -. 変数は以下のような構文で定義されます。変数名は任意のアルファベットとアンダースコア ``_`` 、ハイフン ``-`` を用いることができます。 :: = .. Values are defined as a sequence of literal characters and variable expansions. A variable expansion has the form $(), which represents the value of the variable in the current environment. Some examples are shown below. 値(value)にはリテラル文字と展開された変数が定義できます。変数の展開は ``$(name)`` のような形で表されて、 ```` 変数は現在の環境下において ```` に置き換わります。いくつかの例を以下に示します。 :: CC = gcc CFLAGS = -Wall -g COMMAND = $(CC) $(CFLAGS) -O2 .. In this example, the value of the COMMAND variable is the string gcc -Wall -g -O2. この例では、 ``COMMAND`` 変数の値は文字列 ``gcc -Wall -g -O2`` となります。 .. Unlike make(1), variable expansion is eager and pure (see also the section on Scoping). That is, variable values are expanded immediately and new variable definitions do not affect old ones. For example, suppose we extend the previous example with following variable definitions. ``make(1)`` とは違い、変数の展開は *先行して(eager)* 行われ、 *純粋な(pure)* メカニズムとなっています(詳細は ":ref:`label4.8`",":ref:`label6.1`" を参照してください)。これはつまり、変数の値は即座に展開されることによって、新しい変数への束縛が古い値に影響されないことを意味しています。例えば、前回の例を以下のような変数の束縛に拡張した場合について考えてみましょう。 :: X = $(COMMAND) COMMAND = $(COMMAND) -O3 Y = $(COMMAND) .. In this example, the value of the X variable is the string gcc -Wall -g -O2 as before, and the value of the Y variable is gcc -Wall -g -O2 -O3. この例では、変数 ``X`` の値は前回のように文字列 ``gcc -Wall -g -O2`` が定義されて、変数 ``Y`` の値は ``gcc -Wall -g -O2 -O3`` となります。 .. _label4.2: 変数に値を追加 --------------------- .. Variables definitions may also use the += operator, which adds the new text to an existing definition. The following two definitions are equivalent. 変数はまた、既存の変数に新しい文字列を追加する演算子 ``+=`` を用いることができます。例えば、以下の2つの文は等価です。 :: # CLAGS変数にオプションを追加 CFLAGS = $(CFLAGS) -Wall -g # 上と下の束縛は等価です CFLAGS += -Wall -g .. index:: single: 配列 .. _label4.3: 配列 --------------------- .. Arrays can be defined by appending the [] sequence to the variable name and defining initial values for the elements as separate lines. Whitespace is significant on each line. The following code sequence prints c d e. 配列は変数名の後ろに ``[]`` を追加し、初期値を改行を用いて要素を指定することで定義できます。各々の行でのスペースはOMakeにおいて重要な役割を担っています。例えば、以下のコードは文字列 ``c d e`` が出力されます。 :: X[] = a b c d e f println($(nth 2, $(X))) .. index:: single: 特殊文字 single: クオーティング .. _label4.4: 特殊文字とクオート ----------------------- .. The following characters are special to omake: $():,=#\. To treat any of these characters as normal text, they should be escaped with the backslash character \. 文字 ``$():,=#\`` はOMakeの特殊文字に指定されています。これらの文字を通常の文字としてOMakeで扱うためには、バックスラッシュ文字 ``\`` でエスケープする必要があります。 :: DOLLAR = \$ .. Newlines may also be escaped with a backslash to concatenate several lines. 文字列を連結させるために、改行もまたエスケープする必要があります。 :: FILES = a.c\ b.c\ c.c .. Note that the backslash is not an escape for any other character, so the following works as expected (that is, it preserves the backslashes in the string). バックスラッシュは他の文字でエスケープする必要が *ない* ことに注意してください。よって以下のような例は正常に動作します(これはつまり、文字列中のバックスラッシュが正常に保たれていることを表しています)。 :: DOSTARGET = C:\WINDOWS\control.ini .. An alternative mechanism for quoting special text is the use $"..." escapes. The number of double-quotations is arbitrary. The outermost quotations are not included in the text. ある文章をクオーティングしたい場合は ``"#..."`` エスケープを使用します。ダブルクオーテーションの数は任意で、最も外側のクオーテーションは文字列に含まれません。 :: A = $""String containing "quoted text" "" B = $"""Multi-line text. The # character is not special""" .. index:: single: 関数定義 single: return single: value .. _label4.5: 関数定義 ---------------- .. Functions are defined using the following syntax. 関数は以下のような構文を用いて定義されます。 :: () = .. The parameters are a comma-separated list of identifiers, and the body must be placed on a separate set of lines that are indented from the function definition itself. For example, the following text defines a function that concatenates its arguments, separating them with a colon. パラメータは識別のためにカンマを用いて分割し、コードは関数定義からインデントした状態で、別の行に設置する必要があります。例えば、以下のコードは引数 ``a`` と ``b`` をコロンを用いて結びつける関数について定義しています。 :: ColonFun(a, b) = return($(a):$(b)) .. The return expression can be used to return a value from the function. A return statement is not required; if it is omitted, the returned value is the value of the last expression in the body to be evaluated. ``return`` は関数から値を返す命令文です。 ``return`` 文は必須ではありません。この文が除外された場合、最後に関数が評価した命令文の返り値が返されます。 .. NOTE: as of version 0.9.6, return is a control operation, causing the function to immediately return. In the following example, when the argument a is true, the function f immediately returns the value 1 without evaluating the print statement. .. warning:: バージョン0.9.6から ``return`` 文は関数を制御する命令文となりましたので、return文が呼ばれた場合、関数はただちに値を返して終了します。以下の例では引数 ``a`` が ``true`` であったのなら、関数 ``f`` はただちにprint文を評価することなく値1を返します。 :: f(a) = if $(a) return 1 println(The argument is false) return 0 .. In many cases, you may wish to return a value from a section or code block without returning from the function. In this case, you would use the value operator. In fact, the value operator is not limited to functions, it can be used any place where a value is required. In the following definition, the variable X is defined as 1 or 2, depending on the value of a, then result is printed, and returned from the function. 多くの場合、あなたは関数から直接値を返さずに、セクションやネストされたコードブロックから値を返したいと思うことがあるでしょう。このような場合に、あなたは ``value`` 演算子を使用できます。実際、 ``value`` 演算子は関数だけに限らず、値が必要となった場合はどこでも使用することができます。以下の定義では、変数 ``X`` は ``a`` の値に依存して1か2が束縛されて、結果を出力し、関数から値を返します。 :: f_value(a) = X = if $(a) value 1 else value 2 println(The value of X is $(X)) value $(X) .. Functions are called using the GNU-make syntax, $( is a comma-separated list of values. For example, in the following program, the variable X contains the value foo:bar. 関数はGNU-makeの構文 ``$( )`` を用いて呼び出します。 ```` はカンマで分割された値のリストです。例えば、以下のプログラムでは、変数 ``X`` は値 ``foo:bar`` を含みます。 :: X = $(ColonFun foo, bar) .. If the value of a function is not needed, the function may also be called using standard function call notation. For example, the following program prints the string “She says: Hello world”. 関数の戻り値を必要としない場合には、通常の関数表記を用いて関数を呼び出すこともできます。例えば、以下のプログラムでは文字列“She says: Hello world”を出力します。 :: Printer(name) = println($(name) says: Hello world) Printer(She) .. index:: single: コメント .. _label4.6: コメント ---------------- .. Comments begin with the # character and continue to the end of the line. コメントは ``#`` 文字から始まり、行の末尾まで続きます。 .. index:: single: include single: open .. _label4.7: ファイルのインクルード ----------------------------- .. Files may be included with the include or open form. The included file must use the same syntax as an OMakefile. ファイルのインクルードには ``include`` か ``open`` 文を使います。インクルードされたファイルは ``OMakefile`` として、同じ構文で使用できます。 :: include $(Config_file) .. The open operation is similar to an include, but the file is included at most once. ``open`` 文は ``include`` と似ていますが、一回しかインクルードされないのが特徴です。 :: open Config # 2回目のopenは無視されますので、 # この行はなんの影響も与えません。 open Config .. If the file specified is not an absolute filenmame, both include and open operations search for the file based on the OMAKEPATH variable. In case of the open directive, the search is performed at parse time, and the argument to open may not contain any expressions. ファイル名が絶対パスで指定されていない場合、 ``include`` と ``open`` 文の両方は ``OMAKEPATH`` 変数上のパスを探します。 ``open`` 文の場合、この検索は *パースする際に実行される* ので、 ``open`` の引数に他の式を含める必要はありません。 .. index:: single: section single: export .. _label4.8: スコーピング、セクション ------------------------------- .. Scopes in omake are defined by indentation level. When indentation is increased, such as in the body of a function, a new scope is introduced. omakeのスコープはインデントのレベルで定義されます。インデントレベルが上がると、omakeでは新しいスコープが導入されます。 .. The section form can also be used to define a new scope. For example, the following code prints the line X = 2, followed by the line X = 1. ``section`` 文は新しいスコープを追加したい場合に有効です。例えば、以下のコードは ``X = 2`` を出力した後で、 ``X = 1`` を出力します。 :: X = 1 section X = 2 println(X = $(X)) println(X = $(X)) .. This result may seem surprising–the variable definition within the section is not visible outside the scope of the section. この結果について驚くかもしれませんが─ ``section`` 内での変数の束縛は外部のスコープには影響を及ぼしていないのです。 .. The export form, which will be described in detail in Section 6.3, can be used to circumvent this restriction by exporting variable values from an inner scope. For example, if we modify the previous example by adding an export expression, the new value for the X variable is retained, and the code prints the line X = 2 twice. ":ref:`label6.3`" で説明する ``export`` 文を使えば、内部スコープの変数をエクスポートすることでこの制限から抜け出すことができます。例えば、私たちが前回のサンプルに ``export`` 文を追加した場合、変数 ``X`` の新しい値が返されて、 ``X = 2`` が2回出力されます。 :: X = 1 section X = 2 println(X = $(X)) export println(X = $(X)) .. There are also cases where separate scoping is quite important. For example, each OMakefile is evaluated in its own scope. Since each part of a project may have its own configuration, it is important that variable definitions in one OMakefile do not affect the definitions in another. 分離されたスコープが非常に重要な結果を及ぼす場合があります。例えば、各々の ``OMakefile`` はそれ自身のスコープで評価されます。つまり各々のプロジェクトの一部は独立した設定となっているので、一つの ``OMakefile`` で変数を定義しても、これは他の ``OMakefile`` の定義に影響を及ぼしません。 .. To give another example, in some cases it is convenient to specify a separate set of variables for different build targets. A frequent idiom in this case is to use the section command to define a separate scope. 別の例を見てみましょう。異なったビルドターゲットを指定するために、変数を分割するほうが便利である場合を考えます。この場合の頻繁に使う慣用句として、分割されたスコープを定義する ``section`` 文を使用することが挙げられます。 :: section CFLAGS += -g %.c: %.y $(YACC) $< .SUBDIRS: foo .SUBDIRS: bar baz .. In this example, the -g option is added to the CFLAGS variable by the foo subdirectory, but not by the bar and baz directories. The implicit rules are scoped as well and in this example, the newly added yacc rule will be inherited by the foo subdirectory, but not by the bar and baz ones; furthermore this implicit rule will not be in scope in the current directory. この例では、 ``foo`` サブディレクトリには ``CFLAGS`` 変数に ``-g`` オプションが追加されていますが、 ``bar`` と ``baz`` ディレクトリには追加されていません。この例の場合ですとスコープのルールは非常によく働いており、 ``foo`` サブディレクトリには新しいyaccルールが追加されていますが、 ``bar`` と ``baz`` は追加されていません。さらにいうと、この追加されたルールは現在のディレクトリに影響を及ぼしていません。 .. index:: single: 条件分岐 single: if .. _label4.9: 条件分岐 ---------------- .. Top level conditionals have the following form. トップレベルでの条件分岐は以下のような形となります。 :: if elseif else .. The expression is evaluated, and if it evaluates to a true value (see Section 9.2 for more information on logical values, and Boolean functions), the code for the is evaluated; otherwise the remaining clauses are evaluated. There may be multiple elseif clauses; both the elseif and else clauses are optional. Note that the clauses are indented, so they introduce new scopes. まず ```` が評価されて、もしそれが *true* の値(真偽値についての詳細は ":ref:`label9.2`" を参照してください)であるならば ```` のコードが評価されます。そうでなければ、残りの節が評価されます。また、 ``if`` 文は複数の ``elseif`` 宣言句を持たせることができます。 ``elseif`` と ``else`` 宣言句はなくても構いません。ただし、新しいスコープを導入するため、それぞれの宣言句はインデントされている必要があります。 .. When viewed as a predicate, a value corresponds to the Boolean false, if its string representation is the empty string, or one of the strings false, no, nil, undefined, or 0. All other values are true. ``if`` 文では、評価する文字列が空であったり、内容が ``false`` , ``no`` , ``nil`` , ``undefined`` , ``0`` であった場合、真偽値は *false* として評価されます。それ以外はすべて *true* になります。 .. The following example illustrates a typical use of a conditional. The OSTYPE variable is the current machine architecture. 以下の例では典型的な条件分岐の使い方を示しています。 ``OSTYPE`` 変数は現在使っているマシンのアーキテクチャを表しています。 :: # アーキテクチャ上での主要な拡張子 if $(equal $(OSTYPE), Win32) EXT_LIB = .lib EXT_OBJ = .obj EXT_ASM = .asm EXE = .exe export elseif $(mem $(OSTYPE), Unix Cygwin) EXT_LIB = .a EXT_OBJ = .o EXT_ASM = .s EXE = export else # 他のアーキテクチャの場合は強制終了する eprintln(OS type $(OSTYPE) is not recognized) exit(1) .. index:: single: switch single: match single: case single: default single: 正規表現 .. _label4.10: マッチング ------------------- .. Pattern matching is performed with the switch and match forms. パターンマッチングは ``switch`` と ``match`` 文を使って実現できます。 :: switch case case ... default .. The number of cases is arbitrary. The default clause is optional; however, if it is used it should be the last clause in the pattern match. ``case`` の数は任意です。 ``default`` 宣言句はなくても構いませんが、使う場合は一番最後の宣言句で用いるべきです。 .. For switch, the string is compared with the patterns literally. ``switch`` の場合、文字列は ```` と『文字通りに』比較されます。 :: switch $(HOST) case mymachine println(Building on mymachine) default println(Building on some other machine) .. Patterns need not be constant strings. The following function tests for a literal match against pattern1, and a match against pattern2 with ## delimiters. ```` は定数である必要はありません。以下の関数は ``pattern1`` のマッチ、そして ``##`` デリミタを用いた ``pattern2`` のマッチを表しています。 :: Switch2(s, pattern1, pattern2) = switch $(s) case $(pattern1) println(Pattern1) case $"##$(pattern2)##" println(Pattern2) default println(Neither pattern matched) .. For match the patterns are egrep(1)-style regular expressions. The numeric variables $1, $2, ... can be used to retrieve values that are matched by \(...\) expressions. ``match`` の場合、パターンとしてegrep(1)─正規表現─が使用できます。数値変数 ``$1, $2, ...`` は ``\(...\)`` 表現を使って値を取得できます。 :: match $(NODENAME)@$(SYSNAME)@$(RELEASE) case $"mymachine.*@\(.*\)@\(.*\)" println(Compiling on mymachine; sysname $1 and release $2 are ignored) case $".*@Linux@.*2\.4\.\(.*\)" println(Compiling on a Linux 2.4 system; subrelease is $1) default eprintln(Machine configuration not implemented) exit(1) .. index:: single: オブジェクト single: フィールド single: メソッド .. _label4.11: オブジェクト --------------------- .. OMake is an object-oriented language. Generally speaking, an object is a value that contains fields and methods. An object is defined with a . suffix for a variable. For example, the following object might be used to specify a point (1, 5) on the two-dimensional plane. OMakeはオブジェクト指向言語です。一般的に、オブジェクトはフィールド(訳注: プロパティもしくはメンバ変数と置き換えても良いです)とメソッドを持っています。オブジェクトは変数名の最後に ``.`` を加えることで定義できます。例えば、以下のオブジェクトは2次元平面上での点(1, 5)を表しています。 :: Coord. = x = 1 y = 5 print(message) = println($"$(message): the point is ($(x), $(y)") # Xに5を束縛 X = $(Coord.x) # これは "Hi: the point is (1, 5)" と出力されます。 Coord.print(Hi) .. The fields x and y represent the coordinates of the point. The method print prints out the position of the point. オブジェクトのフィールド ``x`` と ``y`` は点の座標を表しています。 ``print`` メソッドは点の現在位置を出力します。 .. index:: single: クラス single: class .. _label4.12: クラス --------------- .. We can also define classes. For example, suppose we wish to define a generic Point class with some methods to create, move, and print a point. A class is really just an object with a name, defined with the class directive. オブジェクトと同様にして *クラス* も定義できます。例えば、私たちは現在、オブジェクトを生成したり、移動したり、位置を出力するメソッドを持った ``Point`` クラスを作りたいものとしましょう。クラスはオブジェクトの作り方と似ていますが、 ``class`` 宣言句を用いて名前を定義付ける点が異なります。 :: Point. = class Point # フィールドの通常の値 x = 0 y = 0 # 座標から新しいクラスを生成する new(x, y) = this.x = $(x) this.y = $(y) return $(this) # 点を右に移動する move-right() = x = $(add $(x), 1) return $(this) # 点を出力する print() = println($"The point is ($(x), $(y)") p1 = $(Point.new 1, 5) p2 = $(p1.move-right) # "The point is (1, 5)" と出力 p1.print() # "The point is (2, 5)" と出力 p2.print() .. Note that the variable $(this) is used to refer to the current object. Also, classes and objects are functional—the new and move-right methods return new objects. In this example, the object p2 is a different object from p1, which retains the original (1, 5) coordinates. 変数 ``$(this)`` は現在のオブジェクトを参照していることに注目してください。また、クラスとオブジェクトは新しいオブジェクトを返す ``new`` と ``move-right`` メソッドを持っています。これは、オブジェクト ``p2`` とオブジェクト ``p1`` が別物であり、 ``p1`` はオリジナルの座標(1, 5)を保持していることを表しています。 .. index:: single: 継承 .. _label4.13: 継承 --------------- .. Classes and objects support inheritance (including multiple inheritance) with the extends directive. The following definition of Point3D defines a point with x, y, and z fields. The new object inherits all of the methods and fields of the parent classes/objects. クラスとオブジェクトは継承(多重継承を含む)を ``extends`` 文によってサポートしています。以下の ``Point3D`` では、 ``x`` , ``y`` , ``z`` フィールドを持ったクラスを定義しています。新しいオブジェクトは、親クラスやオブジェクトが持つすべてのフィールドやメソッドを継承します。 :: Z. = z = 0 Point3D. = extends $(Point) extends $(Z) class Point3D print() = println($"The 3D point is ($(x), $(y), $(z))") # "new"メソッドはオーバーライドされていませんので、 # 下のメソッドは新しく点(1, 5, 0)を返します。 p = $(Point3D.new 1, 5) .. index:: single: static. single: where() single: CheckProg() single: ConfMsgChecking() single: ConfMsgResult() .. _label4.14: static. --------------- .. The static. object is used to specify values that are persistent across runs of OMake. They are frequently used for configuring a project. Configuring a project can be expensive, so the static. object ensure that the configuration is performed just once. In the following (somewhat trivial) example, a static section is used to determine if the LATEX command is available. The $(where latex) function returns the full pathname for latex, or false if the command is not found. ``static.`` オブジェクトはOMakeが動作している間、ずっと一定の値を保持していたい場合に使うオブジェクトです。このオブジェクトはプロジェクトを設定する際に頻繁に用いられます。プロジェクトを設定する変数が何回も書き換えられるのはリスクが高いので、 ``static.`` オブジェクトは設定がちょうど一回だけ行われることを保証してくれます。以下の(どこか冗長な)サンプルでは、 ``static.`` 節がLaTeXコマンドが使用可能であるかどうか調べるために使われています。 ``$(where latex)`` 関数は ``latex`` の絶対パスか、latexコマンドが存在しない場合は ``false`` を返します。 :: static. = LATEX_ENABLED = false print(--- Determining if LaTeX is installed ) if $(where latex) LATEX_ENABLED = true export if $(LATEX_ENABLED) println($'(enabled)') else println($'(disabled)') .. The OMake standard library provides a number of useful functions for programming the static. tests, as described in Chapter 14. Using the standard library, the above can be rewritten as OMakeの標準ライブラリを用いると第14章( :ref:`label14` )にあるような ``static.`` をプログラミングするための、多くの有用な関数を試すことができます。標準ライブラリを用いると、上のコードは以下のように書き直せます。 :: open configure/Configure static. = LATEX_ENABLED = $(CheckProg latex) .. As a matter of style, a static. section that is used for configuration should print what it is doing using the ConfMsgChecking and ConfMsgResult functions (of course, most of helper functions in the standard library would do that automatically). プロジェクトの設定として使われている ``static.`` 節は、 ``ConfMsgChecking`` や ``ConfMsgResult`` 関数( :ref:`label14.1.1` )を使って、 ``static.`` 節でどういう動作をしているのかについて出力すべきです(もちろん、標準ライブラリにある多くの関数が、この作業を自動的に行ってくれます)。 .. index:: single: .STATIC single: awk() .. _label4.14.1: .STATIC ^^^^^^^^^^^^^^^^^^ .. This feature was introduced in version 0.9.8.5. *この機能はバージョン 0.9.8.5 で搭載されました。* .. There is also a rule form of static section. The syntax can be any of the following three forms. ``.STATIC`` 節の書き方は ``static.`` 節の書き方と似ています。構文は以下の3つのどれを選んでも書くことができます。 :: # bodyで定義されたすべての変数をエクスポート .STATIC: # 特にファイル依存を指定したい場合 .STATIC: # ファイル依存と同様に、どの変数をエクスポートしたいのか指定する場合 .STATIC: : .. The are the variable names to be defined, the are file dependencies—the rule is re-evaluated if one of the dependencies is changed. The and can be omitted; if so, all variables defined in the are exported. ```` は定義する変数名、 ```` はファイル依存─依存先のファイルのある一つが変更された場合、対象のルールは再評価されます─を指定します。 ```` と ```` はもし必要ならば除外することができ、 ```` 中で定義されたすべての変数はエクスポートされます。 .. For example, the final example of the previous section can also be implemented as follows. たとえば、前回のセクションで示した最後のサンプルは以下のように改良できます。 :: open configure/Configure .STATIC: LATEX_ENABLED = $(CheckProg latex) .. The effect is much the same as using static. (instead of .STATIC). However, in most cases .STATIC is preferred, for two reasons. 効果は( ``.STATIC`` を使用する代わりに) ``static.`` を使用した場合とほとんど似ています。しかしながら、殆どの場合において ``.STATIC`` のほうが優位です。理由は2つあります。 .. First, a .STATIC section is lazy, meaning that it is not evaluated until one of its variables is resolved. In this example, if $(LATEX_ENABLED) is never evaluated, the section need never be evaluated either. This is in contrast to the static. section, which always evaluates its body at least once. まず、 ``.STATIC`` 節は遅延評価されます。これはつまり、 ``.STATIC`` 内の変数が一つでも解決されないのならば、評価されることはないということを意味しています。例えばもし ``$(LATEX_ENABLED)`` が決して評価されない変数だとすると、 ``.STATIC`` 節は決して評価されることはありません。これは少なくとも一回はいつでも評価される ``static.`` 節とは対照的です。 .. A second reason is that a .STATIC section allows for file dependencies, which are useful when the .STATIC section is used for memoization. For example, suppose we wish to create a dictionary from a table that has key-value pairs. By using a .STATIC section, we can perform this computation only when the input file changes (not on every fun of omake). In the following example the awk function is used to parse the file table-file. When a line is encountered with the form key = value, the key/value pair is added the the TABLE. 次に、 ``.STATIC`` 節はファイル依存を指定できます。これは、 ``.STATIC`` 節がメモ化として用いられる場合に有効です。例えば、キーと値のペアを持ったテーブルから辞書を作りたい場合を考えてみましょう。 ``.STATIC`` 節を使うことによって、omakeはこの計算を(omakeが毎回動くときに計算するのではなく)入力されたファイルが変更された場合のみ計算するようにふるまいます。以下の例では、 ``awk`` 関数がファイル ``table-file`` をパースするために用いられています。 ``awk`` 関数は ``key = value`` の形をした行を発見する度に、そのキーと値のペアを ``TABLE`` 変数に追加します。 :: .STATIC: table-file TABLE = $(Map) awk(table-file) case $'^\([[:alnum:]]+\) *= *\(.*\)' TABLE = $(TABLE.add $1, $2) export .. It is appropriate to think of a .STATIC section as a rule that must be recomputed whenever the dependencies of the rule change. The targets of the rule are the variables it exports (in this case, the TABLE variable). ルールの依存関係が変わった場合はいつでも ``.STATIC`` 節は再計算されます。このルール内での対象は、エクスポートする変数となります(この場合ですと ``TABLE`` 変数が相当します)。 .. index:: single: .MEMO .. _label4.14.1.1: .MEMO """""""""""""""""" .. A .MEMO rule is just like a .STATIC rule, except that the results are not saved between independent runs of omake. ``.MEMO`` ルールは、その結果が独立して動いている ``omake`` インスタンス間で保存されない点を除いて、 ``.STATIC`` ルールと等価です。 .. index:: single: :key: single: .MEMO single: 再帰関数 .. _label4.14.1.2: \:key: """""""""""""""""" .. The .STATIC and .MEMO rules also accept a :key: value, which specifies a “key” associated with the values being computed. It is useful to think of a .STATIC rule as a dictionary that associates keys with their values. When a .STATIC rule is evaluated, the result is saved in the table with the :key: defined by the rule (if a :key: is not specified, a default key is used instead). In other words, a rule is like a function. The :key: specifies the function “argument”, and the rule body computes the result. ``.STATIC`` と ``.MEMO`` ルールはまた、計算された値とリンクしている『キー』を表す ``:key:`` を使うことができます。 ``.STATIC`` ルールを、キーと値がリンクした辞書として考えることは有用です。 ``.STATIC`` ルールが評価された場合、結果は指定されたルールによって定義された ``:key:`` がテーブル内に保存されます( ``:key:`` が指定されていない場合、デフォルトのキーが代わりに用いられます)。言い換えると、ルールは関数のようなものです。 ``:key:`` は関数の『引数』を表しており、ルール部分で結果を計算します。 .. To illustrate, let's use a .MEMO rule to implement a Fibonacci function. これを確かめるために、 ``.MEMO`` ルールをフィボナッチ関数に改良してみましょう。 :: fib(i) = i = $(int $i) .MEMO: :key: $i println($"Computing fib($i)...") result = if $(or $(eq $i, 0), $(eq $i, 1)) value $i else add($(fib $(sub $i, 1)), $(fib $(sub $i, 2))) value $(result) println($"fib(10) = $(fib 10)") println($"fib(12) = $(fib 12)") .. When this script is run, it produces the following output. このスクリプトを実行した場合、以下のような結果となります。 :: Computing fib(10)... Computing fib(9)... Computing fib(8)... Computing fib(7)... Computing fib(6)... Computing fib(5)... Computing fib(4)... Computing fib(3)... Computing fib(2)... Computing fib(1)... Computing fib(0)... fib(10) = 55 Computing fib(12)... Computing fib(11)... fib(12) = 144 .. Note that the Fibonacci computation is performed just once for each value of the argument, rather than an exponential number of times. In other words, the .MEMO rule has performed a memoization, hence the name. Note that if .STATIC were used instead, the values would be saved across runs of omake. フィボナッチ関数は各々の引数の場合において、一回だけしか計算されていないことに注目してください。これは普通にプログラムした場合ですと、指数関数的に計算時間が増えてしまいます。言い換えると、 ``.MEMO`` ルールは計算結果をメモ化(memoization)しているからこそ、この名前なのです。 ``.STATIC`` ルールを代わりに使った場合、すべての ``omake`` インスタンスにおいて値が保存されていることに注意してください。 .. As a general guideline, whenever you use a .STATIC or .MEMO rule within a function body, you will usually want to use a :key: value to index the rule by the function argument. However, this is not required. In the following, the .STATIC rule is used to perform some expensive computation once. 一般的には、あなたは ``.STATIC`` か ``.MEMO`` ルールを関数内で用いる場合はいつでも、ふつう ``:key:`` を使いたくなるでしょう。しかしながら、これは必須ではありません。以下の例では、 ``.STATIC`` ルールが、何か計算時間のかかる作業を一回だけ行う場合を表しています。 :: f(x) = .STATIC: y = $(expensive-computation) add($x, $y) .. Additonal care should be taken for recursive functions, like the Fibonacci function. If the :key: is omitted, then the rule would be defined in terms of itself, resulting in a cyclic dependency. Here is the output of the Fibonacci program with an omitted :key:. あなたがフィボナッチ関数のような再帰的な関数を定義する場合、さらに以下の点に注意すべきです。 ``:key:`` を除外してしまった場合、ルールは関数自体に対して定義されてしまい、循環された依存関係で評価されてしまいます。以下は ``:key:`` を除いたフィボナッチ関数の出力結果です。 :: Computing fib(10)... Computing fib(8)... Computing fib(6)... Computing fib(4)... Computing fib(2)... Computing fib(0)... fib(10) = 0 fib(12) = 0 .. The reason for this behavior is that the result value is not saved until the base case i = 0 || i = 1 is reached, so fib calls itself recursively until reaching fib(0), whereupon the result value is fixed at 0. この動作は ``i = 0 || i = 1`` の場合に達するまで ``result`` の値が保存されていないので、 ``fib`` は自身を ``fib(0)`` に達するまで再帰的に呼び出し、そして ``result`` の値は0に修正されてしまうために生じます。 .. In any case, recursive definitions are perfectly acceptable, but you will usually want a :key: argument so that each recursive call has a different :key:. In most cases, this means that the :key: should include all arguments to the function. 再帰的な定義が無難に動作する場合もありますが、あなたは普通 ``:key:`` 引数をつけることで、各々の再帰的な呼び出しが異なった ``:key:`` を持つようにするでしょう。これは多くの場合において、 ``:key:`` が関数の引数すべてに含めるべきであることを示しています。 .. index:: single: 整数型 single: 浮動小数点型 single: 配列 single: 文字列 single: ファイル single: ディレクトリ single: マップ single: 辞書 single: チャネル single: 関数 single: 無名関数 single: 字句解析 single: パーサ .. _label4.15: 定数 ----------------- .. Internally, OMake represents values in several forms, which we list here. OMakeではいろんな方法でそれぞれの値を表すことができます。私たちはこれを以下のリストにしました。 .. int * Constructor: $(int ) 9.4.1. * Object: Int 12.1.4. * An integer is a represented with finite precision using the OCaml representation (31 bits on a 32 platform, and 63 bits on a 64 bit platform). * See also: arithmetic 9.4.3. * **int** - 整数型 * コンストラクタ: ``$(int )`` (:ref:`label9.4.1`) * オブジェクト: ``Int`` (:ref:`label12.1.4`) * 有限の値をもった整数型で、精度はプラットフォーム上のOCamlに依存します(32ビットのプラットフォーム上では31ビット、64ビットのプラットフォーム上では63ビット)(訳注: 1ビットは正負の判定に使われます)。 * 詳細は ":ref:`label9.4.3`" を参照してください。 .. float * Constructor: $(float ) 9.4.2. * Object: Float 12.1.5. * A float is a floating-point value, represented in IEEE 64-bit format. * See also: arithmetic 9.4.3. * **float** - 浮動小数点型 * コンストラクタ: ``$(float )`` (:ref:`label9.4.2`) * オブジェクト: ``Float`` (:ref:`label12.1.5`) * 浮動小数点型で、精度は64ビットです。 .. array * Constructor: $(array , ..., ) 9.3.1. * Object: Array 12.1.7. * An array is a finite list of values. Arrays are also defined with an array definition X[] = ... * See also: nth 9.3.5, nth-tl 9.3.8, length 9.3.4, … * **array** - 配列 * コンストラクタ: ``$(array , ..., )`` (:ref:`label9.3.1`) * オブジェクト: ``Array`` (:ref:`label12.1.7`) * 配列は有限の数の値をもったリストを表します。配列はまた以下のように定義することもできます。 :: X[] = ... * 詳細は ":ref:`label9.3.5`", ":ref:`label9.3.8`", ":ref:`label9.3.4`" を参照してください。 .. string * Object: String 12.1.8. * By default, all constant character sequences represent strings, so the simple way to construct a string is to write it down. Internally, the string may be parsed as several pieces. A string often represents an array of values separated by whitespace. osh>S = This is a string - : : Sequence osh>length($S) - : 4 : Int * A data string is a string where whitespace is significant. It represents a single value, not an array. The constructors are the quotations $"..." and $'...'. osh>S = $'''This is a string''' - : : String * See also: Quoted strings 7.2. * **string** - 文字列 * オブジェクト: ``String`` (:ref:`label12.1.8`) * 通常、すべての文字からなるシーケンスは配列として表現されるため、単純にソース中に書き表すことで初期化できます。内部で文字列はいくつかの断片としてパースされます。文字列はしばしば、ホワイトスペース(訳注: ホワイトスペースはスペース、タブを含んだ空白文字のことです)によって分割された値のシーケンスとして定義されます。 :: osh>S = This is a string - : : Sequence osh>length($S) - : 4 : Int * *データ* 文字列は、ホワイトスペースが重要な意味を持つ場合に用いられます。これは単純な一つの値として定義されるので、配列にはなりません。コンストラクタはクオーテーション ``$"..."`` と ``$'...'`` で表現できます。 :: osh>S = $'''This is a string''' - : : String * 詳細は ":ref:`label7.2`" を参照してください。 .. file * Constructor: $(file ) 10.1.1. * Object: File 12.1.13. * A file object represents the abstract name for a file. The file object can be viewed as an absolute name; the string representation depends on the current directory. osh>name = $(file foo) - : /Users/jyh/projects/omake/0.9.8.x/foo : File osh>echo $(name) foo osh>cd .. - : /Users/jyh/projects/omake : Dir osh>echo $(name) 0.9.8.x/foo * See also: vmount 10.6.1. * **file** - ファイル * コンストラクタ: ``$(file )`` (:ref:`label10.1.1`) * オブジェクト: ``File`` (:ref:`label12.1.13`) * ファイルオブジェクトはファイルの絶対パスを表すオブジェクトです。ファイルオブジェクトは絶対パスとして見ることができます。文字列への変換はカレントディレクトリに依存しています。 :: osh>name = $(file foo) - : /Users/jyh/projects/omake/0.9.8.x/foo : File osh>echo $(name) foo osh>cd .. - : /Users/jyh/projects/omake : Dir osh>echo $(name) 0.9.8.x/foo * 詳細は ":ref:`label10.1.1`" を参照してください。 .. note:: 訳注: 原文では ":ref:`label10.6.1`" となっていますが、これはおそらく ":ref:`label10.1.1`" の間違いであると思われますので、置き換えました。 .. directory * Constructor: $(dir ) 10.1.1. * Object: Dir 12.1.14. * A directory object is like a file object, but it represents a directory. * **directory** - ディレクトリ * コンストラクタ: ``$(dir )`` * オブジェクト: ``Dir`` (:ref:`label12.1.14`) * ディレクトリオブジェクトはファイルオブジェクトと似ていますが、ディレクトリとしてふるまいます。 * **map (dictionary)** - マップ (辞書) * オブジェクト: ``Map`` (:ref:`label12.1.2`) * マップ/辞書オブジェクトは値と値を結びつけるテーブルです。 ``Map`` オブジェクトは空のマップです。データ構造は永続的に保持されて、すべての演算は分かりやすく関数的です。特別な構文 ``$|key|`` によって文字列のキーを表現することができます。 :: osh>table = $(Map) osh>table = $(table.add x, int) osh>table. += $|y| = int osh>table.find(y) - : "int" : Sequence .. map (dictionary) * Object: Map 12.1.2. * A map/dictionary is a table that maps values to values. The Map object is the empty map. The data structure is persistent, and all operations are pure and functional. The special syntax $|key| can be used for keys that are strings. osh>table = $(Map) osh>table = $(table.add x, int) osh>table. += $|y| = int osh>table.find(y) - : "int" : Sequence .. channel * Constructor: $(fopen , ) 10.8.4. * Objects: InChannel 12.1.16, OutChannel 12.1.17. * Channels are used for buffered input/output. * **channel** - チャネル * コンストラクタ: ``$(fopen , )`` (:ref:`label10.8.4`) * オブジェクト: ``InChannel`` (:ref:`label12.1.16`), ``OutChannnel`` (:ref:`label12.1.17`) * チャネルオブジェクトは入力や出力のバッファとして使います。 .. function * Constructor: $(fun , ) 9.5.1. * Object: Fun 12.1.9. * Functions can be defined in several ways. o As an anonymous function, $(fun i, j, $(add $i, $j)) o As a named function, f(i, j) = add($i, $j) o This feature will be introduced in version 0.9.9.0.As an anonymous function argument. osh>foreach(i => $(add $i, 1), 1 2 3) - : : Array * **function** - 関数 * コンストラクタ: ``$(fun , )`` (:ref:`label9.5.1`) * オブジェクト: ``Fun`` (:ref:`label12.1.9`) * 関数オブジェクトはいろんな方法で定義できます。 * 無名関数 :: $(fun i, j, $(add $i, $j)) * 名前をつけた関数 :: f(i, j) = add($i, $j) * *この機能はバージョン0.9.9.0で導入されました。* 無名関数の引数 :: osh>foreach(i => $(add $i, 1), 1 2 3) - : : Array .. lexer * Object: Lexer 10.11.9. * This object represents a lexer. * **lexer** - 字句解析 * オブジェクト: ``Lexer`` (:ref:`label10.11.9`) * このオブジェクトは字句解析器(レキサ)として表現します。 .. parser * Object: Parser 10.11.13. * This object represents a parser. * **parser** - パーサ * オブジェクト: ``Parser`` (:ref:`label10.11.13`) * このオブジェクトはパーサとして表現します。