# 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
``````

Example for versions iconc 9.4
``````procedure main ()
if A = 0 then {
return;
}
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
``````