OP language (v0.3)

From Native Big Data Documentation
Jump to: navigation, search


Op language is a symbolic functional programming language used by NBD to fast implement mathematichal expressions and algoritms. Op is a compiled language but it is not a native language as C or C++. OP code compiles to a symbolic execution tree than can be evaluated later.


Bases of the OP language

A program developed in op language is composed by 'op objects'. A 'op object' is a mathemathical expression witch haves other 'op objects' as parameters. A code written in OP language will be compiled in an tree of 'op objects'.

  • An OP object is a mathemathical expression.
  • OP is a reflective language. Variables in OP are not typed but the type can be known at runtime.
  • Everything in OP act as an object. (Object oriantation)
  • OP is a functional language too. Everything in OP act as a function. OP works with anonimous arrow funcions with closures.
  • Everything in OP is a math expression. An OP code is a set of operations named op objects (op_t).
  • A op objects is compossed by :
    • The operator ( '+' . '*' , ';' , ...)
    • A list of operands. An operand can be any NBD object, including other op objects. A OP program is a tree of op objects.

Data types of the OP language

The same as NBD:

  • null: The null object
  • booleans: true of false
  • Numbers:
    • Integers  : 60 bit integer. (60 lower bits of 'int64_t')
    • Dates  : 60 bit integer. (60 lower bits of 'int64_t')
    • Floats  : 63 bit double. ( 1 sign bit , 11 exponent bits and 52 mantissa bits (51 explicitly stored))
    • double_t  : 80 bit double. ( C long double: 1 sign bit , 15 exponent bits and 64 mantissa bits )
    • complex_t : Complex numbers with 2x 80 bit double (C long double).

Integer and floats works faster than doubles and complex because don't need to be stored in the memory heap.

  • storage objects:
    • array_t: Like javascript arrays [ ... ]
    • hash_t: Like javascript objects { ... }
  • Language types:
    • op_t: Is a compiled operation. Example "1+2+3" compiles to { "_cl": "op_t", "op":"+", "args": [1,2,3] }
    • function_t: Is a compiled function. Example "(a,b)=>{ a+b }"
    • nfunction_t: Is a C native function. Example "Date.new"
  • Proxy objects:
    • splitted_d: An object that is divided in several fragments.
    • located_d: An object that is saved in one or more servers.
    • link_t: An object that points to other object (like foreign keys in sql databases).

Proxy objects are transparent to the user. This means that a proxy object that points to an array will inherit all the methods of arrays and a OP. OP programmers can work with proxy objects in the same ways as they work with local objects. Native Big Data will paralelize the work as needed.


Syntax of the OP language

Operators

A operation is a part of the OP code than compiles to an op object. An Operation have always an operator, some operands and always returns a value. The operators always oparerate from left to right. Every operand is evaluated just before it is used, (not before the operand is called as other languages):


Operators in OP

  • Constants: NBD serialized object in JSON format. Examples:
    • '{ "a":1, "b":2 }'
    • '[1,2,3]'
    • '12'

In op constants are cloned every time is created. The next example will return: [ [1,2,0], [1,2,1], [1,2,2], [1,2,3] ]

var out = [];
for (var i=0;i<4;i++)
{
	var s_1 = [1,2];
	s_1[]= i;
	out[]=s_1
};out

In the last example s_1[]= i is the same as s_1.push(i) . OP is designed to use the operands in the most confortable way for the programmer.

  • Functions ('=>' operator): (params) => { op code }. Examples:
    • "(a,b)=>{ a }" Defines a function than returns the fisrt parameter
    • "(a,b)=>{ b }" Defines a function than returns the second parameter
  • Calling functions:
    • () operator like C and JavaScript. In OP everything is a funcion:
      • max(3,8) returns 8
      • "[ 30, ()=>{ 1 } , (a,b)=>{a*b} , (a,b) => {a} ](3,5)" will return [30, 1, 15, 3]
      • "3(8)" returns 3
  • var and val: Declares a variable in the current scope-block. The diference between var and val is that val objects are deleted from the heap when the scope-block ends. The left part of the '"' operator must be a variabe,

