Esta página aún no está traducida al español. Leer la versión en inglés

Statements

Every statement of Antril - blocks, local declarations, if, the forms of loop, switch, try, throw, return, break and continue, checked, region, unsafe and delete.

Última actualización: 11 min de lectura Editar en GitHub

En esta página

A function's body is a block of statements. This page lists every statement the compiler accepts. Expressions are described in Expressions and patterns in Patterns.

Statement Form
Block { statements }
Empty ;
Local declaration T name = value;, T a, b = 2;, const T name = value;
Expression expression; (a call, an assignment, ++x, await t…)
if if (condition) statement [else statement]
loop six forms: see loop
do do statement loop (condition);
static loop static loop (E in T) statement
switch switch (value) { pattern => statement … }
try try { } catch (T e) { } finally { }
throw throw value;, throw;
return return;, return value;
break, continue break;, continue;
yield yield value;, yield break; (in iterators)
checked, unchecked checked { … }, unchecked { … }
region region { … }
unsafe unsafe { … }
delete delete value;
effect effect { … }

Blocks

A block { … } groups statements and opens a scope: a local declared inside it is not seen after the }. Wherever a statement is expected, a single statement can stand without braces:

Antril
if (ready)
	Start();

A lone ; is an empty statement.

Local declarations

A local variable is declared with its type first, then its name and an optional value. Several locals of one type share a declaration, each with its own value or none:

Antril
i32 count = 0;
i32 width = 4, height = 3;
i32 a, b = 2;      // a starts at 0
  • A local of a type that has a zero value (numbers, bool, enums, value types, nullable types) starts at that value when it has no initializer.
  • A local of a class or str needs a value: C c; is AN2016 (c needs a value: a C has no default). Declare it nullable (C? c;, null) or give it one.
  • The type is always written: there is no var for locals (var is only a pattern).
  • A name can be declared once in a function, including inner blocks: declaring x inside a block where an outer x is visible is AN2003. Two sibling blocks can each declare their own x.

const declares a local constant. Its value is computed when the program compiles, from literals, other constants and operators (see Members):

Antril
const i32 Limit = 3, Twice = Limit * 2;

Assigning a constant is AN2140.

Expression statements

An expression followed by ; is a statement: a call, an assignment (x = 1;, x += 2;, also chained: a = b = 4;), an increment (i++;), an await, or new of an object whose constructor does the work.

if

Antril
if (temperature > 30)
	Console.WriteLine("hot");
else if (temperature > 15)
	Console.WriteLine("mild");
else
	Console.WriteLine("cold");

The condition is a bool; an integer is not a condition (if (x) with i32 x is AN2084). An else belongs to the nearest if without one.

loop

loop is the only looping keyword. What is in its parentheses decides the form:

Form What it does
loop (T x in items) body Runs body for each element of an array, a string, a collection or an iterator.
loop (condition) body Runs while condition is true.
do body loop (condition); Runs body once, then while condition is true.
loop (T i = a..b) body i from a up to b, without b. a..=b includes b.
loop (T i = start; condition; step) body Declares i, runs while condition holds, evaluates step after each turn.
loop (T i = start) body Without end: i starts at start and goes up by one each turn, until a break or return.
AntrilRun
import System;

Main()
{
	loop (i32 i = 5..=7)
		Console.Write(i);
	Console.WriteLine();

	loop (i32 k = 0; k < 6; k += 2)
		Console.Write(k);
	Console.WriteLine();

	loop (i64 j = 10)
	{
		if (j > 12)
			break;
		Console.Write(j);
	}
	Console.WriteLine();

	List<i32> list = new List<i32>();
	list.Add(4);
	list.Add(5);
	loop (i32 x in list)
		Console.Write(x);
	Console.WriteLine();

	loop (u16 unit in "hey")
		Console.Write(unit + " ");
	Console.WriteLine();

	i32 n = 1;
	loop (n < 100)
		n *= 3;
	Console.WriteLine(n);

	do
		n -= 50;
	loop (n > 0);
	Console.WriteLine(n);
}
Terminal
larva run
567
024
101112
45
104 101 121 
243
-7
  • Elements. loop (T x in c) walks an array (each dimension in row order, for a multi-dimensional one), a string (its code units, as numbers), any collection with an Iterator() method (List<T>, Dictionary<K, V>, HashSet<T>…), and an Iterator<T> that a function gives with yield (see Iterators and async). The element type is written.
  • Ranges. The counter of a range or counter loop is an integer (AN2014 for anything else). The bounds are evaluated once. A range whose end is not above its start runs zero times: loop (i32 r = 3..0) does nothing.
  • C-style. The parser also accepts a comma between the condition and the step: loop (i32 k = 0; k < 6, k += 2). Write a ;.
  • The counter of every form is a new local, seen only inside the loop.

static loop

static loop (E in T) statement, inside a function whose last type parameter is a pack T..., repeats the statement once per type of the pack, when the program compiles. Inside, E is that type:

AntrilRun
import System;

