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

# vipsi - shell and script language

## data types

### numbers

        1234                is an integer number
        -1234               a negative one
        123.456e-78         huh, floating point...
        $123affe            hexadecimal notation
        -$b00.b00f
        %10100101           binary notation
        +%1010.0101
        'mixa'              base 256  ((unicode))

numbers are stored internally in an at least 8-byte IEEE floating point format which allows for a precision of up to 53 bits including sign bit (approx. ±16 decimal digits) and an exponent of 11 bits (approx. ±308 decimal digits).

maximum values are:

    min./max. integer:       ±((1<<53)-1)
                           = ±9.007199254741e+15

    min./max. values:        ±(((1<<53)-1)<<52)<<1023
                           = ±1.7976931348623e+308

    nearest values to null:  ±1>>1022
    (full precision)       = ±2.2250738585072e-308

    nearest values to null:  ±(1>>52)>>1022
    (denormalized)         = ±4.9406564584125e-324

besides that are some abnormal monstrosities like NaNs and signed zeros.

### texts and strings

        "hello"             a simple text
        "say \"hello\""     escaping a control

texts are stored internally in a format that allows for virtually any text length and can store any unicode character (and some more) including character code 0. there is no problem storing binary daty in a string. in fact, it is common practice to read whole files into a string before starting work on them. ;-)

when reading text from a file in binary mode the resulting text consists only of characters with codes in range 0 ... 255. you can do manual conversion with convert if required, mocrifying your binary data into a real and unicode compliant text. when reading a text in the preferred way with get from an opened stream then the conversion is already done for you. the default encoding is UTF-8. writing works similar - just reverse.

individual characters and substrings are accessed with either leftstr() and the like or an array-like notation:

        put "Anton"[3]                 // prints: t
        put "Anton Bruckner"[3 to 5]   // prints: ton
        put "Cäsar Cicero"[to 5]       // prints: Cäsar
        put "Cäsar Cicero"[7 to]       // prints: Cicero
        put "Casiopeia"[ to ]          // prints: Casiopeia

indexes start at 1, ranges are declared with the first and last index inclusive.

### lists and arrays

        { }                   an empty list
        { 1, 2, 3 }           a list with three items
        { "a", "b", 44 }      again three items
        { 1, {"a","b"} }      two items. the second item is itself a list
        { x=22, y=1.5, z=0 }  items may by named

lists may be of any size and nested to any level until you run out of RAM.

lists can be initialized with { ... } in one go, including nested sub-lists and naming of list items.

individual items and substrings are accessed with either by name or an array-like notation:

        var my_list = { 1, 2, 3, a=4, b=5, c=6 }
        put my_list.a                  // prints: 4
        put my_list[3]                 // prints: 3
        put my_list[3 to 5]            // prints: { 3, a=4, b=5 }
        put my_list[to 4]              // prints: { 1, 2, 3, a=4 }
        put my_list[5 to]              // prints: { b=5, c=6 }
        put my_list[ to ]              // prints: { 1, 2, 3, a=4, b=5, c=6 }

        var list2 = { 1, z={ 2, z="Anton", 3}, 4 }
        put list2.z                    // prints: { 2, z="Anton", 3 }
        put list2.z.z                  // prints: Anton
        put list2[2,2,to 3]            // prints: Ant
        put list2.z[2,to 3]            // prints: Ant

indexes start at 1, ranges are declared with the first and last index inclusive.

accessing a list item beyond the end of an list automatically creates all the intermediate items, which are unnamed and set to 0.0.

### procedures

        proc foo()  { }
        proc bee(a) { put a }
        proc x(a,b) { return a+b }
        proc fak(n) { if n<=1 return 1; else return n*fak(n-1); then }
        proc add(*) { var i=count(locals),n=0; do while --i; n+=locals[i]; loop; return n }

procedures are a data type. once defined, they can be executed, disassembled, passed to other procedures as argument or put into a list. procedures in a list can access 'neighbour' data elements by name, thus supplying a light-weight approach for object oriented programming. procedures can either take a fixed number of arguments or a variable one, introduced with an asterics *. they can return a result of any data type (number, text, list or a procedure) or no result. the result they return may vary depending on the argument data or other criteria. procedures may be defined locally inside other procedures.

        proc foo(a) { return a }       // defines a procedure
        put foo(123)                   // prints the number 123
        put foo("abc")                 // prints the text abc
        put foo                        // prints the foo: proc ( a ) { return a }

        proc foo(){x=0;y=0}            // defines a procedure...
        var a={x=1,y=2,Clear=foo}      // ... and puts it in a list
        put a                          // prints { x=1, y=2, Clear=proc ( ) { x = 0 ; y = 0 }  }
        a.Clear()                      // executes the procedure
        put a                          // prints { x=0, y=0, Clear=proc ( ) { x = 0 ; y = 0 }  }