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()
Better Ring Notepad
Ring Notepad comes with the next updates
Support *.cf extension
Using Hash function (SHA256) for better “Save Changes?” message
Ring Notepad - X Button - Ask for saving changes?
Better RingQt
The next classes are added to RingQt
QStackedWidget
QCalendarWidget
QOpenGLFunctions
QOpenGLContext
QSurfaceFormat
QOpenGLWidget
QOpenGLVersionProfile
QOpenGLFunctions_3_2_Core
QVector2D
QVector3D
QVector4D
QQuaternion
QMatrix4x4
QOpenGLPaintDevice
QPaintDevice
QOpenGLTimerQuery
QOpenGLDebugLogger
QOpenGLFramebufferObject
QOpenGLVertexArrayObject
QOpenGLBuffer
QOpenGLShaderProgram
QOpenGLShader
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
RingQt Classes Chapter - The classes are sorted.
Better Ring VM
Better Error Message
List2Str() function support lists contains numbers
Correct support for numbers contains _ as separator
Creating lists without variables (statement –> Expression –> List)
IsNULL() - Not case sensitive - treat Null and null like NULL
Support adding the Self object to an attribute in this object
Using ‘:’ operator then keyword will create lower case literal
Printing objects - respect decimals() function
When literal is not closed - determine the start of the literal
Better message when printing objects contains lists
VarPtr() - Support getting a pointer to variables in the local scope
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