Describe<T...>(T values) : str
{
	str text = "";
	static loop (E in T)
		text = text + typeof(E).Name + " ";
	return text;
}

Main()
{
	Console.WriteLine(Describe(1, "a", 2.5));
}
Terminal
larva run
Int32 String Float64 

A static loop among a type's members declares members instead; see Generics. from N (numbering the members) goes only on that form: in a body it is AN0036.

break and continue

break leaves the innermost loop or switch statement; continue goes to the next turn of the innermost loop. Outside them they are AN2010 and AN2011.

Inside a switch statement, break leaves the switch, not the loop around it, while continue goes on to the loop's next turn:

AntrilRun
import System;

Main()
{
	loop (i32 i = 0..5)
	{
		switch (i)
		{
			1 => continue;
			3 => break;
			_ => { }
		}
		Console.Write(i);
	}
	Console.WriteLine();
}
Terminal
larva run
0234

return

return value; leaves a function that has a result type; return; leaves one without. Returning a value from a function without a result is AN2009, and a function with a result whose end can be reached without return is AN2001. In an iterator, return; ends the sequence like yield break;.

A finally runs before the function returns.

switch

A switch statement matches a value against arms, in order, and runs the first arm whose pattern matches (and whose when condition holds):

AntrilRun
import System;

Main()
{
	loop (i32 n in [0, 3, 7, 12])
	{
		switch (n)
		{
			0 => Console.WriteLine("zero");
			1..5 =>
			{
				Console.Write("small ");
				Console.WriteLine(n);
			}
			> 10 => Console.WriteLine("big");
		}
	}
}
Terminal
larva run
zero
small 3
big
  • Each arm is pattern [when condition] => statement. The statement can be a block.
  • Arms end with ; (the statement's own end) or with ,.
  • When no arm matches, nothing runs: 7 above prints nothing. Add _ => … to handle the rest.
  • Every pattern form works; see Patterns.

The switch expression (value switch { … }) gives a value; see Expressions.

try, catch and finally

AntrilRun
import System;

Main()
{
	loop (i32 i = 0..3)
	{
		try
		{
			if (i == 0)
				throw new KeyNotFoundError();
			if (i == 1)
				throw new InvalidOperationError("bad state");
			Int32.Parse("x");
		}
		catch (KeyNotFoundError)
		{
			Console.WriteLine("missing key");
		}
		catch (InvalidOperationError e)
		{
			Console.WriteLine("invalid: " + e.Message);
		}
		catch
		{
			Console.WriteLine("anything else");
		}
	}
}
Terminal
larva run
missing key
invalid: bad state
anything else
  • try is followed by any number of catch clauses and an optional finally; at least one of them (AN0018).
  • catch (T name) handles exceptions of the class T and the classes derived from it. The name can be left out. T is an object type (AN2017).
  • catch without parentheses handles any exception.
  • The clauses are tried in order; the first that matches runs.
  • finally runs when the try ends in any way: normally, by an exception (caught or not), or by return, break or continue.

yield and await cannot go inside a catch (AN2113, AN2116). See Exceptions for declaring exception classes and what an uncaught exception does.

throw

throw value; throws an object of a class derived from System.Exception. A type parameter constrained with T : exception can be thrown too.

throw; inside a catch throws the exception being handled again; elsewhere it is AN2006.

Warning

Not yet available: throwing values that are not objects. throw 5; is AN2007 (only objects are thrown).

checked and unchecked

Integer arithmetic wraps around by default: Int32.MaxValue + 1 is Int32.MinValue. Inside checked { … }, an integer operation whose result does not fit its type throws OverflowError. unchecked { … } turns the check off again inside a checked block. Both also exist as expressions: checked(a + b).

AntrilRun
import System;

Main()
{
	i32 big = Int32.MaxValue;
	Console.WriteLine(big + 1);
	try
	{
		checked
		{
			i32 x = big + 1;
			Console.WriteLine(x);
		}
	}
	catch (OverflowError e)
	{
		Console.WriteLine("overflow: " + e.Message);
	}
}
Terminal
larva run
-2147483648
overflow: the number does not fit its type

region

region { … } frees the objects made inside it when the block ends, however it ends. It matters in projects built with gc: arena; see Memory.

unsafe

unsafe { … } allows pointers, addresses (&x) and reading through them (*p, p[i], p->field) inside the block. A project with unsafe: deny rejects it (AN1104). See Memory.

delete

delete obj; runs an object's destructor and frees it, in projects built with gc: manual. Its operand is an object (AN2012 otherwise). Write it inside unsafe code; see Memory.

yield

yield value; gives the next value of an iterator and yield break; ends it. They go in a function whose result is Iterator<T>; see Iterators and async.

effect

effect { … } as a statement starts an effect that runs now and again whenever a reactive value it read changes. Written as an expression, it gives the Effect so that it can be stopped. See Reactive values.

¿Te resultó útil esta página?

No se guarda ninguna dirección; tu nombre de usuario sí, si iniciaste sesión.

Esc