Control structures - Palamecia/mint GitHub Wiki

Control structures allow you to execute different parts of a script depending on certain conditions. Mint uses four kinds of control structures:

Caution

Inserting a new line before the { that starts the statement block is a syntax error. The block must follow immediately. This prevents some invalid states in the interactive mode.

Conditional control structures

The if statement

The if statement allows you to execute a part of the script only when a condition becomes true.

It is introduced by the if keyword followed by an expression. The statement opens a block of script that is executed if the expression evaluates to true.

Note

The expression is considered inside the opened block by the let keyword.

The if statement can use two kinds of expressions:

  • A simple expression: In this case, the result of the expression is cast to a boolean.
  • An "in" expression: In this case, the left part of the expression is passed to the in method of the object on the right side, and the result is cast to a boolean.

Important

If the object on the right side of the "in" expression does not overload the in method, the object is cast to an iterator to use the iterator's method implementation. The method can also return an iterator. In this case, the iterator's in method implementation of the returned object is also used.

Example:

if value > 10 {
    // Script to be executed when value > 10
}

if 'e' in str {
    // Script to be executed when str contains 'e'
}

if 5 not in values {
    // Script to be executed when values does not contain 5
}

An if statement can be immediately followed by an elif statement, allowing you to execute a part of the script only when the condition is false and another condition becomes true. An elif statement can also be followed by other elif statements.

It is introduced by the elif keyword followed by an expression. The statement opens a block of script that is executed if the expression evaluates to true.

Example:

if value > 10 {
    // Script to be executed when value > 10
} elif threshold < 10 {
    // Script to be executed when value <= 10 and threshold < 10
} elif value < 0 {
    // Script to be executed when value <= 10, threshold >= 10 and value < 0
}

An if or elif statement can also be followed by an else statement, allowing you to execute a part of the script only when all the previous conditions are false.

It is introduced by the else keyword. The statement opens a block of script that is executed if all the previous expressions evaluates to false.

Example:

if value > 10 {
    // Script to be executed when value > 10
} elif threshold < 10 {
    // Script to be executed when value <= 10 and threshold < 10
} else {
    // Script to be executed when value <= 10 and threshold >= 10
}

Caution

Inserting a new line between the } and the elif or else keyword is a syntax error. The next statement must follow immediately. This prevents some invalid states in the interactive mode.

The switch statement

The switch statement allows you to execute parts of a script from different points depending on the result of an expression.

It is introduced by the switch keyword followed by an expression. The statement opens a block containing the script and the descriptions of the different entry points.

Note

The expression is considered inside the opened block by the let keyword.

An entry point is introduced by the case keyword followed by a value and finished by the : operator.

The result of the expression is compared to the value using the == operator. If the result of the comparison cast to a boolean is true, the execution of the part of the script starts from this point.

Example:

switch value {
case 0:
    // Script to be executed when value == 0
case 1:
    // Script to be executed when value == 0 or value == 1
case 2:
    // Script to be executed when value == 0 or value == 1 or value == 2
}

The case keyword can also be followed by the is operator. In this case, the result of the expression is compared to the value using the is operator.

Example:

switch value {
case is none:
    // Script to be executed when value is none
case is null:
    // Script to be executed when value is none or value is null
case 0:
    // Script to be executed when value is none or value is null or value == 0
}

The case keyword may be followed by the in operator. In this case, the result of the expression is used to search the value using the in operator.

An expression following an in operator can also use special syntaxes like a range operator or a list of values.

Example:

switch value {
case in 0...5:
    // Script to be executed when value is in the range 0...5
case in 7..9:
    // Script to be executed when value is in the range 7..9
case in 10, 12, 24, 32:
    // Script to be executed when value is in the list
case in 'aeiou':
    // Script to be executed when value is in the string
}

A special entry point can also be introduced by the default keyword. This entry point is used when all the previous entry points were passed without entering a part of the script.

Important

The default entry point must be the last entry point of the list because no more entry points will be evaluated after it.

Example:

switch value {
case 0:
    // Script to be executed when value == 0
case 1:
    // Script to be executed when value == 0 or value == 1
default:
    // Script to be executed in any case
}

The execution of the part of the script can be stopped with the break keyword. In this case, the execution will continue with the first instruction after the block of the switch statement.

Example:

switch value {
case 0:
    // Script to be executed when value == 0
    break
case 1:
    // Script to be executed when value == 1
    break
case 2:
    // Script to be executed when value == 2
}

Loop control structures

Loop control structures allow you to create a block of script that can be re-executed several times depending on some conditions. Each block of a loop control structure provides two features:

The execution of the part of the script can be stopped with the break keyword. In this case, the execution will continue with the first instruction after the block of the statement.

Example:

for i in values {
    if i is none {
        break
    }
    // Script to be executed with the new value of i while i is not none
}

The execution of the part of the script can go to the next loop statement with the continue keyword. In this case, the execution will continue as if the end of the block was reached.

Example:

while value != expected {
    if value < 0 {
        // Script to be executed to fix the value of value
        continue
    }
    // Script to be executed while value != expected
}

The while statement

The while statement allows you to re-execute a part of the script while a condition remains true.

It is introduced by the while keyword followed by an expression. The statement opens a block of script that is executed while the expression evaluates to true.

Note

The expression is considered inside the opened block by the let keyword.

The while statement uses the same kinds of expressions as the if statement.

Example:

while value > 10 {
    // Script to be executed while value > 10
}

while 'e' in str {
    // Script to be executed while str contains 'e'
}

