From c4a5f8ab1efce20f0e1181ffe34639facb19594a Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Mon, 12 Aug 2019 16:26:21 +0100 Subject: [PATCH] Move expanding pattern matches to its own transformations I think this will make it easier to understand how pattern matching works --- ast.scm | 41 ++++++++++++++++++++++++++++++----------- codegen.scm | 5 ++++- tests.scm | 14 ++++++-------- typecheck.scm | 8 ++++++-- 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/ast.scm b/ast.scm index 9af3653..8a98617 100644 --- a/ast.scm +++ b/ast.scm @@ -75,19 +75,31 @@ ['stack (either (p x) (inner (caddr x)))] [else (p x)])) -(define (let-bindings e) - (define (pattern-match binding body) - (if (eqv? (ast-type binding) 'var) - (list (cons binding body)) - (let* ([constructor (car binding)] - [destructor (lambda (i) (dtor-name constructor i))]) - (flat-map (lambda (y i) - (pattern-match y `((,(destructor i) ,@body)))) - (cdr binding) - (range 0 (length (cdr binding))))))) - (flat-map (lambda (x) (pattern-match (car x) (cdr x))) (cadr e))) +(define let-bindings cadr) (define let-body cddr) + ; (let ([(foo a b) (foo 123 345)]) a) + ; | + ; v + ; (let ([a (foo~0 (foo 123 345)] + ; [b (foo~1 (foo 123 345)]) a) +(define (expand-pattern-matches x) + (define (pattern-match binding) + (let ([binding-name (car binding)] + [body (cadr binding)]) + (if (eqv? (ast-type binding-name) 'var) + (list (list binding-name body)) + (let* ([sum-name (car binding-name)] + [destructor (lambda (i) (dtor-name sum-name i))]) + (flat-map (lambda (y i) + (pattern-match (list y `(,(destructor i) ,body)))) + (cdr binding-name) + (range 0 (length (cdr binding-name)))))))) + (case (ast-type x) + ['let `(let ,(flat-map pattern-match (let-bindings x)) + ,@(map expand-pattern-matches (let-body x)))] + [else (ast-traverse expand-pattern-matches x)])) + (define (lambda? x) (and (list? x) (eq? (car x) 'lambda))) @@ -112,6 +124,13 @@ (filter (lambda (x) (eqv? (statement-type x) 'defines)) program)) +(define (program-map-exprs f program) + (map (lambda (x) + (case (statement-type x) + ['expr (f x)] + [else x])) + program)) + (define (program-body program) ; hack to have multi-expression bodies `(let () diff --git a/codegen.scm b/codegen.scm index 7a37097..8e3a7d5 100644 --- a/codegen.scm +++ b/codegen.scm @@ -658,7 +658,10 @@ (set! cur-lambda 0) (let* ([data-layouts (program-data-layouts program)] - [type-annotated (annotate-types program)] + [pattern-matched (program-map-exprs + expand-pattern-matches + program)] + [type-annotated (annotate-types pattern-matched)] [stack-annotated (annotate-stack-values data-layouts type-annotated)] diff --git a/tests.scm b/tests.scm index 2b6e09a..bcd878a 100644 --- a/tests.scm +++ b/tests.scm @@ -61,6 +61,12 @@ (bar . (abs Bool A)) (bar~0 . (abs A Bool)))) +(test (expand-pattern-matches '(let ([(foo x y) (foo 123 234)] [z (f 123)]) x)) + '(let ([x (foo~0 (foo 123 234))] + [y (foo~1 (foo 123 234))] + [z (f 123)]) + x)) + (test-types (typecheck '((lambda (x) (+ ((lambda (y) (x y 3)) 5) 2)))) '(abs (abs Int (abs Int Int)) Int)) @@ -137,14 +143,6 @@ 'Int) - ; pattern matching -(test (let-bindings '(let ([(foo x) a]) x)) - '((x (foo~0 a)))) - -(test (let-bindings '(let ([x (foo 42)] [(foo y) x]) x)) - '((x (foo 42)) - (y (foo~0 x)))) - ; type annotations (test (annotate-types diff --git a/typecheck.scm b/typecheck.scm index 35e8188..a526620 100644 --- a/typecheck.scm +++ b/typecheck.scm @@ -259,7 +259,8 @@ ; we typecheck the lambda calculus only (only single arg lambdas) (define (typecheck prog) - (cadr (check (init-adts-env prog) (normalize (program-body prog))))) + (let ([expanded (program-map-exprs expand-pattern-matches prog)]) + (cadr (check (init-adts-env expanded) (normalize (program-body expanded)))))) ; before passing annotated types onto codegen @@ -309,8 +310,11 @@ (define ann-expr car) (define ann-type caddr) + + ; prerequisites: expand-pattern-matches (define (annotate-types prog) - (denormalize (program-body prog) + (denormalize + (program-body prog) (caddr (check (init-adts-env prog)(normalize (program-body prog)))))) -- 2.30.2