Ring 1.7 での変更点は?

Ring 1.7 公開版の新機能と変更点を学びます。

新機能と変更一覧

Ring 1.7 の新機能!

  • 新しい命令: Load Package
  • ringvm_see() および ringvm_give() 関数
  • ring_state_new() および ring_state_mainfile() 関数
  • トレースライブラリの改善
  • Ring ノートパッドの改善
  • RingQt の改善
  • Ring2EXE の改善
  • RingZip の改善
  • 取扱説明書の改訂
  • Ring VM の改善
  • RingLibuv 拡張機能

新しい命令: Load Package

‘Load’ 命令により、複数の Ring ソースファイルを同じプロジェクトで使用できます。

しかし、これらのファイルでは同じグローバルスコープを共有しています。

さて、現在では “Load Package” 命令もあります。

“Load Package” では新しいグローバルスコープへライブラリ (*.ring ファイル) を読み込むことができます。

これはグローバル変数との名前衝突回避となりますので、ライブラリの作成するときに非常に便利です。

用例:

ファイル: loadpackage.ring

x = 100
? "Hello, World!"
load package "testloadpackage.ring"

? x
test()

ファイル: testloadpackage.ring

? "Hello from testloadpackage.ring"

x = 1000

test()

func test
        ? x

実行結果:

Hello, World!
Hello from testloadpackage.ring
1000
100
1000

ringvm_see() および ringvm_give() 関数

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() 関数を使用すると Give 命令の挙動を変更します。

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

用例:

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

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

実行結果:

Name: Mahmoud
Hello Mahmoud

ring_state_new() および ring_state_mainfile() 関数

ring_state_new() および ring_state_mainfile() 関数で Ring プログラムから別の Ring プログラムを実行できます。

ring_state_main() 関数とは異なり、こちらは Ring ステートの削除時に制御できます!

これは GUI プログラムから別の GUI プログラムを実行するときに重要です。

この場合の理由は GUI ライブラリ (RingQt) を共有しており、

呼び出し元は qApp.Exec() を呼び出すからです。

よって、下位プログラムを停止せずにメインプログラムへ戻ります。

ここで下位プログラムのステートを削除してしまうと、下位プログラムのイベント実行時に問題が発生します。

ステートを保持することは、下位 GUI プログラムの収容先となっている GUI プログラムでは重要です。

トレースライブラリの改善

トレースライブラリの更新により、デバッガのブレークポイントで “callstack” 命令を利用できるようになりました。

この命令は関数のコールスタックを表示します。

用例:

load "tracelib.ring"

func main
        ? "Hello from main!"
        test1()

func test1
        ? "Hello from test1!"
        test2()

func test2
        ? "Hello from test2!"
        test3()

func test3
        ? "Hello from test3!"
        breakpoint()
コールスタック

Ring ノートパッドの改善

このような更新が Ring ノートパッドにあります。

  1. 拡張子 *.cf への対応
  2. ハッシュ関数 (SHA256) 使用時の改善 - “Save Changes?” (変更を保存しますか?) メッセージ
  3. Ring ノートパッド - ×ボタン - Saving Changes? で問い合わせるようになりました。

RingQt の改善

このクラスを RingQt へ追加しました。

  1. QStackedWidget
  2. QCalendarWidget
  3. QOpenGLFunctions
  4. QOpenGLContext
  5. QSurfaceFormat
  6. QOpenGLWidget
  7. QOpenGLVersionProfile
  8. QOpenGLFunctions_3_2_Core
  9. QVector2D
  10. QVector3D
  11. QVector4D
  12. QQuaternion
  13. QMatrix4x4
  14. QOpenGLPaintDevice
  15. QPaintDevice
  16. QOpenGLTimerQuery
  17. QOpenGLDebugLogger
  18. QOpenGLFramebufferObject
  19. QOpenGLVertexArrayObject
  20. QOpenGLBuffer
  21. QOpenGLShaderProgram
  22. QOpenGLShader
  23. QOpenGLTexture

Ring2EXE の改善

C/C++ コンパイラがないとき、想定された動作を行うために Ring2EXE を更新しました。

この場合は、アプリケーションの配布に適した生成物を取得することができます (exe ファイルと ring ファイル)。

RingZip の改善

このライブラリの更新により、サブフォルダにあるファイルの展開に対応しました!

取扱説明書の改訂

  1. RingQt クラスの章 - クラス一覧の並べ替えを行いました。

