vipsi - operators
Author: kio@little-bat.de
Keywords: vipsi shell script interpreter programming

# vipsi - shell and script language

## the built-in words

### operators

#### operator precedence

vipsi evaluates expressions with proper operator hierarchy.

        2+3*4  ==  2+(3*4)

the exact listing of all operator precedences is like this:

    highest:    round brackets:     ( … )
                unary operator:     ++  --  [ … ]
                bit shifting:       >>  <<
                bit masking:        &  |  ^
                multiplication:     *  /  %
                addition:           +  -
                concatenation:      # ##
                comparision:        ==  !=  >=  <=  >  <
                boolean:            &&  ||
                triadic selector:   ? … : …
    lowest:     assignment:         =  +=  -=  *=  /=  %=  #=

assignments are right-oriented: if an expression is made up with multiple assignments, the rightmost assignment operator is evaluated first.

#### automatic type casting

operators which only take one type of argument try their best, to convert any type of argument to the required type. in addition, if a list is supplied to an operator, which takes no list, then the operation is applied to all items in the list.

    	123 + "456"     =   579                 numeric addition
    	123 # "456"     =   "123456"            text concatenation
    	123 + {4,5,6}   =   {127,128,129}       numeric addition, one argument is a list
    	{1,2,3}+{4,5,6} =   {5,7,9}             numeric addition, both arguments are lists
    	123 ## {4,5,6}  =   {123,4,5,6}         list concatenation

automatic type casting is not performed for comparison operators. there are ambiguities which can't be resolved. instead, in case of different types, only the data types themselve are compared, just to make them sortable. in addition, comparing NaNs (not-a-numer, e.g. the result of 0.0/0.0) is handled in accordance to IEEE, which in essence means, that if a=NaN then a!=a, making it unsortable. sorry for that.

boolean operators `&&` and `||` and the triadic operator `?:` are not expanded for list arguments. when pruning is implemented for them some day this would become very tricky.

#### "++" pre and post increment

    num_value = [++variable_ref|variable_ref++]

pre- or post-increment numeric variable.

e.g.: `var i=0; do while i<10; put i++; loop.`

#### "--" pre and post decrement

    num_value = [--variable_ref|variable_ref--]

pre- or post-decrement numeric variable.

e.g.: `var i=10; do while i>0; put --i; loop.`

#### "!" boolean (logical) not

    num_value = !num_value

logical negation.

e.g.: `if (!exists boo) log "variable boo is missing",nl then.`

#### "~" bitwise not (bit toggle)

    num_value = ~num_value

bitwise negation.

e.g.: `a = a & ~$20.`

#### "@" identifier from text

    identifier = @text_value

create identifier from text expression.

e.g.: `var t="a"; var a=1; log @t;`

#### "=" assignment

    variable_ref = value

assign value to variable.
assignment operators are right-oriented, that means: if multiple assignments are made in one expression, they are evaluated right-to-left.

e.g.: `var a = 47; var x,y,z; x=y=z=47;`

#### "+=" add to target

    variable_ref += num_value

add value to variable.
assignment operators are right-oriented, that means: if multiple assignments are made in one expression, they are evaluated right-to-left.

e.g.: `var a=20; a += 33;`

#### "-=" subtract from target

    variable_ref -= num_value

subtract value from variable.
assignment operators are right-oriented, that means: if multiple assignments are made in one expression, they are evaluated right-to-left.

e.g.: `var a=33; a -= 20;`

#### "*=" multiply to target

    variable_ref *= num_value

multiply variable with value.
assignment operators are right-oriented, that means: if multiple assignments are made in one expression, they are evaluated right-to-left.

e.g.: `var a=5; a *= 4;`

#### "/=" divide target

    variable_ref /= num_value

divide variable by value.
assignment operators are right-oriented, that means: if multiple assignments are made in one expression, they are evaluated right-to-left.

e.g.: `var a=20; a /= 5;`

#### "%=" divide and store remainder

    variable_ref %= num_value

divide variable by value and store remainder.
assignment operators are right-oriented, that means: if multiple assignments are made in one expression, they are evaluated right-to-left.

e.g.: `var a=20; a %= 6;`

#### "#=" concatenate to target

    variable_ref #= text

append text to text.
assignment operators are right-oriented, that means: if multiple assignments are made in an expression, they are evaluated right-to-left.

e.g.: `var a="abc"; a #= "de";`

#### "+" add

    [num_value|list_value] = [num_value|text_value|list_value] + [num_value|text_value|list_value]

1. operator: add two numerical values.
   add two numerical values or text values, which are converted to numbers, results in a number. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they should match in size and the operation is applied to all matching items.

   e.g.: `4+5 = 9; ({4,5}+3) = {7,8}; ({2,3})+{4,5} = {6,8}.`

   operator priority is below multiplication. text + text may some day result in text for high precision calculations.

2. optional number sign for positive number.
   note: preceding a text with operator + converts it to a number.

   e.g. `log +123, +$affe, +"0123", +"$affe";`

#### "-" subtract

    [num_value|list_value] = [num_value|text_value|list_value] - [num_value|text_value|list_value]

1. operator: subtract two numerical values.
   subtract two numerical values or text values, which are converted to numbers, results in a number. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they should match in size and the operation is applied to all matching items.

   e.g.: `9-5 = 4; ({4,5})-3 = {1,2}; ({4,5})-{2,3} = {2,2}.`

   operator priority is below multiplication. text - text may some day result in text for high precision calculations.

2. number sign for negative number.
   note: preceding a text with operator - converts it to a number.

   e.g. `log -123, -$affe, -"0123", -"$affe";`

#### "*" multiply

    [num_value|list_value] = [num_value|text_value|list_value] * [num_value|text_value|list_value]

