Control flow
Raven is expression-oriented, but it also supports statement-form control flow for running code in order, repeating work, and leaving a block early.
Expression and statement context
Every occurrence of code appears in either an expression context or a statement context.
Concept
- An expression context expects a value.
- A statement context expects an action rather than a value.
- Expressions are valid in statement context; their values are discarded unless captured.
- Some constructs are statement-only because they do not yield a value.
Example
val value = if flag { 1 } else { 2 }
if flag {
Log("side effect")
}
Rules
- Expression contexts include assignment right-hand sides, invocation
arguments,
matchscrutinees and arms,ifexpression branches, and the final position of a block expression. - Statement contexts include block bodies before the final expression, method bodies, accessor bodies, and any location terminated by a newline or semicolon.
- Statement-form
return,yield return,yield break,break,continue, statement-formthrow, and statement-formtryare valid only in statement context. - Statements are terminated by a newline, an optional semicolon,
}, or a construct-closing keyword such aselse,catch, orfinally. - Newlines inside parentheses, brackets, or braces do not terminate statements.
- End-of-file fulfills the same terminating role as a newline.
When extra tokens remain on the same line after a statement has already
completed, the parser reports RAV1019: Expected newline or ';' to terminate the statement.【F:src/Raven.CodeAnalysis/DiagnosticDescriptors.xml†L256-L262】 Insert
semicolons to separate statements intentionally written on one line or move the
remaining tokens to the following line.
System.Console.WriteLine("Examples") 42 // RAV1019
System.Console.WriteLine("Examples") ff; // RAV1019
var x = 2 test // RAV1019
Line continuations
Line continuation is layout-sensitive and uses at most one newline.
Concept
When the parser still expects more of the current expression, one newline is treated as continuation trivia instead of as a statement terminator.
Example
val sum =
1
+ offset
val labelled = 42 // comment stays with the literal
val next =
labelled
val chain = source
.Child
.SubChild
val first = source.Call()
.Ok // starts a new target-typed expression (blank line breaks continuation)
x
+ 2 // same expression
x
.Foo() // same expression
x
+ 2 // new statement
x
.Foo() // new statement (member binding / target-typed form)
val a = 42
val b = 1; b = 3
Rules
- One newline may continue the current expression.
- Two or more consecutive newlines always terminate the current expression statement.
- Continuation commonly occurs after assignment operators, before binary
operators, and before member access (
.or->). - Indentation on the continued line remains trivia and does not change the semantics of the continued expression.