Followers 0

# ObjectScript: A new programming language

## 0 posts in this topic

[b]Welcome to the ObjectScript![/b]

The ObjectScript is a new embedded programing language that mixes benefits of JavaScript, Lua and PHP. The ObjectScript has syntax from JavaScript, multiple results from Lua, OOP from PHP and much more.

[b]Getting Started[/b]

ObjectScript is a dynamically typed language. That means you do not have to specify the data type of a variable when you declare it, and data types are converted automatically as needed during script execution. So, for example, you could define a variable as follows
[source lang="jscript"]
var a = 12;
[/source]
And later, you could assign the same variable a string value, for example
[source lang="jscript"]
a = "Hello World!";
[/source]
Because ObjectScript is dynamically typed, this assignment does not cause an error message.

ObjectScript is case-sensitive, [b]null[/b] is not the same as [b]Null[/b], [b]NULL[/b], or any other variant.

[b]Types and Values[/b]

ObjectScript recognizes the following types of values

[list]
[*][b]null[/b], a special keyword denoting a null value
[*][b]boolean[/b], either true or false
[*][b]number[/b], such as 10, 0x123, 2.3, 5.7e23
[*][b]string[/b], such as "Hello World!"
[*][b]object[/b], such as {"one", "two", 12:"at index 12"}
[*][b]array[/b], such as ["one", 31]
[*][b]function[/b], such as function(){ print "Hello World!" }
[*][b]userdata[/b], allows arbitrary C data to be stored in ObjectScript variables
[/list]

[b]null[/b], [b]boolean[/b], [b]number[/b] and [b]string[/b] are primitive types.

[b]object[/b], [b]array[/b], [b]function[/b] and [b]userdata[/b] are not primitive types and could be used as named containers for values.

[b]Nulls[/b]

Null is a type with a single value [b]null[/b]. All variables have a [b]null[/b] value by default, before a first assignment, and you can assign [b]null[/b] to a variable to delete it. ObjectScript uses [b]null[/b] as a kind of non-value.

[b]Bolleans[/b]

The boolean type has two values, [b]false[/b] and [b]true[/b], which represent the traditional boolean values. However, they do not hold a monopoly of condition values: In ObjectScript, any value may represent a condition. Conditionals (such as the ones in control structures) consider [b]false[/b], [b]null[/b] and [b]NaN[/b] (not a number) as [b]false[/b] and anything else as [b]true[/b].

Beware that ObjectScript considers both zero and the empty string as [b]true[/b] in conditional tests.

[b]Numbers[/b]

The number type represents real (double-precision floating-point) numbers. You can write numeric constants with an optional decimal part, plus an optional decimal exponent. Examples of valid numeric constants are
[source lang="jscript"]
12 // decimal, base 10
3.14
2e10
0xfe // hexadecimal, "hex" or base 16
0123 // octal, base 8
[/source]
[b]Strings[/b]

