What is new in Ring 1.7?

In this chapter we will learn about the changes and new features in Ring 1.7 release.

List of changes and new features

Ring 1.7 comes with many new features!

  • New Command: Load Package

  • ringvm_see() and ringvm_give() functions

  • ring_state_new() and ring_state_mainfile() functions

  • Better Trace Library

  • Better Ring Notepad

  • Better RingQt

  • Better Ring2EXE

  • Better RingZip

  • Better Documentation

  • Better Ring VM

  • RingLibuv Extension

New Command: Load Package

Using the ‘load’ command we can use many ring source files in the same project

But all of these files will share the same global scope

Now we have the “Load Package” command too

Using “Load Package” we can load a library (*.ring file) in new global scope

This is very useful to create libraries that avoid conflicts in global variables

Example:

File: loadpackage.ring

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

File: testloadpackage.ring

? "Hello from testloadpackage.ring" x = 1000 test() func test ? x 

Output:

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

ringvm_see() and ringvm_give() functions

Using the ringvm_see() function we can redefine the behavior of the See command

Also we can use ring_see() to have the original behavior

Example:

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 

Output:

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 

Using the ringvm_give() function we can redefine the behavior of the Give command

Also we can use ring_give() to have the original behavior

Example:

see "Name: " give name see "Hello " + name func ringvm_give see "Mahmoud" + nl return "Mahmoud" 

Output:

Name: Mahmoud Hello Mahmoud 

ring_state_new() and ring_state_mainfile() functions

Using ring_state_new() and ring_state_mainfile() we can run Ring programs from Ring programs

But unlike ring_state_main(), Here we can control when to delete the Ring state!

This is important when we run GUI programs from GUI programs

Because they will share the GUI Library (RingQt), And In this case the caller will call

qApp.Exec()

So the sub program, will not stop and will return to the Main program

Here deleting the State of the sub programs will lead to a problem when we run the sub program events

So keeping the state is important for sub GUI programs hosted in GUI programs.

Better Trace Library

The Trace library is updated, In the Debugger at break points we have now the “callstack” command

This command will print the functions call stack.

Example:

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() 
Call Stack

Better Ring Notepad

Ring Notepad comes with the next updates

  1. Support *.cf extension

  2. Using Hash function (SHA256) for better “Save Changes?” message

  3. Ring Notepad - X Button - Ask for saving changes?

Better RingQt

The next classes are added to 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

Better Ring2EXE

Ring2EXE is updated to works as expected when we don’t have a C/C++ compiler

Where we can distribute applications and get (exe file and ringo file) in this case.

Better RingZip

The library is updated to support extracting files contains sub folders!

Better Documentation

  1. RingQt Classes Chapter - The classes are sorted.

Better Ring VM

  1. Better Error Message

  2. List2Str() function support lists contains numbers

  3. Correct support for numbers contains _ as separator

  4. Creating lists without variables (statement –> Expression –> List)

  5. IsNULL() - Not case sensitive - treat Null and null like NULL

  6. Support adding the Self object to an attribute in this object

  7. Using ‘:’ operator then keyword will create lower case literal

  8. Printing objects - respect decimals() function

  9. When literal is not closed - determine the start of the literal

  10. Better message when printing objects contains lists

  11. VarPtr() - Support getting a pointer to variables in the local scope

  12. replace performance instructions with normal instructions when creating new threads

RingLibuv Extension

Ring 1.7 comes with the RingLibuv extension

Libuv is a multi-platform support library with a focus on asynchronous I/O.

Example (Events Loop):

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 

Output:

Idling... 

Example (Server):

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] 

Output:

When we run the client, We will see the message “New Connection”

Then the message “hello from the client”

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

Example (Using Threads):

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!" 

Output:

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

For more information about this extension (RingLibuv) check the chapter: Using RingLibuv