2.4. Expressions

2.4.1. Assignment

exp := exp '=' exp
exp := exp '<-' exp
exp := exp ':=' exp

daScript implements 3 kind of assignment: the normal assignment(=):

a = 10

“move” assignment

var b = new Foo
var a: Foo?
a <- b

move assignment nullifies source (b) It’s main purpose is to correctly move ownership, and optimize copying if you don’t need source for heay types (such as arrays, tables). Some external handled types can be non assignable, but still moveable;

var

“clone” assignment

a := b

Clone assignment is syntactic sugar for calling clone(var a: auto&; b: auto&) if it exists or basic assignment for POD types. It is also implemented for das_string, array and table types, and creates ‘deep’ copy.

Some external handled types can be non assignable, but still copyable;

2.4.2. Operators

2.4.2.1. ?: Operator

exp := exp_cond '?' exp1 ':' exp2

conditionally evaluate an expression depending on the result of an expression.

2.4.2.2. ?? Null-coalescing operator

exp := exp1 '??' exp2

Conditionally evaluate an expression2 depending on the result of an expression1. Given code is equivalent to:

exp := (exp1 '!=' null) '?' deref(exp1) ':' exp2

It evaluates expressions until the first non-null value (just like || operators for the first ‘true’ one).

Operator precendence is also follows C# design, so that ?? has lower priority than ||

2.4.2.3. ?. - Null-propagation operator

exp := value '?.' key

If value is not null exists, return deref of field ‘key’ for struct, else return null.

struct TestObjectFooNative
    fooData : int

struct TestObjectBarNative
    fooPtr: TestObjectFooNative?
    barData: float

def test
    var a: TestObjectFooNative?
    var b: TestObjectBarNative?
    var idummy: int
    var fdummy: float
    a?.fooData ?? idummy = 1 // will return reference to idummy, since a is null
    assert(idummy == 1)

    a = new TestObjectFooNative
    a?.fooData ?? idummy = 2 // will return reference to a.fooData, since a is now not null
    assert(a.fooData == 2 & idummy == 1)

    b = new TestObjectBarNative
    b?.fooPtr?.fooData ?? idummy = 3 // will return reference to idummy, since while b is not null, but b.?barData is still null
    assert(idummy == 3)

    b.fooPtr <- a
    b?.fooPtr?.fooData ?? idummy = 4 // will return reference to b.fooPtr.fooData
    assert(b.fooPtr.fooData == 4 & idummy == 3)

2.4.2.4. Arithmetic

exp:= 'exp' op 'exp'

daScript supports the standard arithmetic operators +, -, *, / and %. Other than that is also supports compact operators (+=, -=, *=, /=, %=, ^=, <<=, >>=) and increment and decrement operators(++ and –);:

a += 2
// is the same as writing
a = a + 2
x++
// is the same as writing
x = x + 1

All operators work normally with (u)int* and float* and double.

2.4.2.5. Relational

exp:= 'exp' op 'exp'

Relational operators in daScript are : ==, <, <=, <, <=, !=

These operators return true if the expression is false and a value different than true if the expression is true.

2.4.2.6. Logical

exp := exp op exp
exp := '!' exp

Logical operators in daScript are : &, |, !

The operator & (logical and) returns false if its first argument is false, otherwise returns its second argument. The operator | (logical or) returns its first argument if is different than false, otherwise returns the second argument.

It is important to understand, that it won’t nesessariy ‘evaluates’ all arguments.

The ‘!’ operator will return false if the given value to negate was true or false otherwise.

2.4.2.7. Bitwise Operators

exp:= 'exp' op 'exp'
exp := '~' exp

daScript supports the standard C-like bitwise operators &, |, ^, ~, <<, >>. Those operators only work on (unsigned) integer values.

2.4.2.8. Pipe Operators

exp:= 'exp' |> 'exp'
exp:= 'exp' <| 'exp'

daScript supports pipe operators. Pipe operator is similar to ‘call’ expression with other expresion is first argument.

def addX(a, b)
    assert(b == 2 | b == 3)
    return a + b
def test
    let t = 12 |> addX(2) |> addX(3)
    assert(t == 17)
    return true
def addOne(a)
    return a + 1

def test
    let t =  addOne <| 2
    assert(t == 3)

2.4.2.9. Operators precedence

post++  post--  .   ->  ?.

highest

|>  <|

-  +  ~  !   ++  --

??

/  *  %

+  -

<<  >> <<< >>>

<  <=  >  >=

==  !=

&

^

|

?  :

+=  =  -=  /=  *=  %=  &=  |=  ^=  <<=  >>=  <- <<<= >>>=

',' comma

lowest

2.4.3. Struct Constructor

struct Foo
  x: int = 1
  y: int = 2

let fExplicit = [[Foo x = 13, y = 11]] // x = 13, y = 11
let fPartial  = [[Foo x = 13]]         // x = 13, y = 0

(see Structs).

2.4.4. Array Contructor

exp := '[['type[] [explist] ']]'

Creates a new fixed size array:

let a = [[int[] 1, 2]]     // creates array of two elements
let a = [[int[2] 1, 2]]    // creates array of two elements
let a = [[int[2] 1, 2, 3]] // error, too many initializers

Arrays can be also created with array comprehensions:

let q <- [[ for x in range(0, 10); x * x ]]