Initial compiler model (includes low level pattern language model and redex to low level lanaguage compiler)

This commit is contained in:
Steven Jaconette 2010-09-08 10:15:21 -05:00 committed by Casey Klein
parent 837291a793
commit f5482e5703
2 changed files with 3412 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,630 @@
#lang racket
(require redex)
(require "match.rkt")
(require racket/set)
(require profile)
(define lit-table (make-hash))
(define or-table (make-hash))
(define nt-table (make-hash))
(define set-from-list
(λ (lst)
(apply set lst)))
(define-struct nt-struct (match-bool match-set))
(define lang '(define-language T
(n (number_1 ... number_1 ...))
(m ((number_1 number_1) ...))
(o ((number_1 ... number_1 ...) ...))
(q ((number_1 ... number_1 ...) ... (number_1 ... number_1 ...) ...))
))
#;(define lang '(define-language T
(e (e e ...) (if0 e e e) x v)
(v (λ (x ...) e) number * +)
(E (v ... E e ...) (if0 E e e) hole)
(x (variable-except if0 λ * +)))
)
#;(define lang-rr
'(reduction-relation T
(--> (in-hole C (and false B))
(in-hole C false)
)
(--> (in-hole C (and true B))
(in-hole C B)
)
(--> (in-hole C (or false B))
(in-hole C B))
(--> (in-hole C (or true B))
(in-hole C true))
))
#;(define-metafunction λv
subst-vars : ((x any) ... any) -> any
[(subst-vars ((x_1 any_1) x_1)) any_1]
[(subst-vars ((x_1 any_1) (any_2 ...)))
((subst-vars ((x_1 any_1) any_2)) ...)]
[(subst-vars (side-condition
((x_1 any_1) any_2)
(not (eq? (term x_1) (term any_2)))))
any_2]
[(subst-vars ((x_1 any_1) (x_2 any_2) ... any_3))
(subst-vars ((x_1 any_1) (subst-vars ((x_2 any_2) ... any_3))))]
[(subst-vars (any)) any])
(define lang-rr
'(reduction-relation
λv
(--> ((x_1 any_1) x_1)
any_1)
(--> ((x_1 any_1) (any_2 ...))
,(map subst-vars (term (((x_1 any_1) any_2) ...))) )
(--> (side-condition
((x_1 any_1) any_2)
(and (not (list? any_2))
(not (eq? (term x_1) (term any_2)))))
any_2)
(--> ((x_1 any_1) (x_2 any_2) (x_3 any_3) ... any_4)
,(subst-vars (term ((x_1 any_1) ,(subst-vars (term ((x_2 any_2) (x_3 any_3) ... any_4)))))))
(--> (any)
any)
)
)
#;(define-metafunction λv
subst : (x any any) -> any
;; 1. x_1 bound, so don't continue in λ body
[(subst (x_1 any_1 (λ (x_2 ... x_1 x_3 ...) any_2)))
(λ (x_2 ... x_1 x_3 ...) any_2)]
;; 2. general purpose capture avoiding case
[(subst (side-condition
(x_1 any_1 (λ (x_2 ...) any_2))
(not (memq (term x_1) (term (x_2 ...))))))
,(term-let ([(x_new ...) (variables-not-in (term (x_1 any_1 any_2)) (term (x_2 ...)))])
(term
(λ (x_new ...) (subst (x_1 any_1 (subst-vars ((x_2 x_new) ... any_2)))))))]
;; 3. replace x_1 with e_1
[(subst (x_1 any_1 x_1)) any_1]
;; 4. x_1 and x_2 are different, so don't replace
[(subst (side-condition
(x_1 any_1 x_2)
(not (eq? (term x_1) (term x_2)))))
x_2]
;; the last cases cover all other expressions
[(subst (x any (e_1 e_2 ...)))
(,(subst (x any e_1)) (subst (x any e_2)) ...)]
[(subst (x any (if0 e_1 e_2 e_3)))
(if0 (subst (x any e_1)) (subst (x any e_2)) (subst (x any e_3)))]
[(subst (x any number)) number]
[(subst (x any +)) +]
[(subst (x any *)) *])
#;(define lang-rr
'(reduction-relation
λv
(--> (x_1 any_1 (λ (x_2 ... x_1 x_3 ...) any_2))
(λ (x_2 ... x_1 x_3 ...) any_2))
(--> (side-condition
(x_1 any_1 (λ (x_2 ...) any_2))
(not (memq (term x_1) (term (x_2 ...)))))
,(term-let ([(x_new ...) (variables-not-in (term (x_1 any_1 any_2)) (term (x_2 ...)))])
(term
(λ (x_new ...) ,(subst (term (x_1 any_1 ,(subst-vars (term ((x_2 x_new) ... any_2))))) )))) )
(--> (x_1 any_1 x_1)
any_1)
(--> (side-condition
(x_1 any_1 x_2)
(not (eq? (term x_1) (term x_2))))
x_2)
(--> (x any (e_1 e_2 ...))
(,(subst (term (x any e_1))) ,@(map subst (term ((x any e_2) ...)))) )
(--> (x any (if0 e_1 e_2 e_3))
(if0 ,(subst (term (x any e_1))) ,(subst (term (x any e_2))) ,(subst (term (x any e_3)))))
(--> (x any number)
number)
(--> (x any +)
+)
(--> (x any *)
*)
)
)
#;(define-metafunction λv
subst-n : ((x any) ... any) -> any
[(subst-n ((x_1 any_1) (x_2 any_2) ... any_3))
(subst (x_1 any_1 (subst-n (x_2 any_2) ... any_3)))]
[(subst-n (any_3)) any_3])
#;(define lang-rr '(reduction-relation
λv
(--> ((x_1 any_1) (x_2 any_2) ... any_3)
,(subst (term (x_1 any_1 ,(subst-n (term ((x_2 any_2) ... any_3)))))))
(--> (any_3)
any_3)
)
)
#;(define lang-rr '(reduction-relation
λv
(--> (in-hole E (* number_1 number_2))
(in-hole E ,(* (term number_1) (term number_2))))
(--> (in-hole E (+ number_1 number_2))
(in-hole E ,(+ (term number_1) (term number_2))))
(--> (in-hole E (if0 0 e_1 e_2))
(in-hole E e_1))
(--> (in-hole E (if0 (side-condition number_1 (not (zero? (term number_1)))) e_1 e_2))
(in-hole E e_2))
(--> (in-hole E (side-condition ((λ (x ...) e) v ...)
(= (length (term (x ...)))
(length (term (v ...))))))
(in-hole E ,(subst-n (term ((x v) ... e))))))
)
(define (compile-define-language-nts dl)
(match dl
[`(define-language ,(? symbol? name)
,non-terms ...)
(map (λ (x) (car x))
non-terms)]
[_
'error]))
(define (compile-define-language-lit dl nts)
(match dl
[`(define-language ,(? symbol? name)
,non-terms ...)
(map (λ (x) (extract-literals/pat nts (cdr x) lit-table))
non-terms)]
[_
'error]))
(define (extract-literals/pat nts pat ht)
(let loop ([pat pat])
(match pat
[`any (void)]
[`number (void)]
[`string (void)]
[`natural (void)]
[`integer (void)]
[`real (void)]
[`variable (void)]
[`(variable-except ,s ...) (void)]
[`(variable-prefix ,s) (void)]
[`variable-not-otherwise-mentioned (void)]
[`hole (void)]
[(? symbol? s)
(unless (regexp-match #rx"_" (symbol->string s))
(unless (regexp-match #rx"^\\.\\.\\." (symbol->string s))
(unless (memq s nts)
(hash-set! ht s #t)
)))]
[`(name ,name ,pat) (loop pat)]
[`(in-hole ,p1 ,p2)
(loop p1)
(loop p2)]
[`(hide-hole ,p) (loop p)]
[`(side-condition ,p ,g ,e)
(loop p)]
[`(cross ,s) (void)]
[_
(let l-loop ([l-pat pat])
(when (pair? l-pat)
(loop (car l-pat))
(l-loop (cdr l-pat))))])))
(define (compile-define-language-or dl nts)
(match dl
[`(define-language ,(? symbol? name)
,non-terms ...)
(map (λ (x) (hash-set! or-table (car x) (build-or (cdr x) nts (hash-map lit-table (λ (x y) x)) #t)))
non-terms)]
[_
'error]))
(define (build-or pat-l nts syms dl)
(let loop ([pat-l pat-l]
[nts nts]
[syms syms])
(if (pair? pat-l)
(if (eqv? (length pat-l) 1)
(translate-redex (car pat-l) nts syms dl)
`(or ,(translate-redex (car pat-l) nts syms dl)
,(loop (cdr pat-l) nts syms)))
(translate-redex pat-l nts syms dl))))
(define (translate-redex pat nts syms dl)
(let loop ([pat pat])
(match pat
[`(,repeated ,(? (λ (x) (eq? x '...)) ep))
`(repeat ,(loop repeated) '())]
[`(,repeated ,(? (λ (x) (eq? x '...)) ep) ,next ...)
`(repeat ,(loop repeated) ,(loop next))]
[`any (if dl 'wc '(lit-name any wc))]
[`number (if dl 'lit-number '(lit-name number lit-number))]
[`string (if dl 'lit-string '(lit-name string lit-string))]
[`natural (if dl 'lit-natural '(lit-name natural lit-natural))]
[`integer (if dl 'lit-integer '(lit-name integer lit-integer))]
[`real (if dl 'lit-real '(lit-name real lit-real))]
[`variable (if dl 'lit-variable '(lit-name variable lit-variable))]
[`(variable-except ,s ...) `(lit-variable-except ,@s)]
[`(variable-prefix ,s) `(lit-variable-prefix ,s)]
[`variable-not-otherwise-mentioned (if dl `(lit-variable-except ,@syms) `(lit-name variable-not-otherwise-mentioned (lit-variable-except ,@syms)))]
[`hole 'lit-hole]
; for now if it has an underscore assume it's a non-terminal
[(? symbol? s)
(if (memq s nts)
(if dl
`(nt ,s)
`(lit-name ,s (nt ,s)))
(if (has-underscore? s)
(let ((split (split-underscore s)))
(cond
((equal? split 'any) `(lit-name ,s wc))
((equal? split 'number) `(lit-name ,s lit-number))
((equal? split 'string) `(lit-name ,s lit-string))
((equal? split 'natural) `(lit-name ,s lit-natural))
((equal? split 'integer) `(lit-name ,s lit-integer))
((equal? split 'real) `(lit-name ,s lit-real))
((equal? split 'variable) `(lit-name ,s lit-variable))
((equal? split 'variable-not-otherwise-mentioned) `(lit-name ,s (lit-variable-except ,@syms)))
((equal? split 'hole) `(lit-name ,s lit-hole))
(else `(lit-name ,s (nt ,split)))
)
)
`',s))]
[`(name ,name ,pat) `(lit-name ,name ,(loop pat))]
[`(in-hole ,p1 ,p2)
`(lit-in-hole
,(loop p1)
,(loop p2))]
[`(hide-hole ,p) `(lit-hide-hole ,(loop p))]
[`(side-condition ,p #;,g ,e)
`(lit-side-condition ,(loop p) ,e)]
[`(cross ,s) (void)]
[e
(if (pair? pat)
`(cons ,(loop (car pat))
,(loop (cdr pat)))
(if (empty? pat)
''()
e))]
)))
;; split-underscore : symbol -> symbol
;; returns the text before the underscore in a symbol (as a symbol)
;; raise an error if there is more than one underscore in the input
(define (split-underscore sym)
(let ([str (symbol->string sym)])
(cond
[(regexp-match #rx"^([^_]*)_[^_]*$" str)
=>
(λ (m) (string->symbol (cadr m)))]
[(regexp-match #rx"^([^_]*)_!_[^_]*$" str)
=>
(λ (m) (string->symbol (cadr m)))]
[else
(error 'compile-pattern "found a symbol with multiple underscores: ~s" sym)])))
;; has-underscore? : symbol -> boolean
(define (has-underscore? sym)
(memq #\_ (string->list (symbol->string sym))))
(define build-hole-table
(λ (old-ht)
(unless (equal? hole-table old-ht)
(let ((prev (make-hash)))
(hash-for-each
hole-table
(λ (key val)
(hash-set! prev key val)))
(hash-for-each
or-table
(λ (key val)
;(printf "~a: ~a\n" key `(term (detect-hole2 0 ,val)))
(hash-set! hole-table key (term (detect-hole2 0 ,val)))))
(build-hole-table prev))))
)
(define state '())
(define hole-var '())
(define nt-func '())
(define wrap-production-with-name
(λ (x)
(set! state x)
(set! hole-var '())
(set! nt-func '())
(wrap-production-with-name-helper x)
)
)
(define wrap-production-with-name-helper
(λ (exp)
(match exp
[`(cons ,(? (λ (x) (eqv? 1 (term (detect-hole2 0 ,x)))) p1)
,(? (λ (x) (eqv? 0 (term (detect-hole2 0 ,x)))) p2))
`(cons ,(wrap-production-with-name-helper p1) ,(wrap-production-with-name-helper p2))]
[`(cons ,(? (λ (x) (eqv? 0 (term (detect-hole2 0 ,x)))) p1)
,(? (λ (x) (eqv? 1 (term (detect-hole2 0 ,x)))) p2))
`(cons ,(wrap-production-with-name-helper p1) ,(wrap-production-with-name-helper p2))]
[`(cons ,(? (λ (x) (eqv? 0 (term (detect-hole2 0 ,x)))) p1)
,(? (λ (x) (eqv? 0 (term (detect-hole2 0 ,x)))) p2))
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
`(lit-name ,x (cons ,p1 ,p2)))]
[`(lit-name ,id ,(? (λ (x) (eqv? 1 (term (detect-hole2 0 ,x)))) p))
`(lit-name ,id ,(wrap-production-with-name-helper p))]
[`(lit-name ,id ,(? (λ (x) (eqv? 0 (term (detect-hole2 0 ,x)))) p))
`(lit-name ,id ,p)]
[`(lit-side-condition ,(? (λ (x) (eqv? 0 (term (detect-hole2 0 ,x)))) p) ,any)
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
`(lit-name ,x (lit-side-condition ,p ,any))
)]
[`(lit-side-condition ,(? (λ (x) (eqv? 1 (term (detect-hole2 0 ,x)))) p) ,any)
(wrap-production-with-name-helper p)]
[`(repeat ,p1 ,(? (λ (x) (eqv? 0 (term (detect-hole2 0 ,x)))) p2))
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
`(lit-name ,x (repeat ,p1 ,p2))
)]
[`(repeat ,p1 ,(? (λ (x) (eqv? 1 (term (detect-hole2 0 ,x)))) p2))
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
`(repeat (lit-name ,x ,p1) ,(wrap-production-with-name-helper p2))
)]
[`(lit-in-hole ,p1 ,(? (λ (x) (eqv? 0 (term (detect-hole2 0 ,x)))) p2))
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
`(lit-name ,x (lit-in-hole ,p1 ,p2))
)]
[`(lit-in-hole ,p1 ,(? (λ (x) (eqv? 1 (term (detect-hole2 0 ,x)))) p2))
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
(let ((y (variable-not-in state 'y)))
(set! hole-var y)
`(lit-in-hole (lit-name ,x ,p1) (lit-name ,y ,p2))
)
)]
['lit-hole
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
(set! hole-var x)
`(lit-name ,x lit-hole)
)]
[`(nt ,id)
(if (eqv? 1 (term (detect-hole2 0 (nt ,id))))
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
(set! hole-var x)
(set! nt-func id)
`(lit-name ,x wc)
)
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
`(lit-name ,x (nt ,id))
)
)]
[`',(? (λ (x) (or (symbol? x) (equal? '() x))) ex)
exp]
[_ (if (or (number? exp) (string? exp) (boolean? exp))
exp
(let ((x (variable-not-in state 'x)))
(set! state (cons x state))
`(lit-name ,x ,exp)
))])
)
)
(define build-right-hand-side
(λ (x)
(if (equal? nt-func '())
(if (equal? hole-var '())
`(set! results (cons (cons ,(build-right-hand-side-helper x) '()) results))
`(set! results (cons (cons ,(build-right-hand-side-helper x) (term ,hole-var)) results))
)
`(for ((,hole-var (in-list (,(string->symbol (format "~s~s" nt-func '-list)) (term ,hole-var)))))
(set! results (cons (cons ,(build-right-hand-side-helper x) (cdr ,hole-var)) results))
)
)
)
)
(define build-right-hand-side-helper
(λ (exp)
(match exp
[`(lit-name ,(? (λ (x) (not (equal? hole-var x))) x) ,p)
(if (or (not (cons? p)) (and (cons? p) (not (equal? (car p) 'lit-name))))
`(term ,x)
(build-right-hand-side-helper p))]
[`(lit-name ,(? (λ (x) (equal? hole-var x)) x) lit-hole)
'the-hole]
[`(lit-name ,(? (λ (x) (equal? hole-var x)) x) wc)
`(car ,hole-var)]
[`(lit-name ,(? (λ (x) (equal? hole-var x)) x) ,p)
`(term ,x)]
[`(cons ,p1 ,p2)
`(cons ,(build-right-hand-side-helper p1) ,(build-right-hand-side-helper p2))]
[`(lit-in-hole ,p1 ,p2)
(build-right-hand-side-helper p1)]
[`(repeat ,p1 ,p2)
`(append ,(build-right-hand-side-helper p1) ,(build-right-hand-side-helper p2))]
[_
exp]
)))
(define make-or-list
(λ (exp)
(match exp
[`(or ,pro1 ,pro2)
(cons pro1 (make-or-list pro2))]
[_ (cons exp '())]
)
)
)
(define-namespace-anchor here)
(define (compile-dl lang)
(let* ([lang lang]
[nts (compile-define-language-nts lang)]
[lit-table lit-table]
[or-table or-table]
[nt-table nt-table]
[hole-table hole-table])
(compile-define-language-lit lang nts)
(compile-define-language-or lang nts)
(caching-enabled? #f)
; Initialize the hole table
(hash-for-each
or-table
(λ (key val)
(hash-set! hole-table key (term (detect-hole 0 ,val)))
))
(build-hole-table '())
(caching-enabled? #t)
(printf "~a\n ~a\n ~a\n ~a\n\n\n" nts lit-table or-table hole-table)
(hash-for-each
or-table
(λ (key val)
(let ((val val))
(printf "non-terminal: ~a\n" key)
(printf "~a\n~a\n\n"
`(term (matrix (a)
(
((,val -> (set! results (cons #t results))) ,@(map (λ (x) (list x #f)) (remove-duplicates (term (Get-Free-Name-Patterns ,val () ())))))
)
()
()
0
#f))
`(term (matrix (a)
( ,@(map (λ (x)
(let ((row (wrap-production-with-name x)))
`((,row -> ,(build-right-hand-side row))
,@(map (λ (x) (list x #f)) (remove-duplicates (term (Get-Free-Name-Patterns ,row () ())))))))
(make-or-list val)))
()
()
0
#f)))
(let ((compiled-bool (car (apply-reduction-relation* red
(term (matrix (a)
(
((,val -> (set! results (cons #t results))) ,@(map (λ (x) (list x #f)) (remove-duplicates (term (Get-Free-Name-Patterns ,val () ())))))
)
()
()
0
#f)))))
(compiled-set (car (apply-reduction-relation* red
(term (matrix (a)
( ,@(map (λ (x)
(let ((row (wrap-production-with-name x)))
(printf "Row: ~a Wrapped: ~a\n" x row)
`((,row -> ,(build-right-hand-side row))
,@(map (λ (x) (list x #f)) (remove-duplicates (term (Get-Free-Name-Patterns ,row () ())))))))
(make-or-list val)))
()
()
0
#f))))
))
(printf "compiled bool: ~a\n\n" compiled-bool)
(printf "compiled set: ~a\n\n" compiled-set)
(hash-set! nt-table
key
(make-nt-struct
(term (define ,(string->symbol (format "~s~s" key '-bool))
(λ (a)
(let ((results (list)))
,compiled-bool
(and (andmap values results) (positive? (length results))))
)
)
)
(term (define ,(string->symbol (format "~s~s" key '-list))
(λ (a)
(let ((results (list)))
,compiled-set
results
)
)
))
))
))))
#;(let ((rr (compile-reduction-relation lang-rr nts (hash-map lit-table (λ (x y) x)))))
(print rr)
(apply-reduction-relation* red rr))
)
)
(define (compile-reduction-relation rr nts syms)
(let* ([lit-table lit-table]
[or-table or-table]
[nt-table nt-table]
[hole-table hole-table]
[e rr])
(let loop ([e e])
(match e
[`(reduction-relation ,L ,rules ...)
(term (matrix (a) ,(map loop rules) () () 0 #f))]
[`(--> ,pat ,t)
(let ((p (translate-redex pat nts syms #f)))
(printf "Left hand side: ~a\n\n" p)
(printf "Right hand side: ~a\n\n" t)
`((,p -> (set! results (cons (term ,t) results))) ,@(map (λ (x) (list x #f)) (remove-duplicates (term (Get-Free-Name-Patterns ,p () ())))))
)])
)))
(compile-dl lang)
(define-language T
(B true
false
(and B B))
(C (and C B)
hole))
(define bool-red-test
(reduction-relation T
(--> (in-hole C (and false B))
(in-hole C false)
)
(--> (in-hole C (and true B))
(in-hole C B)
)))
(caching-enabled? #f)
(define #f)
(define set-union)
(define singleton set)
(define no-context #f)
(define in-context #t)
(define context-match (make-parameter no-context))
(define rev (λ (x)
(if (cons? x)
(reverse x)
x)))
(define or-fun (λ (x ...) (or x ...)))
(define sing-fun (λ (x) #t))
(define the-hole (term hole))