4 * ----------------------------------------------------------------
7 * Copyright (C) 2001 Jason Hickey, Caltech
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Author: Jason Hickey
24 * @email{jyh@cs.caltech.edu}
43 module Pos
= MakePos
(struct let name = "Fir_type" end)
47 (************************************************************************
49 ************************************************************************)
51 let ty_int8 = TyRawInt
(Rawint.Int8
, false)
52 let ty_int16 = TyRawInt
(Rawint.Int16
, true)
53 let ty_int32 = TyRawInt
(Rawint.Int32
, true)
54 let ty_int64 = TyRawInt
(Rawint.Int64
, true)
55 let ty_uint64 = TyRawInt
(Rawint.Int64
, false)
57 let ty_float32 = TyFloat
Rawfloat.Single
58 let ty_float64 = TyFloat
Rawfloat.Double
59 let ty_float80 = TyFloat
Rawfloat.LongDouble
61 let ty_char = TyRawInt
(Rawint.Int8
, true)
62 let ty_subscript = TyRawInt
(precision_subscript
, signed_subscript
)
64 let ty_string = TyArray
ty_char
65 let ty_ml_string = TyArray
(TyEnum
256)
67 let int_set_zero = IntSet.of_point
0
68 let false_set = int_set_zero
69 let int_set_one = IntSet.of_point
1
70 let true_set = int_set_one
72 let ty_bool = TyEnum
2
73 let ty_unit = TyEnum
1
74 let ty_void = TyEnum
0
76 (* Type of the FC main function. *)
78 * BUG: Assumes the 2 argument form of main.
80 let ty_fc_sym1 = new_symbol_string
"ty_fc_main"
81 let ty_fc_sym2 = new_symbol_string
"ty_fc_main"
83 TyAll
( [ ty_fc_sym1; ty_fc_sym2 ],
87 TyFun
( [ TyVar
ty_fc_sym1; ty_int32 ], ty_void );
89 TyFun
( [ TyVar
ty_fc_sym2; TyRawData
; ty_int32 ], ty_void );
94 (************************************************************************
96 ************************************************************************)
99 * Var should be an atom.
101 let var_of_atom pos a
=
106 let pos = string_pos
"var_of_atom" pos in
107 raise
(FirException
(pos, StringAtomError
("not a var", a
)))
109 let rec var_of_fun pos a
=
111 AtomTyApply
(a
, _
, _
) ->
117 let pos = string_pos
"var_of_fun" pos in
118 raise
(FirException
(pos, StringAtomError
("not a var", a
)))
120 (************************************************************************
122 ************************************************************************)
127 let apply_type_dir tenv
pos v tyl
=
128 let pos = string_pos
"apply_type_dir" pos in
129 match tenv_lookup tenv
pos v
with
130 TyDefLambda
(vars
, ty
) ->
131 subst_type_simul
pos ty vars tyl
132 | TyDefUnion
(vars
, fields
) ->
133 let len1 = List.length vars
in
134 let len2 = List.length tyl
in
137 raise
(FirException
(pos, ArityMismatch
(len1, len2)))
139 let tags_num = List.length fields
in
140 let tag_set = IntSet.of_interval
(Closed
0) (Open
tags_num) in
141 TyUnion
(v
, tyl
, tag_set)
146 raise
(FirException
(pos, StringError
"dependent tuples are not polymorphic"))
149 * Expand the union fields.
151 let apply_union_dir tenv
pos v tyl
=
152 match tenv_lookup tenv
pos v
with
153 TyDefUnion
(vars
, fields
) ->
158 let len1 = List.length vars
in
159 let len2 = List.length tyl
in
161 raise
(FirException
(pos, ArityMismatch
(len1, len2)));
162 List.fold_left2 subst_add_type_var subst_empty vars tyl
164 List.map
(List.map
(fun (ty
, b
) -> subst_type
tvenv ty
, b
)) fields
166 raise
(FirException
(pos, TyDefError tyd
))
168 let union_size_dir tenv
pos tv
=
169 match tenv_lookup tenv
pos tv
with
173 raise
(FirException
(string_pos
"union_size" pos, TyDefError tyd
))
176 * Expand a type one level.
178 let rec tenv_expand_dir tenv
pos ty
=
181 tenv_expand_dir tenv
pos (apply_type_dir tenv
pos v tyl
)
183 | TyExists
([], ty
) ->
184 tenv_expand_dir tenv
pos ty
189 * Destruct a union type.
191 let dest_union_tydef pos ty
=
192 let pos = string_pos
"dest_union_tydef" pos in
194 TyDefUnion
(vars
, fields
) ->
198 raise
(FirException
(pos, StringTydefError
("not a union type", ty
)))
201 * Check that the type var is a dependent tuple type.
203 let is_dtuple_tydef_dir tenv
pos ty_var
=
204 let pos = string_pos
"dest_dtuple_tydef" pos in
205 match tenv_lookup tenv
pos ty_var
with
212 (************************************************************************
214 ************************************************************************)
219 let rec is_fun_type_dir tenv
pos ty
=
220 match tenv_expand_dir tenv
pos ty
with
224 | TyExists
(_, ty
) ->
225 is_fun_type_dir tenv
pos ty
229 let rec is_pointer_type_dir tenv
pos ty
=
230 match tenv_expand_dir tenv
pos ty
with
244 | TyExists
(_, ty
) ->
245 is_pointer_type_dir tenv
pos ty
255 raise
(FirException
(pos, StringTypeError
("invalid pointer test", ty
)))
260 let rec dest_exists_type_dir tenv
pos ty
=
261 match tenv_expand_dir tenv
pos ty
with
262 TyExists
(vars
, ty
) ->
267 let rec dest_all_type_dir tenv
pos ty
=
268 let pos = string_pos
"dest_all_type_dir" pos in
269 match tenv_expand_dir tenv
pos ty
with
271 let vars2, ty
= dest_all_type_dir tenv
pos ty
in
276 let dest_all_type_rename_dir tenv
pos ty ty_vars
=
277 let pos = string_pos
"dest_all_type_rename_dir" pos in
278 let ty_vars'
, ty
= dest_all_type_dir tenv
pos ty
in
279 let len1 = List.length
ty_vars'
in
280 let len2 = List.length
ty_vars in
283 raise
(FirException
(pos, ArityMismatch
(len1, len2)))
286 List.fold_left2
(fun subst v1 v2
->
287 subst_add_type_var
subst v1
(TyVar v2
)) subst_empty
ty_vars'
ty_vars
292 * Break apart the function type.
293 * Also destruct the universal quantifier.
295 let rec dest_all_fun_type_dir tenv
pos ty
=
296 match tenv_expand_dir tenv
pos ty
with
297 TyFun
(ty_vars, ty_res
) ->
299 | TyAll
(vars
, ty
) ->
300 let vars'
, ty_vars, ty_res
= dest_all_fun_type_dir tenv
pos ty
in
301 vars @ vars'
, ty_vars, ty_res
303 raise
(FirException
(pos, NotAFunction ty
))
305 let dest_fun_type_dir tenv
pos ty
=
306 match tenv_expand_dir tenv
pos ty
with
307 TyFun
(ty_vars, ty_res
) ->
310 raise
(FirException
(pos, NotAFunction ty
))
313 * Get some random new type for the function
314 * by using new vars for the all quantifiers.
316 let poly_fun_type_dir tenv
pos ty
=
317 let pos = string_pos
"poly_fun_type" pos in
318 let ty_vars, ty_args
, ty_res
= dest_all_fun_type_dir tenv
pos ty
in
319 let ty_vars'
= List.map
(fun v
-> TyVar
(new_symbol_pre
"poly" v
)) ty_vars in
320 let subst = List.fold_left2 subst_add_type_var subst_empty
ty_vars ty_vars'
in
321 let ty_args = List.map
(subst_type
subst) ty_args in
322 let ty_res = subst_type
subst ty_res in
325 let rec dest_union_type_dir tenv
pos ty
=
326 match tenv_expand_dir tenv
pos ty
with
327 TyUnion
(tv
, tl
, i
) ->
330 raise
(FirException
(pos, NotAUnion ty
))
332 let dest_tuple_type_dir tenv
pos ty
=
333 match tenv_expand_dir tenv
pos ty
with
337 raise
(FirException
(pos, StringTypeError
("not a tuple type", ty
)))
339 let dest_dtuple_type_dir tenv
pos ty
=
340 match tenv_expand_dir tenv
pos ty
with
341 TyDTuple
(ty_var
, fields
) ->
344 raise
(FirException
(pos, StringTypeError
("not a dependent tuple type", ty
)))
346 let dest_tag_type_dir tenv
pos ty
=
347 match tenv_expand_dir tenv
pos ty
with
348 TyTag
(ty_var
, fields
) ->
351 raise
(FirException
(pos, StringTypeError
("not a tag type", ty
)))
353 let rec dest_array_type_dir tenv
pos ty
=
354 match tenv_expand_dir tenv
pos ty
with
358 raise
(FirException
(pos, StringTypeError
("not an array type", ty
)))
360 let dest_case_type_dir tenv
pos ty
=
361 match tenv_expand_dir tenv
pos ty
with
365 raise
(FirException
(pos, StringTypeError
("not a case type", ty
)))
367 let dest_object_type_dir tenv
pos ty
=
368 match tenv_expand_dir tenv
pos ty
with
370 let subst = subst_add_type_var subst_empty v ty
in
373 raise
(FirException
(pos, StringTypeError
("not an object type", ty
)))
375 let unfold_object_type_dir tenv
pos ty
=
376 match tenv_expand_dir tenv
pos ty
with
378 let subst = subst_add_type_var subst_empty v ty
in
383 let is_frame_type_dir tenv
pos ty
=
384 match tenv_expand_dir tenv
pos ty
with
390 let dest_frame_type_dir tenv
pos ty
=
391 match tenv_expand_dir tenv
pos ty
with
392 TyFrame
(label
, tyl
) ->
395 raise
(FirException
(pos, StringTypeError
("not a frame type", ty
)))
397 let is_rawdata_type_dir tenv
pos ty
=
398 match tenv_expand_dir tenv
pos ty
with
405 * Existential unpacking.
407 let unpack_type_dir tenv
pos v ty
=
408 let pos = string_pos
"unpack_type" pos in
409 let vars, ty
= dest_exists_type_dir tenv
pos ty
in
411 List.fold_left
(fun (subst, i
) v'
->
412 let subst = subst_add_type_var
subst v'
(TyProject
(v
, i
)) in
413 subst, succ i
) (subst_empty
, 0) vars
418 * Get the subscript value from the type.
420 let rec sub_value_of_type_dir tenv
pos ty
=
421 let pos = string_pos
"sub_value_of_type" pos in
422 match tenv_expand_dir tenv
pos ty
with
425 | TyTag
(ty_var
, tyl
) ->
429 | TyRawInt
(pre
, signed
) ->
430 RawIntSub
(pre
, signed
)
453 sub_value_of_type_dir tenv
pos ty
455 raise
(Invalid_argument
"sub_value_of_type")
457 (************************************************************************
459 ************************************************************************)
462 * Figure out the type of a field in a frame.
464 let apply_frame genv
pos v tyl
(_, v_field
, v_subfield
) =
465 let pos = string_pos
"apply_frame_dir" pos in
466 let vars, fields
= genv_lookup_frame genv
pos v
in
468 try SymbolTable.find fields v_field
with
470 raise
(FirException
(pos, StringVarError
("unbound field", v_field
)))
473 let rec search = function
474 (v_subfield'
, ty, i
) :: subfields ->
475 if Symbol.eq v_subfield' v_subfield
then
480 raise
(FirException
(pos, StringVarError
("unbound subfield", v_subfield
)))
484 let ty = subst_type_simul
pos ty vars tyl
in
488 * All the rest are straightforward.
490 let apply_type genv
= apply_type_dir (tenv_of_genv genv
)
491 let apply_union genv
= apply_union_dir (tenv_of_genv genv
)
493 let expand_type genv
= tenv_expand_dir (tenv_of_genv genv
)
494 let union_size genv
= union_size_dir (tenv_of_genv genv
)
496 let is_dtuple_tydef genv
= is_dtuple_tydef_dir (tenv_of_genv genv
)
498 let is_fun_type genv
= is_fun_type_dir (tenv_of_genv genv
)
499 let is_pointer_type genv
= is_pointer_type_dir (tenv_of_genv genv
)
500 let is_frame_type genv
= is_frame_type_dir (tenv_of_genv genv
)
501 let is_rawdata_type genv
= is_rawdata_type_dir (tenv_of_genv genv
)
503 let dest_exists_type genv
= dest_exists_type_dir (tenv_of_genv genv
)
504 let dest_all_type genv
= dest_all_type_dir (tenv_of_genv genv
)
505 let dest_all_type_rename genv
= dest_all_type_rename_dir (tenv_of_genv genv
)
506 let dest_all_fun_type genv
= dest_all_fun_type_dir (tenv_of_genv genv
)
507 let dest_fun_type genv
= dest_fun_type_dir (tenv_of_genv genv
)
508 let poly_fun_type genv
= poly_fun_type_dir (tenv_of_genv genv
)
509 let dest_union_type genv
= dest_union_type_dir (tenv_of_genv genv
)
510 let dest_tuple_type genv
= dest_tuple_type_dir (tenv_of_genv genv
)
511 let dest_dtuple_type genv
= dest_dtuple_type_dir (tenv_of_genv genv
)
512 let dest_tag_type genv
= dest_tag_type_dir (tenv_of_genv genv
)
513 let dest_array_type genv
= dest_array_type_dir (tenv_of_genv genv
)
514 let dest_case_type genv
= dest_case_type_dir (tenv_of_genv genv
)
515 let dest_object_type genv
= dest_object_type_dir (tenv_of_genv genv
)
516 let dest_frame_type genv
= dest_frame_type_dir (tenv_of_genv genv
)
518 let unfold_object_type genv
= unfold_object_type_dir (tenv_of_genv genv
)
520 let sub_value_of_type genv
= sub_value_of_type_dir (tenv_of_genv genv
)
522 let unpack_type genv
= unpack_type_dir (tenv_of_genv genv
)
524 (************************************************************************
525 * EXPRESSION CHECKING
526 ************************************************************************)
529 * Type of an allocation.
531 let type_of_alloc_op op
=
533 AllocTuple
(_, ty_vars, ty, _)
534 | AllocUnion
(ty_vars, ty, _, _, _) ->
536 | AllocDTuple
(ty, _, _, _)
538 | AllocVArray
(ty, _, _, _)
539 | AllocMalloc
(ty, _) ->
541 | AllocFrame
(v
, tyl
) ->
546 * Get argument and result types of unary operators.
548 let type_of_unop pos op
=
549 let pos = string_pos
"type_of_unop" pos in
559 | UMinusRawIntOp
(pre
, signed
)
560 | NotRawIntOp
(pre
, signed
) ->
561 let ty = TyRawInt
(pre
, signed
) in
564 | RawBitFieldOp
(pre
, signed
, _, _) ->
565 if pre
= Rawint.Int64
then
566 raise
(FirException
(pos, StringError
"RawBitFieldOp cannot return Int64"));
567 TyRawInt
(pre
, signed
), TyRawInt
(Rawint.Int32
, signed
)
585 | FloorFloatOp pre
->
586 let ty = TyFloat pre
in
589 | IntOfFloatOp pre
->
592 | FloatOfIntOp pre
->
594 | FloatOfFloatOp
(pre1
, pre2
) ->
595 TyFloat pre1
, TyFloat pre2
596 | FloatOfRawIntOp
(fpre
, rpre
, rsigned
) ->
597 TyFloat fpre
, TyRawInt
(rpre
, rsigned
)
598 | IntOfRawIntOp
(pre
, signed
) ->
599 TyInt
, TyRawInt
(pre
, signed
)
600 | RawIntOfIntOp
(pre
, signed
) ->
601 TyRawInt
(pre
, signed
), TyInt
602 | RawIntOfEnumOp
(pre
, signed
, n
) ->
603 TyRawInt
(pre
, signed
), TyEnum n
604 | RawIntOfRawIntOp
(pre1
, signed1
, pre2
, signed2
) ->
605 TyRawInt
(pre1
, signed1
), TyRawInt
(pre2
, signed2
)
606 | RawIntOfFloatOp
(pre
, signed
, fpre
) ->
607 TyRawInt
(pre
, signed
), TyFloat fpre
609 | LengthOfBlockOp
(subop
, ty) ->
611 match subop
.sub_script
with
613 | RawIntIndex
(p
, s
) -> TyRawInt
(p
, s
)
617 | DTupleOfDTupleOp
(ty_var
, ty_fields
) ->
618 TyDTuple
(ty_var
, None
), TyDTuple
(ty_var
, Some ty_fields
)
619 | UnionOfUnionOp
(ty_var
, tyl
, s1
, s2
) ->
620 TyUnion
(ty_var
, tyl
, s1
), TyUnion
(ty_var
, tyl
, s2
)
621 | RawDataOfFrameOp
(ty_var
, tyl
) ->
622 TyRawData
, TyFrame
(ty_var
, tyl
)
624 (* BUG: wait until we understand these *)
625 | RawIntOfPointerOp
_
626 | PointerOfRawIntOp
_
627 | PointerOfBlockOp
_ ->
628 raise
(FirException
(pos, NotImplemented
"type checking for rawint/pointer conversions"))
631 * Get the argument and result type for a binary operation.
633 let type_of_binop pos op
=
634 let pos = string_pos
"type_of_binop" pos in
636 (* Bitwise operations on enumerations. *)
643 (* Standard binary operations on NAML ints *)
659 (* Comparisons on NAML ints *)
666 ty_bool, TyInt
, TyInt
668 (* Similar to ML's ``compare'' function. *)
673 * Standard binary operations on native ints. The precision is
674 * the result precision; the inputs should match this precision.
676 | PlusRawIntOp
(pre
, signed
)
677 | MinusRawIntOp
(pre
, signed
)
678 | MulRawIntOp
(pre
, signed
)
679 | DivRawIntOp
(pre
, signed
)
680 | RemRawIntOp
(pre
, signed
)
681 | SlRawIntOp
(pre
, signed
)
682 | SrRawIntOp
(pre
, signed
)
683 | AndRawIntOp
(pre
, signed
)
684 | OrRawIntOp
(pre
, signed
)
685 | XorRawIntOp
(pre
, signed
)
686 | MaxRawIntOp
(pre
, signed
)
687 | MinRawIntOp
(pre
, signed
) ->
688 let ty = TyRawInt
(pre
, signed
) in
692 * BUG (?): Someone may want to check this one again. --emre
694 | RawSetBitFieldOp
(pre
, signed
, _, _) ->
695 let ty = TyRawInt
(pre
, signed
) in
696 ty, TyRawInt
(Rawint.Int32
, signed
), ty
698 (* Comparisons on native ints *)
699 | EqRawIntOp
(pre
, signed
)
700 | NeqRawIntOp
(pre
, signed
)
701 | LtRawIntOp
(pre
, signed
)
702 | LeRawIntOp
(pre
, signed
)
703 | GtRawIntOp
(pre
, signed
)
704 | GeRawIntOp
(pre
, signed
) ->
705 let ty = TyRawInt
(pre
, signed
) in
708 | CmpRawIntOp
(pre
, signed
) ->
709 let ty = TyRawInt
(pre
, signed
) in
712 (* Standard binary operations on floats *)
721 | PowerFloatOp pre
->
722 let ty = TyFloat pre
in
725 | LdExpFloatIntOp pre
->
726 let ty = TyFloat pre
in
729 (* Comparisons on floats *)
736 let ty = TyFloat pre
in
739 let ty = TyFloat pre
in
743 * Pointer (in)equality. Arguments must be pointers.
744 * BUG: this is actually polymorphic.
751 * Pointer arithmetic. The pointer in the first argument, and the
752 * returned pointer should be infix pointers (which keep the base
753 * pointer as well as a pointer to anywhere within the block).
755 | PlusPointerOp
(sub
, pre
, signed
) ->
756 TyPointer sub
, TyPointer sub
, TyRawInt
(pre
, signed
)
759 * Get the type of an atom.
761 let rec type_of_atom_aux genv_lookup_var genv
pos a
=
762 let pos = string_pos
"type_of_atom" pos in
771 TyFloat
(Rawfloat.precision x
)
773 TyRawInt
(Rawint.precision i
, Rawint.signed i
)
775 genv_lookup_var genv
pos v
777 genv_lookup_fun genv
pos v
780 TyRawInt
(precision_subscript
, signed_subscript
)
781 | AtomConst
(ty, _, i
) ->
782 let tv, tl
, _ = dest_union_type genv
pos ty in
783 TyUnion
(tv, tl
, IntSet.of_point i
)
784 | AtomTyApply
(_, ty, _)
785 | AtomTyPack
(_, ty, _) ->
788 let ty = genv_lookup_var genv
pos v
in
789 unpack_type genv
pos v
ty
790 | AtomUnop
(op
, a
) ->
791 let ty, _ = type_of_unop pos op
in
793 | AtomBinop
(op
, _, _) ->
794 let ty, _, _ = type_of_binop pos op
in
797 let type_of_atom = type_of_atom_aux genv_lookup_var
798 let type_of_global_atom = type_of_atom_aux genv_lookup_var_or_global
800 (************************************************************************
802 ************************************************************************)
805 * Assume all binding occurrences have different names.
806 * Get the type of every variable in the program.
808 let rec type_exp genv e
=
809 let pos = string_pos
"type_exp" (exp_pos e
) in
810 match dest_exp_core e
with
811 LetAtom
(v
, ty, _, e
)
812 | LetExt
(v
, ty, _, _, _, _, _, e
)
813 | LetSubscript
(_, v
, ty, _, _, e
)
814 | LetGlobal
(_, v
, ty, _, e
) ->
815 let genv = genv_add_var
genv v
ty in
817 | LetAlloc
(v
, op
, e
) ->
818 let genv = genv_add_var
genv v
(type_of_alloc_op op
) in
823 | TypeCase
(_, _, name, v
, e1
, e2
) ->
824 let genv = genv_add_var
genv v
(genv_lookup_name
genv pos name) in
828 | SetSubscript
(_, _, _, _, _, _, e
)
829 | SetGlobal
(_, _, _, _, _, e
)
830 | Memcpy
(_, _, _, _, _, _, _, e
)
833 | Match
(_, cases
) ->
834 List.fold_left
(fun genv (_, _, e
) ->
835 type_exp genv e
) genv cases
836 | MatchDTuple
(_, cases
) ->
837 List.fold_left
(fun genv (_, _, e
) ->
838 type_exp genv e
) genv cases
841 * Type for a function.
843 let type_fun genv f
(info
, _, ty, vars, e
) =
844 let pos = string_pos
"type_fun" (var_exp_pos f
) in
845 let ty_args, _ = dest_fun_type genv pos ty in
846 let genv = List.fold_left2 genv_add_var
genv vars ty_args in
850 * Get all the var types in the program.
853 let genv = genv_of_prog prog
in
854 SymbolTable.fold
type_fun genv prog
.prog_funs
861 * Caml-master: "compile"