/Develop/Projects/Vcc/

k1.spdns.de / Develop / Projects / Vcc /

Kio's Virtual Instruction Compiler.

intro | invocation | preprocessor | types | functions | operators | instructions  

compiler | memory  

Operators

Operator Hierarchy

Operators of higher priority are evaluated first, operators of same priority are evaluated from left to right.

Table of priority

++, --, !, ~        increment, decrement, boolean not, bitwise complement (prefix operators)
>>, << bit shift
&, |, ^ bitwise and, or, exclusive or
*, /, % multiply, divide, remainder
+, - add, subtract
==, !=, >=, <=, >, < compare
&&, || pruning boolean and, or
?: pruning selector
=, :=, +=, .. <<= assignment

Sequence of argument evaluation

Normally arguments are evaluated from left to right. This is a different thing than evaluating operators from left to right:

a = b + c + d

operators are evaluated from left to right:
first b+c is evaluated and then (b+c) + d

a = b + c

arguments are evaluated from left to right:
first b is evaluated, then c and then the operation can be performed
this becomes important when 'b' and 'c' have side effects, e.g.:

a = *p++ + *p++

Note that in vicci/vcc this sequence of evaluation is guaranteed, while in C / C++ it is not. (It's even allowed to optimize it to 'a=*p+*p;p+=2;'.)

Keyword 'reverted'

Operators can be defined with the keyword 'reverted' which means, that their arguments will be evaluated from right to left. Note that this does not affect the evaluation sequence of operators of same priority! Normally you will not do this, because it may come unexpected to the user/programmer. But there is one exception where the built-in operators of vicci/vcc always use reverse order:

All assignment operators are 'reverted'!

This is for better code robustness. The destination of the assignment is determined last so that side effects of the assigned value are allowed to move the destination around. In a target system which uses garbage collections this can happen with each memory allocation, but also in 'static' systems if you modify an array while you assign a value to an item within:

a[i] = foo()    // and foo modifies a

String or Array Operators

String operators work on arrays of characters or numbers. Both arrays must contain the same data type.

operator +

str operator+ ( str, str )
str operator+ ( str, <number> )

Operator+ concatenates two strings. If the 2nd argument is numeric, then it is implicitely converted to a decimal number representation.

operator+=

append rightside item value or string value to leftside string variable.

operators == != >= <= > and <

compare two strings arithmetically. The first array item (at index 0) is most significant. If one string is shorter, then the first 'missing' character is smaller than it's existing counterpart in the other string. That is, an empty string is the 'smallest' possible.

Numeric operators

Most numeric operators work on all numeric data types, most even on any mixture thereof.

Assignment operators

All built-in assignment operators are defined as 'reverted'!

operator =

stores the value from the right side into the variable referred to on the left side. If the data is of an allocated type, then the destination is destroyed afterwards(!).
Operator= cannot be redefined. If you want to implement custom assignment behaviour for a struct or array, define init(T¢), copy(T¢) and kill(T¢) instead.

operator :=

Basically the same as operator=, except that the destination is assumed to be void and not destroyed. This can be used in custom creators.
In addition, operator:= can be used to assign a new target for a reference variable:

int a,b
int& p = a // here: same as 'int p := a'
p := b // reassign reference
operator +=

add to variable.

operator -=

Subtract from variable.

operator *=

Multiply varibale with value.

operator /=

Divide variable by value.

operator %=

Store remainder of division in variable.
a%b == a - int(a/b)*b
a == int(a/b)*b + a%b

operator &=

Store result of bitwise 'and' in variable.

operator |=

Store result of bitwise 'or' in variable.

operator ^=

Store result of bitwise 'xor' in variable.

operator >>=

Store result of bitshift 'right' in variable.
If the variable is a signed int, then shifting is done sign-extended, that is, the sign bit (the msb) is copied to the neighbour bits.
If the variable is unsigned, padding is always done with '0' bits.
If the variable is float, then the binary exponent is decremented, effectively dividing the number by a power of 2. This is the same as for integers for positive numbers, but slightly different for negative numbers, because negative integers are stored as twoes complement, floats are not.
If the shift offset is negative, then the variable is shifted left instead.
The shift offset for integers is taken modulo an implementation dependent high number. (i386_64: 64)

operator <<=

Store result of bitshift 'left' in variable.
If the variable is integer, padding is done with '0' bits.
If the variable is float, then the binary exponent is incremented, effectively multiplying the number with a power of 2. This is the same as for integers for positive numbers, but slightly different for negative numbers, because negative integers are stored as twoes complement, floats are not.
If the shift offset is negative, then the variable is shifted right instead.
The shift offset for integers is taken modulo an implementation dependent high number. (i386_64: 64)

Pruning Operators

Pruning operators cannot be redefined.

Selection operator :?

The boolean value of the 1st argument of this triadic operator determines, whether the second or the 3rd argument is evaluated. Both must yield the same type of result.

Boolean operator &&

Boolean 'and': If the first operand is 0 then the result is 0 and the 2nd argument is completely irrelevant and not evaluated.

Boolean operator ||

Boolean 'or': If the first operand is true then the result is 1 and the 2nd argument is completely irrelevant and not evaluated.

Compare

operators == != >= <= > and <

Comparison operators return a boolean value 0 or 1.
If a signed and an unsigned integer are compared, then these operators work correct with respect to the signedness, e.g. uint(-1) != -1.

Arithmetic Operators

Integers: no overflow checking.
Float: maybe.
The result of small integers is typically one sizetype larger than the operands.
If one of both operands is signed, then the result is signed.
If one of both operands is float, then the result is float.

operator +
operator -
operator *
operator /
operator %

Remainder of division:
a%b == a - int(a/b)*b
a == int(a/b)*b + a%b

Bit Operators

operator &

Arguments must be integer.
in case of mixed signedness: signed & unsigned = signed.

operator |

Arguments must be integer.
in case of mixed signedness: signed | unsigned = signed.

operator ^

Arguments must be integer.
in case of mixed signedness: signed ^ unsigned = signed.

operator >>

Bitwise shift 'right'.
If the target is a signed int, then shifting is done sign-extended, that is, the sign bit (the msb) is copied to the neighbour bits.
If the target is unsigned, padding is always done with '0' bits.
If the target is float, then the binary exponent is decremented, effectively dividing the number by a power of 2. This is the same as for integers for positive numbers, but slightly different for negative numbers, because negative integers are stored as twoes complement, floats are not.
If the shift offset is negative, then the target is shifted left instead.
The shift offset for integers is taken modulo an implementation dependent high number. (i386_64: 64)

operator <<

Bitwise shift 'left'.
If the target is integer, padding is done with '0' bits.
If the target is float, then the binary exponent is incremented, effectively multiplying the number with a power of 2. This is the same as for integers for positive numbers, but slightly different for negative numbers, because negative integers are stored as twoes complement, floats are not.
If the shift offset is negative, then the target is shifted right instead.
The shift offset for integers is taken modulo an implementation dependent high number. (i386_64: 64)

Monadic Postfix Operators

operator ++

Post-increment: Get the value from a variable and after that increment the variable by 1.

int a,i
a = i++;

Define postfix ++ for a struct:
this is not a member function!

Foo operator++ ( Foo&, void );
operator --

Post-decrement: same as post-increment, except that it decrements by 1.

Monadic Prefix Operators

operator ++

Pre-increment: Increment the variable by 1 and then get the value from it.

int a,i
a = ++i;

Define prefix operator ++ for a struct:
this is not a member function!

Foo operator++ ( void, Foo& );
operator --

Pre-decrement: same as pre-increment, except that it decrements by 1.

operator !

Boolean NOT.
Works on all data types. For allocated data types (ararys and structs) it returns whether the data is allocated (variable!=NULL) or not (variable==NULL).
The result is 0 or 1.

operator ~

Bitwise complement.
For signed integers and floats this is the same as 'a = -1-a'.

operator &

'Address of': Convert a variable reference into a pointer.

operator *

'Content of': Convert a pointer into a variable reference.

Not considered operators:

[]

Access item in an array by index.

.

Access named item in a struct or member function.

()

call function or function pointer.

Archive

Name Letzte Änderung Länge 
lib-Z80-Rop/ 2020-11-30 15:50 21 
lib-Z80-Vss/ 2017-11-12 09:55 452 
lib/ 2019-10-30 17:02
Libraries/ 2019-10-30 17:11
OSX-Qt40/ 2019-10-30 17:02
OSX/ 2020-09-05 12:54
Source/ 2019-10-30 17:02 11 
Tests/ 2019-10-30 17:02
LICENSE 2019-10-30 17:25 1323 
README.md 2019-10-30 17:25 288 
TODO.txt 2020-10-18 12:42 340 
macspin.gif

powered by vipsi - your friendly VIP Script Interpreter

Valid HTML Valid CSS