低水準関数 — プログラミング言語 Ring 1.14 取扱説明書

Skip to content

# 低水準関数

低水準関数の用法です。

    * callgarbagecollector()| callgc()
    * variablepointer()     | varptr()
    * space()
    * nullpointer()         | nullptr()
    * object2pointer()      | obj2ptr()
    * pointer2object()      | ptr2obj()
    * ispointer()           | isptr()
    * pointercompare()      | ptrcmp()
    * setpointer()          | setptr()
    * getpointer()          | getptr()
    * pointer2string()      | ptr2str()
    * memorycopy()          | memcpy()
    * ringvm_cfunctionslist()
    * ringvm_functionslist()
    * ringvm_classeslist()
    * ringvm_packageslist()
    * ringvm_memorylist()
    * ringvm_calllist()
    * ringvm_fileslist()
    * ringvm_settrace()
    * ringvm_tracedata()
    * ringvm_traceevent()
    * ringvm_tracefunc()
    * ringvm_scopescount()
    * ringvm_evalinscope()
    * ringvm_passerror()
    * ringvm_hideerrorMsg()
    * ringvm_callfunc()
    * ringvm_see()
    * ringvm_give()
    * ringvm_info()

## callgc() 関数

文法:

    callgc()                        # 略式名
    callgarbagecollector()          # 正式名

この関数は、関数実行中に代入操作では解放されない一時作業用変数を用いるループで強制的にガベージコレクター呼び出すために使用します。

この関数が必要になることは非常に稀なことですが、ゲームエンジンでイベントループなどを作成して、 関数を呼び出して即席でリストの作成を開始するときに便利です。

用例

    While True

            # イベントの処理
            # 一時作業領域による関数の呼び出し。 myfunc(["temp list"]) などのリストです。

            # ガベージコレクターの呼び出し
            callgc()
    End

ちなみに

Ring のガベージコレクターは関数の実行終了後または、 代入ステートメントを使用したときに自動的に動作します。

## varptr() 関数

varptr() 関数は C / C++ 関数へポインタを渡します。

文法:

    varptr(cVariableName, cPointerType) ---> 低水準オブジェクト (C ポインタ)
    variablepointer(cVariableName,cPointerType) ---> 低水準オブジェクト (C ポインタ)

用例:

    r = 10
    z = 20
    see r + nl
    see varptr("r","int")
    see varptr("z","int")

実行結果:

    10
    00E3C740
    int
    2
    00E3BEC0
    int
    2

注釈

低水準オブジェクトのリストには三つの項目 (ポインタ、型、ステータス) を有しています。

## space() 関数

space() 関数は指定されたバイト数のメモリ領域を確保します。

文法:

    Space(nBytesCount) ---> 文字列

用例:

    mystring = space(200)
    See "String Size : " + len(mystring) + nl
    See "String : " + mystring + nl
    See "String Pointer : "
    See varptr("mystring",:char)

実行結果:

    String Size : 200
    String :                                                                                                                String Pointer : 00FF8FE8
    char
    2

注釈

C 関数へバッファを渡すは space() と VarPtr() 関数が必要です。

ちなみに

space() 関数で確保したメモリを解放するには、代入演算子を使います。

    mystring = space(1000)  # メモリの確保 (1000 バイト)
    mystring = NULL         # mystring で確保されたメモリの解放

注釈

ローカル変数は関数の実行終了後に自動解放されますのでメモリの手動解放は不要です。

## nullpointer() 関数

文法:

    nullptr()                       # 略式名
    nullpointer()           # 正式名

仮引数でポインタを扱うことを想定しており、オプション扱いの仮引数に NULL ポインタを受け入れる場合は C 関数へ NULL ポインタを必ず渡してください。

用例:

