4D v16.3

シンタックスの詳細

ホーム

 
4D v16.3
シンタックスの詳細

シンタックスの詳細  


 

 

コンパイラは、4Dコマンドの通常の構文ルールに従っていることを期待します。コンパイルのためにデータベースを特に変更する必要はありません。

とはいえ、この節ではコマンドについての注意点や詳細について項目別に説明します。

  • 変数のデータ型を決定付けるようなコマンドは、データ型矛盾の原因になることがあります。
  • コマンドの中には複数のシンタックスを持つものがあり、どのシンタックスが最適なのか知っておくと役に立ちます。

文字列に対して処理を行うコマンドでは、Character code関数のみが特段の注意を必要とします。インタプリタモードでは、空でない文字列や空の文字列をこの関数に渡せます。
コンパイルモードでは、空の文字列を渡すことができません。
Character codeに、空の文字列が格納された変数を渡すと、コンパイラはコンパイル中にエラーを見つけることはできません。

通信  

SEND VARIABLE(variable)
RECEIVE VARIABLE(variable)

上記2つのコマンドは変数をディスクに保存または読み込む場合に使用されます。変数が引数としてこれらのコマンドに渡されます。
コマンドに渡す変数の型は、常に同じ型でなければなりません。変数のリストをファイルに送る場合を考えてみましょう。誤ってデータ型を変えてしまう恐れを取り除くため、送信する変数のデータ型をリストの先頭で指定することをおすすめします。そうすると、これらの変数を受け取る際には、常に最初にインジケータが返されることになります。RECEIVE VARIABLEコマンドを呼び出したら、Case of文を使用して、次から受け取るデータを処理できます。

 SET CHANNEL(12;"File")
 If(OK=1)
    $Type:=Type([Client]Total_TO)
    SEND VARIABLE($Type)
    For($i;1;Records in selection)
       $Send_TO:=[Client]Total_TO
       SEND VARIABLE($Send_TO)
       NEXT RECORD
    End for
 End if
 SET CHANNEL(11)
 SET CHANNEL(13;"MyFile")
 If(OK=1)
    RECEIVE VARIABLE($Type)
    Case of
       :($Type=Is string var)
          RECEIVE VARIABLE($String)
  `受信した変数の処理
       :($Type=Is real)
          RECEIVE VARIABLE($Real)
  `受信した変数の処理
       :($Type=Is text)
          RECEIVE VARIABLE($Text)
  `受信した変数の処理
    End case
 End if
 SET CHANNEL(11)

Field(フィールドポインタ) または (テーブル番号;フィールド番号)
Table(テーブルポインタ) または (テーブル番号) または (フィールドポインタ)

これら2つのコマンドは、与えられた引数によって、戻り値のデータ型が異なります。
  • ポインタを与えると、Table関数は数値を返します。
  • 数値を与えると、Table関数はポインタを返します。
コンパイラでは、これらの関数から結果のデータ型を決定できません。このような場合は、コンパイラコマンドを使用して明確に定義してください。

Open documentAppend documentCreate Document関数によって返されるドキュメント参照番号のデータ型は時間型です。

演算  

Mod (value;divider)

4Dでは25を3で割った余りを求める場合、次の2通りの方法があります。

 Variable:=Mod(25;3)

または

 Variable:=25%3

コンパイラはこの2つの式を区別します。Mod関数はすべての数値に使用できますが、%演算子は整数と倍長整数にしか使用できません。%演算子のオペランドが、倍長整数データ型の範囲を越えた場合には、返される結果は保証されません。

IDLE
ON EVENT CALL (Method{; ProcessName})
ABORT

IDLEコマンドは例外処理を行うために4Dランゲージに追加されました。ON EVENT CALLコマンドを用いる場合は、必ずこのIDLEコマンドも使用してください。

このコマンドはイベント管理命令として定義することができます。

4Dのカーネルだけがシステムイベント(マウスクリックやキー操作など)を検知できます。ほとんどの場合、カーネルコールはコンパイル後のコードそのものによって起動され、ユーザに対しては透過的です。

他方、4Dがイベント待ちループなどの中でイベントの受信を待っている場合はカーネルコールがないことが明白です。

  `「MouseClick」メソッド
 If(MouseDown=1)
    <>vTest:=True
    ALERT("マウスクリックされました。")
 End if
 
  `「Wait」メソッド
 <>vTest:=False
 ON EVENT CALL("MouseClick")
 While(<>vTest=False)
  `イベント待ちのループ
 End while
 ON EVENT CALL("")

この場合、IDLEコマンドを次のように追加します。

  `「Wait」メソッド
 <>vTest:=False
 ON EVENT CALL("MouseClick")
 While(<>vTest=False)
    IDLE
  `イベントを検知させるためのカーネルコール
 End while
 ON EVENT CALL("")