Ring VM の改善

  1. エラーメッセージの改善
  2. List2Str() 関数で数値を有するリストに対応
  3. 分離記号 _ のある数値の対応を修正
  4. 変数を使用せずにリストを作成 (ステートメント –> 式 –> リスト)
  5. isNULL() - 英数大小文字同一視 - Null および null は NULL と同等に扱われます。
  6. このオブジェクトで属性に Self オブジェクトの追加へ対応
  7. ‘:’ 演算子を使用後に小文字リテラルのキーワードを作成
  8. オブジェクトの表示 - decimals() 関数の考慮
  9. 定数を閉られていない場合 - 定数の始点を決定
  10. リストのあるオブジェクトの表示時におけるエラーメッセージの改善
  11. VarPtr() - ローカルスコープにある変数のポインタの取得に対応
  12. 新しいスレッドの作成時に perfomance 命令を normal 命令へ交換

RingLibuv 拡張機能

Ring 1.7 から RingLibuv 拡張機能を利用できるようなりました。

Libuv は非同期 I/O に主眼を置いたマルチプラットフォーム対応ライブラリです。

用例 (イベントループ):

load "libuv.ring"

counter = 0
idler = NULL

func main
        idler = new_uv_idle_t()
        uv_idle_init(uv_default_loop(), idler)
        uv_idle_start(idler, "wait()")
        ? "Idling..."
        uv_run(uv_default_loop(), UV_RUN_DEFAULT);
        uv_loop_close(uv_default_loop());
        destroy_uv_idle_t(idler)

func wait
        counter++
        if counter >= 100000
                uv_idle_stop(idler)
        ok

実行結果:

Idling...

用例 (サーバ):

load "libuv.ring"
load "objectslib.ring"

? "Testing RingLibuv - Server Side - Using Classes"

open_object(:MyServer)

class MyServer from ObjectControllerParent

        DEFAULT_PORT    = 13370
        DEFAULT_BACKLOG = 1024

        addr    = new_sockaddr_in()
        server  = NULL
        client  = NULL
        myloop  = NULL

        func start
                myloop = uv_default_loop()
                server = new_uv_tcp_t()
                uv_tcp_init(myloop, server)
                uv_ip4_addr("127.0.0.1", DEFAULT_PORT, addr)
                uv_tcp_bind(server, addr, 0)
                r = uv_listen(server, DEFAULT_BACKLOG, Method(:newconnection) )
                if r
                        ? "Listen error " + uv_strerror(r)
                        return 1
                ok
                uv_run(myloop, UV_RUN_DEFAULT)
                destroy_uv_tcp_t(server)
                destroy_uv_sockaddr_in(addr)

        func newconnection
                ? "New Connection"
                aPara   = uv_Eventpara(server,:connect)
                nStatus = aPara[2]
                if nStatus < 0
                        ? "New connection error : " + nStatus
                        return
                ok
                client = new_uv_tcp_t()
                uv_tcp_init(myloop, client)
                if uv_accept(server, client) = 0
                                uv_read_start(client, uv_myalloccallback(),
                                                        Method(:echo_read))
                ok

        func echo_read
                aPara = uv_Eventpara(client,:read)
                nRead = aPara[2]
                buf   = aPara[3]
                if nRead > 0
                        req = new_uv_write_t()
                                wrbuf = uv_buf_init(get_uv_buf_t_base(buf), nread)
                        uv_write(req, client, wrbuf, 1, Method(:echo_write))
                        ? uv_buf2str(wrbuf)
                        message = "message from the server to the client"
                        buf = new_uv_buf_t()
                        set_uv_buf_t_len(buf,len(message))
                        set_uv_buf_t_base(buf,varptr("message","char *"))
                        uv_write(req, client, buf, 1, Method(:echo_write))
                ok

        func echo_write
                aPara = uv_Eventpara(client,:read)
                req   = aPara[1]

実行結果:

クライアントを実行すると、 “New Connection” メッセージが表示されます。

そして “hello from the client” メッセージが表示されます。

Testing RingLibuv - Server Side - Using Classes
New Connection
hello from the client

用例 (スレッドの使用):

load "libuv.ring"
load "objectslib.ring"

? "Testing RingLibuv - Threads - Using Classes"

open_object(:MyThreads)

class MyThreads from ObjectControllerParent

        func Start
                one_id = new_uv_thread_t()
                two_id = new_uv_thread_t()
                uv_thread_create(one_id, Method(:One))
                uv_thread_create(two_id, Method(:Two))
                uv_thread_join(one_id)
                uv_thread_join(two_id)
                destroy_uv_thread_t(one_id)
                destroy_uv_thread_t(two_id)

        func one
                ? "Message from the First Thread!"

        func Two
                ? "Message from the Second Thread!"

実行結果:

Testing RingLibuv - Threads - Using Classes
Message from the First Thread!
Message from the Second Thread!

この拡張機能 (RingLibuv) についての詳細情報は、この章をご確認ください: RingLibuv の用法