author :
date :
updated : iri, october 2011
updated : iri, december 2011

Scol Language particular syntax

Scol is a functional and interpreted language, with static types and polymorphic.

Syntax

Scol determine independently the expected types.

The basic types are:

I       : integer
S       : string
F       : float
Chn     : SCOL channel
Srv     : SCOL server
Env     : SCOL environment
Comm    : communication
[u0 u1] : Tuples where u0, u1 are Scol types
[u0 r1] : List where u0 is a Scol type

Types can be declared by the addition of Scol plugins (dll) or by the use of "typedef" or structures "struct". "nil" can claim any of these types, for example it will be used to change the value of a variable to null or test if a variable has been initialized.

Data Structures

With struct :

The data structures are declared as follows:

struct MYDATA [ MD_sName : S, MD_iValue : I] mkMYDATA;;

You can access an element of a structure by ".MD_sName" for example:

struct MYDATA [ MD_sName : S, MD_iValue : I] mkMYDATA;;
fun crData(name, value)=
  mkMYDATA [name value]
;;

fun getDataName(mydatastr)=
  mydatastr.MD_sName
;;

fun main()=
  let crData "name" 1 -> mydatastr in
    _fooS strcat ">>> nom : " (getDataName mydatastr);
 0;;

Note : you must initialize your structure before use it !

With typedef :

Definition :

typedef NewType =
T1 type1
| T2 type2
| T3 type3
| Tn;;

To access it, use match :

fun maFonction (X)=
    match X with
    (T1 e -> instruction1)
    | (T2 e -> instruction2)
    | (T3 e -> instruction3)
    | (TN e -> instructionN)
    | (_ -> instructionDefault);;

For example :

typedef NewType =    /* New scol type named 'NewType'. It can set by a "subtype" (in fact in function) T1, T2, ... */
T1 I
| T2 F
| T3 S
| Tn;;

typeof X = NewType;;    /* Global variable declaration (see below) */

fun maFonction ()=
    match X with
    (T1 e -> (_fooS "X is an integer"; 0)
    | (T2 e -> (_fooS "X is a float"; 0)
    | (T3 e -> (_fooS "X is a string"; 0)
    | (_ -> (_fooS "X is another thing"; 0);;

Operators

In Scol, standard operators are supported, it is also possible to use masks (&, |, ~) and bit shifts (>>, <<). The only truly special case concern the float, it will use the standard operators followed by a "."

fun addfloat(v1, v2)=
  v1 +. v2   
;;

fun addint(v1, v2)=
  v1 + v2   
;;

For the string, you could use this :

fun addString (s1, s2)=
  strcat s1 s2;;

Global variables

There are different ways to declare global variables, the first by the type of the variable and the second by an initial value.

// Declaring a variable by value, here a Int type (because the given value is an integer)
var iMyVar = 0;;

// Declaring a variable by value, here a String type (because the given value is an string)
var sMyVar = "Hello World";;

// Declaring a variable by a type
typeof iMyVar = I;;
typeof sMyVar = S;;

To set a value to these varaible, use set function (it's a function even if the return is ignored usually) :

set sMyVar = "Hello World";
set iMyVar = 0;

Locale variables

A local variable declared with "let value -> varname in ", has a lifetime limited to the following statement. The Scol language set this limit by ";" or end of a bracket or brace.

fun main()=
  let "Hello World" -> text in
  {
    _fooS ">>> local variable";  //Without the brace the "text" variable would not be known at the next line
    _fooS strcat ">>> value : " text;
  };
  0;;

If logic

When using the "if" test, Scol has the distinction of require to write the complete test. "if" without the "else" or without the "then " will not compile. Another special case, the return value in "then" and "else" should contain the same type.

fun main()=
  let 1 -> i in
  if (i == 1) then
     set i = 0
  else nil;

  let 1 -> i in
  if (i >= 1) then
  {
     if (i == 1) then nil else
       set i = i - 1;
  }
  else nil;
  0;;

While loop

The syntax of the loop is composed of "while" followed by "do":

fun main()=
  let 0 -> i in
  while (i <= 10) do
  {
    _fooS strcat ">>> i value : " (itoa i);
    set i = i + 1;
  };
 0;;

Lists

The use of the lists is very common in Scol, it can, unlike arrays, change its size dynamically. In scol lists are nested tuples, this means that we can treat a list as a tuple of two components, the first will contain the first item in the list and the second then rest of the list without the first element. A list can contain any type and always ends with "nil".

var lMyList = "elem1"::"elem2"::"elem3"::nil;;
typeof lMyList2 = [S r1];;

fun main()=
  // parsing, we copy the list into a local variable to avoid modifying the global list
  let lMyList -> l in
  while (l != nil) do
  {
    // we get the first element
    let hd l -> elem in
    {
      _fooS strcat ">>> elem : " elem;

      // we add "elem" to lMyList2
      set lMyList2 = elem::lMyList2;
    };
    // we remove the first element of l
    set l = tl l;
  };

  // another method for the same result
  let lMyList -> l in
  while (l != nil) do
  {
    // we get the first element
    let l -> [elem next] in
    {
      _fooS strcat ">>> elem : " elem;

      // we add "elem" to lMyList2
      set lMyList2 = elem::lMyList2;

      // we remove the first element of l
      set l = next;
    };
  };

  // another method for the same result
  let sizelist lMyList -> size in
  let 0 -> i in
  while (i < size) do
  {
    // we get the first element at the i position in the list
    let nth_list lMyList i -> elem in
    {
      _fooS strcat ">>> elem : " elem;
      // we add "elem" to lMyList2
      set lMyList2 = elem::lMyList2;
    }
    // increment i
    set i = i + 1;
  };
  0;;

Note : to test if a list is ended, compare it with nil :

if myList == nil then
  // to do something when the list is empty
else
  // to do another thing when the list is not empty

Recursive functions

Recursive functions can avoid the use of intensive loops execution time. Here is an example of a recursive function to process the items in a list based on the previous example. The recursive function is very often used and this is natural in Scol.

var lMyList = "elem1"::"elem2"::"elem3"::nil;;
typeof lMyList2 = [S r1];;

fun recursiveParse(l)=
  if l == nil then nil else
  let l -> [elem next] in
  {
    _fooS strcat ">>> elem : " elem;

    // we add "elem" to lMyList2
    set lMyList2 = elem::lMyList2;

    // we recall the function with the following data to be processed
    recursiveParse next;
  };;

fun main()=
  recursiveParse lMyList;
  0;;

Callbacks

Callbacks allow a call to a function defined in a variable. A window object (ObjWin) for example can call a function when it is closed or being moved. It is also possible to define a variable of function type.

typeof cbMyfun = fun [S] I;;

fun cbTest1(svalue)=
  _fooS strcat ">>> value : " svalue;
  0;;

fun main()=
  set cbMyFun = @cbTest1;
  exec cbMyFun with ["Hello world !"];
  0;;

Prototype

A function must be defined before use it. Sometimes, we can not do it. In this case, the function must be prototyped before use it (but it must be defined in the current environment ! Otherwise error "empty prototype" !)

proto myFunctionPrototyped = fun [u0] u1;;

You can find examples here