while 5 not in values {
    // Script to be executed while values does not contain 5
}

The for statement

The for statement allows you to re-execute a part of the script for each element of an object.

It is introduced by the for keyword followed by a symbol name, the in operator, and an expression. The statement opens a block of script that is executed for each element found in the object given by the expression on the right side of the in operator.

Note

The expression on the right side of the in operator is considered inside the opened block by the let keyword. The expression on the left side of the in operator is considered like inside a virtual block around the loop's structure by the let keyword.

The symbol between the for keyword and the in operator is used to store the current element. These elements must be provided by an iterator. If the result of the expression is not an iterator, the in method of the given object is called to get an iterator.

Important

If the object given by the expression does not overload the in method, the object is cast to an iterator to iterate over it. If the method exists but the value returned by the method is not an iterator, the result is also cast to an iterator to iterate over it.

Example:

for i in 0...count {
    // Script to be executed with the new value of i
}

The for statement can also use several symbols separated by ,. In this case, a temporary iterator will be created with each symbol, and the := method will be used to get the element. This behavior allows you to get each sub-element of an iterator element of the object stored in a different symbol. This is useful to iterate over a hash.

Example:

for key, value in dict {
    // Script to be executed with the new values of key and value
}

The custom for statement

The custom for statement allows you to re-execute a part of the script for each element of an object that cannot be browsed with an iterator.

It is introduced by the for keyword followed by a custom range description. The statement opens a block of script that is executed for each element found by the custom range.

A custom range description starts with a ( and ends with a ) and contains three steps separated by ,:

  • The initialization step, executed before the first execution of the loop.
  • The update step, executed before each next execution of the loop.
  • The end check step, executed after the initialization/update step to check the end of the loop.

Note

The custom range update and end check steps are considered inside the opened block by the let keyword. The custom range initialization step is considered like inside a virtual block around the loop's structure by the let keyword.

Example:

for (pos = str.indexOf(c), pos = str.indexOf(c, pos + 1), defined pos) {
    // Script to be executed with the new value of pos
}

Tip

The custom for statement can also be used to reproduce the behavior of the "do while" structure of C.

Example:

for (do = true, do = not obj.isOver(), do) {
    obj.perform()
}

Generator expressions

Each conditional or loop control structure can be preceded by a move assignment or a copy assignment operation to create a generator expression. In this case, the result of each statement in the structure's block will be yielded to an iterator, which will then be used as the right side of the operation. This is the same behavior as if the control structure were in a generator function with a yield keyword before each line.

Example:

let var foo = for let var i in myList {
    func1(i)
    func2(i)
    func3(i)
}

// Is equivalent to

let var foo = def [...] {
    for let var i in myList {
        yield func1(i)
        yield func2(i)
        yield func3(i)
    }
} ()

This control structure can also be used between [ and ] tokens to generate an array. In this case, each value of the generated iterator is expanded to set up the array as if the unpack operator was used.

Print control structures

The print statement

The print statement allows you to send each value returned by a part of the script to the standard output.

It is introduced by the print keyword. The statement opens a block of script. Each value obtained in this block is sent to the standard output.

Example:

print {
    1 + 1               // Prints 2 to the standard output
    func()              // Prints the result of func() to the standard output
    for line in lines {
        line            // Prints the content of line to the standard output
    }
}

Important

A custom conversion mechanism is used to convert the value to a string printable on the output. To ensure the format of the value, it is recommended to perform the conversion to string explicitly.

The parametrized print statement

The parametrized print statement allows you to send each value returned by a part of the script to a custom output.

It is introduced by the print keyword followed by a custom output description. The statement opens a block of script. Each value obtained in this block is sent to the custom output.

A custom output description starts with a ( and ends with a ) and contains an expression giving the custom output object. If the value returned is a number or a string, a minimal file printer is created with the given file descriptor or file path. Otherwise, the write method of the object is called with each value to perform the print.

Example:

print (2) {
    // Script to be executed to print data on the error output
}

print (obj) {
   'value'  // Equivalent to obj.write('value')
}

Note

The module system.terminal also provides tools to perform extended print operations on a terminal.

Exception handling control structures

The try statement

The try statement allows you to specify a part of the script that will be aborted if an exception is raised.

It is introduced by the try keyword. The statement opens a block of script that could raise exceptions.

Example:

try {
    // Script that could raise exceptions
}

If an exception is raised in a try statement, the execution of the script will continue with the first instruction after the block of the statement. Exceptions raised inmodule loading or a function call are also handled.

An exception is raised with the raise keyword followed by an expression. The expression allows you to create an object that will describe the context of the exception.

Example:

try {
    // ...
    if error {
        raise ErrorException(error)
    }
    // ...
}

If an exception is raised outside of a try statement, the context of the exception will be printed on the error output, and the execution of the script will be stopped as if an error occurred. To print the context of the exception, the show method of the context object is called. If the context object does not implement this method, the value of the object is printed instead.

The catch statement

The catch statement allows you to execute a part of the script if an exception is raised in a try statement.

It is introduced by the catch keyword followed by a symbol name. The statement opens a block of script that is executed if an exception was raised in the previous try statement. The symbol is used to store the context of the exception.

Example:

try {
    // Script that could raise exceptions
} catch e {
    // Script to recover a normal state after the e exception
}

Caution

Inserting a new line between the } and the catch keyword is a syntax error. The catch statement must follow immediately. This prevents some invalid states in the interactive mode.


« Type casting   Function definition »
⚠️ **GitHub.com Fallback** ⚠️