forked from coalton-lang/coalton
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtoplevel-specializations.lisp
93 lines (66 loc) · 3.66 KB
/
toplevel-specializations.lisp
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
(in-package #:coalton-impl)
(defun process-toplevel-specializations (specializations env)
(declare (type list specializations)
(type tc:environment env)
(values tc:specialization-entry-list tc:environment))
(let ((out-specializations nil))
(loop :for elem :in specializations
:do (multiple-value-bind (specialization new-env)
(process-specialization elem env)
(push specialization out-specializations)
(setf env new-env)))
(values
out-specializations
env)))
(defun process-specialization (elem env)
(declare (type list elem)
(type tc:environment env)
(values tc:specialization-entry tc:environment &optional))
(unless (= (length elem) 4)
(ast:error-parsing elem "Malformed specialization"))
(let* ((from (second elem))
(to (third elem))
(type (fourth elem)))
(unless (and (symbolp from) (symbolp to))
(ast:error-parsing elem "Malformed specialization"))
(let* ((from-ty (tc:lookup-value-type env from :no-error t))
(to-ty (tc:lookup-value-type env to :no-error t))
(from-name (tc:lookup-name env from))
(to-name (tc:lookup-name env to))
(type (tc:fresh-inst (tc:parse-and-resolve-type env type))))
(unless from-ty
(ast:error-parsing elem "Unable to specialize unknown function ~A" from))
(unless to-ty
(ast:error-parsing elem "Unable to specialize unknown function ~A" to))
(unless (eq :value (tc:name-entry-type from-name))
(ast:error-parsing elem "Unable to specialize ~A because it is a ~A" from (tc:name-entry-type from-name)))
(unless (eq :value (tc:name-entry-type to-name))
(ast:error-parsing elem "Unable to specialize ~A to ~A because it is a ~A" from to (tc:name-entry-type to-name)))
(let* ((from-ty (tc:fresh-inst from-ty))
(to-ty (tc:fresh-inst to-ty)))
(tc:with-pprint-variable-context ()
(when (null (tc:qualified-ty-predicates from-ty))
(ast:error-parsing elem "Unable to specialize function ~A~%of type ~A. ~%Only functions with type class constraints may be specialized." from from-ty)))
(unless (null (tc:qualified-ty-predicates to-ty))
(ast:error-parsing elem "Unable to make ~A a specialization target for ~A. ~%Only functions without type class constraints may be specialization targets." to from))
(tc:with-pprint-variable-context ()
(unless (null (tc:qualified-ty-predicates type))
(ast:error-parsing elem "Unable to specialize ~A to type ~A with type class constraints." from type)))
(tc:with-pprint-variable-context ()
(unless (tc:type= (tc:qualified-ty-type to-ty) (tc:qualified-ty-type type))
(ast:error-parsing elem "Function ~A of type ~A~%does not match declared type ~A" to to-ty type)))
(when (tc:type= (tc:qualified-ty-type from-ty) (tc:qualified-ty-type to-ty))
(ast:error-parsing elem "Function ~A does not have a more specefic type than ~A" to from))
(handler-case
(tc:match (tc:qualified-ty-type from-ty) (tc:qualified-ty-type to-ty))
(tc:coalton-type-error (e)
(declare (ignore e))
(tc:with-pprint-variable-context ()
(ast:error-parsing elem "Function ~A of type ~A is not a valid specialization ~%for ~A of type ~A" to to-ty from from-ty))))
(let ((entry (tc:make-specialization-entry
:from from
:to to
:to-ty (tc:qualified-ty-type to-ty))))
(values
entry
(tc:add-specialization env entry)))))))