ObjectScript API, integration with C ++. Part 1: working with the stack, calling OS functions from C ++
- Tutorial
ObjectScript is a new open source object-oriented programming language. ObjectScript extends the capabilities of languages such as JavaScript, Lua, and PHP. His presentation took place on a hub some time ago in this article and aroused interest and heated discussion among readers. Therefore, I decided not to dwell on the presentation and describe the ObjectScript API. I will try to make articles as short as possible by breaking the API description into several parts.
A minimal program using OS (ObjectScript) is as follows:
Those. create an OS instance, work with it and delete it correctly, but not with the help of an operator
OS instances can be created simultaneously as many as desired, if necessary, they will work completely independently of each other.
Next, I will give an example of code that should be located instead of TODO: main code here .
So, let's use the C ++ tools to simulate the following OS code:
What we have here: a global function call with two parameters, the first is a constant string, the second is the result of mathematical operations.
The first thing to do is prepare a function call. To do this, you need to put two values on the stack, the first is the function itself, the second is
Now we add to the stack the parameters with which the function will be called:
Now simulate the mathematical operations for the second parameter:
Done! the method
At the moment, we will have 4 values on the stack: 1 - function, 2 - null, 3 - string, 4 - number. Excellent! you can call:
That's it, we look at the console (
In this case, the stack will be completely empty, because 4 values used when calling the function will be removed from the stack.
We simulate the following code on the OS:
Create a new object on the stack:
Set the first property
-1 is a relative pointer to the top of the stack, i.e. add an object to the stack for which we will set the property (the object is added to the stack by reference).
The method
We will do the same with the second property, but in a shorter way:
-2 is a relative pointer to the second value from the top of the stack (this is our object), and now there is a line at the top of the stack
Now save our object to the global variable bar :
There are currently no values in the stack. Now we execute the code
Done, now we do
and look at the console, it should be like this:
We simulate the following code on the OS:
We start as usual:
At this stage, we called a function with 2 parameters and requested 1 result at the output (concat returns 1 default result, if we request 0 results, then after the function call there will be no values in the stack with results, if we require 2 or more values, then the first result will be from the concat function, and the rest will be complemented by nulls).
Now call
in the console should be like this:
Full text of the program:
You can download the ObjectScript source code and an example from this article at this link , open proj.win32 \ examples.sln , the stack_usage project .
Part 1: working with the stack, calling OS functions from C ++
A minimal program using OS (ObjectScript) is as follows:
#include "objectscript.h"
using namespace ObjectScript;
int main()
{
OS * os = OS::create();
// TODO: main code here
os->release();
return 0;
}
Those. create an OS instance, work with it and delete it correctly, but not with the help of an operator
delete
, but with a method call release
. OS instances can be created simultaneously as many as desired, if necessary, they will work completely independently of each other.
Next, I will give an example of code that should be located instead of TODO: main code here .
So, let's use the C ++ tools to simulate the following OS code:
print("10 * (3+2) = ", 10 * (3+2))
What we have here: a global function call with two parameters, the first is a constant string, the second is the result of mathematical operations.
The first thing to do is prepare a function call. To do this, you need to put two values on the stack, the first is the function itself, the second is
this
for this function. If the function does not use this, well, for example, a static function, then this
you need to put it in quality null
. We do it like this: os->getGlobal("print"); // #1 - количество значений в стеке
os->pushNull(); // #2
Now we add to the stack the parameters with which the function will be called:
os->pushString("10 * (3+2) = "); // #3 - первый параметр
Now simulate the mathematical operations for the second parameter:
os->pushNumber(10); // #4
os->pushNumber(3); // #5
os->pushNumber(2); // #6
os->runOp(OP_ADD); // #5 - 3+2
os->runOp(OP_MUL); // #4 - 10 * (3+2)
Done! the method
runOp
can perform mathematical, logical and bitwise operators on values in the stack using the OS kernel tools. In other words, if necessary, type conversions will happen, etc. ... it OP_ADD
performs the addition operator on two values at the top of the stack (i.e. what was placed on the stack the last two times). In this case, the result will replace them on the stack (i.e., two values will be removed from the stack, and the result will be added). OP_MUL
- similarly for multiplication. At the moment, we will have 4 values on the stack: 1 - function, 2 - null, 3 - string, 4 - number. Excellent! you can call:
os->call(2); // вызвать функцию с 2 параметрами
That's it, we look at the console (
print
output the result to the console), it should be like this:10 * (3+2) = 50
In this case, the stack will be completely empty, because 4 values used when calling the function will be removed from the stack.
Example 2
We simulate the following code on the OS:
bar = {firsname="James", lastname="Bond"}
bar.profession = "actor"
print bar
Create a new object on the stack:
os->newObject(); // #1
Set the first property
firsname="James"
:os->pushStackValue(-1); // #2
-1 is a relative pointer to the top of the stack, i.e. add an object to the stack for which we will set the property (the object is added to the stack by reference).
os->pushString("firsname"); // #3 - имя свойства
os->pushString("James"); // #4 - будущее значение свойста
os->setProperty(); // #1
The method
setProperty
sets the property and takes the used values from the stack (in this case, three values are used on the top of the stack: object, property name and value). We will do the same with the second property, but in a shorter way:
os->pushString("Bond"); // #2 - значение
os->setProperty(-2, "lastname"); // #1
-2 is a relative pointer to the second value from the top of the stack (this is our object), and now there is a line at the top of the stack
"Bond"
. Now save our object to the global variable bar :
os->setGlobal("bar"); // #0
There are currently no values in the stack. Now we execute the code
bar.profession = "actor"
:os->getGlobal("bar"); // #1 - помещаем в стек значение переменной bar
os->pushString("actor"); // #2
os->setProperty(-2, "profession"); // #1
os->pop(); // #0 - убераем значение переменной bar из стека
Done, now we do
print bar
:os->getGlobal("print"); // #1
os->pushNull(); // #2
os->getGlobal("bar"); // #3
os->call(1); // #0
and look at the console, it should be like this:
{"firsname":"James","lastname":"Bond","profession":"actor"}
Example 3
We simulate the following code on the OS:
print(concat(5, " big differences"))
We start as usual:
os->getGlobal("print"); // #1 - добавляем в стек глобальную функцию print
os->pushNull(); // #2 - добавляем this для функции print
os->getGlobal("concat"); // #3 - добавляем в стек глобальную функцию concat
os->pushNull(); // #4 - добавляем this для функции concat
os->pushNumber(5); // #5 - первый параметр для concat
os->pushString(" big differences"); // #6 - второй параметр для concat
os->call(2, 1); // #3 - вызываем функцию concat
At this stage, we called a function with 2 parameters and requested 1 result at the output (concat returns 1 default result, if we request 0 results, then after the function call there will be no values in the stack with results, if we require 2 or more values, then the first result will be from the concat function, and the rest will be complemented by nulls).
Now call
print
:os->call(1); // #0
in the console should be like this:
5 big differences
Full text of the program:
#include "objectscript.h"
using namespace ObjectScript;
int main()
{
OS * os = OS::create();
/*
print("10 * (3+2) = ", 10 * (3+2))
*/
os->getGlobal("print"); // #1 - stack values, it's print function from standart library
os->pushNull(); // #2 - null, it's function this, each call of function must have this
// push the first argument
os->pushString("10 * (3+2) = "); // #3 - we have 3 stack values here
// prepare second argument
os->pushNumber(10); // #4
os->pushNumber(3); // #5
os->pushNumber(2); // #6
os->runOp(OP_ADD); // #5 - 3+2
os->runOp(OP_MUL); // #4 - 10 * (3+2)
os->call(2); // call function with 2 arguments
/*
bar = {firsname="James", lastname="Bond"}
bar.profession = "actor"
print bar
*/
os->newObject(); // #1 - new object
os->pushStackValue(-1); // #2 - the same object, -1 - is relative pointer to the top stack value
os->pushString("firsname"); // #3 - property key
os->pushString("James"); // #4 - property value
os->setProperty(); // #1 - setProperty uses 3 stack values and pop them
// second way of same functionality
os->pushString("Bond"); // #2 - property value
os->setProperty(-2, "lastname"); // #1
os->setGlobal("bar"); // #0 - assign object value to global bar variable, pop value
// let's do bar.profession = "actor"
os->getGlobal("bar"); // #1 - our global a variable
os->pushString("actor"); // #2 - property value
os->setProperty(-2, "profession"); // #1
os->pop(); // #0
// let's do print bar
os->getGlobal("print"); // #1
os->pushNull(); // #2
os->getGlobal("bar"); // #3
os->call(1); // #0
/*
print(concat(5, " big differences"))
*/
os->getGlobal("print"); // #1 - print function
os->pushNull(); // #2 - this for print
os->getGlobal("concat"); // #3 - concat function
os->pushNull(); // #4 - this for concat
os->pushNumber(5); // #5
os->pushString(" big differences"); // #6
os->call(2, 1); // #3 - result is already at the top of stack
os->call(1); // #0
os->release();
return 0;
}
You can download the ObjectScript source code and an example from this article at this link , open proj.win32 \ examples.sln , the stack_usage project .