From 37f9cc184f0fff9d7b4c62aefc56fcecd2588d11 Mon Sep 17 00:00:00 2001 From: Yu Zhang Date: Wed, 25 Dec 2024 19:03:31 +0800 Subject: [PATCH] add loop label --- next/language/fundamentals.md | 11 +++++ next/sources/language/src/controls/top.mbt | 48 +++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/next/language/fundamentals.md b/next/language/fundamentals.md index d9741bfe..e13849c4 100644 --- a/next/language/fundamentals.md +++ b/next/language/fundamentals.md @@ -779,6 +779,17 @@ A functional loop consumes arguments and returns a value. It is defined using th Currently in `loop exprs { ... }`, `exprs` is nonempty list, while `for { ... }` is accepted for infinite loop. ``` +### Labelled Continue/Break + +When a loop is labelled, it can be referenced from a `break` or `continue` from +within a nested loop. For example: + +```{literalinclude} /sources/language/src/controls/top.mbt +:language: moonbit +:start-after: start loop label +:end-before: end loop label +``` + ## Iterator An iterator is an object that traverse through a sequence while providing access diff --git a/next/sources/language/src/controls/top.mbt b/next/sources/language/src/controls/top.mbt index 768859cc..6b4cc9d5 100644 --- a/next/sources/language/src/controls/top.mbt +++ b/next/sources/language/src/controls/top.mbt @@ -1,3 +1,4 @@ +///| fn a() -> Int { let x = 1 let y = 1 @@ -16,6 +17,7 @@ fn a() -> Int { // end conditional expressions 1 } +///| fn c() -> Unit { let size = 0 // start conditional expressions 3 @@ -108,6 +110,7 @@ test "for loop 1" (t : @test.T) { t.snapshot!(filename="for_loop_1") } +///| fn d() -> Unit { // start for loop 2 for i = 0, j = 0; i + j < 100; i = i + 1, j = j + 1 { @@ -116,6 +119,7 @@ fn d() -> Unit { // end for loop 2 } +///| fn infinite_loop() -> Unit { // start for loop 3 for i = 1; ; i = i + 1 { @@ -143,6 +147,7 @@ test "for loop 4" (t : @test.T) { t.snapshot!(filename="for_loop_4") } +///| fn e() -> Unit { // start for loop 5 for x in [1, 2, 3] { @@ -211,7 +216,6 @@ test { i += j } assert_eq!(i, 45) - let mut k = 0 for l in 0..=10 { k += l @@ -220,7 +224,42 @@ test { } // end for loop 10 +// start loop label +test "break label" { + let mut count = 0 + let xs = [1, 2, 3] + let ys = [4, 5, 6] + let res = outer~: for i in xs { + for j in ys { + count = count + i + break outer~ j + } + } else { + -1 + } + assert_eq!(res, 4) + assert_eq!(count, 1) +} + +test "continue label" { + let mut count = 0 + let init = 10 + let res =outer~: loop init { + 0 => 42 + i => { + for { + count = count + 1 + continue outer~ i - 1 + } + } + } + assert_eq!(res, 42) + assert_eq!(count, 10) +} +// end loop label + // start guard 1 +///| fn guarded_get(array : Array[Int], index : Int) -> Int? { guard index >= 0 && index < array.length() else { None } Some(array[index]) @@ -231,17 +270,20 @@ test { } // end guard 1 +///| fn process(string : String) -> String { string } // start guard 2 +///| enum Resource { Folder(Array[String]) PlainText(String) JsonConfig(Json) } +///| fn getProcessedText( resources : Map[String, Resource], path : String @@ -255,6 +297,7 @@ fn getProcessedText( } // end guard 2 +///| fn g() -> Unit { let condition = true let expr = Some(5) @@ -266,6 +309,7 @@ fn g() -> Unit { } // start match 1 +///| fn decide_sport(weather : String, humidity : Int) -> String { match weather { "sunny" => "tennis" @@ -277,4 +321,4 @@ fn decide_sport(weather : String, humidity : Int) -> String { test { assert_eq!(decide_sport("sunny", 0), "tennis") } -// end match 1 \ No newline at end of file +// end match 1