Last active
May 23, 2021 07:27
-
-
Save Yoxem/34b07d59f88c3805174425cf7a440843 to your computer and use it in GitHub Desktop.
finding duplicated variable and type interfence using Racket
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
/* | |
lambda 函數的案例 | |
(define foo (lambda (x) 10) [fv ()]) | |
(foo foo) | |
*/ | |
typedef union object object; | |
typedef struct closure closure; | |
// closure 的型別 | |
typedef struct closure{ | |
object (* function); | |
object* fv; | |
} closure; | |
// object 的型別 | |
typedef union object{ | |
closure cl; | |
long i; | |
float f; | |
} object; | |
// 函數 | |
object foo(closure cl, object x){ | |
object tmp1; | |
tmp1.i = 10; | |
return tmp1; | |
}; | |
/* 函數延伸處 | |
... | |
*/ | |
int main(void){ | |
// 建立 foo | |
closure closure1; | |
closure1.function = (object *)foo; | |
object closure1_o; | |
closure1_o.cl = closure1; | |
// (foo foo) | |
object object2; | |
object2 = ((object (*)(closure cl, object x))(closure1_o.cl.function))(closure1_o.cl,closure1_o); | |
// 檢查 (foo foo) 的內容物,應該是 10 | |
printf("%ld", object2.i); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
/* | |
lambda 函數的案例 | |
(define foo (lambda (x) 10) [fv ()]) | |
(foo foo) | |
*/ | |
(typedef [U object] object) | |
(typedef [Struct closure] closure) | |
// closure 的型別 | |
typedef struct closure{ | |
object (* function); | |
object* fv; | |
} closure; | |
(typedef [Struct closure | |
([object (* function)] | |
[(object *) fv])] | |
closure) | |
(typedef [union object( | |
[closure cl] | |
[long i] | |
[float f] | |
)] object) | |
// 函數 | |
(fn object foo [(closure cl) (object x)] | |
( | |
(def object tmp1) | |
(set (ref tmp1 i) 10) | |
tmp1 | |
}; | |
/* 函數延伸處 | |
... | |
*/ | |
(fn int main void { | |
// 建立 foo | |
(def closure closure1) | |
(set (ref closure1 function) (cast (object *)) foo) | |
(def object closure1_o) | |
(set (ref closure1_o cl) closure1) | |
// (foo foo) | |
(def object object2) | |
// (object (*)(closure cl, object x)) -> [type object * [(closure c1) (object x)]] | |
(set object2 [call (cast [type object * [(closure c1) (object x)]] [ref [ref closure1_o cl] function]) (ref closure1_o cl) closure1_o]; | |
// 檢查 (foo foo) 的內容物,應該是 10 | |
(printf "%ld" (ref object2 i)) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
(require nanopass/base) | |
;(let ((x 10) | |
; (y 8)) | |
;(lambda (z) (+ x y z))) | |
(define (neq? x y) (not (eq? x y))) | |
(define (variable? x) | |
(and (symbol? x))) | |
(define primitive-list '(+ - * / +. -. *. /. and or)) | |
(define (primitive? x) | |
(memq x primitive-list)) | |
(define (datatype? x) | |
(memq x '(int flo bool void))) | |
(define (constant? x) | |
(or | |
(flonum? x) | |
(integer? x) | |
(boolean? x))) | |
(define-language L0 | |
(terminals | |
(variable (x)) | |
(primitive (pr)) | |
(datatype (dt)) | |
(constant (c))) | |
(Expr (e body) | |
x | |
pr | |
c | |
(begin e* ... e) | |
(def t x e) | |
(lambda ([t* x*] ... ) e) | |
(e0 e1 ...)) | |
(Type (t) | |
dt | |
(-> t* ... t) | |
) | |
) | |
(define-language L1 | |
(terminals | |
(datatype (dt))) | |
(Type (t) | |
dt | |
(-> t* ... t) | |
) | |
) | |
(define table-list `(,primitive-list)) | |
;;; | |
; 找尋有沒有重複定義的變數 | |
;;; | |
(define (find-dup-var exp table) | |
(match exp | |
[(? primitive? c) table] | |
[(? constant? c) table] | |
; 逐一執行找尋重複變數的子程式 | |
[(list* 'begin e* ... e) (let loop | |
[(head (car (append e* (list e)))) | |
(tail (cdr (append e* (list e)))) | |
(t table) | |
] | |
(if (equal? tail '(())) | |
(find-dup-var head t) | |
(let | |
[(t1 (find-dup-var head t))] | |
(loop (car tail) (cdr tail) t1)) | |
))] | |
[(? variable? x) (cond | |
; 如果 x 在 table 的其中一格裡面,就是正常的,回傳 table | |
[(memq x (flatten table)) table] | |
; 如果不在,就回傳 exception | |
[else (raise (format "~a is not defined." x))])] | |
; 定義變數 | |
[`(def ,t ,x ,e) (cond | |
[(memq x (last table)) (raise (format "~a is duplicated defined." x))] | |
; 將 table 最後一個列表,加入 x 元素 | |
[else (begin | |
[set! table (list-set table [- (length table) 1] [append (last table) (list x)])] | |
table)])] | |
; lambda 函數 | |
[`(lambda ,var-type-ls ,body) (begin | |
;(display var-type-ls) | |
(define var-ls (map cadr var-type-ls)) | |
(if | |
; 找看看有沒有重複的變數定義於 lambda 裡面 | |
(check-duplicates var-ls) | |
(raise (format "lambda have duplicated variables: ~a" (check-duplicates var-ls) )) | |
; table 開新的儲存區,然後再逐一檢查 body 裡面的表達式 | |
[let | |
[(new-table (reverse (cons var-ls (reverse table))))] | |
(find-dup-var body new-table) | |
table | |
]))] | |
; 函數調用 | |
[(list* e* ... e) (let | |
[(exps (cons e* e))] | |
(for | |
[(exp (car exps))] | |
(set! table (find-dup-var exp table))) | |
table | |
)] | |
)) | |
(define (find-dup-var-main exp) (find-dup-var exp '(()))) | |
;uncaught exception: "x is not defined." | |
;(find-dup-var '(begin (+ x y) 3 (def int x 99) x (def int y 10) (lambda (x y z) (+ x y s))) table-list) | |
;uncaught exception: "s is not defined." | |
;(find-dup-var '(begin 3 (def int x 99) x (def int y 10) (lambda (x y z) (+ x y s))) table-list) | |
;uncaught exception: "lambda have duplicated variables: z" | |
;(find-dup-var '(lambda (x z) (begin 54 (+ x y 12))) table-list) | |
;(define ex-0 '(begin | |
; 10.0 | |
; (+ 2 2) | |
;(def int x 10) | |
;(def flo y (+. 2.0 2.0)) | |
;)) | |
(define-parser parse-L0 L0) | |
(define-parser parse-L1 L1) | |
(define (list-remove-last ls) | |
(reverse (cdr (reverse ls)))) | |
;; 初級函數型別 | |
[define prim-func-type | |
(make-hash | |
`((+ . ,(parse-L1 '[-> int int int])) | |
(- . ,(parse-L1 '[-> int int int])) | |
(* . ,(parse-L1 '[-> int int int])) | |
(/ . ,(parse-L1 '[-> int int int])) | |
(+. . ,(parse-L1 '[-> flo flo flo])) | |
(-. . ,(parse-L1 '[-> flo flo flo])) | |
(*. . ,(parse-L1 '[-> flo flo flo])) | |
(/. . ,(parse-L1 '[-> flo flo flo])) | |
(and . ,(parse-L1 '[-> bool bool bool])) | |
(or . ,(parse-L1 '[-> bool bool bool])) | |
)) | |
] | |
(define (quoting-to-quasiquoting ls) | |
`((unquote-splicing ls)) | |
) | |
[define (get-type x a) (let [(result #f)(has-value #f)] (for ((i (reverse a)) #:break (eq? has-value #t)) | |
(if (memq x (hash-keys i)) | |
[begin | |
(set! result (hash-ref i x)) | |
(set! has-value #t)] | |
#f)) result)] | |
(define-pass type-inference : L0 (ast) -> L1 () | |
[definitions | |
(define orig-hash-table (make-hash)) | |
(define empty-env `(,orig-hash-table))] | |
(type-infer : Expr (exp env) -> * () | |
; 常數 | |
[,c (cond | |
[(flonum? exp) `(flo ,env)] | |
[(integer? exp) `(int ,env)] | |
[(boolean? exp) `(bool ,env)])] | |
; 基本運算符調用 | |
[,pr `(,[hash-ref prim-func-type pr] ,env)] | |
; 變數 | |
[,x `(,(get-type x env) ,env)] | |
; 逐一執行指令。用 named let | |
[(begin ,body* ... ,body) (let [(exprs (append body* (list body))) | |
(tmp-env env)] | |
;(display exprs) | |
(let loop | |
[(head (car exprs)) | |
(tail (cdr exprs))] | |
(if (equal? tail '()) | |
(type-infer head tmp-env) ; 如果執行到最後一行則傳回最後一行的回傳值 | |
(begin | |
(set! tmp-env (list-ref (type-infer head env) 1)) | |
;(display table) | |
(loop (car tail) (cdr tail))))))] | |
; 定義變數 | |
[(def ,t ,x ,e) | |
(let | |
[(rhs-type (parse-L0 (unparse-L1 [list-ref (type-infer e env) 0])))] | |
(cond | |
[(equal? (unparse-L0 t) (unparse-L0 rhs-type)) (hash-set! (list-ref env [- (length env) 1]) x (parse-L1 (unparse-L0 t))) | |
; 回傳 void 值 | |
`(void ,env)] | |
[else (error (format "Expect type of ~a : ~a, found type ~a" x t rhs-type))] | |
) | |
)] | |
; lambda | |
; (lambda [(int x) (int y)] -> t* = (int int) x* = (x y)) | |
[(lambda ([,t* ,x*] ... ) ,body) | |
(let* | |
[(new-hash-table (make-hash)) | |
(extended-env (append env (list new-hash-table)))] ; 創立新表格附著在後面 | |
(for | |
[(t t*) | |
(x x*)] | |
(hash-set! (list-ref extended-env [- (length extended-env) 1]) x [parse-L1 (unparse-L0 t)])) | |
;(display (format "匿名函數掃描中~a" table)) | |
(let* | |
[ | |
(return-type (list-ref (type-infer body extended-env) 0)) ; 回傳值型別 | |
;(total-type (quoting-to-quasiquoting total-type-raw)) | |
] | |
(define t*-unparsed (map (lambda (x) (unparse-L0 x)) t*)) | |
;(define t*-unparsed-ast (unparse-L1 t*-unparsed)) | |
`[,(parse-L1 `(-> ,@t*-unparsed ,(unparse-L1 return-type))) ,env] | |
))] | |
[(,e0 ,e1 ...) (let* | |
((operator-type [list-ref (type-infer e0 env) 0]) | |
(arguments-type [map (lambda (x) (unparse-L1 (list-ref (type-infer x env) 0))) e1]) | |
(operator-type-without-return (reverse (cdr (reverse (cdr (unparse-L1 operator-type))))))) | |
(display exp)(display operator-type)(display arguments-type)(display env) | |
(if (equal? operator-type-without-return arguments-type) | |
`(,(parse-L1 (last (unparse-L1 operator-type))) ,env) | |
[begin (raise (format "expect argument type ~a, found ~a" operator-type-without-return arguments-type))]) | |
)] | |
) | |
[list-ref (type-infer ast empty-env) 0] | |
) | |
;[(and (list? e) (= 3 (length e))) | |
; (let ([op (car e)] [e0 (type-infer (cadr e))] [e1 (type-infer (caddr e))]) | |
; `(,op ,e0 ,e1))])) | |
;(define l1 (parse-L0 '(+ 1 0.1))) | |
;(type-inference l1) | |
;; convert x -> x1, y -> y2, etc. | |
(define-pass eta-conversion : L0 (ast) -> L0 () | |
[definitions | |
(define var-table `(,(make-hash))) | |
(define (combine-two-list x y) | |
(if (equal? x '()) | |
'() | |
(cons `(,(car x) ,(car y)) (combine-two-list (cdr x) (cdr y)))))] | |
(convert : Expr (exp env) -> Expr () | |
[,pr pr] | |
[(lambda ([,t* ,x*] ...) ,body) | |
(let* | |
((new-x* (map gensym x*)) | |
(t*-new-x*-pair-ls [combine-two-list t* new-x*]) | |
(new-env [append env (list (make-hash))])) | |
(for ([i x*] | |
[j new-x*]) | |
(hash-set! (last new-env) i j)) | |
;(display new-env) | |
`(lambda [[,t* ,new-x*] ...] ,(convert body new-env)))] | |
[,x | |
;(display (format "執行 ~a\n" x)) | |
(hash-ref (last env) x)] | |
[,c c] | |
[(def ,t ,x ,e) (let | |
[(new-var (gensym x))] | |
;(display (format "執行def ~a\n" x)) | |
(hash-set! (last env) x new-var) | |
`(def ,t ,new-var ,(convert e env))) | |
] | |
) | |
(convert ast var-table) | |
) | |
; (define l1 (parse-L0 '(begin (def int x 10) (def int y x) x ((lambda [(int x) (int y)] y) x y) y))) (eta-conversion l1) | |
(define (atom? x) (and | |
[not (pair? x)] | |
[not (list? x)])) | |
(define (def-undef-lambda-begin ls) | |
[let | |
[(return '())] | |
[for | |
((i ls)) | |
[match i | |
((list 'lambda var-pair body) | |
[let* | |
((new-lambda (gensym 'lam)) | |
(new-lambda-type (unparse-L1 (type-inference (parse-L0 i))) | |
) | |
(new-body (define-undef-lambda body))) | |
(set! return (append return (list `(def ,new-lambda-type ,new-lambda ,new-body) new-lambda))) | |
]) | |
(else (set! return (append return (list (define-undef-lambda i)))))]] | |
return | |
] | |
) | |
(define (def-undef-lambda-apply ls) | |
[let | |
[(new-define '()) | |
(new-apply '())] | |
[for | |
((i ls)) | |
[match i | |
((list 'lambda var-pair body) | |
[let* | |
((new-lambda (gensym 'lam)) | |
(new-lambda-type (unparse-L1 (type-inference (parse-L0 i))) | |
) | |
(new-body (define-undef-lambda body)) | |
(new-lambda-define `(def ,new-lambda-type ,new-lambda (lambda ,var-pair ,new-body)))) | |
(set! new-define (append new-define (list new-lambda-define))) | |
(set! new-apply (append new-apply (list new-lambda))) | |
]) | |
((list a ...) (let* | |
[[result (def-undef-lambda-apply a)] | |
[new-result (last result)] | |
[new-sub-define (cdr (list-remove-last result))]] ; 出來的結果會有 begin,但在括號內,我們不需要 | |
;(display new-sub-define) | |
(set! new-define (append new-define new-sub-define)) | |
(set! new-apply (append new-apply (list new-result))) | |
)) | |
(else (set! new-apply (append new-apply (list (define-undef-lambda i)))))]] | |
`(begin ,@new-define ,new-apply) | |
] | |
) | |
(define (define-undef-lambda x) | |
;; 用 match 重寫 | |
(match x | |
[(? atom? x) x] | |
; TODO | |
[(list 'def t x (list a b ...)) | |
[let* | |
[(raw-result (def-undef-lambda-apply (append (list a) b))) | |
(new-rhs (last raw-result)) | |
(new-def `(def ,t ,x ,new-rhs))] | |
(append (list-remove-last raw-result) (list new-def)) | |
]] ;TODO | |
[(list 'def t x e) (match e | |
[(list 'lambda var-pair body) `(def ,t ,x ,e)] | |
[else `(def ,t ,x ,(define-undef-lambda e))])] | |
[(list 'begin a ...) `(begin ,@(def-undef-lambda-begin a))] | |
[(list 'lambda var-pair body) | |
[let* | |
((new-lambda (gensym 'lam)) | |
(new-lambda-type (unparse-L1 (type-inference (parse-L0 x))) | |
) | |
(new-body (define-undef-lambda body))) | |
`(begin (def ,new-lambda-type ,new-lambda (lambda ,var-pair ,new-body)) ,new-lambda)]] | |
[(list a b ...) (def-undef-lambda-apply x)] | |
)) | |
;; 用 match 重寫 | |
;[flatten-begin '(begin | |
; 12 | |
; 5 | |
; y | |
; (begin 12 1 (begin (lambda [(x 5)(y 7)] y))) | |
; )] | |
; -> '(begin 12 5 y 12 1 (lambda ((x 5) (y 7)) y)) | |
(define [flatten-begin x] | |
(match x | |
[(list (list 'begin i ...) o ...) (append (flatten-begin i) (flatten-begin o))] | |
[(list a b ...) (append (list (flatten-begin a)) (flatten-begin b))] | |
[(? pair? x) x] | |
[(? null? x) x] | |
[(? atom? x) x] | |
[(list a) (list a)] | |
) | |
) | |
(define-pass remove-undefined-lambda : L0 (ast) -> L0 () | |
[definitions | |
[define unparsed-ast (unparse-L0 ast)] | |
[define removed-result-ast (flatten-begin(define-undef-lambda unparsed-ast))] | |
] | |
(parse-L0 removed-result-ast) | |
) | |
;;; | |
; Test-area | |
;;; | |
;(define-undef-lambda '(begin 7 x (lambda [(int x)(flo y)] y) 10)) | |
;(define-undef-lambda '(begin 7 x (def int x 2) (def int x (begin (lambda [(int x)(flo y)] y) 10)) )) | |
;(define-undef-lambda '(lambda ([int x]) (lambda ([int y]) 12))) | |
;(define-undef-lambda '((lambda ([int x]) 20) (lambda ((flo y)) 12))) ; 錯誤需要debug?? | |
;(define-undef-lambda '((lambda ([int x]) 20) ((lambda ((flo y)) 8) (lambda ((flo z)) 10) 12))) | |
;(define-undef-lambda '(begin 12 [def int kk ((lambda ([int x]) 20) ((lambda ((flo y)) 8) (lambda ((flo z)) 10) 12))] 1.0)) | |
;(parse-L0 (flatten-begin (define-undef-lambda '(begin 12 [def int kk ((lambda ([int x]) 20) ((lambda ((flo y)) 8) (lambda ((flo z)) 10) 12))] 1.0)))) | |
(define test-0 '(lambda ((int x)) 9)) | |
(define test-1 '([lambda ((int x)) (lambda ((flo y)) x)] 9)) | |
(define test-2 '(begin 12 [lambda ((int x)) x] 9)) | |
(define test-3 '(begin 12 | |
[def int kk | |
((lambda ([int x]) 20) ((lambda (((-> flo int) y) (int z)) 8) (lambda ((flo z)) 10) 12))] | |
1.0 | |
kk)) | |
(define test-4 '([lambda ((int x)) (lambda ((flo y)) x)] 9)) | |
(define test-5 '(begin 12 [lambda ((int x)) x] 9)) | |
(define test-6 | |
'(begin | |
3.0 | |
(def bool x (and (or #t #t) #f)) | |
(def flo y 10.0) | |
; uncaught exception: "lambda have duplicated variables: y" | |
;(lambda ([int x] [int y] [int y]) (+ x y 10)) | |
;uncaught exception: "z is not defined." | |
;(lambda ([int x] [int y]) (+ x y z 10)) | |
;(def flo k (lambda (x y z) (+ y x z g))) | |
(def flo z (+. 10.0 y)) | |
(+. 1.0 3.0) | |
z | |
(lambda ([int x] [int y]) 9.9) | |
)) | |
(define [compiler ast] | |
(display "Start compiling...\n") | |
(let* | |
[(found-dup-var-ast (find-dup-var-main ast)) | |
(ann-lambda-defined-ast (define-undef-lambda ast)) | |
(ann-lambda-defined-L0 (parse-L0 ann-lambda-defined-ast)) | |
(begin-flattened-L0 (remove-undefined-lambda ann-lambda-defined-L0)) | |
(etaed-L0 (eta-conversion begin-flattened-L0)) | |
(type-infered-type [begin (display etaed-L0)(type-inference etaed-L0)])] | |
(display "End compiling...\n") | |
ann-lambda-defined-L0 | |
) | |
) | |
(compiler test-0) | |
(compiler test-1) | |
(compiler test-2) | |
(compiler test-3) | |
(compiler test-4) | |
(compiler test-5) | |
(compiler test-6) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
(require nanopass/base) | |
;(let ((x 10) | |
; (y 8)) | |
;(lambda (z) (+ x y z))) | |
(define (neq? x y) (not (eq? x y))) | |
(define (variable? x) | |
(and (symbol? x))) | |
(define primitive-list '(+ - * / +. -. *. /. and or)) | |
(define (primitive? x) | |
(memq x primitive-list)) | |
(define (datatype? x) | |
(memq x '(int flo bool void))) | |
(define (constant? x) | |
(or | |
(flonum? x) | |
(integer? x) | |
(boolean? x))) | |
(define-language L0 | |
(terminals | |
(variable (x)) | |
(primitive (pr)) | |
(datatype (dt)) | |
(constant (c))) | |
(Expr (e body) | |
x | |
pr | |
c | |
(begin e* ... e) | |
(def t x e) | |
(lambda ([t* x*] ... ) e) | |
(e0 e1 ...)) | |
(Type (t) | |
dt | |
(-> t* ... t) | |
) | |
) | |
(define-language L1 | |
(terminals | |
(datatype (dt))) | |
(Type (t) | |
dt | |
(-> t* ... t) | |
) | |
) | |
(define table-list `(,primitive-list)) | |
;;; | |
; 找尋有沒有重複定義的變數 | |
;;; | |
(define (find-dup-var exp table) | |
(match exp | |
[(? primitive? c) table] | |
[(? constant? c) table] | |
; 逐一執行找尋重複變數的子程式 | |
[(list* 'begin e* ... e) (let loop | |
[(head (car (append e* (list e)))) | |
(tail (cdr (append e* (list e)))) | |
(t table) | |
] | |
(if (equal? tail '(())) | |
(find-dup-var head t) | |
(let | |
[(t1 (find-dup-var head t))] | |
(loop (car tail) (cdr tail) t1)) | |
))] | |
[(? variable? x) (cond | |
; 如果 x 在 table 的其中一格裡面,就是正常的,回傳 table | |
[(memq x (flatten table)) table] | |
; 如果不在,就回傳 exception | |
[else (raise (format "~a is not defined." x))])] | |
; 定義變數 | |
[`(def ,t ,x ,e) (cond | |
[(memq x (last table)) (raise (format "~a is duplicated defined." x))] | |
; 將 table 最後一個列表,加入 x 元素 | |
[else (begin | |
[set! table (list-set table [- (length table) 1] [append (last table) (list x)])] | |
table)])] | |
; lambda 函數 | |
[`(lambda ,var-type-ls ,body) (begin | |
;(display var-type-ls) | |
(define var-ls (map cadr var-type-ls)) | |
(if | |
; 找看看有沒有重複的變數定義於 lambda 裡面 | |
(check-duplicates var-ls) | |
(raise (format "lambda have duplicated variables: ~a" (check-duplicates var-ls) )) | |
; table 開新的儲存區,然後再逐一檢查 body 裡面的表達式 | |
[let | |
[(new-table (reverse (cons var-ls (reverse table))))] | |
(find-dup-var body new-table) | |
table | |
]))] | |
; 函數調用 | |
[(list* e* ... e) (let | |
[(exps (cons e* e))] | |
(for | |
[(exp (car exps))] | |
(set! table (find-dup-var exp table))) | |
table | |
)] | |
)) | |
(define (find-dup-var-main exp) (find-dup-var exp '(()))) | |
;uncaught exception: "x is not defined." | |
;(find-dup-var '(begin (+ x y) 3 (def int x 99) x (def int y 10) (lambda (x y z) (+ x y s))) table-list) | |
;uncaught exception: "s is not defined." | |
;(find-dup-var '(begin 3 (def int x 99) x (def int y 10) (lambda (x y z) (+ x y s))) table-list) | |
;uncaught exception: "lambda have duplicated variables: z" | |
;(find-dup-var '(lambda (x z) (begin 54 (+ x y 12))) table-list) | |
;(define ex-0 '(begin | |
; 10.0 | |
; (+ 2 2) | |
;(def int x 10) | |
;(def flo y (+. 2.0 2.0)) | |
;)) | |
(define-parser parse-L0 L0) | |
(define-parser parse-L1 L1) | |
(define (list-remove-last ls) | |
(reverse (cdr (reverse ls)))) | |
;; 初級函數型別 | |
[define prim-func-type | |
(make-hash | |
`((+ . ,(parse-L1 '[-> int int int])) | |
(- . ,(parse-L1 '[-> int int int])) | |
(* . ,(parse-L1 '[-> int int int])) | |
(/ . ,(parse-L1 '[-> int int int])) | |
(+. . ,(parse-L1 '[-> flo flo flo])) | |
(-. . ,(parse-L1 '[-> flo flo flo])) | |
(*. . ,(parse-L1 '[-> flo flo flo])) | |
(/. . ,(parse-L1 '[-> flo flo flo])) | |
(and . ,(parse-L1 '[-> bool bool bool])) | |
(or . ,(parse-L1 '[-> bool bool bool])) | |
)) | |
] | |
(define (quoting-to-quasiquoting ls) | |
`((unquote-splicing ls)) | |
) | |
[define (get-type x a) (let [(result #f)(has-value #f)] (for ((i (reverse a)) #:break (eq? has-value #t)) | |
(if (memq x (hash-keys i)) | |
[begin | |
(set! result (hash-ref i x)) | |
(set! has-value #t)] | |
#f)) result)] | |
(define-pass type-inference : L0 (ast) -> L1 () | |
[definitions | |
(define orig-hash-table (make-hash)) | |
(define empty-env `(,orig-hash-table))] | |
(type-infer : Expr (exp env) -> * () | |
; 常數 | |
[,c (cond | |
[(flonum? exp) `(flo ,env)] | |
[(integer? exp) `(int ,env)] | |
[(boolean? exp) `(bool ,env)])] | |
; 基本運算符調用 | |
[,pr `(,[hash-ref prim-func-type pr] ,env)] | |
; 變數 | |
[,x `(,(get-type x env) ,env)] | |
; 逐一執行指令。用 named let | |
[(begin ,body* ... ,body) (let [(exprs (append body* (list body))) | |
(tmp-env env)] | |
;(display exprs) | |
(let loop | |
[(head (car exprs)) | |
(tail (cdr exprs))] | |
(if (equal? tail '()) | |
(type-infer head tmp-env) ; 如果執行到最後一行則傳回最後一行的回傳值 | |
(begin | |
(set! tmp-env (list-ref (type-infer head env) 1)) | |
;(display table) | |
(loop (car tail) (cdr tail))))))] | |
; 定義變數 | |
[(def ,t ,x ,e) | |
(let | |
[(rhs-type (parse-L0 (unparse-L1 [list-ref (type-infer e env) 0])))] | |
(cond | |
[(equal? (unparse-L0 t) (unparse-L0 rhs-type)) (hash-set! (list-ref env [- (length env) 1]) x (parse-L1 (unparse-L0 t))) | |
; 回傳 void 值 | |
`(void ,env)] | |
[else (error (format "Expect type of ~a : ~a, found type ~a" x t rhs-type))] | |
) | |
)] | |
; lambda | |
; (lambda [(int x) (int y)] -> t* = (int int) x* = (x y)) | |
[(lambda ([,t* ,x*] ... ) ,body) | |
(let* | |
[(new-hash-table (make-hash)) | |
(extended-env (append env (list new-hash-table)))] ; 創立新表格附著在後面 | |
(for | |
[(t t*) | |
(x x*)] | |
(hash-set! (list-ref extended-env [- (length extended-env) 1]) x [parse-L1 (unparse-L0 t)])) | |
;(display (format "匿名函數掃描中~a" table)) | |
(let* | |
[ | |
(return-type (list-ref (type-infer body extended-env) 0)) ; 回傳值型別 | |
;(total-type (quoting-to-quasiquoting total-type-raw)) | |
] | |
(define t*-unparsed (map (lambda (x) (unparse-L0 x)) t*)) | |
;(define t*-unparsed-ast (unparse-L1 t*-unparsed)) | |
`[,(parse-L1 `(-> ,@t*-unparsed ,(unparse-L1 return-type))) ,env] | |
))] | |
[(,e0 ,e1 ...) (let* | |
((operator-type [list-ref (type-infer e0 env) 0]) | |
(arguments-type [map (lambda (x) (unparse-L1 (list-ref (type-infer x env) 0))) e1]) | |
(operator-type-without-return (reverse (cdr (reverse (cdr (unparse-L1 operator-type))))))) | |
(display exp)(display operator-type)(display arguments-type) | |
(if (equal? operator-type-without-return arguments-type) | |
`(,(parse-L1 (last (unparse-L1 operator-type))) ,env) | |
[begin (raise (format "expect argument type ~a, found ~a" operator-type-without-return arguments-type))]) | |
)] | |
) | |
[list-ref (type-infer ast empty-env) 0] | |
) | |
;[(and (list? e) (= 3 (length e))) | |
; (let ([op (car e)] [e0 (type-infer (cadr e))] [e1 (type-infer (caddr e))]) | |
; `(,op ,e0 ,e1))])) | |
;(define l1 (parse-L0 '(+ 1 0.1))) | |
;(type-inference l1) | |
;; convert x -> x1, y -> y2, etc. | |
(define-pass eta-conversion : L0 (ast) -> L0 () | |
[definitions | |
(define var-table `(,(make-hash))) | |
(define (combine-two-list x y) | |
(if (equal? x '()) | |
'() | |
(cons `(,(car x) ,(car y)) (combine-two-list (cdr x) (cdr y)))))] | |
(convert : Expr (exp env) -> Expr () | |
[,pr pr] | |
[(lambda ([,t* ,x*] ...) ,body) | |
(let* | |
((new-x* (map gensym x*)) | |
(t*-new-x*-pair-ls [combine-two-list t* new-x*]) | |
(new-env [append env (list (make-hash))])) | |
(for ([i x*] | |
[j new-x*]) | |
(hash-set! (last new-env) i j)) | |
;(display new-env) | |
`(lambda [[,t* ,new-x*] ...] ,(convert body new-env)))] | |
[,x | |
;(display (format "執行 ~a\n" x)) | |
(hash-ref (last env) x)] | |
[,c c] | |
[(def ,t ,x ,e) (let | |
[(new-var (gensym x))] | |
;(display (format "執行def ~a\n" x)) | |
(hash-set! (last env) x new-var) | |
`(def ,t ,new-var ,(convert e env))) | |
] | |
) | |
(convert ast var-table) | |
) | |
; (define l1 (parse-L0 '(begin (def int x 10) (def int y x) x ((lambda [(int x) (int y)] y) x y) y))) (eta-conversion l1) | |
(define (atom? x) (and | |
[not (pair? x)] | |
[not (list? x)])) | |
(define (def-undef-lambda-begin ls) | |
[let | |
[(return '())] | |
[for | |
((i ls)) | |
[match i | |
((list 'lambda var-pair body) | |
[let* | |
((new-lambda (gensym 'lam)) | |
(new-lambda-type (unparse-L0 (type-inference (parse-L0 i))) | |
) | |
(new-body (define-undef-lambda body))) | |
(set! return (append return (list `(def ,new-lambda-type ,new-lambda ,new-body) new-lambda))) | |
]) | |
(else (set! return (append return (list (define-undef-lambda i)))))]] | |
return | |
] | |
) | |
(define (def-undef-lambda-apply ls) | |
[let | |
[(new-define '()) | |
(new-apply '())] | |
[for | |
((i ls)) | |
[match i | |
((list 'lambda var-pair body) | |
[let* | |
((new-lambda (gensym 'lam)) | |
(new-lambda-type (unparse-L1 (type-inference (parse-L0 i))) | |
) | |
(new-body (define-undef-lambda body)) | |
(new-lambda-define `(def ,new-lambda-type ,new-lambda (lambda ,var-pair ,new-body)))) | |
(set! new-define (append new-define (list new-lambda-define))) | |
(set! new-apply (append new-apply (list new-lambda))) | |
]) | |
((list a ...) (let* | |
[[result (def-undef-lambda-apply a)] | |
[new-result (last result)] | |
[new-sub-define (cdr (list-remove-last result))]] ; 出來的結果會有 begin,但在括號內,我們不需要 | |
;(display new-sub-define) | |
(set! new-define (append new-define new-sub-define)) | |
(set! new-apply (append new-apply (list new-result))) | |
)) | |
(else (set! new-apply (append new-apply (list (define-undef-lambda i)))))]] | |
`(begin ,@new-define ,new-apply) | |
] | |
) | |
(define (define-undef-lambda x) | |
;; 用 match 重寫 | |
(match x | |
[(? atom? x) x] | |
; TODO | |
[(list 'def t x (list a b ...)) | |
[let* | |
[(raw-result (def-undef-lambda-apply (append (list a) b))) | |
(new-rhs (last raw-result)) | |
(new-def `(def ,t ,x ,new-rhs))] | |
(append (list-remove-last raw-result) (list new-def)) | |
]] ;TODO | |
[(list 'def t x e) (match e | |
[(list 'lambda var-pair body) `(def ,t ,x ,e)] | |
[else `(def ,t ,x ,(define-undef-lambda e))])] | |
[(list 'begin a ...) `(begin ,@(def-undef-lambda-begin a))] | |
[(list 'lambda var-pair body) | |
[let* | |
((new-lambda (gensym 'lam)) | |
(new-lambda-type (unparse-L0 (type-inference (parse-L0 x))) | |
) | |
(new-body (define-undef-lambda body))) | |
`(begin (def ,new-lambda-type ,new-lambda (lambda ,var-pair ,new-body)) ,new-lambda)]] | |
[(list a b ...) (def-undef-lambda-apply x)] | |
)) | |
;; 用 match 重寫 | |
;[flatten-begin '(begin | |
; 12 | |
; 5 | |
; y | |
; (begin 12 1 (begin (lambda [(x 5)(y 7)] y))) | |
; )] | |
; -> '(begin 12 5 y 12 1 (lambda ((x 5) (y 7)) y)) | |
(define [flatten-begin x] | |
(match x | |
[(list (list 'begin i ...) o ...) (append (flatten-begin i) (flatten-begin o))] | |
[(list a b ...) (append (list (flatten-begin a)) (flatten-begin b))] | |
[(? pair? x) x] | |
[(? null? x) x] | |
[(? atom? x) x] | |
[(list a) (list a)] | |
) | |
) | |
(define-pass remove-undefined-lambda : L0 (ast) -> L0 () | |
[definitions | |
[define unparsed-ast (unparse-L0 ast)] | |
[define removed-result-ast (flatten-begin(define-undef-lambda unparsed-ast))] | |
] | |
(parse-L0 removed-result-ast) | |
) | |
(define test-0 '((lambda ((int x)) 9))) | |
(define test-1 '([lambda ((int x)) (lambda ((flo y)) x)] 9)) | |
(define test-2 '(begin 12 [lambda ((int x)) x] 9)) | |
(define test-3 '(begin 12 | |
[def int kk | |
((lambda ([int x]) 20) ((lambda (((-> flo int) y) (int z)) 8) (lambda ((flo z)) 10) 12))] | |
1.0 | |
kk)) | |
(define test-4 '([lambda ((int x)) (lambda ((flo y)) x)] 9)) | |
(define test-5 '(begin 12 [lambda ((int x)) x] 9)) | |
(define test-6 | |
'(begin | |
3.0 | |
(def bool x (and (or #t #t) #f)) | |
(def flo y 10.0) | |
; uncaught exception: "lambda have duplicated variables: y" | |
;(lambda ([int x] [int y] [int y]) (+ x y 10)) | |
;uncaught exception: "z is not defined." | |
;(lambda ([int x] [int y]) (+ x y z 10)) | |
;(def flo k (lambda (x y z) (+ y x z g))) | |
(def flo z (+. 10.0 y)) | |
(+. 1.0 3.0) | |
z | |
(lambda ([int x] [int y]) 9.9) | |
)) | |
;;; | |
; Test-area | |
;;; | |
;(define-undef-lambda '(begin 7 x (lambda [(int x)(flo y)] y) 10)) | |
;(define-undef-lambda '(begin 7 x (def int x 2) (def int x (begin (lambda [(int x)(flo y)] y) 10)) )) | |
;(define-undef-lambda '(lambda ([int x]) (lambda ([int y]) 12))) | |
;(define-undef-lambda '((lambda ([int x]) 20) (lambda ((flo y)) 12))) ; 錯誤需要debug?? | |
;(define-undef-lambda '((lambda ([int x]) 20) ((lambda ((flo y)) 8) (lambda ((flo z)) 10) 12))) | |
;(define-undef-lambda '(begin 12 [def int kk ((lambda ([int x]) 20) ((lambda ((flo y)) 8) (lambda ((flo z)) 10) 12))] 1.0)) | |
;(parse-L0 (flatten-begin (define-undef-lambda '(begin 12 [def int kk ((lambda ([int x]) 20) ((lambda ((flo y)) 8) (lambda ((flo z)) 10) 12))] 1.0)))) | |
(define [compiler ast] | |
(display "Start compiling...\n") | |
(let* | |
[(found-dup-var-ast (find-dup-var-main ast)) | |
(ann-lambda-defined-ast (define-undef-lambda ast)) | |
(ann-lambda-defined-L0 (parse-L0 ann-lambda-defined-ast)) | |
(begin-flattened-L0 (remove-undefined-lambda ann-lambda-defined-L0)) | |
(etaed-L0 (eta-conversion begin-flattened-L0)) | |
(type-infered-type (type-inference etaed-L0))] | |
(display "End compiling...\n") | |
ann-lambda-defined-L0 | |
) | |
) | |
(compiler test-1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment