diff --git a/src/Lean/Elab/Do.lean b/src/Lean/Elab/Do.lean index df48ce3f3b..f1638229a8 100644 --- a/src/Lean/Elab/Do.lean +++ b/src/Lean/Elab/Do.lean @@ -1301,9 +1301,41 @@ def doUnlessToCode (doSeqToCode : List Syntax → M CodeBlock) (doUnless : Synta def doFor := parser! "for " >> sepBy1 doForDecl ", " >> "do " >> doSeq ``` -/ def doForToCode (doSeqToCode : List Syntax → M CodeBlock) (doFor : Syntax) (doElems : List Syntax) : M CodeBlock := do - let doForDecls := doFor[1].getArgs + let doForDecls := doFor[1].getSepArgs if doForDecls.size > 1 then - throwError! "parallel 'do' not implemented yet" + /- + Expand + ``` + for x in xs, y in ys do + body + ``` + into + ``` + let s := toStream ys + for x in xs do + match Stream.next? s with + | none => break + | some (y, s') => + s := s' + body + ``` + -/ + -- Extract second element + let doForDecl := doForDecls[1] + let y := doForDecl[0] + let ys := doForDecl[2] + let doForDecls := doForDecls.eraseIdx 1 + let body := doFor[3] + withFreshMacroScope do + let auxDo ← + `(do let mut s := toStream $ys + for $doForDecls:doForDecl,* do + match Stream.next? s with + | none => break + | some ($y, s') => + s := s' + do $body) + doSeqToCode (getDoSeqElems (getDoSeq auxDo) ++ doElems) else let ref := doFor let x := doForDecls[0][0] diff --git a/tests/lean/run/forParallel.lean b/tests/lean/run/forParallel.lean new file mode 100644 index 0000000000..656a52f8e3 --- /dev/null +++ b/tests/lean/run/forParallel.lean @@ -0,0 +1,6 @@ +-- set_option trace.Elab true +def f (xs : Array Nat) (ys : List (Nat × Nat)) (s : String) : IO Unit := do + for x in xs, (y₁, y₂) in ys, c in s do + IO.println s!"x: {x}, y₁: {y₁}, y₂: {y₂}, c: {c}" + +#eval f #[1, 2, 3, 4] [(5, 15), (6, 16), (7, 17)] "hello"