Expressions

Expressions can be categorized in many different ways: type of action, appearance, whether it also assigns the value somewhere or if its purpose has a special meaning.

There are 5 types of action for expressions in SGScript: arithmetic, bitwise, logical, comparison and special.

expressionappearancetype of actionassign# in.
add A + B arithmeticno2
subtract A - B arithmeticno2
multiply A * B arithmeticno2
divide A / B arithmeticno2
modulo A % B arithmeticno2
pre-increment ++ A arithmeticself1
pre-decrement -- A arithmeticself1
post-increment A ++ arithmeticself1
post-decrement A -- arithmeticself1
add-assign A += B arithmeticyes2
subtract-assign A -= B arithmeticyes2
multiply-assign A *= B arithmeticyes2
divide-assign A /= B arithmeticyes2
modulo-assign A %= B arithmeticyes2
bitwise AND A & B bitwiseno2
bitwise OR A | B bitwiseno2
bitwise XOR A ^ B bitwiseno2
left shift A << B bitwiseno2
right shift A >> B bitwiseno2
bitwise AND-assign A &= B bitwiseyes2
bitwise OR-assign A |= B bitwiseyes2
bitwise XOR-assign A ^= B bitwiseyes2
left shift-assign A <<= B bitwiseyes2
right shift-assign A >>= B bitwiseyes2
bitwise invert ~ A bitwiseno1
logical AND A && B logicalno2
logical OR A || B logicalno2
first-not-null A ?? B logicalno2
logical AND-assign A &&= B logicalyes2
logical OR-assign A ||= B logicalyes2
first-not-null-assign A ??= B logicalyes2
logical invert ! A logicalno1
less than A < B comparisonno2
less than or equal A <= B comparisonno2
greater than A > B comparisonno2
greater than or equal A >= B comparisonno2
equal A == B comparisonno2
not equal A != B comparisonno2
strict equality A === B comparisonno2
strict inequality A !== B comparisonno2
raw comparison A <=> B comparisonno2
error suppression @ A specialno1
declare-local var A specialmaybeany
declare-global global A specialmaybeany
array literal [ A, B, .. ] specialnoany
dict. literal {A=1,B=2,..} specialnoany
map literal map{[A]=B} specialnoany
assign A = B specialyes1
concatenate A $ B specialno2
concatenate-assign A $= B specialyes2
concatenate A .. B specialno2
concatenate-assign A ..= B specialyes2
property A . B specialmaybe2
index A [ B ] specialmaybe2
multi-index-assign A[]<dict.lit>specialyesany
multi-property-assign A.<dict.lit> specialyesany
function call A ([B,..]) specialno<=256
comp. function call O!A ([B,..]) specialno<=256
function definition function A.. specialmaybe0
inline if if(A,B,C) specialno3(2)
subexpression ( A[, ..] ) specialmaybeany
thread-call thread f() specialmaybe<=256
subthread-call subthread f()specialmaybe<=256
new-call new f() specialmaybe<=256

Some notes on the special cases:

compatible function call / inheritance call / global method call ( O!A ([B,..]) )

CFC is created to encourage users to reduce memory usage without sacrificing clarity of code. Object and its processing function can reside in different locations (like class instance / inherited class) and still be easily accessible.

Properties:

Example WITHOUT:

function create_object()
{
    object = { x = 0, y = 0 };
    function object.move( x, y ){ this.x = x; this.y = y; @this.move_callback(); }
    function object.tick( delta ){ this.move( this.x + delta, this.y ); }
    return object;
}

Example WITH:

function Object_Move( x, y ){ this.x = x; this.y = y; @this.move_callback(); }
function create_object()
{
    object = { x = 0, y = 0 };
    function object.tick( delta ){ this!Object_Move( this.x + delta, this.y ); }
    return object;
}

Now, by itself it may not mean much, however let's see what happens if the following code is used:

for( i = 0; i < 100; ++i )
    objects.push( create_object() );

Without the usage of a global method, there's a key 'move' in each object that points to the function. In real software there may be no less than 10 such keys in many instances of many objects. And if there are no overrides planned for it, there's no need for it to be there but we can't really move it. Classes are an option that involves a few more allocations and it requires more memory to use them. Using .call/sys_call or replacing this with an argument would sacrifice readability and the option to relocate functions, as well as performance, this being a double call. This is where CFC comes in - syntax allows to clearly state the object and function used, and the required interface for the object to be compatible with said function.