The right part can be everything valid in OP. The operator returns the value. Examples:

    • "var a=100" returns 100
    • "val b=12"
    • "val c=[34,45,34]"


  • Sequence operator ';': Evaluates a set of operations and returns the last one.
    • Every sequence defines a new scope-block.
    • Subsecuences can be created with "(" ")".
    • The return of every operation is stored in the system '_' var.
    • Examples:
      • "1;2;3" returns 3
      • "var a=12;a" return 12
      • (a,b) => ( a=a*2 ; b = b/3 ; a*b ) is equivalent to (a,b)=>(a*2*b/3)
      • "var a=1;(var a=1000;a)" returns 1000 (two scope-blocks and the second "var a" overloads the first )
      • "var a=1;(var a=1000;a);a" returns 1
      • "var a=1;(var a=a+1000;a)" returns 1001
      • "var a=1;_+1;_*3" returns 6 (1+1)*3
  • Arithmetic basic operators '+' , '*' : The arithmetic operators like others languages. Can be applied to almost everything and ,in general, '*' and '+' are not conmutative. Examples:
    • "var a=2;var b=3;(a+b)*(a-b)" returns -5
    • "var t = ( (a,b)=> { a+b } ) * 5" will return the same function as "(a,b)=>{ (a+b) * 5 }"
    • "var t = 5 * ( (a,b)=> { a+b } ) " will return the same function as "(a,b)=>{ 5 * (a+b) }"
    • [1,2,3] * 12 will return [12,24,36]
    • { "a":1 , b: [1,2,3] } * 2 will return { "a":2 , b: [2,4,6] }
    • "1" + "2" will return "12"
    • "(5 + 3i)" * 2 will return 10 + 6i
  • '/' , '-' are unary operators (inverse and oposite). Can be convinned with '+' and '*'
    • "/2" is equivalent to 0.5
    • "3/2" is equivalent to 3*(1/0.5)
  •  % modulus: The rest of divide two integers.
  • ** The power operator. Like pascal. Examples:
    • a ** 5 = a*a*a*a*a .
    • 4 ** -1 = 0.25
    • 4 ** 0.5 = 2
  • Bits (only with integer numbers):
    • &: Bit and operator
    • |  : Bit or operator
    • ^ : Bit xor operator
    •  ! : Bit negation
  • Logical (only with boolean):
    • && logical and
    • || logical or
    • ^^ logical xor
    •  ! logical negation
  • < , > , <= , >= , == , != : comparation with any comparable objects.
  • Flux operations:
    • ( ) blocks. A block is defined with ‘(‘ and ‘)’ characters. Blocks changes the precedence order of the operations.

WARNING: In op blocks are not defined with “{}” or “({})”. Blocks are only defined with “(“ … “)”

      • ( 3 + 1 ) * 4 will return 16
      • 3 + 1 * 4 will return 7
    • = assignation: assigns a value to somethink. Variables are defined only inside sequence blocks defined by ( ; ; ; ). “+=” , -= , /= and *= are also valid
    •  ? : conditional : Like C : if the first operand evaluates to a true value returns the second operand. The 3st operand is returned in other case.
      • var mx = ((a,b) => ( a>b ? a : b ))
    • || : return first non false or null element. Example:
      • false || null || 3 || 4 -> 3
    • && safe operation: Return until null or false. Example:
      • a > 0 && b[a]  : return b[a] if a>0 or false in other case
      • a && b[a]  : return b[a] if a is not false or null
  • Objects:
    • [] arrays. Lists are created like json / javascript:
      • (a) =>( [ a,a*2,a*3] ) will return a list of values
    • {} JS objects. JS objects are created like json:
      • (a) => ( { ‘id’ : ‘name_of_’ + a , ‘value’ : a} )
    • Strings are created like javascript. “ or ‘ can be used.
    • Date( yyyy, mm, dd, hh, min, sec, milisec) or Date( miliseconds from 01/01/1970 00:00:00 ) can be used to define a date object
  • Getters and setters:
    • [] operates like javascript:
    • (a) => ( a[0] )
    • (a) => ( a[“id”] )
    • (a) => ( s = [] ; s [0] = a ; s[1] = a*a ; s )


  • Calling methods: Objects can have methods:
    • ( var a = [ 1,2,3] ; a.length() )


Scopes & closures

Every op program is linked with a scope. A scope stores all variables defined by var and tmp operators. Every variable is known by its name and can be overloaded every time it is declared in a scope-block:

Examples:

  • "var out=[];var a=1;out.push(a)" will return [1]
  • "var out=[];var a=1;out.push(a);(var a=2;out.push(a));out.push(a)" will return [1,2,1]

In the last example there are two sequences and the second one creates a local.

Variables are accesible inside nested functions. This is called closures:

  • "var a = 2;var t= ((b)=>{a*b});a++;t(3)" will return 9

Closures with "var" variables acts like javascript and other "lexical scoping" language. In some cases you want to create a function with the current value of the variable:

  • "var f=[]; for (var i=0;i<3;i++) { f.push( (a)=>{a*i} ) };f(5)" This will return [ 15,15,15 ]

This is because when the functions are executed the local var 'i' has a value of 3. The way to create diferent functions based in a parameter in languages like javascript is not trivial and often needs to create a factory of functions or use the 'let' keyword:

Javascript code:

  • var f=[]; for (var i=0;i<3;i++) { f.push( (a)=>{ return a*i} ) };[ f[0](5), f[1](5), f[2](5) ] will return [15,15,15]
  • var f=[]; var ff = (b) => { return ( (a)=>{ return a*b} ) }; for (var i=0;i<3;i++) { f.push( ff(i) ) };[ f[0](5), f[1](5), f[2](5) ] will return [0,5,10]
  • var f=[]; for (let i=0;i<3;i++) { f.push( (a)=>{ return a*i} ) };[ f[0](5), f[1](5), f[2](5) ] will return [0,5,10 ]


In OP the same can be done easily: In OP code:

  • var f=[]; for (var i=0;i<3;i++) { var i=i; f.push( (a)=>{a*i} ) };f(5) This will return [0,5,10]
  • var f=[]; for (val i=0;i<3;i++) { f.push( (a)=>{a*i} ) };f(5) This will return [0,5,10]


This is because "var i = i" evaluates i before the second 'i'is created and then creates i and stores the value.