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