From 506562e6ee2038cd0a408fb524fcb08834be133a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20G=C3=A9lineau?= Date: Tue, 3 Jan 2017 23:42:21 -0500 Subject: [PATCH 1/5] support infix data constructors using braces --- rascal-lib/rascal/private/adt.rkt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rascal-lib/rascal/private/adt.rkt b/rascal-lib/rascal/private/adt.rkt index aa69a22..f8ae98e 100644 --- a/rascal-lib/rascal/private/adt.rkt +++ b/rascal-lib/rascal/private/adt.rkt @@ -3,7 +3,7 @@ (require racket/require (only-in macrotypes/typecheck postfix-in)) (require (for-syntax (multi-in racket [base function format list match syntax]) - (multi-in syntax/parse [class/local-value experimental/specialize]) + (multi-in syntax/parse [class/local-value class/paren-shape experimental/specialize]) rascal/private/util/stx) (postfix-in - (multi-in racket [base function match splicing])) rascal/private/base @@ -40,6 +40,10 @@ #:attr [arg 1] '() #:attr len 0 #:attr nullary? #t] + [pattern (~braces ~! arg1 tag:id arg2) + #:attr [arg 1] (list #'arg1 #'arg2) + #:attr len 2 + #:attr nullary? #f] [pattern (tag:id arg ...+) #:attr len (length (attribute arg)) #:attr nullary? #f] From 31c48b8de6a60ea4d4d70d04f896b2cef9a2e64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20G=C3=A9lineau?= Date: Tue, 3 Jan 2017 23:56:09 -0500 Subject: [PATCH 2/5] use infix :: instead of cons everywhere To demonstrate that it's now possible to define infix data constructors. Note that infix pattern-matching is not supported yet, so we have to write [(:: x xs) body]. --- rascal-lib/rascal/prelude.rkt | 32 ++++++++++++------------ rascal-test/tests/rascal/integration.rkt | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/rascal-lib/rascal/prelude.rkt b/rascal-lib/rascal/prelude.rkt index c179b34..7220488 100644 --- a/rascal-lib/rascal/prelude.rkt +++ b/rascal-lib/rascal/prelude.rkt @@ -169,48 +169,48 @@ ;; --------------------------------------------------------------------------------------------------- (data (List a) - (cons a (List a)) + {a :: (List a)} nil) (instance (forall [a] (Eq a) => (Eq (List a))) [equal? (λ (x y) (case x - [(cons a as) (case y - [(cons b bs) (and (equal? a b) - (equal? as bs))] + [(:: a as) (case y + [(:: b bs) (and (equal? a b) + (equal? as bs))] [nil false])] [nil (case y - [(cons _ _) false] - [nil true])]))]) + [(:: _ _) false] + [nil true])]))]) (instance (forall [a] (Show a) => (Show (List a))) [show (λ (x) (case x - [(cons v vs) {"(cons " <> (show v) <> " " <> (show vs) <> ")"}] + [(:: v vs) {"{" <> (show v) <> " :: " <> (show vs) <> "}"}] [nil "nil"]))]) (def foldl : (forall [a b] (-> (-> b (-> a b)) (-> b (-> (List a) b)))) (λ (f acc lst) (case lst [nil acc] - [(cons x xs) (foldl f (f acc x) xs)]))) + [(:: x xs) (foldl f (f acc x) xs)]))) (def foldr : (forall [a b] (-> (-> a (-> b b)) (-> b (-> (List a) b)))) (λ (f acc lst) (case lst [nil acc] - [(cons x xs) (f x (foldr f acc xs))]))) + [(:: x xs) (f x (foldr f acc xs))]))) (instance (forall [a] (Semigroup (List a))) - [append (λ (xs ys) (foldr cons ys xs))]) + [append (λ (xs ys) (foldr :: ys xs))]) (def reverse : (forall [a] (-> (List a) (List a))) - (foldl (flip cons) nil)) + (foldl (flip ::) nil)) (instance (Functor List) - [map (λ (f) (foldl (λ (acc x) (cons (f x) acc)) nil))]) + [map (λ (f) (foldl (λ (acc x) {(f x) :: acc}) nil))]) (instance (Monad List) [join (λ (xss) (case xss - [nil nil] - [(cons ys yss) (case ys - [nil (join yss)] - [(cons z zs) (cons z (join (cons zs yss)))])]))]) + [nil nil] + [(:: ys yss) (case ys + [nil (join yss)] + [(:: z zs) {z :: (join {zs :: yss})}])]))]) diff --git a/rascal-test/tests/rascal/integration.rkt b/rascal-test/tests/rascal/integration.rkt index 1bc4dc0..cb00427 100644 --- a/rascal-test/tests/rascal/integration.rkt +++ b/rascal-test/tests/rascal/integration.rkt @@ -79,8 +79,8 @@ (check-typecheck-success (require rascal/prelude) (def x : (List String) - (cons "a" (cons "b" nil)))) + {"a" :: {"b" :: nil}})) (check-typecheck-success (require rascal/prelude) (def x : (List Integer) - (cons 1 (cons 2 nil))))))) + {1 :: {2 :: nil}}))))) From 55f666918e28d0213012eb235a918c7d2bce519c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20G=C3=A9lineau?= Date: Wed, 4 Jan 2017 00:02:53 -0500 Subject: [PATCH 3/5] support infix type constructors using braces I don't see any code in the prelude in which it would make sense to use this yet, so I won't demonstrate it there, but here's a small program demonstrating that it works: #lang rascal (data {a && b} {a & b}) (def mypair : {String && String} {"foo" & "bar"}) --- rascal-lib/rascal/private/adt.rkt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rascal-lib/rascal/private/adt.rkt b/rascal-lib/rascal/private/adt.rkt index f8ae98e..4e67f77 100644 --- a/rascal-lib/rascal/private/adt.rkt +++ b/rascal-lib/rascal/private/adt.rkt @@ -23,6 +23,10 @@ #:attr [arg 1] '() #:attr len 0 #:attr nullary? #t] + [pattern (~braces ~! arg1:id tag:id arg2:id) + #:attr [arg 1] (list #'arg1 #'arg2) + #:attr len 2 + #:attr nullary? #f] [pattern (tag:id arg:id ...+) #:attr len (length (attribute arg)) #:attr nullary? #f] From 179e6a50668e9c1acec79dd6e24ab4189cf2f9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20G=C3=A9lineau?= Date: Wed, 4 Jan 2017 08:39:41 -0500 Subject: [PATCH 4/5] add a test for infix type constructors --- rascal-test/tests/rascal/integration.rkt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rascal-test/tests/rascal/integration.rkt b/rascal-test/tests/rascal/integration.rkt index cb00427..f590172 100644 --- a/rascal-test/tests/rascal/integration.rkt +++ b/rascal-test/tests/rascal/integration.rkt @@ -84,3 +84,10 @@ (require rascal/prelude) (def x : (List Integer) {1 :: {2 :: nil}}))))) + +(describe "syntax" + (describe "infix type constructors" + (it "is supported" + (check-typecheck-success + (data {a && b} + {a & b}))))) From d365ee656d30892387b1006ba49d6eb23f174e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20G=C3=A9lineau?= Date: Wed, 4 Jan 2017 08:41:03 -0500 Subject: [PATCH 5/5] also use the infix type in a type annotation otherwise, the test is useless, because it passes even without the patch to support infix type constructors: it simply parses {a && b} as (a && b), a constructor "a" with arguments "&&" and "b". --- rascal-test/tests/rascal/integration.rkt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rascal-test/tests/rascal/integration.rkt b/rascal-test/tests/rascal/integration.rkt index f590172..d036aea 100644 --- a/rascal-test/tests/rascal/integration.rkt +++ b/rascal-test/tests/rascal/integration.rkt @@ -90,4 +90,6 @@ (it "is supported" (check-typecheck-success (data {a && b} - {a & b}))))) + {a & b}) + (def mypair : {String && String} + {"foo" & "bar"})))))