この用例は LibSDL ライブラリから RingSDL にある SDL_BlitSurface() 関数を使用しています。 この関数は第二仮引数、および最後の仮引数で SDL_Rect ポインタを受け入れます。 また、関数は NULL ポインタを受け入れるために、 NULLPointer() 関数で NULL ポインタを渡せます。

    SDL_BlitSurface(text, nullpointer(), surface, nullpointer())

注釈

前述のコードは単体では動作しません。最初に RingSDL の用法を学ぶ必要があります。

ちなみに

NULLPointer() 関数の代わりに NULL を仮引数として渡せます。

    SDL_BlitSurface(text, NULL, surface, NULL)

## object2pointer() 関数

この関数は Ring リスト用の C ポインタとオブジェクトを取得します。

文法:

    obj2ptr(List|Object) --> 低水準オブジェクト (C ポインタ)             # 略式名
    object2pointer(List|Object) --> 低水準オブジェクト (C ポインタ)      # 正式名

注釈

メモリ上に存在する合法なポインタか必ず確認してください (解放したメモリのポインタは指さないでください)

## pointer2object() 関数

この関数は低水準オブジェクト (C ポインタ) から Ring のリスト、および / またはオブジェクトを取得します。

文法:

    ptr2obj(Low Level Object) ---> リスト|オブジェクト                       # 略式名
    pointer2object(Low Level Object) ---> リスト|オブジェクト        # 正式名

注釈

メモリ上に存在する合法なポインタか必ず確認してください (解放したメモリのポインタは指さないでください)

用例:

    # リストの作成
    mylist = 1:5

    # リストのポインタを作成
    x = object2pointer(mylist)
    see x

    see nl

    # リストへ項目を追加
    mylist + "welcome"

    # リストの項目を表示
    y = pointer2object(x)
    see y

実行結果:

    0069A5D8
    OBJECTPOINTER
    0

    1
    2
    3
    4
    5
    welcome

注釈

Ring の代入演算子は値によりリストとオブジェクトをコピーします。 参照によりコピーするには object2pointer() および pointer2object() 関数を使用します。

ちなみに

object2pointer() および pointer2object() は stdlib で使用されています。 Tree クラスの実装では子ノード (別オブジェクト) は親ノード (オブジェクト) を参照して作成します。

Object2Pointer() および Pointer2Object() 関数は低水準関数であるため、

メモリの問題を防止するため使用時は十分な注意を払ってください。

ローカル変数のポインタを作成した場合、

このローカル変数はメソッドや関数の実行終了後にメモリから自動解放されます。

つまり、 Object2Pointer() 関数でポインタを作成してしまうとダングリングポインタとなってしまいます。

すなわち、ポインタが解放したメモリのメモリ番地を指してしまいます。

このような誤った使いかたは不正なポインタの原因となりクラッシュやメモリ破壊が起きてしまいます。

ポインタを使うときは (Using Object2Pointer() または Pointer2Object 関数の使用)、絶対に解放したメモリをポインタで指さないでください。

簡潔に言うなら、メモリはそのままにしてください (まだ必要とされるものは絶対に削除しない)。

すなわち、ローカル変数を使用してから削除するのではなく、クラス属性やグローバル変数をお使いください。

## ispointer() 関数

仮引数がポインタ (C オブジェクト) か検査します。

文法:

    IsPtr(vPara) ---> True|False            # 略式名
    IsPointer(vPara) ---> True|False        # 正式名

用例:

    fp = fopen(filename(),"r")

    ? type(fp)

    ? ispointer(fp)

実行結果:

    file
    1

## ptrcmp() 関数

ptrcmp() 関数はポインタ (C オブジェクト) 同士を比較します。

文法:

    ptrcmp(oObject1,oObject2) ---> oObject1 と oObject2 が等しいならば値は 1
                                   oObject1 と oObject2 が等しくないならば値は 0
    pointercompare(oObject1,oObject2) ---> oObject1 と oObject2 が等しいならば値は 1
                                           oObject1 と oObject2 が等しくないならば値は 0

用例:

    fp = fopen("ptrcmp.ring","r")
    fp2 = fp
    fp3 = fopen("ptrcmp.ring","r")

    see ptrcmp(fp,fp2) + nl
    see ptrcmp(fp,fp3) + nl

    fclose(fp)
    fclose(fp3)

実行結果:

    1
    0

## setpointer() 関数

ポインタのアドレスを別のポインタのアドレスへ設定します。

文法:

    setptr(pointer,nNewAddress)                     # 略式名
    setpointer(pointer,nNewAddress)         # 正式名

注釈

setPointer() と getPointer() 関数を使うことでメモリのアドレスを変更できます。

## getpointer() 関数

ポインタのアドレスを取得します。

文法:

    getptr(pointer) ---> nAddress           # 略式名
    getpointer(pointer) ---> nAddress       # 正式名

用例:

    ? "Sample about using setPointer() and getPointer() functions"
    ? copy("=",50)
    pointer = NULLPOINTER()
    ? pointer
    ? "Type: " + type(pointer)
    ? "Address: " + Upper(hex(getpointer(pointer)))
    ? copy("=",50)
    name = "ring"
    pointer = varptr(:name,:char)
    ? pointer
    ? "Type: " + type(pointer)
    ? "Address: " + Upper(hex(getpointer(pointer)))
    ? copy("=",50)
    setpointer(pointer, getpointer(pointer) + 1 )
    ? "After Update"
    ? "Address: " + Upper(hex(getpointer(pointer)))
    ? copy("=",50)

実行結果:

    ==================================================
    00000000
    NULLPOINTER
    0

    Type: NULLPOINTER
    Address: 0
    ==================================================
    026E2BA8
    char
    0

    Type: char
    Address: 26E2BA8
    ==================================================
    After Update
    Address: 26E2BA9
    ==================================================

## pointer2string() 関数

ポインタからバイナリデータの文字列へ変換します。

文字列からポインタへ再変換したいときは VarPtr() 関数をお使いください。

文法:

    ptr2str(pointer,nStart,nCount) ---> cString                     # 略式名
    pointer2string(pointer,nStart,nCount) ---> cString      # 正式名

注釈

pointer2String() はデータとして別領域にコピーを返します。

注釈

nStart が 0 ならば、一文字目が始点となります。

用例:

    name = "ring"
    pointer = varptr(:name,:char)
    ? pointer
    ? "Type: " + type(pointer)
    ? "Address: " + Upper(hex(getpointer(pointer)))

    ? "Get 4 bytes starting from the pointer address"
    mystring = Pointer2String(pointer,0,4)
    ? mystring

    ? "Get 2 bytes starting from the pointer address + 1"
    mystring2 = Pointer2String(pointer,1,2)
    ? mystring2

実行結果:

    01E03380
    char
    0

    Type: char
    Address: 1E03380
    Get 4 bytes starting from the pointer address
    ring
    Get 2 bytes starting from the pointer address + 1
    in

## memcpy() 関数

文法:

    memcpy(pDestinationPointer,cSourceString,nSize)         # 略式名
    memorycopy(pDestinationPointer,cSourceString,nSize)     # 正式名

用例:

    str = space(9)
    pointer = varptr(:str,"char")
    memcpy(pointer,"one",3)
    ? str
    setPointer(pointer,getPointer(pointer)+3)
    memcpy(pointer,"one",3)
    ? str
    setPointer(pointer,getPointer(pointer)+3)
    memcpy(pointer,"one",3)
    ? str

実行結果:

    one
    oneone
    oneoneone

## ringvm_cfunctionslist() 関数

C で記述された関数のリストを返す Ring 低水準関数です。

文法:

    RingVM_CFunctionsList() ---> リスト

用例:

    See RingVM_CFunctionsList()

## ringvm_functionslist() 関数

Ring で記述された関数のリストを返す関数です。

各リストメンバは次の項目のリストを有しています。

- 関数名

- プログラムカウンタ (PC) - バイトコードによる関数の位置

- ソースコードファイル名

- プライベートフラグ (クラスにあるプライベートメソッドならば)

文法:

    RingVM_FunctionsList() ---> リスト

用例:

    test()

    func test
            see ringvm_functionslist()

実行結果:

    test
    8
    B:/ring/tests/scripts/functionslist.ring
    0

## ringvm_classeslist() 関数

クラスのリストを返す関数です。

各リストメンバは次の項目のリストを有しています。

- クラス名

- プログラムカウンタ (PC) - バイトコードによるクラスの位置

- 親クラス名

- メソッドのリスト

- フラグ (親クラス情報の収集)

- パッケージへのポインタ (または未使用のパッケージならば NULL)

文法:

    RingVM_ClassesList() ---> リスト

用例:

    see ringvm_classeslist()

    class class1
            func f1
    class class2 from class1
    class class3 from class1

実行結果:

    class1
    9

    f1
    13
    B:/ring/tests/scripts/classeslist.ring
    0
    0
    00000000
    class2
    16
    class1
    0
    00000000
    class3
    20
    class1
    0
    00000000

## ringvm_packageslist() 関数

パッケージのリストを返す関数です。

各リストメンバは次の項目のリストを有しています。

- パッケージ名

- クラスのリスト

文法:

    RingVM_PackagesList() ---> リスト

用例:

    see ringvm_packageslist()

    package package1
            class class1

    package package2
            class class1

    package package3
            class class1

実行結果:

    package1
    class1
    11

    0
    00FEF838
    package2
    class1
    17

    0
    00FEF978
    package3
    class1
    23

    0
    00FEFF68

## ringvm_memorylist() 関数

メモリのスコープと変数のリストを返す関数です。

各リストメンバには、次の異なるスコープにある変数のリストを有しています。

スコープリストにある各項目のリストには次の項目があります。

- 変数の名前

- 変数の型

- 変数の値

- 値がリストの場合はポインタの型 (リスト/項目)

- プライベートフラグ (変数がクラスの属性ならば)

文法:

    RingVM_MemoryList() ---> リスト

用例:

    x = 10
    test()
    func test
            y = 20
            see ringvm_memorylist()

実行結果:

    true
    2
    1
    0
    0
    false
    2
    0
    0
    0
    nl
    1

    0
    0
    null
    1

    0
    0
    ring_gettemp_var
    4
    00000000
    0
    0
    ccatcherror
    1
    NULL
    0
    0
    ring_settemp_var
    4
    00000000
    0
    0
    ring_tempflag_var
    2
    0
    0
    0
    stdin
    3
    50512DB8
    file
    0
    0
    0
    stdout
    3
    50512DD8
    file
    0
    0
    0
    stderr
    3
    50512DF8
    file
    0
    0
    0
    this
    4
    00000000
    0
    0
    sysargv
    3
    B:/ring/bin/ring
    B:/ring/tests/scripts/memorylist.ring
    0
    0
    x
    2
    10
    0
    0
    y
    2
    20
    0
    0

## ringvm_calllist() 関数

関数呼び出しリストのリストを返す関数です。

各リストメンバは次の項目のリストを有しています。

- 関数の型

- 関数の名前

- プログラムカウンタ (PC)

- スタックポインタ (SP)

- 一時作業用。メモリのリスト

- メソッドまたは関数のフラグ

- 呼び出し元のプログラムカウンタ (PC)

- FuncExec フラグ

- ListStart フラグ

- 多重リストのポインタ

- ステートリスト

文法:

    RingVM_CallList() ---> リスト

用例:

    hello()
    func hello
            test()

    func test
            mylist = ringvm_calllist()
            for t in mylist see t[2] + nl next

実行結果:

    function hello() in file B:/ring/tests/scripts/calllist.ring
    called from line 1
    function test() in file B:/ring/tests/scripts/calllist.ring
    called from line 3
    ringvm_calllist

## ringvm_fileslist() 関数

Ring ファイルのリストを返す関数です。

文法:

    RingVM_FilesList() ---> リスト

用例:

    load "stdlib.ring"
    see ringvm_fileslist()

実行結果:

    C:/ring/tests/scripts/fileslist.ring
    C:\ring\bin\stdlib.ring
    eval
    stdlib.ring
    stdlib.rh
    stdclasses.ring
    stdfunctions.ring
    stdbase.ring
    stdstring.ring
    stdlist.ring
    stdstack.ring
    stdqueue.ring
    stdmath.ring
    stddatetime.ring
    stdfile.ring
    stdsystem.ring
    stddebug.ring
    stddatatype.ring
    stdconversion.ring
    stdodbc.ring
    stdmysql.ring
    stdsecurity.ring
    stdinternet.ring
    stdhashtable.ring
    stdtree.ring

## ringvm_settrace() 関数

ringvm_settrace() はトレース関数名を決定する関数です。

トレース関数は Ring 関数でありイベントごとに呼び出されます。

文法:

    RingVM_SetTrace(cCode)

## ringvm_tracedata() 関数

関数内でイベントをトレースします。

ringvm_tracedata() 関数はイベントデータを取得します。

イベントデータのリストには次の項目があります。

- ソースコードの行番号

- ソースファイル名

- 関数またはメソッド名

- メソッドまたは関数 (Bool : True=メソッド、 False=関数またはファイル)

文法:

    RingVM_TraceData() ---> aDataList

## ringvm_traceevent() 関数

関数内でイベントをトレースします。

ringvm_traceevent() 関数はイベントの種類を検出します。

- 改行

- 関数の前

- 関数の後

- ランタイムエラー

- C 関数の前

- C 関数の後

文法:

    RingVM_TraceEvent() ---> nTraceEvent

## ringvm_tracefunc() 関数

この関数はイベントのトレースで使用する関数名を返します。

文法:

    RingVM_TraceEvent() ---> cCode

## ringvm_scopescount() 関数

RingVM_ScopesCount() 関数は、 アプリケーションで使用されているスコープの本数を検出します。

プログラムの開始時において、スコープは存在します (グローバルスコープのみ)。

関数の呼び出し時に、新しいスコープが作成されます。

関数実行終了後は、関数のスコープは削除されます。

文法:

    RingVM_ScopesCount() ---> nScopes

## ringvm_evalinscope() 関数

ringvm_evalinscope() は eval() 関数と類似する関数です。

eval() とは異なり、現在のスコープにあるコードを実行します。

RingVM_EvalInScope() は指定されたスコープにあるコードを実行します。

文法:

    RingVM_EvalInScope(nScope,cCode)

## ringvm_passerror() 関数

ランタイムエラーが発生した時はエラーメッセージを表示後に Ring はプログラムの実行を終了します。

ringvm_passerror() 関数を使うと、 前述の動作を回避してプログラムの実行を継続できます。

文法:

    RingVM_PassError()

## ringvm_hideerrormsg() 関数

RingVM_HideErrorMsg() 関数は、 ランタイムエラーメッセージの表示を有効または無効化します。

文法:

    RingVM_HideErrorMsg(lStatus)

## ringvm_callfunc() 関数

eval() 関数ではなく ringvm_callfunc() 関数を使うと、 文字列から関数を呼び出します。

文法:

    RingVM_CallFunc(cFuncName)

## 用例 - トレース関数の用法

この用例では、プログラムのイベントをトレースするためにトレース関数を使用しています！

トレースライブラリは低水準関数よりも実用的です！

    load "tracelib.ring"

    ringvm_settrace("mytrace()")

    see "Hello, world!" + nl
    see "Welcome" + nl
    see "How are you?" +nl
    mytest()
    new myclass { mymethod() }

    func mytest
            see "Message from mytest" + nl

    func mytrace
            see "====== The Trace function is Active ======" + nl +
                    "Trace Function Name : " + ringvm_TraceFunc() + nl +
                    "Trace Event : "
            switch ringvm_TraceEvent()
                    on TRACEEVENT_NEWLINE           see "New Line"
                    on TRACEEVENT_NEWFUNC           see "New Function"
                    on TRACEEVENT_RETURN            see "Return"
                    on TRACEEVENT_ERROR             see "Error"
                    on TRACEEVENT_BEFORECFUNC       see "Before C Function"
                    on TRACEEVENT_AFTERCFUNC        see "After C Function"
            off
            see nl +
                    "Line Number : " + ringvm_tracedata()[TRACEDATA_LINENUMBER] + nl +
                    "File Name   : " + ringvm_tracedata()[TRACEDATA_FILENAME] + nl +
                    "Function Name : " + ringvm_tracedata()[TRACEDATA_FUNCNAME] + nl +
                    "Method or Function : "
                    if ringvm_tracedata()[TRACEDATA_METHODORFUNC] =
                                     TRACEDATA_METHODORFUNC_METHOD
                            see "Method"
                    else
                            if ringvm_tracedata()[TRACEDATA_FUNCNAME] = NULL
                                    see "Command"
                            else
                                    see "Function"
                            ok
                    ok
                    see nl + Copy("=",42) + nl

    class myclass
            func mymethod
                    see "Message from mymethod" + nl

実行結果:

    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : After C Function
    Line Number : 3
    File Name   : test1.ring
    Function Name : ringvm_settrace
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 5
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================
    Hello, world!
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 6
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================
    Welcome
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 7
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================
    How are you?
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 8
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Function
    Line Number : 8
    File Name   : test1.ring
    Function Name : mytest
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 12
    File Name   : test1.ring
    Function Name : mytest
    Method or Function : Function
    ==========================================
    Message from mytest
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 14
    File Name   : test1.ring
    Function Name : mytest
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : Return
    Line Number : 8
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 9
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 43
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : Before C Function
    Line Number : 9
    File Name   : test1.ring
    Function Name : ismethod
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : After C Function
    Line Number : 9
    File Name   : test1.ring
    Function Name : ismethod
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Function
    Line Number : 9
    File Name   : test1.ring
    Function Name : mymethod
    Method or Function : Method
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 44
    File Name   : test1.ring
    Function Name : mymethod
    Method or Function : Method
    ==========================================
    Message from mymethod
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : Return
    Line Number : 9
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : Before C Function
    Line Number : 9
    File Name   : test1.ring
    Function Name : ismethod
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : After C Function
    Line Number : 9
    File Name   : test1.ring
    Function Name : ismethod
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : Before C Function
    Line Number : 9
    File Name   : test1.ring
    Function Name : ismethod
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : After C Function
    Line Number : 9
    File Name   : test1.ring
    Function Name : ismethod
    Method or Function : Function
    ==========================================
    ====== The Trace function is Active ======
    Trace Function Name : mytrace()
    Trace Event : New Line
    Line Number : 11
    File Name   : test1.ring
    Function Name :
    Method or Function : Command
    ==========================================

## 用例 - トレースライブラリ

この用例では、トレースライブラリ作成用のトレース関数を使用します。