ABORT  

このコマンドは、エラー処理プロジェクトメソッド内でのみ使用してください。これは4Dで使用した場合とまったく同じように動作しますが、EXECUTE FORMULAAPPLY TO SELECTIONAPPLY TO SUBSELECTIONコマンドから呼び出されたメソッド内の場合は例外です。このような状況は避けた方がよいでしょう。

配列  

コンパイラが配列のデータ型を決める際に使用する4Dコマンドは、以下の7種類です。

COPY ARRAY(source;destination)
SELECTION TO ARRAY(フィールド;配列)
ARRAY TO SELECTION(配列;フィールド)
SELECTION RANGE TO 配列(start;end;フィールド;配列)
LIST TO ARRAY(list;配列{; itemRefs})
ARRAY TO LIST(配列;list{; itemRefs})
DISTINCT VALUES(フィールド;配列)

COPY ARRAYコマンドは2個の配列型の引数を使用します。引数の一方がどこにも定義されていないと、コンパイラは定義されている方のデータ型から未定義の配列のデータ型を決定します。
この場合、以下のように処理されます。

  • 最初の引数が定義されている場合:2番目の配列には、最初の配列のデータ型が適用されます。
  • 2番目の引数が定義されている場合:最初の配列に2番目の配列のデータ型が適用されます。

コンパイラはデータ型を厳密にチェックするので、COPY ARRAYコマンドは同じ型の配列間で行わなければなりません。このため、整数と倍長整数と実数、あるいは、テキスト配列と文字配列で文字列の長さが一定でない場合等のように、型の似ている配列間のコピーをする際には要素を1つずつコピーする必要があります。
例えば、整数型の配列要素を実数型の配列にコピーする場合、次のように行います。

 $Size:=Size of array(ArrInt)
 ARRAY REAL(ArrReal;$Size)
  `実数配列を整数配列と同じ配列サイズ(要素数)にする。
 For($i;1;$Size)
    ArrReal{$i}:=ArrInt{$i}
  `個々の要素についてコピーを行う。
 End for

処理中に配列の次元数を変更することはできませんので、注意してください。1次元配列を2次元配列にコピーすると、エラーメッセージが出力されます。

4Dのインタプリタモードと同様、これら4つのコマンドでは配列の定義は要求されません。型が定義されていない配列にはコマンドで指定した フィールドのデータ型が割り当てられます。

 SELECTION TO ARRAY([MyTable]IntField;MyArray)

"IntField"が整数フィールドの場合、"MyArray"は整数配列になります。

配列が定義されている場合は、フィールドと同じデータ型になっているかどうか確認してください。整数、倍長整数、実数は似ていますが、同じ型ではありません。
た だし、テキストや文字のデータ型では、多少許容範囲が広くなります。デフォルトにより、文字型のフィールドを使用するコマンドで配列をあらかじめ定義せず に引数として使った場合、配列に割り当てられるデフォルトのデータ型はテキストです。あらかじめ配列を文字またはテキスト型として宣言されている場合、 ユーザの指定が適用されます。

テキスト型のフィールドについても同様で、宣言された型が優先されます。
SELECTION TO ARRAYSELECTION RANGE TO ARRAYARRAY TO SELECTIONDISTINCT VALUESコマンドは、1次元の配列でしか使用できません。
SELECTION TO ARRAYコマンドにはもう1つのシンタックスがあります。
SELECTION TO ARRAY(テーブル;配列).
この場合、配列変数は倍長整数になります。SELECTION RANGE TO ARRAYコマンドについても同様です。

LIST TO ARRAYおよびARRAY TO LISTコマンドに使用できる配列は次の2種類だけです。

  • 1次元の文字配列
  • 1次元のテキスト配列
このコマンドの場合、引数に使う配列をあらかじめ宣言する必要はありません。デフォルトでは、宣言されていない配列は、テキスト配列になります。配列があらかじめテキストか文字型で宣言されていない場合、ユーザの指定した型になります。

ポインタについての節で説明したように、配列を定義するコマンドの引数にポインタ参照が使われていると、コンパイラは型の矛盾を発見できません。

 SELECTION TO ARRAY([Table]Field;Pointer->)

Pointer->が示すのが配列だとして、コンパイラは配列の型およびフィールド型をチェックすることができません。型の矛盾が起こらないようにするのは、開発者は気をつけるべきです。ポインタが示す配列を必ず定義してください。
コンパイラは、引数にポインタを使用している配列定義ステートメントを見つけると、警告メッセージを出力します。警告メッセージはこの種の矛盾を見つける際に役立ちます。

データベースで、ローカル配列(定義されたメソッド内のみで有効な配列)を使用している場合は、使用前に明確に宣言しておく必要があります。

ローカル配列を定義するには、ARRAY REALARRAY INTEGERなど、配列を定義するコマンドを使用します。

