git.iko.soy/rowtype-yoga/purescm
on bytevector help sign in
Unify the two conds generated by case binders and guards
commit849a1f82025e961658d15dcc35d9055cd7c895b9 authorFabrizio Ferrai <fabrizio.ferrai@gmail.com> dateMon 25 Oct 2021, 12:42 (5 years ago) parent8b59a45
6 files changed+84−36
src/Language/PureScript/Scheme/CodeGen/Transpiler.hs+22−19 test/resources/purescript/src/PureScheme/Test/Guard/Take.purs+14 test/resources/scheme/PureScheme.Test.Binder.Guard/lib.sls+3−6 test/resources/scheme/PureScheme.Test.Guard.GCD/lib.sls+3−6 test/resources/scheme/PureScheme.Test.Guard.Min/lib.sls+2−5 test/resources/scheme/PureScheme.Test.Guard.Take/lib.sls+40
src/Language/PureScript/Scheme/CodeGen/Transpiler.hs+22−19
@@ -235,32 +235,34 @@ moduleToLibrary (Module _sourceSpan _comments moduleName _path
235235 caseToScheme values caseAlternatives =
236236 cond clauses
237237 where
238− clauses = map condClause alternatives
238+ clauses = concatMap condClause alternatives
239239 alternatives = toAlternatives values caseAlternatives
240240
241− -- Emit a pair (condition, result) for each case alternative to be used
242− -- by cond.
243− condClause :: Alternative -> (SExpr, SExpr)
241+ -- Emit a list of pairs (condition, result) for each case alternative to be used
242+ -- by cond. Every case alternative can produce multiple of them because there
243+ -- might be multiple guards for each of them.
244+ condClause :: Alternative -> [(SExpr, SExpr)]
244245
245− -- If the result is a guarded expression then the result of the clause
246− -- is a nested cond expression.
246+ -- If the result is a guarded expression then we concatenate the guard
247+ -- conditions to the conditions for the alternative.
247248 condClause (Alternative boundValues (Left guardedExprs))
248− = ( test boundValues
249− , cond $ map guardedExprToClause guardedExprs
250− )
249+ = map guardedExprToClause guardedExprs
251250 where
252251 guardedExprToClause :: GuardedExpr -> (SExpr, SExpr)
253252 guardedExprToClause (guard, result)
254− = ( replaceVariables (exprToScheme guard)
255− (variablesToReplace boundValues)
256− , replaceVariables (exprToScheme result)
257− (variablesToReplace boundValues)
253+ = ( test boundValues $ Just $
254+ replaceVariables
255+ (exprToScheme guard)
256+ (variablesToReplace boundValues)
257+ , replaceVariables
258+ (exprToScheme result)
259+ (variablesToReplace boundValues)
258260 )
259261
260262 -- If the result is a simple expression then the result is just the
261263 -- expression.
262264 condClause (Alternative boundValues (Right result))
263− = (test boundValues, bindersToResult boundValues result)
265+ = [(test boundValues Nothing, bindersToResult boundValues result)]
264266
265267 -- Emit the test for a cond clause.
266268 -- In scheme: (cond ((and test1a test1b) result1) ...)
@@ -285,11 +287,12 @@ moduleToLibrary (Module _sourceSpan _comments moduleName _path
285287 -- (cond ((and (eq? (car v) 'Foo) cond1) result1)
286288 -- ((and (eq? (car v) 'Foo) cond2)) result2)
287289 -- TODO: Maybe we should avoid the repeating of the first check.
288− test :: [(Expr Ann, Binder Ann)] -> SExpr
289− test valueAndBinders =
290− and_ (concatMap (\(value, binder) -> binderToTest (exprToScheme value)
291− binder)
292− valueAndBinders)
290+ test :: [(Expr Ann, Binder Ann)] -> Maybe SExpr -> SExpr
291+ test valueAndBinders maybeGuard = and_ $
292+ concatMap (\(value, binder) -> binderToTest (exprToScheme value) binder) valueAndBinders
293+ <> case maybeGuard of
294+ Nothing -> []
295+ Just g -> [g]
293296
294297 -- Emit a cond clause test for each value and binder.
295298 -- E.g.: (value: 23, binder: 42) -> (= 23 42)
test/resources/purescript/src/PureScheme/Test/Guard/Take.pursnew file+14
@@ -0,0 +1,14 @@
1+module PureScheme.Test.Guard.Take where
2+
3+import Prelude
4+
5+data List a = Nil | Cons a (List a)
6+
7+infixr 6 Cons as :
8+
9+take :: forall a. Int -> List a -> List a
10+take = go Nil
11+ where
12+ go acc n _ | n < 1 = acc
13+ go acc _ Nil = acc
14+ go acc n (x : xs) = go (x : acc) (n - 1) xs
test/resources/scheme/PureScheme.Test.Binder.Guard/lib.sls+3−6
@@ -17,11 +17,8 @@
1717 (scm:lambda
1818 (a)
1919 (scm:cond
20− ((scm:= v 1)
21− (scm:cond
22− ((((Data.Eq.eq Data.Eq.eqInt) a) 2) 3)
23− ((((Data.Eq.eq Data.Eq.eqInt) a) 4) 5)
24− (Data.Boolean.otherwise 6)
25− (scm:else (scm:error #f "Failed pattern match"))))
20+ ((scm:and (scm:= v 1) (((Data.Eq.eq Data.Eq.eqInt) a) 2)) 3)
21+ ((scm:and (scm:= v 1) (((Data.Eq.eq Data.Eq.eqInt) a) 4)) 5)
22+ ((scm:and (scm:= v 1) Data.Boolean.otherwise) 6)
2623 (scm:else (scm:error #f "Failed pattern match")))))))
2724 )
test/resources/scheme/PureScheme.Test.Guard.GCD/lib.sls+3−6
@@ -18,11 +18,8 @@
1818 (scm:cond
1919 ((scm:= v1 0) v)
2020 ((scm:= v 0) v1)
21− (#t
22− (scm:cond
23− ((((Data.Ord.greaterThan Data.Ord.ordInt) v) v1)
24− ((gcd (scm:fx- v v1)) v1))
25− (Data.Boolean.otherwise ((gcd v) (scm:fx- v1 v)))
26− (scm:else (scm:error #f "Failed pattern match"))))
21+ ((((Data.Ord.greaterThan Data.Ord.ordInt) v) v1)
22+ ((gcd (scm:fx- v v1)) v1))
23+ (Data.Boolean.otherwise ((gcd v) (scm:fx- v1 v)))
2724 (scm:else (scm:error #f "Failed pattern match"))))))
2825 )
test/resources/scheme/PureScheme.Test.Guard.Min/lib.sls+2−5
@@ -15,10 +15,7 @@
1515 (scm:lambda
1616 (m)
1717 (scm:cond
18− (#t
19− (scm:cond
20− ((scm:fx<? n m) n)
21− (Data.Boolean.otherwise m)
22− (scm:else (scm:error #f "Failed pattern match"))))
18+ ((scm:fx<? n m) n)
19+ (Data.Boolean.otherwise m)
2320 (scm:else (scm:error #f "Failed pattern match"))))))
2421 )
test/resources/scheme/PureScheme.Test.Guard.Take/lib.slsnew file+40
@@ -0,0 +1,40 @@
1+(library
2+ (PureScheme.Test.Guard.Take lib)
3+ (export Nil Cons take)
4+ (import
5+ (prefix (rnrs) scm:)
6+ (prefix (Data.Ord lib) Data.Ord.)
7+ (prefix (Data.Ring lib) Data.Ring.)
8+ (prefix (Prelude lib) Prelude.))
9+
10+
11+ (scm:define Nil (scm:cons (scm:quote Nil) (scm:vector)))
12+
13+ (scm:define
14+ Cons
15+ (scm:lambda
16+ (value0)
17+ (scm:lambda
18+ (value1)
19+ (scm:cons (scm:quote Cons) (scm:vector value0 value1)))))
20+
21+ (scm:define
22+ take
23+ (scm:letrec*
24+ ((go
25+ (scm:lambda
26+ (acc)
27+ (scm:lambda
28+ (v)
29+ (scm:lambda
30+ (v1)
31+ (scm:cond
32+ ((scm:fx<? v 1) acc)
33+ ((scm:eq? (scm:car v1) (scm:quote Nil)) acc)
34+ ((scm:eq? (scm:car v1) (scm:quote Cons))
35+ (((go ((Cons (scm:vector-ref (scm:cdr v1) 0)) acc))
36+ (scm:fx- v 1))
37+ (scm:vector-ref (scm:cdr v1) 1)))
38+ (scm:else (scm:error #f "Failed pattern match"))))))))
39+ (go Nil)))
40+ )