Skip to content

Commit

Permalink
Labelled break/continue with
Browse files Browse the repository at this point in the history
  • Loading branch information
edemaine committed Sep 12, 2024
1 parent 9a17989 commit 2f80bed
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 17 deletions.
10 changes: 10 additions & 0 deletions civet.dev/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,16 @@ found :=
process item
</Playground>
<Playground>
function process(lists)
:outer for list of lists
for item of list
if item is "abort"
break outer with item
if item is "length"
continue :outer with list.length
</Playground>
## Other Blocks
### Try Blocks
Expand Down
8 changes: 7 additions & 1 deletion source/parser.hera
Original file line number Diff line number Diff line change
Expand Up @@ -4224,7 +4224,11 @@ LabelledStatement
Label
# NOTE: `:label` instead of `label:` to not clash with implicit object literal
Colon:colon Identifier:id Whitespace:w ->
return [ id, colon, w ]
return {
type: "Label",
name: id.name,
children: [ id, colon, w ]
}

# Argument to break/continue, which can include colon or not in input,
# but should not have colon in output
Expand Down Expand Up @@ -5058,6 +5062,7 @@ KeywordStatement
})
return {
type: "BreakStatement",
label: $2?.[1],
with: $3?.[2],
children,
}
Expand All @@ -5082,6 +5087,7 @@ KeywordStatement
})
return {
type: "ContinueStatement",
label: $2?.[1],
with: $3?.[2],
children,
}
Expand Down
28 changes: 17 additions & 11 deletions source/parser/function.civet
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
IterationExpression
IterationFamily
IterationStatement
LabeledStatement
LabelledStatement
Parameter
ParametersNode
StatementTuple
Expand Down Expand Up @@ -268,7 +268,7 @@ function assignResults(node: StatementTuple[] | ASTNode, collect: (node: ASTNode
outer := exp
{type} .= exp
if type is "LabelledStatement"
exp = (exp as LabeledStatement).statement
exp = exp.statement
{type} = exp

switch type
Expand Down Expand Up @@ -369,7 +369,7 @@ function insertReturn(node: ASTNode, outerNode: ASTNode = node): void
outer := exp
{type} .= exp
if type is "LabelledStatement"
exp = (exp as LabeledStatement).statement
exp = exp.statement
{type} = exp

switch type
Expand Down Expand Up @@ -464,14 +464,20 @@ function processBreakContinueWith(statement: IterationStatement | ForStatement):
// break with <expr> overwrites the results of the loop
// continue with <expr> appends to the results of the loop
if control.with
// Verify there wasn't another loop or switch in between
{ancestor} := findAncestor control,
(s: ASTNodeObject): s is IterationStatement | ForStatement | SwitchStatement => (or)
s is statement
s.type is "IterationStatement"
s.type is "ForStatement"
s.type is "SwitchStatement" and control.type is "BreakStatement"
continue unless ancestor is statement
if control.label
continue unless statement.parent is like {
type: "LabelledStatement"
label: { name: ^control.label.name }
}
else
// Verify there wasn't another loop or switch in between
{ancestor} := findAncestor control,
(s: ASTNodeObject): s is IterationStatement | ForStatement | SwitchStatement => (or)
s is statement
s.type is "IterationStatement"
s.type is "ForStatement"
s.type is "SwitchStatement" and control.type is "BreakStatement"
continue unless ancestor is statement

control.children.unshift
if control.type is "BreakStatement"
Expand Down
17 changes: 13 additions & 4 deletions source/parser/types.civet
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type StatementNode =
| ForStatement
| IfStatement
| IterationStatement
| LabeledStatement
| LabelledStatement
| ReturnStatement
| SwitchStatement
| ThrowStatement
Expand Down Expand Up @@ -79,6 +79,7 @@ export type OtherNode =
| FinallyClause
| Index
| Initializer
| Label
| ObjectBindingPattern
| Parameter
| ParametersNode
Expand Down Expand Up @@ -289,6 +290,7 @@ export type BreakStatement
children: Children
parent?: Parent
with: ASTNode?
label: Label?

export type ComptimeStatement
type: "ComptimeStatement"
Expand All @@ -308,6 +310,7 @@ export type ContinueStatement
parent?: Parent
special?: "switch"
with: ASTNode?
label: Label?

export type DoStatement
type: "DoStatement"
Expand Down Expand Up @@ -360,13 +363,19 @@ export type DefaultClause
children: Children
block: BlockStatement

export type LabeledStatement
type: "LabeledStatement"
label: ASTNode
export type LabelledStatement
type: "LabelledStatement"
label: Label
statement: ASTNodeBase
children: Children
parent?: Parent

export type Label
type: "Label"
children: Children
parent?: Parent
name: string

export type AccessStart
type: "AccessStart"
children: Children
Expand Down
2 changes: 1 addition & 1 deletion source/parser/util.civet
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ statementTypes := new Set [
"ForStatement"
"IfStatement"
"IterationStatement"
"LabeledStatement"
"LabelledStatement"
"ReturnStatement"
"SwitchStatement"
"ThrowStatement"
Expand Down
29 changes: 29 additions & 0 deletions test/for.civet
Original file line number Diff line number Diff line change
Expand Up @@ -826,3 +826,32 @@ describe "for", ->
};return results;
}
"""

testCase """
labelled break/continue with
---
function f(arrays)
:outer for array of arrays
:inner for item of array
break :outer with [] if item is "ABORT"
continue outer with [] if item is "SKIP"
break inner with [] if item is "abort"
continue :outer with [] if item is "skip"
break with [] if item is "abort"
continue with [] if item is "skip"
item * item
---
function f(arrays) {
let results;results=[];outer: for (const array of arrays) {
let results1;results1=[];inner: for (const item of array) {
if (item === "ABORT") { results = [];break outer }
if (item === "SKIP") { results.push([]);continue outer }
if (item === "abort") { results1 = [];break inner }
if (item === "skip") { results.push([]);continue outer }
if (item === "abort") { results1 = [];break }
if (item === "skip") { results1.push([]);continue }
results1.push(item * item)
}results.push(results1)
};return results;
}
"""

0 comments on commit 2f80bed

Please sign in to comment.