A string literal is zero or more characters enclosed in double (") quotation marks. The following are examples of string literals
[source lang="jscript"]
"Hello World!"
"one line \n another line"
[/source]
You can call any of the methods of the [b]String[/b] object, for example, you can use the String.length property with a string literal
[source lang="jscript"]
"Hello World!".length
[/source]
or just use length operator
[source lang="jscript"]
#"Hello World!"
[/source]
[b]Objects[/b]

An [b]object[/b] is a list of zero or more pairs of property names and associated values of an object
[source lang="jscript"]
{"one", "two", 12:"at index 12", ["on" .. "e"]: "at index one", some = "extended syntax"}
[/source]
The simplest constructor of [b]object[/b] is the empty constructor {}
[source lang="jscript"]
a = {}; // create an empty object and store its reference in a
[/source]
You should not use an object literal [b]{[/b] at the beginning of a statement. This will lead to not behave as you expect, because the [b]{[/b] will be interpreted as the beginning of a block
[source lang="jscript"]
{
var a = 12;
}
[/source]
Lets view some examples
[source lang="jscript"]
days = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"}
[/source]
will initialize days[0] with the string "Sunday" (the first element has always index 0), days[1] with "Monday", and so on
[source lang="jscript"]
print(days[4]) --> Thursday
[/source]
Constructors do not need to use only constant expressions. You can use any kind of expression for the value
[source lang="jscript"]
tab = {sin(1), sin(2), sin(3), sin(4)}
[/source]
To initialize an [b]object[/b] to be used as a record, ObjectScript offers the following syntax
[source lang="jscript"]
a = {x=0, y=0}
[/source]
is equivalent to
[source lang="jscript"]
a = {["x"]=0, ["y"]=0}
a = {x:0, y:0}
a = {x:0; y:0}
a = {x:0, y:0,}
a = {x=0, y=0}
a = {x:0, y=0}
[/source]
so you can always put a comma after the last entry, you can use ":" or "=" to make pair of a property. You can always use a semicolon (;) instead of a comma (,)
[source lang="jscript"]
a = {x=1, y=3; "one", "two"}
[/source]
Finally, you can avoid usage of comma and semicolon
[source lang="jscript"]
a = {x=1 y=3 "one" "two"}

c = "one";
a = { [c] = "great" }; // the same as { [c]: "great" }
print(a[c]) --> great
print(a["one"]) --> great
print(a.one) --> great

a = { one = "great" }; // the same as { "one": "great" }
print(a[c]) --> great
print(a["one"]) --> great
print(a.one) --> great

a = { one="great", two="awesome" };
a = { one: "great", two: "awesome" }; // JavaScript object notation is fully supported
a = { one: "great", two: "awesome", }; // a comma after the last entry is valid
a = { one: "great" two="awesome" 1="value at index 1" }; // syntax without "," is also valid

a = {"one", "two"};
print(#a) --> 2
[/source]
[b]Arrays[/b]

An [b]array[/b] is a list of indexed values
[source lang="jscript"]
a = ["zero", "one", "two"]
print(a[1]) --> one
print(#a) --> 3
[/source]
[b]Functions[/b]

You can think of functions as procedures that your application can perform
[source lang="jscript"]
var max = function(a, b){ return a < b ? a : b }
[/source]
Functions are first-class values in ObjectScript. That means that functions can be stored in variables, passed as arguments to other functions, and returned as results.

An unconventional, but quite convenient feature of ObjectScript is that functions may return multiple results
[source lang="jscript"]
var func = function(){ return 1, 2 }
var x, y = func()
print x --> 1
print y --> 2
[/source]
The functions are objects themselves. As such, they have properties and methods. Any reference to a function allows it to be invoked using the () operator
[source lang="jscript"]
var func = function(){ print arguments }
var func2 = function(f){ f.apply(null, ...) }
func2(func,1,2,3) --> {1,2,3}
[/source]
Moreover, ObjectScript supports nested functions and closures. The nested functions are functions defined within another function. They are created each time the outer function is invoked. In addition to that, each created function forms a lexical closure: the lexical scope of the outer function, including any local variables and arguments, become part of the internal state of each nested function object, even after execution of the outer function concludes
[source lang="jscript"]
var a = function(){
var x = 2
return function(){ retutn x++ }
}
var b = a()
print b() --> 2
print b() --> 3
print b() --> 4
[/source]
ObjectScript can call functions written in ObjectScript and functions written in C++ or C. All the standard library in ObjectScript is written in C++. Application programs may define other functions in C
[source lang="jscript"]
int test(OS * os, int, int, int, void*)
{
os->pushNumber(123);
return 1;
}

int main(int argc, char* argv[])
{
OS * os = OS::create();

os->pushCFunction(test);
os->setGlobal("test");

os->eval("print(test())"); // outputs 123

os->release();
return 0;
}
[/source]
[b]Userdata[/b]

An [b]userdata[/b] allows arbitrary C++ or C data to be stored in ObjectScript variables. It's used to represent new types created by an application program or a library written in C++ or C.

[b]Assignment and Multiple assignment operator[/b]

Assignment is the basic means of changing the value of a variable or a object property:
[source lang="jscript"]
a = "Hello" .. " world!"
t.n = t.n + 1
[/source]
ObjectScript allows multiple assignment, where a list of values is assigned to a list of variables in one step. Both lists have their elements separated by commas
[source lang="jscript"]
a, b = 1, 2
[/source]
the variable [b]a[/b] gets the value 1 and [b]b[/b] gets 2. In a multiple assignment, ObjectScript first evaluates all values and only then executes the assignments. Therefore, you can use a multiple assignment to swap two values, as in
[source lang="jscript"]
x, y = y, x // swap x for y
a[i], a[j] = a[j], a[i] // swap a[i] for a[j]
[/source]
ObjectScript always adjusts the number of values to the number of variables. When the list of values is shorter than the list of variables, the extra variables receive [b]null[/b] as their values, when the list of values is longer, the extra values are silently discarded
[source lang="jscript"]
a, b, c = 0, 1
print(a, b, c) --> 0 1 null
a, b = a+1, b+1, b+2 -- value of b+2 is ignored
print(a,b) --> 1 2
a, b, c = 0
print(a,b,c) --> 0 null null
[/source]
The last assignment in the above example shows a common mistake. To initialize a set of variables, you must provide a value for each one:
[source lang="jscript"]
a, b, c = 0, 0, 0
print(a, b, c) --> 0 0 0
[/source]
You can use multiple assignment simply to write several assignments in one line. But often you really need multiple assignment, for example, to swap two values. A more frequent use is to collect multiple returns from function calls
[source lang="jscript"]
a, b = f()
[/source]
f() returns two results: [b]a[/b] gets the first and [b]b[/b] gets the second.

[b]Global Variables[/b]

Global variables do not need declarations. You simply assign a value to a global variable to create it. It is not an error to access a non-initialized variable, you just get the special value null as the result
[source lang="jscript"]
print(a) --> null
a = 10
print(a) --> 10
[/source]
Usually you do not need to delete global variables, if your variable is going to have a short life, you should use a local variable. But, if you need to delete a global variable, just assign null to it
[source lang="jscript"]
a = null
print(a) --> null
[/source]
After that, it is as if the variable had never been used. In other words, a global variable is existent if (and only if) it has a non-null value.

[b]Environments and the Global Environment[/b]

Any reference to a global name [b]v[/b] is syntactically translated to [b]_E.v[/b]. Moreover, every function is compiled in the scope of an external local variable called [b]_E[/b], so [b]_E[/b] itself is never a global name in a function.

Despite the existence of this external [b]_E[/b] variable and the translation of global names, [b]_E[/b] is a completely regular name. In particular, you can define new variables and parameters with that name. Each reference to a global name uses the [b]_E[/b] that is visible at that point in the program, following the usual visibility rules of ObjectScript.

Any object used as the value of [b]_E[/b] is called an environment.

ObjectScript keeps a distinguished environment called the global environment. This value is kept at a special object in the C registry. In ObjectScript, the variable [b]_G[/b] is initialized with this same value.

When ObjectScript compiles a function, it initializes the value of its [b]_E[/b] upvalue with the global environment. Therefore, by default, global variables in ObjectScript code refer to entries in the global environment. Moreover, all standard libraries are loaded in the global environment and several functions there operate on that environment.

You can execute any function with a different environment using Function.applyEnv method. For example lets view code of [b]eval[/b] functions inside of [b]core.os[/b] file:
[source lang="jscript"]
function eval(str, env){
return compileText(str).applyEnv(env || _G, null, ...)
}
[/source]
[b]Iterators[/b]

An iterator allows you to iterate over the elements of a collection. For example
[source lang="jscript"]
a = { null true 12 "0" } // is equivalent to { null, true, 12, "0" }
for(k, v in a){
print( k " --> " v ) // is equivalent to print( k, " => ", v )
}
[/source]
outputs
[source]
0 --> null
1 --> true
2 --> 12
3 --> 0
[/source]
ObjectScript compiles the above program to
[source lang="jscript"]
a = { null true 12 "0" }
{
var iter_func = a.__iter();
for(var iter_valid;;){ // infinite loop
iter_valid, k, v = iter_func();
if(!iter_valid) break;
print( k " --> " v )
}
}
[/source]
The first result value of [b]iter_func[/b] indicates either valid or not valid current step, second and other return values are user used values.

Any iterator needs to keep some state between successive calls, so that it knows where it is and how to proceed from there. Closures provide an excellent mechanism for that task. Remember that a closure is a function that accesses local variables from its enclosing function.

For example, [b]array[/b] iterator is declated as
[source lang="jscript"]
Array.__iter = function(){
var i, self = 0, this
return function(){
if(i < #self){
return true, i, self[i++]
}
}
}
[/source]
Note that iterator of function is itself. It's declared as
[source lang="jscript"]
Function.__iter = function(){ return this }
[/source]
So we can write iterator like that
[source lang="jscript"]
var range = function(a, b){
return function(){
if(a <= b){
return true, a++
}
}
}

for(var i in range(10, 13)){
print( "i = ", i )
}
[/source]
outputs
[source]
i = 10
i = 11
i = 12
i = 13
[/source]
[b]Properties, Getters And Setters[/b]

A getter is a method that gets the value of a specific property. A setter is a method that sets the value of a specific property.
[source lang="jscript"]
a = {
_color: "red"
__get@color = function(){ return this._color }
__set@color = function(v){ this._color = v }
}

print a.color --> red
print a["color"] --> red
a.color = "blue"
print a.color --> blue
print a["color"] --> blue
[/source]
Note that @ is not a special symbol, any functions and variables can contain @.

Another example
[source lang="jscript"]
a = {
_color: "red"
__get = function(name){
if(name == "color")
return this._color
}
__set = function(name, v){
if(name == "color")
this._color = v
}
__del = function(name){
if(name == "color")
delete this._color
}
}

print a.color --> red
a.color = "blue"
print a.color --> blue
delete a.color
print a.color --> null
[/source]
[b]Multi dimensional properties[/b]

ObjectScript supports a.color and a["color"] syntax. What about?
[source lang="jscript"]
a[x, y] = 12
[/source]
Yes, ObjectScript supports the above syntax, it's called multi dimensional properties
[source lang="jscript"]
a = {
_matrix = {}
__getdim = function(x, y){
return this._matrix[y*4 + x]
}
__setdim = function(value, x, y){
this._matrix[y*4 + x] = value
}
__deldim = function(x, y){
delete this._matrix[y*4 + x]
}
}
a[1, 2] = 5 // is equivalent to a.__setdim(5, 1, 2)
print a[1, 2] --> 5 // print(a.__getdim(1, 2)
delete a[1, 2] // a.__deldim(1, 2)
print a[1, 2] --> null
[/source]
Note that __setdim method receives the first argument as new property value and other arguments as dimensional attributes of property. For example
[source lang="jscript"]
a = {
_matrix = {}
__getdim = function(x, y, z){
return this._matrix[z*16 + y*4 + x]
}
__setdim = function(value, x, y, z){
this._matrix[z*16 + y*4 + x] = value
}
}
a[1, 2, 3] = 5
print a[1, 2, 3] --> 5
[/source]
[b]Empty dimensional properties[/b]

[source lang="jscript"]
b = a[]
a[] = 2
delete a[]
[/source]
ObjectScript provides following special methods __getempty, __setempty and __delempty that you can use if necessary.

[b]Object-oriented programming (OOP)[/b]

Object-oriented programming is a programming paradigm that uses abstraction to create models based on the real world. It uses several techniques and paradigms, including modularity, polymorphism, and encapsulation.

ObjectScript is OOP language, also you can override arithmetic, bitwise, concatenation, comparison and unary operators.

[b]Core Objects[/b]

ObjectScript has several objects included in its core, there are global variables named Object, Array, String, Number, Boolean and Function.

Every object in ObjectScript is an instance of the object Object and therefore inherits all its properties and methods.

[b]Custom Objects[/b]

[source lang="jscript"]
var a = {
num: 1
__get@number: function(){
return this.num
}
return a.number + b.number
}
}

var b = extends a {
num: 2
}

print a + b --> 3
[/source]
[b]The Class[/b]

ObjectScript is a prototype-based language which contains no class statement. Any object could be used as class.
[source lang="jscript"]
Person = {
__construct = function(firstname, lastname){
this.firstname = firstname
this.lastname = lastname
}
__get@fullname = function(){
return this.firstname .. " " .. this.lastname
}
walk = function(){
print this.fullname .. " is walking!"
}
}
[/source]
[b]The Object (Class Instance)[/b]

To create a new instance of an object we use [b]()[/b] operator for class variable
[source lang="jscript"]
var p = Person("James", "Bond")
[/source]
is equivalent to
[source lang="jscript"]
var p = {}
p.prototype = Person
p.__construct("James", "Bond")
[/source]
run
[source lang="jscript"]
p.walk() --> James Bond is walking!
print p --> {firstname:James,lastname:Bond}
[/source]
[b]Inheritance[/b]

Inheritance is a way to create a class as a specialized version of class. You need to use [b]extends[/b] operator
[source lang="jscript"]
var IvanPerson = extends Person {
__construct: function(){
super("Ivan", "Petrov")
}
}
var p = IvanPerson()
p.walk() --> Ivan Petrov is walking!
print p --> {firstname:Ivan,lastname:Petrov}
[/source]
the [b]extends[/b] operator has syntax extends exp1 exp2 where [b]exp1[/b] and [b]exp2[/b] are any valid expressions, it's equivalent to
[source lang="jscript"]
(function(exp1, exp2){
exp2.prototype = exp1
return exp2
})()
[/source]
[b]Encapsulation[/b]

In the previous example, IvanPerson does not need to know how the Person class's walk() method is implemented, but still can use that method. The IvanPerson class doesn't need to explicitly define that method unless we want to change it. This is called [b]encapsulation[/b], by which every class inherits the methods of its parent and only needs to define things it wishes to change.

[b]Simple and powerful example[/b]

[source lang="jscript"]
var vec3 = {
__construct = function(x, y, z){
this.x = x
this.y = y
this.z = z
}
return vec3(a.x + b.x, a.y + b.y, a.z + b.z)
}
__mul = function(a, b){
return vec3(a.x * b.x, a.y * b.y, a.z * b.z)
}
}

var v1 = vec3(10 20 30)
var v2 = vec3(1 2 3)
var v3 = v1 + v2 * v2
print v3
[/source]
outputs
[source]
{x:11,y:24,z:39}
[/source]

You could download all above examples here https://github.com/unitpoint/objectscript Just clone repo to your computer and play with [b]OS\examples-os\test.os[/b]. You can run [b]OS\OS\examples-os\test.cmd[/b] to execute [b]test.os[/b].

You could view more examples here [b]OS\proj.win32\examples.sln[/b]

P.S. some other articles in russian:

[list]
[*] binding C++ classes & functions http://habrahabr.ru/post/154221
[*] execute ObjectScript from C++ code http://habrahabr.ru/post/152813
[/list]

0

## Create an account

Register a new account

Followers 0

• 11
• 19
• 14
• 23
• 11