Icon

Implementation of programming language Icon

Icon interpreter written in C. It can compile the source code into either bytecode (so-called i-code) with an interpreter attached or into C code. Note that the second option is less popular and support for it is worse.

Examples:

Hello, World!:

Example for versions iconc 9.4
procedure main ()
   write ("Hello, world!")
end

Factorial:

Example for versions iconc 9.4

This example uses recursive factorial definition. 0 to 16 is a generator which returns all integers between 0 and 16, inclusive. every ... do allows to fetch every result returned by the generator and process it (calculate factorial and perform write).

procedure factorial (n)
   if n = 0 then
      return 1
   else if n > 0 then
      return n * factorial (n - 1)
end

procedure main ()
   local i
   every i := 0 to 16 do
      write (i, "! = ", factorial (i))
end

Factorial:

Example for versions iconc 9.4

This example uses iterative factorial definition written in short form. every j *= 1 to i multiplies j by all values returned by the generator 1 to i. The expression in braces calculates factorial by multiplying j by all values between 1 and i and returns it. The outer expression calculates and prints factorials of all numbers returned by the generator 0 to 16.

procedure main ()
   local i, j
   every write (i := 0 to 16, "! = ", { j := 1; every j *:= 1 to i; j })
end

Fibonacci numbers:

Example for versions iconc 9.4

This example uses recursive calculation of Fibonacci numbers with memoization.

global fib_memo

procedure fib (n)
   if n >= 0 then
      return ((/fib_memo [n] := fib (n - 2) + fib (n - 1)) | fib_memo [n])
end

procedure main ()
   local i
   fib_memo := table ()
   fib_memo [0] := 0; fib_memo [1] := 1
   every i := 1 to 16 do {
      writes (fib (i) || ", ")
   }
   write("...")
end

Quadratic equation:

Example for versions iconc 9.4
procedure main () 
    A := read();
    if A = 0 then {
        write("Not a quadratic equation.");
        return;
    }
    B := read();
    C := read();
    D := B*B - 4*A*C;
    if D = 0 then {
        write("x = ", -B/2/A);
        return;
    }
    if D > 0 then {
        write("x1 = ", (-B+sqrt(D))/2/A);
        write("x2 = ", (-B-sqrt(D))/2/A);
    } else {
        write("x1 = (", -B/2/A, ",", sqrt(-D)/2/A, ")");
        write("x2 = (", -B/2/A, ",", -sqrt(-D)/2/A, ")");
    }
end

CamelCase:

Example for versions iconc 9.4

First of all the program reads the string to process and adds a space to its end (|| is concatenation operator). After this text variable is scanned. ? is an operator which binds a string to the expression, so that all string matching functions in the expression are performed on this string.

Commands ReFind and ReMatch from regular expressions library regexp both find all sequences of symbols which match the given regex, but ReFind returns the index of sequence start, and ReMatch — the index of the first character after sequence end. In one iteration ReFind finds the start of the next sequence of non-letter characters. Command tab moves current position pointer to this position and returns part of the string from previous position of the pointer to the new position — a word. After this the word is converted to proper case and concatenated to the resulting string. *word is a function which returns length of the string. map replaces all characters of its first argument which are present in its second argument with corresponding characters from its third argument (in this case — switch case of characters; &lcase and &ucase are built-in constants which contain lowercase and uppercase alphabet). Finally, one more call of tab moves the pointer past the sequence of non-letter characters to the start of next word.

link regexp

procedure main () 
    text := read() || " ";
    cc := "";
    text ? {
        while j := ReFind("[^a-zA-Z]+") do {
            word := tab(j);
            cc ||:= map(word[1],&lcase,&ucase) || map(word[2:*word+1],&ucase,&lcase);
            tab(ReMatch("[^a-zA-Z]+"));
        }
    }
    write (cc);
end