トレースライブラリにより、 すばらしいトレースツールとインタラクティブデバッガを利用できます。

    # イベントのトレース
    TRACEEVENT_NEWLINE      = 1
    TRACEEVENT_NEWFUNC      = 2
    TRACEEVENT_RETURN       = 3
    TRACEEVENT_ERROR        = 4
    TRACEEVENT_BEFORECFUNC  = 5
    TRACEEVENT_AFTERCFUNC   = 6

    # データのトレース
    TRACEDATA_LINENUMBER    = 1
    TRACEDATA_FILENAME      = 2
    TRACEDATA_FUNCNAME      = 3
    TRACEDATA_METHODORFUNC  = 4

    # 関数のメソッド
    TRACEDATA_METHODORFUNC_METHOD           = TRUE
    TRACEDATA_METHODORFUNC_NOTMETHOD        = FALSE

    TRACE_BREAKPOINTS = TRUE

    TRACE_TEMPLIST = []

    func Trace cType
            switch trim(lower(cType))
            on :AllEvents
                    ringvm_settrace("TraceLib_AllEvents()")
            on :Functions
                    ringvm_settrace("TraceLib_Functions()")
            on :PassError
                    ringvm_settrace("TraceLib_PassError()")
            on :Debugger
                    ringvm_settrace("TraceLib_Debugger()")
            on :LineByLine
                    ringvm_settrace("TraceLib_LineByLine()")
            off

    func TraceLib_AllEvents
            if right(ringvm_tracedata()[TRACEDATA_FILENAME],13) = "tracelib.ring"
                    return
            ok
            see "====== The Trace function is Active ======" + nl +
                    "Trace Function Name : " + ringvm_TraceFunc() + nl +
                    "Trace Event : "
            switch ringvm_TraceEvent()
                    on TRACEEVENT_NEWLINE           see "New Line"
                    on TRACEEVENT_NEWFUNC           see "New Function"
                    on TRACEEVENT_RETURN            see "Return"
                    on TRACEEVENT_ERROR             see "Error"
                    on TRACEEVENT_BEFORECFUNC       see "Before C Function"
                    on TRACEEVENT_AFTERCFUNC        see "After C Function"
            off
            see nl +
                    "Line Number : " + ringvm_tracedata()[TRACEDATA_LINENUMBER] + nl +
                    "File Name   : " + ringvm_tracedata()[TRACEDATA_FILENAME] + nl +
                    "Function Name : " + ringvm_tracedata()[TRACEDATA_FUNCNAME] + nl +
                    "Method or Function : "
                    if ringvm_tracedata()[TRACEDATA_METHODORFUNC] =
                                     TRACEDATA_METHODORFUNC_METHOD
                            see "Method"
                    else
                            if ringvm_tracedata()[TRACEDATA_FUNCNAME] = NULL
                                    see "Command"
                            else
                                    see "Function"
                            ok
                    ok
                    see nl + Copy("=",42) + nl

    func TraceLib_Functions
            if right(ringvm_tracedata()[TRACEDATA_FILENAME],13) = "tracelib.ring"
                    return
            ok
            switch ringvm_TraceEvent()
                    on TRACEEVENT_NEWFUNC
                            see "Open Func : " +
                            ringvm_TraceData()[TRACEDATA_FUNCNAME] + nl
                    on TRACEEVENT_RETURN
                            see "Return to Func : " +
                            ringvm_TraceData()[TRACEDATA_FUNCNAME] + nl
            off

    func TraceLib_PassError
            if right(ringvm_tracedata()[TRACEDATA_FILENAME],13) = "tracelib.ring"
                    return
            ok
            switch ringvm_TraceEvent()
                    on  TRACEEVENT_ERROR
                            see nl
                            see "TraceLib : After Error !" + nl
                            ringvm_passerror()
            off

    func TraceLib_Debugger
            if right(ringvm_tracedata()[TRACEDATA_FILENAME],13) = "tracelib.ring"
                    return
            ok
            switch ringvm_TraceEvent()
                    on  TRACEEVENT_ERROR
                            _BreakPoint()
            off

    func TraceLib_LineByLine
            if right(ringvm_tracedata()[TRACEDATA_FILENAME],13) = "tracelib.ring" or
                    ringvm_TraceEvent() != TRACEEVENT_NEWLINE
                    return
            ok
            aList = ringvm_tracedata()
            see "Before Line : " + aList[TRACEDATA_LINENUMBER] + nl
            _BreakPoint()

    func BreakPoint
            if not TRACE_BREAKPOINTS
                    return
            ok
            _BreakPoint()

    func _BreakPoint
            see nl+nl+Copy("=",60) + nl +
            Copy(" ",20)+"Interactive Debugger" + nl +
            Copy("=",60) + nl +
            "Command (Exit)        : End Program" + nl +
            "Command (Cont)        : Continue Execution" + nl +
            "Command (Locals)      : Print local variables names" + nl +
            "Command (LocalsData)  : Print local variables data" + nl +
            "Command (Globals)     : Print global variables names" + nl +
            "We can execute Ring code" + nl +
            Copy("=",60) + nl
            while true
                            see nl + "code:> "
                            give cCode
                    cmd = trim(lower(cCode))
                    if cmd = "exit" or cmd = "bye"
                            shutdown()
                    ok
                    nScope = ringvm_scopescount()-2
                    switch cmd
                            on "locals"
                                    ringvm_EvalInScope(nScope,"see locals() callgc()")
                                    loop
                            on "localsdata"
                                    PrintLocalsData(nScope)
                                    loop
                            on "globals"
                                    ringvm_EvalInScope(nScope,"see globals() callgc()")
                                    loop
                            on "cont"
                                    ringvm_passerror()
                                    exit
                    off
                    Try
                            ringvm_EvalInScope(nScope,cCode)
                            catch
                                            see cCatchError
                            done
            end

    func NoBreakPoints
            TRACE_BREAKPOINTS = FALSE

    func PrintLocalsData nScope
            if nScope = 1   # グローバル
                    ringvm_Evalinscope(nScope,'TRACE_TEMPLIST = globals()')
            else
                    ringvm_Evalinscope(nScope,'TRACE_TEMPLIST = locals() callgc()')
            ok
            see nl
            aTempList = TRACE_TEMPLIST
            TRACE_TEMPLIST = []
            nSpaces = 5
            for TRACE_ITEM in aTempList
                    if len(TRACE_ITEM) + 5 > nSpaces
                            nSpaces = len(TRACE_ITEM) + 5
                    ok
            next
            for TRACE_ITEM in aTempList
                    see "Variable : " +  TRACE_ITEM
                    cVarName = TRACE_ITEM
                    see copy(" ",nSpaces-len(cVarName)) + " Type : "
                    ringvm_Evalinscope(nScope,"see type(" +  TRACE_ITEM +")")
                    ringvm_Evalinscope(nScope,"see Copy(' ',fabs(15-len(type(" +
                                              TRACE_ITEM +"))))")
                    see " Value : "
                    ringvm_Evalinscope(nScope,"see " +  TRACE_ITEM)
                    see nl
            next

## ringvm_see() 関数

ringvm_see() 関数は See 命令の挙動を変更します。

また ring_see() 関数は元の挙動を使用します。

用例:

    see "Hello world" + nl
    see 123 + nl
    see ["one","two","three"]
    see new point {x=10 y=20 z=30}

    func ringvm_see t
            ring_see("We want to print: ")
            ring_See(t)

    class point x y z

実行結果:

    We want to print: Hello world
    We want to print: 123
    We want to print: one
    two
    three
    We want to print: x: 10.000000
    y: 20.000000
    z: 30.000000

## ringvm_give() 関数

ringvm_give() 関数は Give 命令の挙動を変更します。

また ring_give() 関数は元の挙動を使用します。

用例:

    see "Name: " give name
    see "Hello " + name

    func ringvm_give
            see "Mahmoud" + nl
            return "Mahmoud"

実行結果:

    Name: Mahmoud
    Hello Mahmoud

## ringvm_info() 関数

ringvm_info () は Ring VM 構造体に関する情報をリストとして返す内部関数です。

この関数は Ring チームが VM の状態を調査するための高度な検証に限り使用されています。

文法:

    ringvm_info() ---> VM 構造体に関する情報のリスト