aboutsummaryrefslogtreecommitdiff
path: root/semestr-2/racket/luk.rkt
blob: cc319a57d5464f42c1d619dee0a4bd31967db7b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#lang typed/racket

; Do let-env.rkt dodajemy wartosci boolowskie
;
; Miejsca, ktore sie zmienily oznaczone sa przez !!!

; --------- ;
; Wyrazenia ;
; --------- ;
(provide parse typecheck)

(define-type Value (U Boolean Real))
(define-type Expr (U const binop var-expr let-expr if-expr))
(define-type ArithSymbol (U '+ '- '* '/))
(define-type LogicSymbol (U 'and 'or))
(define-type CompSymbol (U '< '= '> '<= '>=))
(define-type BinomSymbol (U ArithSymbol LogicSymbol CompSymbol))

(define-type Binop-list (List BinomSymbol Any Any))
(define-type Let-list (List 'let (List Symbol Any) Any))
(define-type If-list (List 'if Any Any Any))

(define-predicate Binop-list? Binop-list)
(define-predicate Let-list? Let-list)
(define-predicate If-list? If-list)

(struct const    ([val : Value])      #:transparent)
(struct binop    ([op : BinomSymbol] [l : Expr] [r : Expr])   #:transparent)
(struct var-expr ([id : Symbol])       #:transparent)
(struct let-expr ([id : Symbol] [e1 : Expr] [e2 : Expr]) #:transparent)
(struct if-expr  ([eb : Expr] [et : Expr] [ef : Expr]) #:transparent)

(define-predicate Value? Value)
(define-predicate Expr? Expr)
(define-predicate BinomSymbol? BinomSymbol)
(define-predicate ArithSymbol? ArithSymbol)
(define-predicate LogicSymbol? LogicSymbol)
(define-predicate CompSymbol? CompSymbol)
(define-predicate BinomValue? BinomValue)



(: parse (-> Any Expr))
(define (parse q)
  (cond
    [(real? q) (const q)]
    [(eq? q 'true)  (const true)]  ; <---------------------------- !!!
    [(eq? q 'false) (const false)] ; <---------------------------- !!!
    [(symbol? q) (var-expr q)]
    [(Let-list? q)
     (let-expr (first (second q))
               (parse (second (second q)))
               (parse (third q)))]
    [(If-list? q) ; <--- !!!
     (if-expr (parse (second q))
              (parse (third q))
              (parse (fourth q)))]
    [(Binop-list? q)
     (binop (first q)
            (parse (second q))
            (parse (third q)))]
    [else (error "Blad parsowania" q)]))

   


(define (test-parse) (parse '(let [x (+ 2 2)] (+ x 1))))

; ---------- ;
; Srodowiska ;
; ---------- ;
(define-type EType ( U 'real 'boolean ) )
(define-type Env (Listof (Pairof Symbol EType)))
(define-predicate Env? Env)
(struct environ ([xs : Env]))

(: env-empty environ)
(define env-empty (environ null))
(: env-add (-> Symbol EType environ environ))
(define (env-add x v env)
  (environ (cons (cons x v) (environ-xs env))))
(: env-lookup (-> Symbol environ (U EType #f)))
(define (env-lookup x env)
  (: assoc-lookup (-> Env EType))
  (define (assoc-lookup xs)
    (cond [(null? xs) (error "Unknown identifier" x)]
          [(eq? x (car (car xs))) (cdr (car xs))]
          [else (assoc-lookup (cdr xs))]))
  (assoc-lookup (environ-xs env)))


(: typecheck (-> Expr (U EType #f)))
(define (typecheck q)
  (: give (-> Expr environ (U EType #f)))
  (define (give q envi)
  (cond
    [(const? q) (if (boolean? (const-val q)) 'boolean 'real)]
    [(var-expr? q) (env-lookup (var-expr-id q) envi)]
    [(let-expr? q)
     (let ([p (give (let-expr-e1 q) envi)]) (if (false? p) #f (give (let-expr-e2 q) (env-add (let-expr-id q) p envi))))]
    [(binop? q)
     (cond
       ([ArithSymbol? (binop-op q)] (if (and (eq? 'real (give (binop-l q) envi)) (eq? 'real (give (binop-r q) envi))) 'real #f))
       ([LogicSymbol? (binop-op q)] (if (and (eq? 'boolean (give (binop-l q) envi)) (eq? 'boolean (give (binop-r q) envi))) 'boolean #f))
       ([CompSymbol? (binop-op q)] (if (and (eq? 'real (give (binop-l q) envi)) (eq? 'real (give (binop-r q) envi))) 'boolean #f))
       [else #f])]
    [(if-expr? q)
     (if (and (eq? 'real (if-expr-eb q)) 
              (eq? (give (if-expr-et q) envi) (give (if-expr-ef q) envi))) 
         (give (if-expr-et q) envi) 
         #f)]
    [else #f]))


  (give q env-empty))



(define program2
  '(if true
       (let [x 5] (+ 5 false))
       (/ 2 2)))

(define program3
  '(let [x (+ 2 3)]
     (let [y (< 2 3)]
       (+ x y))))

(define program4
  '(let [x (and true true)] x))

(define wtf
  '(and true true))

(typecheck (parse program2))
(typecheck (parse program3))
(typecheck (parse program4))