ikarus/scheme/ikarus.compiler.tag-annotat...

440 lines
15 KiB
Scheme

;;; Ikarus Scheme -- A compiler for R6RS Scheme.
;;; Copyright (C) 2006,2007,2008 Abdulaziz Ghuloum
;;;
;;; This program is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License version 3 as
;;; published by the Free Software Foundation.
;;;
;;; This program is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;; General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; THIS IS WIP
(include-src "ikarus.ontology.ss")
(define tag-analysis-output (make-parameter #f))
(define (introduce-tags x)
(define who 'introduce-tags)
#;
(define primitive-return-types
'(
[= boolean]
[< boolean]
[<= boolean]
[> boolean]
[>= boolean]
[even? boolean]
[odd? boolean]
[rational? boolean]
[rational-valued? boolean]
[real? boolean]
[real-valued? boolean]
[bignum? boolean]
[ratnum? boolean]
[flonum? boolean]
[fixnum? boolean]
[integer? boolean]
[exact? boolean]
[finite? boolean]
[inexact? boolean]
[infinite? boolean]
[positive? boolean]
[negative? boolean]
[nan? boolean]
[number? boolean]
[compnum? boolean]
[cflonum? boolean]
[complex? boolean]
[list? boolean]
[eq? boolean]
[eqv? boolean]
[equal? boolean]
[gensym? boolean]
[symbol-bound? boolean]
[code? boolean]
[immediate? boolean]
[pair? boolean]
[procedure? boolean]
[symbol? boolean]
[symbol=? boolean]
[boolean? boolean]
[boolean=? boolean]
[vector? boolean]
[bitwise-bit-set? boolean]
[bytevector? boolean]
[bytevector=? boolean]
[enum-set=? boolean]
[binary-port? boolean]
[textual-port? boolean]
[input-port? boolean]
[output-port? boolean]
[port? boolean]
[port-eof? boolean]
[port-closed? boolean]
[char-ready? boolean]
[eof-object? boolean]
[hashtable? boolean]
[hashtable-mutable? boolean]
[file-exists? boolean]
[file-regular? boolean]
[file-directory? boolean]
[file-readable? boolean]
[file-writable? boolean]
[file-executable? boolean]
[file-symbolic-link? boolean]
[record? boolean]
[record-field-mutable? boolean]
[record-type-generative? boolean]
[record-type-sealed? boolean]
[record-type-descriptor boolean]
[free-identifier=? boolean]
[bound-identifier=? boolean]
[identifier? boolean]
[char-lower-case? boolean]
[char-upper-case? boolean]
[char-title-case? boolean]
[char-whitespace? boolean]
[char-numeric? boolean]
[char-alphabetic? boolean]
))
(define number!
(let ([i 0])
(lambda (x)
(set-prelex-operand! x i)
(set! i (+ i 1)))))
(define (V* x* env)
(cond
[(null? x*) (values '() env '())]
[else
(let-values ([(x env1 t) (V (car x*) env)]
[(x* env2 t*) (V* (cdr x*) env)])
(values (cons x x*)
(and-envs env1 env2)
(cons t t*)))]))
(define (constant-type x)
(define (numeric x)
(define (size x t)
(T:and t
(cond
[(< x 0) T:negative]
[(> x 0) T:positive]
[(= x 0) T:zero]
[else t])))
(cond
[(fixnum? x) (size x T:fixnum)]
[(flonum? x) (size x T:flonum)]
[(or (bignum? x) (ratnum? x))
(size x (T:and T:exact T:other-number))]
[else T:number]))
(cond
[(number? x) (numeric x)]
[(boolean? x) (if x T:true T:false)]
[(null? x) T:null]
[(char? x) T:char]
[(string? x) T:string]
[(vector? x) T:vector]
[(pair? x) T:pair]
[(eq? x (void)) T:void]
[else T:object]))
(define (V x env)
(struct-case x
[(constant k) (values x env (constant-type k))]
[(prelex) (values x env (lookup x env))]
[(primref op) (values x env T:procedure)]
[(seq e0 e1)
(let-values ([(e0 env t) (V e0 env)])
(cond
[(eq? (T:object? t) 'no)
(values e0 env t)]
[else
(let-values ([(e1 env t) (V e1 env)])
(values (make-seq e0 e1) env t))]))]
[(conditional e0 e1 e2)
(let-values ([(e0 env t) (V e0 env)])
(cond
[(eq? (T:object? t) 'no)
(values e0 env t)]
[(eq? (T:false? t) 'yes)
(let-values ([(e2 env t) (V e2 env)])
(values (make-seq e0 e2) env t))]
[(eq? (T:false? t) 'no)
(let-values ([(e1 env t) (V e1 env)])
(values (make-seq e0 e1) env t))]
[else
(let-values ([(e1 env1 t1) (V e1 env)]
[(e2 env2 t2) (V e2 env)])
(values (make-conditional e0 e1 e2)
(or-envs env1 env2)
(T:or t1 t2)))]))]
[(bind lhs* rhs* body)
(let-values ([(rhs* env t*) (V* rhs* env)])
(for-each number! lhs*)
(let ([env (extend-env* lhs* t* env)])
(let-values ([(body env t) (V body env)])
(values
(make-bind lhs* rhs* body)
env t))))]
[(fix lhs* rhs* body)
(for-each number! lhs*)
(let-values ([(rhs* env t*) (V* rhs* env)])
(let ([env (extend-env* lhs* t* env)])
(let-values ([(body env t) (V body env)])
(values
(make-fix lhs* rhs* body)
env t))))]
[(clambda g cls* cp free name)
(values
(make-clambda g
(map
(lambda (x)
(struct-case x
[(clambda-case info body)
(for-each number! (case-info-args info))
(let-values ([(body env t) (V body env)])
;;; dropped env and t
(make-clambda-case info body))]))
cls*)
cp free name)
env
T:procedure)]
[(funcall rator rand*)
(let-values ([(rator rator-env rator-val) (V rator env)]
[(rand* rand*-env rand*-val) (V* rand* env)])
(apply-funcall rator rand*
rator-val rand*-val
rator-env rand*-env))]
[(forcall rator rand*)
(let-values ([(rand* rand*-env rand*-val) (V* rand* env)])
(values (make-forcall rator rand*)
rand*-env
T:object))]
[else (error who "invalid expression" (unparse x))]))
(define (annotate x t)
(cond
[(T=? t T:object) x]
[else (make-known x t)]))
(define (apply-funcall rator rand* rator-val rand*-val rator-env rand*-env)
(let ([env (and-envs rator-env rand*-env)]
[rand* (map annotate rand* rand*-val)])
(struct-case rator
[(primref op)
(apply-primcall op rand* env)]
[else
(values (make-funcall (annotate rator rator-val) rand*)
env
T:object)])))
(define (apply-primcall op rand* env)
(define (return t)
(values (make-funcall (make-primref op) rand*) env t))
(define (inject ret-t . rand-t*)
(define (extend* x* t* env)
(define (extend x t env)
(struct-case x
[(known expr t0)
(extend expr (T:and t t0) env)]
[(prelex)
(extend-env x t env)]
[else env]))
(cond
[(null? x*) env]
[else (extend (car x*) (car t*)
(extend* (cdr x*) (cdr t*) env))]))
(values
(make-funcall (make-primref op) rand*)
(if (= (length rand-t*) (length rand*))
(extend* rand* rand-t* env)
env) ;;; incorrect number of args
ret-t))
(define (inject* ret-t arg-t)
(define (extend* x* env)
(define (extend x t env)
(struct-case x
[(known expr t0)
(extend expr (T:and t t0) env)]
[(prelex)
(extend-env x t env)]
[else env]))
(cond
[(null? x*) env]
[else (extend (car x*) arg-t
(extend* (cdr x*) env))]))
(values (make-funcall (make-primref op) rand*)
(extend* rand* env)
ret-t))
(case op
[(cons)
(return T:pair)]
[(car cdr
caar cadr cdar cddr
caaar caadr cadar caddr cdaar cdadr cddar cdddr
caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr)
(inject T:object T:pair)]
[(set-car! set-cdr!)
(inject T:void T:pair T:object)]
[(vector make-vector list->vector)
(return T:vector)]
[(string make-string list->string)
(return T:string)]
[(string-length)
(inject T:fixnum T:string)]
[(vector-length)
(inject T:fixnum T:vector)]
[(string-ref)
(inject T:char T:string T:fixnum)]
[(string-set!)
(inject T:void T:string T:fixnum T:char)]
[(vector-ref)
(inject T:object T:vector T:fixnum)]
[(vector-set!)
(inject T:void T:vector T:fixnum T:object)]
[(length)
(inject T:fixnum (T:or T:null T:pair))]
[(bytevector-length)
(inject T:fixnum T:bytevector)]
[(integer->char)
(inject T:char T:fixnum)]
[(char->integer)
(inject T:fixnum T:char)]
[(bytevector-u8-ref bytevector-s8-ref
bytevector-u16-native-ref bytevector-s16-native-ref)
(inject T:fixnum T:bytevector T:fixnum)]
[(bytevector-u16-ref bytevector-s16-ref)
(inject T:fixnum T:bytevector T:fixnum T:symbol)]
[(bytevector-u8-set! bytevector-s8-set!
bytevector-u16-native-set! bytevector-s16-native-set!)
(inject T:void T:bytevector T:fixnum T:fixnum)]
[(bytevector-u16-set! bytevector-s16-set!)
(inject T:void T:bytevector T:fixnum T:fixnum T:symbol)]
[(fx+ fx- fx* fxadd1 fxsub1
fxquotient fxremainder fxmodulo fxsll fxsra
fxand fxdiv fxdiv0 fxif fxior
fxlength fxmax fxmin fxmod fxmod0
fxnot fxxor fxlogand fxlogor fxlognot
fxlogxor)
(inject* T:fixnum T:fixnum)]
[(fx= fx< fx<= fx> fx>= fx=? fx<? fx<=? fx>? fx>=?
fxeven? fxodd? fxnegative? fxpositive? fxzero?
fxbit-set?)
(inject* T:boolean T:fixnum)]
[(fl=? fl<? fl<=? fl>? fl>=?
fleven? flodd? flzero? flpositive? flnegative?
flfinite? flinfinite? flinteger? flnan?)
(inject* T:boolean T:flonum)]
[(char=? char<? char<=? char>? char>=?
char-ci=? char-ci<? char-ci<=? char-ci>? char-ci>=?)
(inject* T:boolean T:char)]
[(string=? string<? string<=? string>? string>=?
string-ci=? string-ci<? string-ci<=? string-ci>?
string-ci>=?)
(inject* T:boolean T:string)]
[(make-parameter
record-constructor
record-accessor
record-constructor
record-predicate
condition-accessor
condition-predicate
enum-set-constructor
enum-set-indexer
make-guardian)
(return T:procedure)]
[(fixnum-width greatest-fixnum least-fixnum)
(return T:fixnum)]
[else
(return T:object)]))
;;;
(define (extend-env* x* v* env)
(cond
[(null? x*) env]
[else
(extend-env* (cdr x*) (cdr v*)
(extend-env (car x*) (car v*) env))]))
(define (extend-env x t env)
(cond
[(T=? t T:object) env]
[else
(let ([x (prelex-operand x)])
(let f ([env env])
(cond
[(or (null? env) (< x (caar env)))
(cons (cons x t) env)]
[else
(cons (car env) (f (cdr env)))])))]))
(define (or-envs env1 env2)
(define (cons-env x v env)
(cond
[(T=? v T:object) env]
[else (cons (cons x v) env)]))
(define (merge-envs1 a1 env1 env2)
(if (pair? env2)
(merge-envs2 a1 env1 (car env2) (cdr env2))
empty-env))
(define (merge-envs2 a1 env1 a2 env2)
(let ([x1 (car a1)] [x2 (car a2)])
(if (eq? x1 x2)
(cons-env x1 (T:or (cdr a1) (cdr a2))
(merge-envs env1 env2))
(if (< x2 x1)
(merge-envs1 a1 env1 env2)
(merge-envs1 a2 env2 env1)))))
(define (merge-envs env1 env2)
(if (eq? env1 env2)
env1
(if (pair? env1)
(if (pair? env2)
(merge-envs2 (car env1) (cdr env1) (car env2) (cdr env2))
empty-env)
empty-env)))
(merge-envs env1 env2))
(define (and-envs env1 env2)
(define (cons-env x v env)
(cond
[(T=? v T:object) env]
[else (cons (cons x v) env)]))
(define (merge-envs1 a1 env1 env2)
(if (pair? env2)
(merge-envs2 a1 env1 (car env2) (cdr env2))
env1))
(define (merge-envs2 a1 env1 a2 env2)
(let ([x1 (car a1)] [x2 (car a2)])
(if (eq? x1 x2)
(cons-env x1 (T:and (cdr a1) (cdr a2))
(merge-envs env1 env2))
(if (< x2 x1)
(cons a2 (merge-envs1 a1 env1 env2))
(cons a1 (merge-envs1 a2 env2 env1))))))
(define (merge-envs env1 env2)
(if (eq? env1 env2)
env1
(if (pair? env1)
(if (pair? env2)
(merge-envs2 (car env1) (cdr env1) (car env2) (cdr env2))
env1)
env2)))
(merge-envs env1 env2))
(define empty-env '())
(define (lookup x env)
(cond
[(eq? env 'bottom) #f]
[else
(let ([x (prelex-operand x)])
(cond
[(assq x env) => cdr]
[else T:object]))]))
(let-values ([(x env t) (V x empty-env)])
(when (tag-analysis-output)
(pretty-print (unparse-pretty x)))
x))