while-continue with labels and docs/tests
This commit is contained in:
parent
22fbd5584b
commit
ebeed385e9
@ -164,33 +164,6 @@ to call it:
|
|||||||
|
|
||||||
If you need to create _unnamed_ function, use alternative syntax (TBD, like { -> } ?)
|
If you need to create _unnamed_ function, use alternative syntax (TBD, like { -> } ?)
|
||||||
|
|
||||||
# Integral data types
|
|
||||||
|
|
||||||
| type | description | literal samples |
|
|
||||||
|--------|---------------------------------|---------------------|
|
|
||||||
| Int | 64 bit signed | `1` `-22` `0x1FF` |
|
|
||||||
| Real | 64 bit double | `1.0`, `2e-11` |
|
|
||||||
| Bool | boolean | `true` `false` |
|
|
||||||
| String | unicode string, no limits | "hello" (see below) |
|
|
||||||
| Void | no value could exist, singleton | void |
|
|
||||||
| Null | missing value, singleton | null |
|
|
||||||
| Fn | callable type | |
|
|
||||||
|
|
||||||
## String details
|
|
||||||
|
|
||||||
### String operations
|
|
||||||
|
|
||||||
Concatenation is a `+`: `"hello " + name` works as expected. No confusion.
|
|
||||||
|
|
||||||
### Literals
|
|
||||||
|
|
||||||
String literal could be multiline:
|
|
||||||
|
|
||||||
"Hello
|
|
||||||
World"
|
|
||||||
|
|
||||||
though multiline literals is yet work in progress.
|
|
||||||
|
|
||||||
# Flow control operators
|
# Flow control operators
|
||||||
|
|
||||||
## if-then-else
|
## if-then-else
|
||||||
@ -248,7 +221,7 @@ Why `void`? Because `break` drops out without the chute, not providing anything
|
|||||||
}
|
}
|
||||||
>>> too much
|
>>> too much
|
||||||
|
|
||||||
## Breaking nested loops
|
### Breaking nested loops
|
||||||
|
|
||||||
If you have several loops and want to exit not the inner one, use labels:
|
If you have several loops and want to exit not the inner one, use labels:
|
||||||
|
|
||||||
@ -268,6 +241,41 @@ If you have several loops and want to exit not the inner one, use labels:
|
|||||||
}
|
}
|
||||||
>>> 5/2 situation
|
>>> 5/2 situation
|
||||||
|
|
||||||
|
### and continue
|
||||||
|
|
||||||
|
We can skip the rest of the loop and restart it, as usual, with `continue` operator.
|
||||||
|
|
||||||
|
var count = 0
|
||||||
|
var countEven = 0
|
||||||
|
while( count < 10 ) {
|
||||||
|
count = count + 1
|
||||||
|
if( count % 2 == 1) continue
|
||||||
|
countEven = countEven + 1
|
||||||
|
}
|
||||||
|
"found even numbers: " + countEven
|
||||||
|
>>> found even numbers: 5
|
||||||
|
|
||||||
|
`continue` can't "return" anything: it just restarts the loop. It can use labeled loops to restart outer ones:
|
||||||
|
|
||||||
|
var count = 0
|
||||||
|
var total = 0
|
||||||
|
// notice the label:
|
||||||
|
outerLoop@ while( count < 5 ) {
|
||||||
|
count = count + 1
|
||||||
|
var innerCount = 0
|
||||||
|
while( innerCount < 10 ) {
|
||||||
|
innerCount = innerCount + 1
|
||||||
|
if( innerCount == 10 )
|
||||||
|
continue@outerLoop
|
||||||
|
}
|
||||||
|
// we don't reach it because continue above restarts our loop
|
||||||
|
total = total + 1
|
||||||
|
}
|
||||||
|
total
|
||||||
|
>>> 0
|
||||||
|
|
||||||
|
Notice that `total` remains 0 as the end of the outerLoop@ is not reachable: `continue` is always called and always make Ling to skip it.
|
||||||
|
|
||||||
The label can be any valid identifier, even a keyword, labels exist in their own, isolated world, so no risk of occasional clash. Labels are also scoped to their context and do not exist outside it.
|
The label can be any valid identifier, even a keyword, labels exist in their own, isolated world, so no risk of occasional clash. Labels are also scoped to their context and do not exist outside it.
|
||||||
|
|
||||||
# Comments
|
# Comments
|
||||||
@ -276,4 +284,31 @@ The label can be any valid identifier, even a keyword, labels exist in their own
|
|||||||
var result = null // here we will store the result
|
var result = null // here we will store the result
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
|
# Integral data types
|
||||||
|
|
||||||
|
| type | description | literal samples |
|
||||||
|
|--------|---------------------------------|---------------------|
|
||||||
|
| Int | 64 bit signed | `1` `-22` `0x1FF` |
|
||||||
|
| Real | 64 bit double | `1.0`, `2e-11` |
|
||||||
|
| Bool | boolean | `true` `false` |
|
||||||
|
| String | unicode string, no limits | "hello" (see below) |
|
||||||
|
| Void | no value could exist, singleton | void |
|
||||||
|
| Null | missing value, singleton | null |
|
||||||
|
| Fn | callable type | |
|
||||||
|
|
||||||
|
## String details
|
||||||
|
|
||||||
|
### String operations
|
||||||
|
|
||||||
|
Concatenation is a `+`: `"hello " + name` works as expected. No confusion.
|
||||||
|
|
||||||
|
### Literals
|
||||||
|
|
||||||
|
String literal could be multiline:
|
||||||
|
|
||||||
|
"Hello
|
||||||
|
World"
|
||||||
|
|
||||||
|
though multiline literals is yet work in progress.
|
||||||
|
|
||||||
|
|
||||||
|
@ -305,6 +305,7 @@ class Compiler {
|
|||||||
"var" -> parseVarDeclaration(id.value, true, cc)
|
"var" -> parseVarDeclaration(id.value, true, cc)
|
||||||
"while" -> parseWhileStatement(cc)
|
"while" -> parseWhileStatement(cc)
|
||||||
"break" -> parseBreakStatement(id.pos, cc)
|
"break" -> parseBreakStatement(id.pos, cc)
|
||||||
|
"continue" -> parseContinueStatement(id.pos, cc)
|
||||||
"fn", "fun" -> parseFunctionDeclaration(cc)
|
"fn", "fun" -> parseFunctionDeclaration(cc)
|
||||||
"if" -> parseIfStatement(cc)
|
"if" -> parseIfStatement(cc)
|
||||||
else -> null
|
else -> null
|
||||||
@ -388,6 +389,27 @@ class Compiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun parseContinueStatement(start: Pos, cc: CompilerContext): Statement {
|
||||||
|
val t = cc.next()
|
||||||
|
|
||||||
|
val label = if (t.pos.line != start.line || t.type != Token.Type.ATLABEL) {
|
||||||
|
cc.previous()
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
t.value
|
||||||
|
}?.also {
|
||||||
|
// check that label is defined
|
||||||
|
cc.ensureLabelIsValid(start, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
return statement(start) {
|
||||||
|
throw LoopBreakContinueException(
|
||||||
|
doContinue = true,
|
||||||
|
label = label,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun ensureRparen(tokens: CompilerContext): Pos {
|
private fun ensureRparen(tokens: CompilerContext): Pos {
|
||||||
val t = tokens.next()
|
val t = tokens.next()
|
||||||
if (t.type != Token.Type.RPAREN)
|
if (t.type != Token.Type.RPAREN)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user