例えば、プロシージャで10個の要素を持つローカルな整数配列を作る場合、次のようなコマンドを使用前に定義しておきます。

 ARRAY INTEGER($MyArray;10)

Get pointer(varName)
Type (object)
EXECUTE FORMULA(statement)
TRACE
NO TRACE

ポインタの配列を初期化する場合、配列の各要素はそれぞれ与えられた変数を表します。
例えばV1、V2、...V12というような12個の変数の場合、以下のように書くことができます。

 ARRAY POINTER(Arr;12)
 Arr{1}:=->V1
 Arr{2}:=->V2
 
 Arr{12}:=->V12

また、以下のように書くこともできます。

 ARRAY POINTER(Arr;12)
 For($i;1;12)
    Arr{$i}:=Get pointer("V"+String($i))
 End for

この処理が終了すると、各要素が変数V1からV12を指すポインタの配列ができます。

この2つの書き方は、両方ともコンパイルできますが、他の場所で変数V1...V12の型が明らかにされていないと、コンパイラはデータ型を決定できません。そのため、このような変数は別の場所で明示的に使用するか、または定義する必要があります。
明示的に変数を定義する方法は、2通りあります。

  • コンパイラコマンドを使用してV1...V12を定義するには以下のように記述します。
 C_LONGINT(V1;V2;V3;V4;V5;V6;V7;V8;V9;V10;V11;V12)
  • メソッドでV1...V12に値を代入するには以下のように記述します。
 V1:=0
 V2:=0
 
 V12:=0

コンパイルされたデータベースの変数のデータ型は1つだけなので、この関数は不必要に思えるかも知れません。しかし、ポインタを 使用する際、この関数が役立ちます。例えば、ポインタが参照する変数のデータ型を知りたい場合、ポインタの性質上、指されているオブジェクトがわかりにく い場合があります。

EXECUTE FORMULAコマンドは、インタプリタモードでは有効ですが、コンパイルモードではその利点を活かすことができません。
コンパイルモードでは、このコマンドに引数として渡されたメソッド名は解釈されます。コンパイラのいくつかの利点を活用できない上に、引数のシンタックスチェックもできません。
また、引数にローカル変数を使用することもできません。
EXECUTE FORMULAコマンドは、複数のステートメントに置き換えることができます。以下に2つの例を挙げます。

 i:=FormFunc
 EXECUTE FORMULA("FORM SET INPUT (Form"+String(i)+")")

これは、以下ように書き換えることができます。

 i:=FormFunc
 VarForm:="Form"+String(i)
 FORM SET INPUT(VarForm)

また次の例では、

 $Num:=SelPrinter
 EXECUTE FORMULA("Print"+$Num)

ここでは、EXECUTE FORMULAコマンドをCase ofに置き換えることができます。

 Case of
    :($Num=1)
       Print1
    :($Num=2)
       Print2
    :($Num=3)
       Print3
 End case

EXECUTE FORMULAコマンドは常に置き換えが可能です。実行するメソッドはデータベースのプロジェクトメソッドのリストから選択されたもので、その数には限りがあります。このため、EXECUTE FORMULAコマンドは必ずCase of文や他のコマンドで置き換えることができます。さらに、コードの実行速度はEXECUTE FORMULAコマンドよりも速くなります。

これらのコマンドはデバッグ処理の段階で使用します。コンパイルされたデータベースでは機能しません。コンパイラはこれらのコマンドを無視するので、メソッド内に残しておいても問題ありません。

変数  

Undefined(variable)
SAVE VARIABLES(document;variable1{; variable2…})
LOAD VARIABLES(document;variable1{; variable2…})
CLEAR VARIABLE(variable)

コンパイラではコンパイルモードの変数は必ず定義されます。データ型は、コンパイルが完了するまでに設定されます。このため、引数が渡されると毎回Undefined関数はFalseを返します。

:アプリケーションがコンパイルモードで実行されているかどうかはIs compiled mode関数を呼び出して確認してください。

インタプリタでは、LOAD VARIABLEコマンドの実行後にUndefined関数を使用して変数が未定義かどうか調べることにより、ドキュメントファイルの存在の有無をチェックできます。コンパイル後はこの方法を使用できません。Undefined関数が常にFalseを返すからです。

このテストはインタプリタでもコンパイル後でも次のようにして実行できます。

  1. どの変数にとっても無効な値で、ロードする変数を初期化します。
  2. LOAD VARIABLEコマンドを実行した後、ロードした変数のうちの1つを初期値と比較します。

