The concept of coroutine must be familiar to everyone now. After all, not only LUA, Go or Kotlin but also C++, they are all support coroutines.
But different languages have different implementations. Such as LUA, coroutines will be scheduled when someone called yield() or resume().
A new language introduced to you today is a scripting language of coroutine preemptive scheduling based on time slices. That is, each coroutine does not need to explicitly call certain functions to give up control, but according to the weight of execution time to control whether to be suspended or run.
Its name is Melang
- Official site: https://melang.org/
- Repo: https://github.com/Water-Melon/Melang
We will discuss the following:
- features
- usage scenarios
Features
For a language, it must have flow control, array, dict, structure or class, etc. These in Melang are no different from other languages. So we will focus on the following:
Coroutine preemptive scheduling
In Melang, each script task is an independent coroutine, and coroutines' execution environments are isolated. But they can communicate with each other by the message queue functions.
Let's look at two examples:
- running multi-tasks by melang execution file
There are two script files:
//a.mln
while (true) {
@mln_print('a');
}
//b.mln
while (true) {
@mln_print('b');
}
Then I execute the following command:
$ melang a.mln b.mln
After execution, you will see the screen print a and b alternately, as follows:
...
b
b
b
a
a
a
a
a
...
And using top
command will find out that only one process (and also only one thread) is performing these two tasks.
Melang scheduling does not occur in the function mln_print
, but will try to switch during the processing of each statement.
- start up multi-tasks in a Melang task
//launcher.mln
@mln_eval('a.mln');
@mln_eval('b.mln');
We create a new script file named launcher.mln
to start up a.mln
and b.mln
by calling function mln_eval
. And then execute:
$ melang launcher.mln
The output is the same as previous example.
Reflection
Reflection means that the class to be operated is known at runtime, and the complete structure of the class can be obtained at runtime and the corresponding method can be called. -- quoted from a netizen
In Melang, the concept of class is called Set, but it is more similar to the structure in C, but also supports function definitions.
Let's look at a simple example:
Human {
name;
age;
@init (name, age) {
this.name = name;
this.age = age;
}
}
Here we define a Set named Human, which has two member variables: name
and age
, and a method init
.
The general instantiation code is as follows:
me = $Human;
This instantiates a Human
object named me
.
However, we can also instantiate it like this:
str = 'Human';
me = $str;
The result is the same.
Then we can call the method of the object:
me.init('Tom', 18);
In Melang, not only Set can be obtained by a string, but also functions and object methods can be used in this way.
Examples for function:
@foo ()
{
@mln_print('foo');
}
a = 'foo';
a();
Here we define a function, and we call it indirectly by a string variable.
Example for object method:
Human {
name;
age;
action;
@init (name, age) {
this.name = name;
this.age = age;
}
}
me = $Human;
me.action = 'init';
me.action('Tom', 18);
@mln_print(me.name);
As you can see in this example, we call the method of an object by a string member variable.
Injection
For an instantiated object, we can still add (or inject) some members and methods to it, for example:
Human {
}
someone = $Human;
someone.age = 20;
@mln_print(someone.age);
The output is 20. The member variable age
was successfully added to the object someone
.
Note: The injection is defined for the object, not Set. Therefore, if you instantiate Human again, there is still no age
.
The above example is the simplest injection. Melang also provides function set
and get
similar to other scripts.
Let's look at an example of method injection:
Human {
age;
}
@printAge()
{
@mln_print(this.age);
}
someone = $Human;
someone.age = 20;
someone.print = printAge;
someone.print();
This example will still output 20, but this time it is output by mln_print
called in the injected method printAge
.
Reactive programming
As we can see in web front-end programming, a variable will be monitored by a set of functions. When the value changes, the callback function will be called. (Note that, in Melang, even if the new value is the same as the old one, it also will be called)
Example:
@eventHandler(newdata, userData)
{
@mln_print(newdata);
@mln_print(userData);
}
n = 0;
@mln_watch(n, eventHandler, 'this is an useData');
for (; n < 5; ++n)
;
Here, variable n
will be tracked by calling the function mln_watch
. When the value of n
changed, the eventHandler
function would be called.
We will see the following output:
1
this is an useData
2
this is an useData
3
this is an useData
4
this is an useData
5
this is an useData
Synchronous code, executed asynchronously
In Melang, code is written in a synchronized form. The advantage is logical coherence.
In traditional languages, synchronous writing also means synchronous processing, so the performance is low. But in Melang, the interpreter will execute completely asynchronously.
Example:
//a.mln
while (true) {
@mln_msgQueueSend('queue', 'a');
ret = @mln_msgQueueRecv('queue');
@mln_print(ret);
}
//b.mln
while (true) {
ret = @mln_msgQueueRecv('queue');
@mln_print(ret);
@mln_msgQueueSend('queue', 'b');
}
These two scripts use the message queue functions to send and receive messages from each other and print them out. For each task, its logic is sequential. For example, a.mln
must send a message first, then receive the message, and then print. If b.mln
does not send a message to a.mln
, then a.mln
will be suspended while receiving the message.
The above is just a simple example, and it is the same when it comes to network I/O. When data arrives on the socket, the interpreter will receive it, then return to the script layer, and change the script task from the suspended state to the running state.
Usage Scenarios
The current usage scenario of Melang is mainly embedded in other applications, which is basically the same as LUA. The Melang project on Github is a launcher. The launcher will call the script-related functions in the core library for initialization and execution. And of course, the core library is also open source.
Melang's core library provides many interfaces such as algorithms, data structures, event mechanisms, multi-process and multi-threaded frameworks. Based on this library, not only can obtain melang script, but also reduce development costs.
In addition, if an application uses the event processing interface provided by the core library, not only events can be processed, but scripts can also be executed in the same thread.
Melang provides a basic function library. Besides string, file system and network IO operations, it also provides functions for accessing MySQL8 and a series of functions such as encryption, decryption and communication.
Although the core library has been updated and upgraded for several years, the language is still in its infancy. And we still need to make a lot of efforts on it. Looking forward to your attention to this project. Thanks for reading.
Top comments (0)