1. operator: multiply two numerical values.
   multiply two numerical values or text values, which are converted to numbers, results in a number. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they should match in size and the operation is applied to all matching items.

   e.g.: `4*5 = 20; ({4,5})*3 = {12,15}; ({4,5})*{2,3} = {8,15}.`

   operator priority is above addition. text * text may some day result in text for high precision calculations.

2. wildcard in path pattern for dir().

   e.g. `var cafélogo = dir("./*.gif");.`

3. flag for del statement to delete all variables in local scope.

   e.g.: `del *.`

4. flag in procedure parameter list to accept any number of arguments.

   e.g.: `proc zähle(a,*){ log "a=",a," argc=",count locals,nl };`

#### "/" divide

    [num_value|list_value] = [num_value|text_value|list_value] / [num_value|text_value|list_value]

operator: divide one numerical value by another.
divide two numerical values or text values, which are converted to numbers, results in a number. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they should match in size and the operation is applied to all matching items.

e.g.: `20/5 = 4; ({40,50})/5 = {8,10}; ({40,50})/{8,5} = {5,10}.`

operator priority is above addition. text / text may some day result in text for high precision calculations.

#### "%" remainder

    [num_value|list_value] = [num_value|text_value|list_value] % [num_value|text_value|list_value]

1. operator: remainder of division of two numerical values.
   divide two numerical values or text values, which are converted to numbers, results in a number. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they must match in size and the operation is applied to all matching items.

   e.g.: `21.5%2.5 = 1.5; ({33,21})%5 = {3,1}; ({36,27}/{5,10}) = {1,7}.`

   operator priority is above addition.
   note: text % text may some day result in text for high precision calculations.

2. flag for binary number literal.

   e.g.: `-%0101.1 = -5.5.`

#### "#" stream selector / concatenate texts

    [put,get,…] #num_value,value[,…]

1. Select stream for i/o instruction:
   open, openin, openout, close, put, get, read, write, ioctl, info, variables, words, pwd, dir and others.

   e.g.: `open #4, "hello.txt"; put#4,"hello world",nl; close#4;`

2. operator: concatenate two texts.
   concatenate two texts or numeric values, which are converted to text, results in a text. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they must match in size and the operation is applied to all matching items.:

           ({1,2,3}#"anton")  =  {!1anton","2anton","3anton"}
           "anton"#{1,2,3}    =  {"anton1","anton2","anton3"}
           "ant"#"0123.40"    =  "ant0123.40"
           "anton"#0123.40    =  "anton123.4"
           123.456#0123.40    =  "123.456123.4"

   operator priority is between add/sub and comparisions:

           e.g.: a#b+c  =  a#(b+c)
           a#b>c  =  (a#b)>c.

#### "##" concatenate lists

    list ## list

operator: concatenate two lists.
concatenate two lists or text or numeric values which are converted to lists, results in a list:

        ({1,2,3}##{4,5,6})  =  { 1,2,3,4,5,6 }
        ({1,2,3}##"anton")  =  { 1,2,3,"anton" }
        "anton"##{1,2,3}  =  { "anton",1,2,3 }
        "ant"##"0123.40"  =  { "ant","0123.40 }
        "anton"##0123.40  =  { "anton",123.4 }
        123.456##0123.40  =  { 123.456,123.4 }

operator priority is between add/sub and comparisions:

        e.g.: a##b+c  =  a##(b+c)
        a##b>c  =  (a##b)>c.

#### > < >= <= != == compare

    num_value = value > value

operator: compare two values.
if values of different type are compared, then the result depends solely on the data types.

e.g.: `if (a>55) log "a>55" then; if(b>"aaa") log "b>aaa" then;`

#### "<<" shift left bitwise

    num_value = num_value << num_value

operator: bitwise shift left, padding with 0.

e.g.: `8<<2 = 32.`

#### ">>" shift right bitwise

    num_value = num_value >> num_value

operator: bitwise shift right, padding with 0.

e.g.: `32>>2 = 8.`

#### "&&" boolean (logical) "and"

    num_value = num_value && num_value

operator: logical AND (pruning not yet implemented).

e.g.: `if (a==0&&a!=0) log "this can not happen" then.`

#### "||" boolean (logical) "or"

    num_value = num_value || num_value

operator: logical OR (pruning not yet implemented).

e.g.: `if (a==0||a!=0) log "this is always true" then.`

#### "&" bitwise "and"

    num_value = num_value & num_value

operator: bitwise AND.
performs the boolean operation AND bitwise on the bits of the numerical arguments or text values, which are converted to numbers, results in a number. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they should match in size and the operation is applied to all matching items.

e.g.: `$FE & $0F = $0E.`

#### "|" bitwise "or"

    num_value = num_value | num_value

operator: bitwise OR.
performs the boolean operation OR bitwise on the bits of the numerical arguments or text values, which are converted to numbers, results in a number. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they should match in size and the operation is applied to all matching items.

e.g.: `$0E | $58 = $5E.`

#### "^" bitwise "exclusive or"

    num_value = num_value ^ num_value

operator: bitwise XOR (exclusive or).
performs the boolean operation XOR bitwise on the bits of the numerical arguments or text values, which are converted to numbers, results in a number. if one operand is a list, the result is a list, where the operation was applied to all items. if both are lists, they should match in size and the operation is applied to all matching items.

e.g.: `$0E ^ $5E = $50.`

#### "." named item selector

    variable_ref = list_value . identifier

operator: select named item in list.

e.g.: `var a={1,2,3}; var a.b=4; rename a[2]="z"; log a.z,a.b;`

#### "... ? ... : ..." select operator (triadic)

    value = num_value1 ? value2 : value3

operator: select value 2 or 3 based on value 1.
note: pruning is not yet implemented.

e.g.: `return a>b ? a : b;`