メソッドは以下のようになります。

 Var1:="xxxxxx"
  `"xxxxxx" この値は、LOAD VARIABLESコマンドにより返されることはない。
 Var2:="xxxxxx"
 Var3:="xxxxxx"
 Var4:="xxxxxx"
 LOAD VARIABLES("Document";Var1;Var2;Var3;Var4)
 If(Var1="xxxxxx")
  `ドキュメントが見つからない。
 
 Else
  `ドキュメントが見つかった。
 
 End if

インタプリタモードでは、この関数には次の2つのシンタックスがあります。
CLEAR VARIABLE(variable)
CLEAR VARIABLE("a")

コンパイル後のデータベースでは、1番目のシンタックスCLEAR VARIABLE (variable)は変数を再度初期化します(数値は0に、文字列やテキストは空にする等)。理由は、コンパイル後は未定義の変数が存在しないからです。

したがって、コンパイル後はテキスト、ピクチャ、BLOB、配列型の変数を除き、CLEAR VARIABLEコマンドで変数のメモリを解放することはできません。

配列の場合、CLEAR VARIABLEコマンドは、要素数が0の新しい配列の定義を意味します。
例えば、CLEAR VARIABLE (MyArray) において、MyArrayが整数配列の場合、以下のいずれか同じ意味を持ちます。

 ARRAY INTEGER(MyArray;0)
  `一次元配列の場合
 ARRAY INTEGER(MyArray;0;0)
  `二次元配列の場合

2番目のシンタックスCLEAR VARIABLE("a")は、コンパイラが名前ではなくアドレスで変数にアクセスするためコンパイラで使用することはできません。

以下のコマンドには、共通する特徴が1つあります。これらのコマンドでは、最初に省略可能な引数[テーブル]があり、2番目の引数にポインタを使用することが可能な点です。

ADD TO SETLOAD SET
APPLY TO SELECTIONLOCKED ATTRIBUTES
COPY NAMED SELECTIONORDER BY
CREATE EMPTY SETORDER BY FORMULA
CREATE SETOUTPUT FORM
CUT NAMED SELECTIONPAGE SETUP
DIALOGPrint form
EXPORT DIFPRINT LABEL
EXPORT SYLKQR REPORT
EXPORT TEXTQUERY
GOTO RECORDQUERY BY FORMULA
GOTO SELECTED RECORDQUERY SELECTION
GRAPH TABLEQUERY SELECTION BY FORMULA
IMPORT DIFREDUCE SELECTION
IMPORT SYLKRELATE MANY
IMPORT TEXTREMOVE FROM SET
INPUT FORM

コンパイルモードでは、省略可能な[テーブル]引数を扱うことが可能です。しかし、これらのコマンドに最初に渡された引数がポインタの場合、コンパイラはポインタが何を参照しているのかわからないため、コンパイラは、最初の引数をテーブルポインタとして扱ってしまいます。

QUERYコマンドのケースで考えてみましょう。シンタックスは以下のとおりです。
QUERY({Table{;formula{;*}})
formulaの最初の要素はフィールドでなければなりません。
次のように書いた場合、

 QUERY(PtrField->=True)

コンパイラは2番目の要素内でフィールドを表す記号を探します。しかし、“=”の記号が見つかった段階で、コンパイラは、これの関数式を判別できないため、エラーメッセージを出力します。

曖昧にならないようにするためには、以下のいずれかのように記述することができます。

 QUERY(PtrTable->;PtrField->=True)

または

 QUERY([Table];PtrField->=True)

テーブルを省略しないことで、曖昧さを避けることができます。

ポインターを使用する際、これらのコマンドには、最初の引数が [aTable]で、2番目の引数がどちらも任意であるという共通性があります。このコンテキストでは、内部的な理由から、コンパイラーはポインターを返すコマンド(例:Current form tableなど)を直接引数として渡すことを許可しません(エラーが発生します)。

例えばFORM SCREENSHOTコマンドなどもこの例にあてはまります。以下のコードはインタープリタモードでは動きますが、コンパイル時に除去されます:

  //コンパイルエラーをトリガー
 FORM SCREENSHOT(Current form table->;$formName;$myPict)

この場合、このコードに中継用の変数を用意してからコンパイラに渡す事ができます:

  //コンパイル可能な同等のコード
 C_POINTER($ptr)
 $ptr:=Current form table
 FORM SCREENSHOT($ptr->;$formName;$myPict)

定数  

独自の4DK#リソース(定数)を作成する場合は、必ず数値の型を倍長整数(L)もしくは実数(R)に、文字列の型を(S)に設定してください。その他の型では警告メッセージが表示されます。



参照 

エラーメッセージ
コンパイラ指示子の使用
最適化のヒント
型指定ガイド

 
プロパティ 

プロダクト: 4D
テーマ: コンパイラ

 
履歴 

 
ARTICLE USAGE

ランゲージリファレンス ( 4D v16)
ランゲージリファレンス ( 4D v16.1)
ランゲージリファレンス ( 4D v16.2)
ランゲージリファレンス ( 4D v16.3)