packages feed

spade-0.1.0.7: docs/language-reference.md

## Language Reference

### Variables

Variables are initialized using `let` statement. For example

```
let a = 10
```

### Conditionals

#### if-then

This is used to conditionally execute parts of a program. For example

```
if age > 10 then
    println("Greater than 10")
endif
```

#### if-then-else

This is used to provide an alternative if the condition does not hold.

```
if age > 10
  then
    println("Greater than 10")
  else
    println("Less than or equal to 10")
endif
```

#### if-then-elseif-else

This is like if-else statemebt but can be used to provide many alternative branches.

```
if age > 10
  then
    println("Greater than 10")
  elseif age > 5 then
    println("Greater than 5")
  elseif age > 2 then
    println("Greater than 2")
  else
    println("Less than or equal to 2")
endif
```

### Loops

Loops are using to execute a sequence of statements repeatedly. Following
looping constructs are available.

#### for statement

This loop can be used to execute some group of statements repeatedly,
while incrementing a variable at each iteration.

Example:

```
for i = 1 to 100
  println(i)
endfor
```

The `break` statement can be used to break out of the loop.

#### while statement

This loop execute a group of statements repeatedly as long as the specified
condition hold.

Example:

```
let i = 10
while i < 0
  println(i)
  let i = i + 1
endwhile
```

The `break` statement can be used to break out of the loop.

#### loop statement

This is an unconditional looping statement.
The only way to exit from the loop is by using a `break` statement.

Example:

```
let l = 0
loop
  println(l)
  let l = l + 1
  if l > 10 then break endif
endloop
getkey()
```

### Functions/Procedures

Functions are declared using the `proc` keyword. For example

```
proc multiply(a, b)
  return a * b
endproc

println(multiply(5, 2))
```

### Anonymous functions or Lambdas

You can create anonymous function using the `fn` keyword. Example where
a callback using an anonymous function is passed to the `filter` function.

```
let mylist = [2, 3, 4, 5, 6]
let filtered = filter(mylist, fn(x) mod(x, 2) == 0 endfn)
```

Anonymous functions can contain only a single expression.

### Scoping

Variables assigned at the top level are globals and are available
inside functions without special syntax.

For example, the program below will print `10` when executed.

```
let a = 10

proc myProc()
  println(a)
endproc

myProc()
```

There is a caveat to this though. Global variables defined below a
function call will not be available inside the function. For example
the following program results in an "Unknown symbol reference" error.

```
proc myProc()
  println(a)
endproc

myProc()

let a = 10
-- ^ Global variable `a` defined after `myProc` call. Variable `a`
-- is not available inside `myProc`.
```

#### Closures

When a function returns an unnamed function, the returned function holds
a copy of the parent functions local scope. For example, the following function
prints `10 20`

```
proc myFunc(x)
  return fn() print(x, " ") endfn
endproc

let fn1 = myFunc(10)
let fn2 = myFunc(20)

fn1()
fn2()
```

### Expressions

Expressions are things that can be evaluated to a value. Following types
of expressions are available in the language.

#### Literals

The language support the following literals.

Integers -> `1500`
Boolean -> `true`, `false`
Floating -> `12.34`
Bytes -> `0x21`
String -> `"SPADE"`
List -> `[12, 34, 56]`
Dictionary -> `{name : "John", age: 34}`
Anonymous function -> `fn(x) x * 2 endfn`

#### Variable expression

These refer to a variable, and evaluate to the same value that is held
by the variable.

#### Conditional expression

These provide conditional evaluation, for example.

```
let x = if x == 0 then 1 else x
```

#### Binary expression

The following binary operators are available.

##### Numeric operators

`+` : addition operator
`-` : substraction operator
`*` : multiplication operator
`/` : division operator

##### Boolean operators

`<`   : less than
`>`   : greater then
`<=`  : less then or equal
`>=`  : greater than or equal
`==`  : equality check
`!==` : non-equality check
`and` : boolean AND
`or`  : boolean OR

The boolean 'not' operation is provided as a function #link: not#.

#### Function calls

Evaluates to the value returned by the function, for example,

```
proc multiply(a, b)
  return a * b
endproc

let a = multiply(5,2)
```

#### Index access

An index in a list/string/bytes expression can be accessed using the index accessor.
For example,

```
let list = [1,2,3,4]
print(list[2]) -- prints 2.
```

NOTE: Indexes starts from 1.

Index accessor can be attached to any expression, for example a function
returning a list. For example,

```
proc myFunc()
 return [1,2,3]
endproc
print(myFunc()[2]) -- prints 2.
```

You can modify values using indexes too.

```
let list = [1,2,3,4]
let list[2] = 10
print(list[2]) -- prints 10
```

This works similarly for bytes and texts.

```
let b = 0xffff
let b[2] = 0
print(b) -- prints 0xff00
```

and for strings


```
let b = "abcd"
let b[2] = "e"
print(b) -- prints "aecd"
```

#### Key access

An key in a dictionary expression can be accessed using the key accessor.
For example,

```
let person = { name: "John", age : 39 }
print(person.name) -- prints "John"
print(person["age"]) -- prints 39

let k = "age"
print(person[k]) -- prints 39
```

Key accessor can be attached to any expression, for example a function
returning a dictionary. For example,

```
proc myFunc()
 return { name: "John", age : 39 }
endproc
print(myFunc().name) -- prints "John"
```

### Builtin data types

#### Numbers

Numbers are either represented as integers (which can be as big as required)
or double precision floating point values.

Mathematical operations convert from integer to floating point values as required.

```
let age = 45
let price = 0.23
```

#### Strings

Strings represent a sequence of unicode code points.

```
let name = "SPADE"
```

#### Bytes

Bytes represent some sequence of bytes.

```
let somebytes = 0xFFAB
```

#### Lists

Lists can hold a sequence of values.

```
let mylist = [ "SPADE", 10]

```

Item at an index `x` in list `l` can be accessed using notation `l[x]`.
Indexes start at `1`, so to access the first item in a list use `l[1]`.

See #link: List Functions#

#### Dictionary

Dictionaries are containers that can hold content at a string key.
For example, the data for a person can be held in a dictionary.

```
let person = { name: "John", age: 45}
```

indvidual items can be accessed using the key access notation. For example
to print the name of the person, we can do something like the following.

See #link: Dictionary Functions#

```
println(person.name)
```