summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/typing.ml982
1 files changed, 491 insertions, 491 deletions
diff --git a/src/typing.ml b/src/typing.ml
index 110e2f8..d7f11eb 100644
--- a/src/typing.ml
+++ b/src/typing.ml
@@ -8,19 +8,19 @@ exception AmbiguousOverload
let ty_assert x k = if not x then raise (Error (k))
let ty_error k = raise (Error (k))
let err_add_loc loc f =
- try f()
- with
- | Error(k) -> raise (LocError(loc, k))
- | LocError(_, _) as e -> raise e
- | Assert_failure (k, a, b) -> raise (LocError (loc,
- "(unexpected) Assertion failure: "^k^" at "^(string_of_int a)^":"^(string_of_int b)))
- | Not_found -> raise (LocError (loc, "(unexpected) Not found"))
- | Invalid_argument(k) -> raise (LocError (loc, "(unexpected) Invalid argument: "^k))
- | Match_failure(k, a, b) -> raise (LocError (loc,
- "(unexpected) Match failure: "^k^" at "^(string_of_int a)^":"^(string_of_int b)))
- | NoCorrespondingPrototype -> raise (LocError (loc, "No corresponding prototype"))
- | AmbiguousOverload -> raise (LocError (loc, "Ambiguous overload"))
- | _ -> raise (LocError (loc, "(unexpected) Other error"))
+ try f()
+ with
+ | Error(k) -> raise (LocError(loc, k))
+ | LocError(_, _) as e -> raise e
+ | Assert_failure (k, a, b) -> raise (LocError (loc,
+ "(unexpected) Assertion failure: "^k^" at "^(string_of_int a)^":"^(string_of_int b)))
+ | Not_found -> raise (LocError (loc, "(unexpected) Not found"))
+ | Invalid_argument(k) -> raise (LocError (loc, "(unexpected) Invalid argument: "^k))
+ | Match_failure(k, a, b) -> raise (LocError (loc,
+ "(unexpected) Match failure: "^k^" at "^(string_of_int a)^":"^(string_of_int b)))
+ | NoCorrespondingPrototype -> raise (LocError (loc, "No corresponding prototype"))
+ | AmbiguousOverload -> raise (LocError (loc, "Ambiguous overload"))
+ | _ -> raise (LocError (loc, "(unexpected) Other error"))
(* AST typés *)
@@ -48,85 +48,85 @@ and texpr_desc =
| TEIdent of ident
| TEAssign of texpression * texpression
| TECallFun of ident * texpression list (* changé : te -> ident *)
- (* calls to non-virtual methods are compiled using TECallFun, with the object cons'ed at
- the begining of the arguments expression list *)
+ (* calls to non-virtual methods are compiled using TECallFun, with the object cons'ed at
+ the begining of the arguments expression list *)
| TECallVirtual of texpression * int * texpression list (* object * index in vtable * arguments *)
| TEUnary of unop * texpression
| TEBinary of texpression * binop * texpression
- | TEMember of texpression * int (* object * position of member *)
+ | TEMember of texpression * int (* object * position of member *)
| TENew of tcls * tproto option * texpression list
and tstr_expression =
- | TSEExpr of texpression
- | TSEStr of string
+ | TSEExpr of texpression
+ | TSEStr of string
and tstatement = {
- ts_loc: loc;
- ts_desc: ts_desc;
- }
+ ts_loc: loc;
+ ts_desc: ts_desc;
+ }
and ts_desc =
- | TSEmpty
- | TSExpr of texpression
- | TSIf of texpression * tstatement * tstatement
- | TSWhile of texpression * tstatement
- | TSFor of texpression list * texpression option * texpression list * tstatement
- | TSBlock of tblock
- | TSReturn of texpression option
- | TSDeclare of type_ref * ident
- | TSDeclareAssignExpr of type_ref * ident * texpression
- | TSDeclareAssignConstructor of typ * ident * tproto option * tident * texpression list (* a faire *)
+ | TSEmpty
+ | TSExpr of texpression
+ | TSIf of texpression * tstatement * tstatement
+ | TSWhile of texpression * tstatement
+ | TSFor of texpression list * texpression option * texpression list * tstatement
+ | TSBlock of tblock
+ | TSReturn of texpression option
+ | TSDeclare of type_ref * ident
+ | TSDeclareAssignExpr of type_ref * ident * texpression
+ | TSDeclareAssignConstructor of typ * ident * tproto option * tident * texpression list (* a faire *)
(* Type of variable, variable name, constructor class name, constructor arguments *)
- | TSWriteCout of tstr_expression list
+ | TSWriteCout of tstr_expression list
and tblock = tstatement list
and tproto = {
- tp_virtual : int option; (* only used for class methods ; if none then not virtual,
- if some then gives the index of the method in the vtable (same for all classes
- of the hierarchy that have that method) *)
- tp_loc : loc;
- tp_name : ident;
- tp_unique_ident : ident; (* label de la fonction dans le code assembleur *)
- tp_class : tident option; (* p_class = none : standalone function *)
- tp_ret_type : type_ref option; (* p_class = some and p_ret_type = none : constructor *)
- tp_args : (type_ref * ident) list;
+ tp_virtual : int option; (* only used for class methods ; if none then not virtual,
+ if some then gives the index of the method in the vtable (same for all classes
+ of the hierarchy that have that method) *)
+ tp_loc : loc;
+ tp_name : ident;
+ tp_unique_ident : ident; (* label de la fonction dans le code assembleur *)
+ tp_class : tident option; (* p_class = none : standalone function *)
+ tp_ret_type : type_ref option; (* p_class = some and p_ret_type = none : constructor *)
+ tp_args : (type_ref * ident) list;
}
and tcls = {
- tc_name : tident;
- tc_size : int;
- tc_super : tident option;
- tc_vtable : (int * tproto) list;
- tc_members : (typ * int) Smap.t; (* type du membre * position du membre dans les données de l'objet *)
- tc_methods : tproto list;
+ tc_name : tident;
+ tc_size : int;
+ tc_super : tident option;
+ tc_vtable : (int * tproto) list;
+ tc_members : (typ * int) Smap.t; (* type du membre * position du membre dans les données de l'objet *)
+ tc_methods : tproto list;
}
let tproto_numbering = ref 1
let tproto_unique_number () =
- let k = !tproto_numbering in
- tproto_numbering := k + 1;
- string_of_int k
+ let k = !tproto_numbering in
+ tproto_numbering := k + 1;
+ string_of_int k
type env = {
- e_globals : typ Smap.t;
- e_funs : tproto list;
- e_classes : tcls Smap.t;
+ e_globals : typ Smap.t;
+ e_funs : tproto list;
+ e_classes : tcls Smap.t;
}
and benv = {
- b_pe : env;
- b_locals : type_ref Smap.t;
- b_class : tcls option;
+ b_pe : env;
+ b_locals : type_ref Smap.t;
+ b_class : tcls option;
}
type tdeclaration =
- | TDGlobal of (typ * ident)
- | TDFunction of (tproto * tblock)
- | TDClass of tcls
+ | TDGlobal of (typ * ident)
+ | TDFunction of (tproto * tblock)
+ | TDClass of tcls
type tprogram = {
- prog_decls : tdeclaration list;
- prog_env : env;
+ prog_decls : tdeclaration list;
+ prog_env : env;
}
(* Quelques fonctions utiles : *)
@@ -135,13 +135,13 @@ let get_c env i =
try Smap.find i env.e_classes with Not_found -> ty_error ("No such class: " ^ i)
let rec bf env t =
- let rec aux = function (* true si bien formé *)
- | T_Int -> true
- | TClass n ->
- Smap.mem n env.e_classes
- | TPoint t -> aux t
- | _ -> false
- in aux t
+ let rec aux = function (* true si bien formé *)
+ | T_Int -> true
+ | TClass n ->
+ Smap.mem n env.e_classes
+ | TPoint t -> aux t
+ | _ -> false
+ in aux t
let num = function
| T_Int -> true
@@ -165,61 +165,61 @@ let build_type_or_ref vt = (* vt -> typ,bool = tr, true si ref *)
| vt -> (see vt),false
let rec subtype env a b = match a, b with
- | T_Int, T_Int -> true
- | T_Void, T_Void -> true
- | Typenull, TPoint(_) -> true
- | TPoint(ka), TPoint(kb) -> subtype env ka kb
- | TClass(i), TClass(j) ->
- if i = j then true
- else let c = get_c env i in
- (* NOT DONE : multiple supers *)
- begin match c.tc_super with
- | None -> false
- | Some(k) -> subtype env (TClass k) (TClass j)
- end
- | _ -> false
+ | T_Int, T_Int -> true
+ | T_Void, T_Void -> true
+ | Typenull, TPoint(_) -> true
+ | TPoint(ka), TPoint(kb) -> subtype env ka kb
+ | TClass(i), TClass(j) ->
+ if i = j then true
+ else let c = get_c env i in
+ (* NOT DONE : multiple supers *)
+ begin match c.tc_super with
+ | None -> false
+ | Some(k) -> subtype env (TClass k) (TClass j)
+ end
+ | _ -> false
let type_size env t = match t with
- | T_Int | Typenull | TPoint(_) -> 4
- | T_Void -> 0
- | TClass(c) -> let c = get_c env c in c.tc_size
+ | T_Int | Typenull | TPoint(_) -> 4
+ | T_Void -> 0
+ | TClass(c) -> let c = get_c env c in c.tc_size
(* pour la surcharge de fonctions *)
let possible_protos env arg_type_list fun_list =
- List.filter
- (fun proto ->
- try List.for_all2
- (fun (t_a, t_a_ref) (t_p, t_p_ref) ->
- if t_p_ref && (not t_a_ref) then false else
- subtype env t_a t_p)
- arg_type_list (List.map fst proto.tp_args)
- with Invalid_argument _ -> false)
- fun_list
+ List.filter
+ (fun proto ->
+ try List.for_all2
+ (fun (t_a, t_a_ref) (t_p, t_p_ref) ->
+ if t_p_ref && (not t_a_ref) then false else
+ subtype env t_a t_p)
+ arg_type_list (List.map fst proto.tp_args)
+ with Invalid_argument _ -> false)
+ fun_list
let closest_proto env arg_type_list fun_list =
- match possible_protos env arg_type_list fun_list with
- | [] -> raise NoCorrespondingPrototype
- | [p] -> p
- | _ -> raise AmbiguousOverload
+ match possible_protos env arg_type_list fun_list with
+ | [] -> raise NoCorrespondingPrototype
+ | [p] -> p
+ | _ -> raise AmbiguousOverload
let find_proto_in_class env cls name arg_type_list =
- let rec aux = function
- | None -> raise NoCorrespondingPrototype
- | Some(k) -> let c = get_c env k in
- let f = List.filter (fun p -> p.tp_name = name) c.tc_methods in
- begin try closest_proto env arg_type_list f
- with NoCorrespondingPrototype -> aux c.tc_super
- end
- in aux (Some cls)
-
+ let rec aux = function
+ | None -> raise NoCorrespondingPrototype
+ | Some(k) -> let c = get_c env k in
+ let f = List.filter (fun p -> p.tp_name = name) c.tc_methods in
+ begin try closest_proto env arg_type_list f
+ with NoCorrespondingPrototype -> aux c.tc_super
+ end
+ in aux (Some cls)
+
let find_cls_mem env cls_name mem_name =
- let rec aux = function
- | None -> raise Not_found
- | Some(k) -> let c = get_c env k in
- begin try let mty, mi = Smap.find mem_name c.tc_members in
- mty, mi
- with Not_found -> aux c.tc_super
- end
- in aux (Some cls_name)
+ let rec aux = function
+ | None -> raise Not_found
+ | Some(k) -> let c = get_c env k in
+ begin try let mty, mi = Smap.find mem_name c.tc_members in
+ mty, mi
+ with Not_found -> aux c.tc_super
+ end
+ in aux (Some cls_name)
(* -------------------------------------------- *)
@@ -241,242 +241,242 @@ and get_expr env e = (* expression -> texpression,(ty,b) *)
and compute_type env e =
- let ttype = (TClass(match env.b_class with | Some c -> c.tc_name | None -> "#")) in
- let e_this =
- { te_loc = e.e_loc;
- te_desc = TEThis;
- type_expr = TPoint(ttype), false, true } in
- let e_this_not_ptr =
- { te_loc = e.e_loc;
- te_desc = TEUnary(Deref, e_this);
- type_expr = ttype, false, true; } in
- match e.e_desc with (* expression -> te_desc,(typ,ref?,left?) *)
+ let ttype = (TClass(match env.b_class with | Some c -> c.tc_name | None -> "#")) in
+ let e_this =
+ { te_loc = e.e_loc;
+ te_desc = TEThis;
+ type_expr = TPoint(ttype), false, true } in
+ let e_this_not_ptr =
+ { te_loc = e.e_loc;
+ te_desc = TEUnary(Deref, e_this);
+ type_expr = ttype, false, true; } in
+ match e.e_desc with (* expression -> te_desc,(typ,ref?,left?) *)
| EInt n -> TEInt n, (T_Int,false,false)
(* false, : pas une ref, pas une val gauche*)
| EBool b -> let n = (if b then 1 else 0) in
- TEInt n, (T_Int,false,false)
+ TEInt n, (T_Int,false,false)
| ENull -> TENull, (Typenull,false,false)
| EIdent i ->
- begin try
- let t, r = Smap.find i env.b_locals in
- TEIdent i, (t, r, true)
- with Not_found ->
- try match env.b_class with
- | Some k -> let mty, mi = find_cls_mem env.b_pe k.tc_name i in
- TEMember(e_this_not_ptr, mi),
- (mty, false, true)
- | None -> raise Not_found
- with Not_found ->
- try let t = Smap.find i env.b_pe.e_globals in
- TEIdent i, (t, false, true)
- with Not_found -> ty_error ("Undeclared identifier: " ^ i)
- end
+ begin try
+ let t, r = Smap.find i env.b_locals in
+ TEIdent i, (t, r, true)
+ with Not_found ->
+ try match env.b_class with
+ | Some k -> let mty, mi = find_cls_mem env.b_pe k.tc_name i in
+ TEMember(e_this_not_ptr, mi),
+ (mty, false, true)
+ | None -> raise Not_found
+ with Not_found ->
+ try let t = Smap.find i env.b_pe.e_globals in
+ TEIdent i, (t, false, true)
+ with Not_found -> ty_error ("Undeclared identifier: " ^ i)
+ end
| EAssign (e1,e2) -> let te1,(ty1,r3,b3) = get_expr0 env e1 in
- let te2,(ty2,_,_) = get_expr0 env e2 in
- ty_assert (b3 || r3) "Can only assign to lvalue";
- ty_assert (num ty1) "Cannot assign to non-numeric type (pointer type is numeric)";
- ty_assert (subtype env.b_pe ty2 ty1) "Incompatible types in assign";
- (* type num et ref compatibles ?*)
- (TEAssign (te1,te2) ),(ty1,false,false)
+ let te2,(ty2,_,_) = get_expr0 env e2 in
+ ty_assert (b3 || r3) "Can only assign to lvalue";
+ ty_assert (num ty1) "Cannot assign to non-numeric type (pointer type is numeric)";
+ ty_assert (subtype env.b_pe ty2 ty1) "Incompatible types in assign";
+ (* type num et ref compatibles ?*)
+ (TEAssign (te1,te2) ),(ty1,false,false)
| EUnary (op,e) -> let te,(ty,b1,b2) = get_expr0 env e in
- (match op with
- | PreIncr | PostIncr | PreDecr | PostDecr ->
- ty_assert (b2 = true) "Can only increment/decrement lvalue";
- ty_assert (ty = T_Int) "Can only increment/decrement integers";
- TEUnary(op,te),(T_Int,b1,false)
- | Plus | Minus | Not ->
- ty_assert (ty = T_Int) "Can only apply unary plus/minus/not to integers";
- TEUnary(op,te),(T_Int,false,false)
- | Ref ->
- ty_assert b2 "Can only reference lvalues";
- TEUnary(op,te),(TPoint ty,false,false) (* verif *)
- | Deref ->
- let t = (match ty with
- | TPoint t -> t
- | _ -> ty_error "Can only dereference pointer" ) in
- TEUnary(op,te), (t,false,true)
- )
+ (match op with
+ | PreIncr | PostIncr | PreDecr | PostDecr ->
+ ty_assert (b2 = true) "Can only increment/decrement lvalue";
+ ty_assert (ty = T_Int) "Can only increment/decrement integers";
+ TEUnary(op,te),(T_Int,b1,false)
+ | Plus | Minus | Not ->
+ ty_assert (ty = T_Int) "Can only apply unary plus/minus/not to integers";
+ TEUnary(op,te),(T_Int,false,false)
+ | Ref ->
+ ty_assert b2 "Can only reference lvalues";
+ TEUnary(op,te),(TPoint ty,false,false) (* verif *)
+ | Deref ->
+ let t = (match ty with
+ | TPoint t -> t
+ | _ -> ty_error "Can only dereference pointer" ) in
+ TEUnary(op,te), (t,false,true)
+ )
| EBinary (e1,op,e2) -> let te1,(ty1,_,b1) = get_expr0 env e1 in
- let te2,(ty2,_,b2) = get_expr0 env e2 in
- (match op with
- | Equal | NotEqual ->
- ty_assert ((subtype env.b_pe ty1 ty2) || (subtype env.b_pe ty2 ty1))
- "Can only apply == or != to two values of compatible type";
- ty_assert (num ty1) "Can only apply == or != to pointers"
- | Lt | Le | Gt | Ge
- | Add | Sub | Mul | Div | Modulo
- | Land | Lor ->
- ty_assert (ty1 = T_Int) "Left operand of binop is not integer";
- ty_assert (ty2 = T_Int) "Right operand of binop is not integer"
- ); (* vérifs *)
- TEBinary(te1,op,te2),(T_Int,false,false)
+ let te2,(ty2,_,b2) = get_expr0 env e2 in
+ (match op with
+ | Equal | NotEqual ->
+ ty_assert ((subtype env.b_pe ty1 ty2) || (subtype env.b_pe ty2 ty1))
+ "Can only apply == or != to two values of compatible type";
+ ty_assert (num ty1) "Can only apply == or != to pointers"
+ | Lt | Le | Gt | Ge
+ | Add | Sub | Mul | Div | Modulo
+ | Land | Lor ->
+ ty_assert (ty1 = T_Int) "Left operand of binop is not integer";
+ ty_assert (ty2 = T_Int) "Right operand of binop is not integer"
+ ); (* vérifs *)
+ TEBinary(te1,op,te2),(T_Int,false,false)
| ECall (e,e_list) ->
- (* TODO : look also within parent classes *)
- let args_values = List.map (get_expr0 env) e_list in
- let args_types = List.map (fun (e, (t, r, l)) -> t, r||l) args_values in
-
- let obj, tproto = (match e.e_desc with
- | EIdent i ->
- let funs = List.filter (fun p -> p.tp_name = i) env.b_pe.e_funs in
- begin match env.b_class with
- | None -> None, closest_proto env.b_pe args_types funs
- | Some k ->
- begin try Some e_this_not_ptr, find_proto_in_class env.b_pe k.tc_name i args_types
- with NoCorrespondingPrototype ->
- None, closest_proto env.b_pe args_types funs
- end
- end
- | EMember(e, i) ->
- let e = type_expr env e in
- begin match e.type_expr with
- | TClass(k), a, b when a || b ->
- Some e, find_proto_in_class env.b_pe k i args_types
- | _ -> ty_error "Invalid argument type for method call (not a class, or not a lvalue)"
- end
- | _ -> ty_error "Calling something that is neither a function nor a method") in
- let l_te = List.map fst args_values in
- let ty,b = match tproto.tp_ret_type with
- | None -> ty_error "Constructor cannot be called as function"
- | Some (ty,b) -> ty,b in
- begin match tproto.tp_virtual, obj with
- | None, None ->
- TECallFun(tproto.tp_unique_ident,l_te),(ty,b,false)
- | None, Some(obj)->
- TECallFun(tproto.tp_unique_ident,obj::l_te),(ty,b,false)
- | Some(idx), Some(obj) ->
- TECallVirtual(obj, idx, l_te),(ty,b,false)
- | _ -> ty_error "(should not happen) Virtual function applied to no object..."
- end
+ (* TODO : look also within parent classes *)
+ let args_values = List.map (get_expr0 env) e_list in
+ let args_types = List.map (fun (e, (t, r, l)) -> t, r||l) args_values in
+
+ let obj, tproto = (match e.e_desc with
+ | EIdent i ->
+ let funs = List.filter (fun p -> p.tp_name = i) env.b_pe.e_funs in
+ begin match env.b_class with
+ | None -> None, closest_proto env.b_pe args_types funs
+ | Some k ->
+ begin try Some e_this_not_ptr, find_proto_in_class env.b_pe k.tc_name i args_types
+ with NoCorrespondingPrototype ->
+ None, closest_proto env.b_pe args_types funs
+ end
+ end
+ | EMember(e, i) ->
+ let e = type_expr env e in
+ begin match e.type_expr with
+ | TClass(k), a, b when a || b ->
+ Some e, find_proto_in_class env.b_pe k i args_types
+ | _ -> ty_error "Invalid argument type for method call (not a class, or not a lvalue)"
+ end
+ | _ -> ty_error "Calling something that is neither a function nor a method") in
+ let l_te = List.map fst args_values in
+ let ty,b = match tproto.tp_ret_type with
+ | None -> ty_error "Constructor cannot be called as function"
+ | Some (ty,b) -> ty,b in
+ begin match tproto.tp_virtual, obj with
+ | None, None ->
+ TECallFun(tproto.tp_unique_ident,l_te),(ty,b,false)
+ | None, Some(obj)->
+ TECallFun(tproto.tp_unique_ident,obj::l_te),(ty,b,false)
+ | Some(idx), Some(obj) ->
+ TECallVirtual(obj, idx, l_te),(ty,b,false)
+ | _ -> ty_error "(should not happen) Virtual function applied to no object..."
+ end
| EMember (e, id) ->
- let e, (ty, r, l) = get_expr0 env e in
- begin match ty with
- | TClass(c_name) ->
- begin try let mty, mi = find_cls_mem env.b_pe c_name id in
- TEMember(e, mi), (mty, false, true)
- with | Not_found -> ty_error ("Class " ^ c_name ^ " has no member " ^ id)
- end
- | _ -> ty_error "Cannot get member of expression that is not a class"
- end
+ let e, (ty, r, l) = get_expr0 env e in
+ begin match ty with
+ | TClass(c_name) ->
+ begin try let mty, mi = find_cls_mem env.b_pe c_name id in
+ TEMember(e, mi), (mty, false, true)
+ with | Not_found -> ty_error ("Class " ^ c_name ^ " has no member " ^ id)
+ end
+ | _ -> ty_error "Cannot get member of expression that is not a class"
+ end
| ENew (cls_name, args) ->
- let c = get_c env.b_pe cls_name in
- let args_values = List.map (get_expr0 env) args in
- let args_types = List.map (fun (e, (t, r, l)) -> t, r||l) args_values in
- let candidates = List.filter (fun p -> p.tp_ret_type = None) c.tc_methods in
- begin match candidates with
- | [] ->
- ty_assert (args = []) "Only default constructor exists and it has 0 arguments";
- TENew(c, None, []), (TPoint(TClass(cls_name)), false, false)
- | _ ->
- let p = closest_proto env.b_pe args_types candidates in
- (* closest_proto makes sure the prototypes match, no problem here *)
- let l_te = List.map fst args_values in
- TENew(c, Some p, l_te), (TPoint(TClass(cls_name)), false, false)
- end
+ let c = get_c env.b_pe cls_name in
+ let args_values = List.map (get_expr0 env) args in
+ let args_types = List.map (fun (e, (t, r, l)) -> t, r||l) args_values in
+ let candidates = List.filter (fun p -> p.tp_ret_type = None) c.tc_methods in
+ begin match candidates with
+ | [] ->
+ ty_assert (args = []) "Only default constructor exists and it has 0 arguments";
+ TENew(c, None, []), (TPoint(TClass(cls_name)), false, false)
+ | _ ->
+ let p = closest_proto env.b_pe args_types candidates in
+ (* closest_proto makes sure the prototypes match, no problem here *)
+ let l_te = List.map fst args_values in
+ TENew(c, Some p, l_te), (TPoint(TClass(cls_name)), false, false)
+ end
| EThis ->
- begin match env.b_class with
- | Some c -> TEThis, (TPoint(TClass(c.tc_name)), false, true)
- | None -> ty_error "Cannot use this outside of method"
- end
+ begin match env.b_class with
+ | Some c -> TEThis, (TPoint(TClass(c.tc_name)), false, true)
+ | None -> ty_error "Cannot use this outside of method"
+ end
(* Statements *)
let rec type_stm ret_type env s =
- err_add_loc s.s_loc (fun () ->
- let d, ty = compute_type_stm ret_type env s in
- { ts_loc = s.s_loc; ts_desc = d }, ty)
+ err_add_loc s.s_loc (fun () ->
+ let d, ty = compute_type_stm ret_type env s in
+ { ts_loc = s.s_loc; ts_desc = d }, ty)
and compute_type_stm ret_type env s = match s.s_desc with (* statement -> ts_desc,stm_type *)
| SEmpty -> TSEmpty,env
| SExpr e -> let te,(ty,_) = get_expr env e in (* verif ty est bien typé *)
- (TSExpr te) , env
+ (TSExpr te) , env
| SBlock b -> build_block ret_type env b
| SReturn None ->
- let ty, ref = ret_type in
- ty_assert (ty = T_Void) "Function must return non-void value";
- (TSReturn None) , env
+ let ty, ref = ret_type in
+ ty_assert (ty = T_Void) "Function must return non-void value";
+ (TSReturn None) , env
| SReturn (Some e0) -> let te,(ty,r,l) = get_expr0 env e0 in
- let rty, rref = ret_type in
- ty_assert (rty = ty) "Invalid return type";
- ty_assert (if rref then r||l else true) "Function must return reference";
- TSReturn (Some te), env
+ let rty, rref = ret_type in
+ ty_assert (rty = ty) "Invalid return type";
+ ty_assert (if rref then r||l else true) "Function must return reference";
+ TSReturn (Some te), env
| SIf (e,s1,s2) -> let te,(ty,_) = get_expr env e in
- let ts1,ty1 = type_stm ret_type env s1 in (* vérifs règle *)
- let ts2,ty2 = type_stm ret_type env s2 in
- ty_assert (ty = T_Int) "Condition in if statement must be integer";
- (TSIf (te,ts1,ts2)) , env
+ let ts1,ty1 = type_stm ret_type env s1 in (* vérifs règle *)
+ let ts2,ty2 = type_stm ret_type env s2 in
+ ty_assert (ty = T_Int) "Condition in if statement must be integer";
+ (TSIf (te,ts1,ts2)) , env
| SFor (el1,eopt,el3,s) -> let tel1 = List.map (type_expr env) el1 in (* et fait les vérifs pr e1 et e3 ? *)
- let tel3 = List.map (type_expr env) el3 in
- let teopt = (match eopt with
- | None -> None
- | Some e -> let te,(ty,_) = get_expr env e in
- ty_assert (ty = T_Int) "Condition in for statement must be integer";
- Some te)
- in
- ignore( type_stm ret_type env s ); (* vérifie i *)
- let ts, _ = type_stm ret_type env s in (* fait le truc d'avant aussi *)
- TSFor (tel1,teopt,tel3,ts) , env
+ let tel3 = List.map (type_expr env) el3 in
+ let teopt = (match eopt with
+ | None -> None
+ | Some e -> let te,(ty,_) = get_expr env e in
+ ty_assert (ty = T_Int) "Condition in for statement must be integer";
+ Some te)
+ in
+ ignore( type_stm ret_type env s ); (* vérifie i *)
+ let ts, _ = type_stm ret_type env s in (* fait le truc d'avant aussi *)
+ TSFor (tel1,teopt,tel3,ts) , env
(* traduire règles restantes du for*)
| SWhile(e,s) -> let ts,tys = type_stm ret_type env s in
- let te,(ty,_) = get_expr env e in
- ty_assert (ty = T_Int) "Condition in while statement must be integer";
- TSWhile(te,ts),env
+ let te,(ty,_) = get_expr env e in
+ ty_assert (ty = T_Int) "Condition in while statement must be integer";
+ TSWhile(te,ts),env
(* pq while n'est pas dans les règles données ? *)
| SDeclare(vt,i) -> let ty,b = build_type_or_ref vt in
- ty_assert (bf env.b_pe ty) "Malformed type";
- ty_assert (not (Smap.mem i env.b_locals) ) "Variable redefinition";
- let env0 =
- { b_pe = env.b_pe;
- b_locals = Smap.add i (ty,b) env.b_locals;
- b_class = env.b_class } in
- TSDeclare( (ty,b) ,i) , env0
+ ty_assert (bf env.b_pe ty) "Malformed type";
+ ty_assert (not (Smap.mem i env.b_locals) ) "Variable redefinition";
+ let env0 =
+ { b_pe = env.b_pe;
+ b_locals = Smap.add i (ty,b) env.b_locals;
+ b_class = env.b_class } in
+ TSDeclare( (ty,b) ,i) , env0
| SDeclareAssignExpr(vt,i,e) -> let ty,b = build_type_or_ref vt in
- ty_assert (bf env.b_pe ty) "Malformed type";
- ty_assert (not (Smap.mem i env.b_locals)) "Variable redefinition";
- let te,(tye,r,l) = get_expr0 env e in
- ty_assert (if b then r || l else true) "Can only assigne lvalue/reference to reference type var";
- ty_assert (subtype env.b_pe tye ty) "Invalid data type for assign.";
- let env0 =
- { b_pe = env.b_pe;
- b_locals = Smap.add i (ty,b) env.b_locals;
- b_class = env.b_class } in
- TSDeclareAssignExpr( (ty,b) ,i,te) , env0
+ ty_assert (bf env.b_pe ty) "Malformed type";
+ ty_assert (not (Smap.mem i env.b_locals)) "Variable redefinition";
+ let te,(tye,r,l) = get_expr0 env e in
+ ty_assert (if b then r || l else true) "Can only assigne lvalue/reference to reference type var";
+ ty_assert (subtype env.b_pe tye ty) "Invalid data type for assign.";
+ let env0 =
+ { b_pe = env.b_pe;
+ b_locals = Smap.add i (ty,b) env.b_locals;
+ b_class = env.b_class } in
+ TSDeclareAssignExpr( (ty,b) ,i,te) , env0
| SDeclareAssignConstructor(vt,i,ti,e_l) ->
- let ty, b = build_type_or_ref vt in
- ty_assert (bf env.b_pe ty) "Malformed type";
- ty_assert (not (Smap.mem i env.b_locals)) "Variable redefinition";
- ty_assert (not b) "Cannot have reference on a newly created object";
- ty_assert (ty = (TClass ti)) "Invalid type for constructor";
- let c = get_c env.b_pe ti in
- let args_values= List.map (get_expr0 env) e_l in
- let args_types = List.map (fun (e, (t, r, l)) -> t, r||l) args_values in
- let candidates = List.filter (fun p -> p.tp_ret_type = None) c.tc_methods in
- begin match candidates with
- | [] ->
- ty_assert (e_l = []) "Only default constructor exists and it has 0 arguments";
- TSDeclareAssignConstructor(ty, i, None, ti, []), env
- | _ ->
- let p = closest_proto env.b_pe args_types candidates in
- (* closest_proto makes sure the prototypes match, no problem here *)
- let l_te = List.map fst args_values in
- let env0 =
- { b_pe = env.b_pe;
- b_locals = Smap.add i (ty,b) env.b_locals;
- b_class = env.b_class } in
- TSDeclareAssignConstructor(ty, i, Some p, ti, l_te), env0
- end
+ let ty, b = build_type_or_ref vt in
+ ty_assert (bf env.b_pe ty) "Malformed type";
+ ty_assert (not (Smap.mem i env.b_locals)) "Variable redefinition";
+ ty_assert (not b) "Cannot have reference on a newly created object";
+ ty_assert (ty = (TClass ti)) "Invalid type for constructor";
+ let c = get_c env.b_pe ti in
+ let args_values= List.map (get_expr0 env) e_l in
+ let args_types = List.map (fun (e, (t, r, l)) -> t, r||l) args_values in
+ let candidates = List.filter (fun p -> p.tp_ret_type = None) c.tc_methods in
+ begin match candidates with
+ | [] ->
+ ty_assert (e_l = []) "Only default constructor exists and it has 0 arguments";
+ TSDeclareAssignConstructor(ty, i, None, ti, []), env
+ | _ ->
+ let p = closest_proto env.b_pe args_types candidates in
+ (* closest_proto makes sure the prototypes match, no problem here *)
+ let l_te = List.map fst args_values in
+ let env0 =
+ { b_pe = env.b_pe;
+ b_locals = Smap.add i (ty,b) env.b_locals;
+ b_class = env.b_class } in
+ TSDeclareAssignConstructor(ty, i, Some p, ti, l_te), env0
+ end
| SWriteCout(str_e_list) ->
let args =
List.map
- (fun e -> match e.se_desc with
- | SEExpr e0 -> let te,(ty,_) = get_expr env {e_loc = e.se_loc; e_desc = e0} in
- ty_assert (ty = T_Int) "Expected integer or string in cout<<"; TSEExpr te
- | SEStr s -> TSEStr(s) (* osef *)
- )
- str_e_list
+ (fun e -> match e.se_desc with
+ | SEExpr e0 -> let te,(ty,_) = get_expr env {e_loc = e.se_loc; e_desc = e0} in
+ ty_assert (ty = T_Int) "Expected integer or string in cout<<"; TSEExpr te
+ | SEStr s -> TSEStr(s) (* osef *)
+ )
+ str_e_list
in
TSWriteCout(args) , env
-
+
and build_block ret_type env b = (* utilisé ds compute_type_stm et def_global_fun *)
let two_stms (env,l) s =
let ts,env2 = type_stm ret_type env s in
@@ -493,17 +493,17 @@ and get_block ret_type env b =
(* Déclarations de fonction *)
let parse_args env a =
- let args = List.map
- (fun (t, i) ->
- let t, r = build_type_or_ref t in
- ty_assert (bf env t) ("Malformed argument type for argument " ^ i ^ ".");
- (t, r), i)
- a in
- let rec aux = function
- | [] -> ()
- | p::q -> ty_assert (not (List.mem p q)) ("Argument name appears twice : " ^ p); aux q
- in aux (List.map snd args);
- args
+ let args = List.map
+ (fun (t, i) ->
+ let t, r = build_type_or_ref t in
+ ty_assert (bf env t) ("Malformed argument type for argument " ^ i ^ ".");
+ (t, r), i)
+ a in
+ let rec aux = function
+ | [] -> ()
+ | p::q -> ty_assert (not (List.mem p q)) ("Argument name appears twice : " ^ p); aux q
+ in aux (List.map snd args);
+ args
let get_fun env p b = (* p : proto b : block -> tp, tb, env2*)
assert (p.p_class = None);
@@ -512,32 +512,32 @@ let get_fun env p b = (* p : proto b : block -> tp, tb, env2*)
(* Check there is not already a function with similar prototype *)
let args_type = List.map fst ty_args in
ty_assert (not (List.exists
- (fun p -> p.tp_name = name && (List.map fst p.tp_args) = args_type) env.e_funs))
- ("Redefinition of function: " ^ name);
+ (fun p -> p.tp_name = name && (List.map fst p.tp_args) = args_type) env.e_funs))
+ ("Redefinition of function: " ^ name);
let ret_type = build_type_or_ref
(match p.p_ret_type with
- | Some k -> k
- | None -> ty_error "Internal error (function with no return type)" ) in
+ | Some k -> k
+ | None -> ty_error "Internal error (function with no return type)" ) in
(* Add to env *)
let tproto = {
- tp_loc = p.p_loc ;
- tp_name = name ;
- tp_unique_ident = name ^ (tproto_unique_number());
- tp_class = None ;
- tp_virtual = None ;
- tp_ret_type = Some ret_type ;
- tp_args = ty_args; } in
+ tp_loc = p.p_loc ;
+ tp_name = name ;
+ tp_unique_ident = name ^ (tproto_unique_number());
+ tp_class = None ;
+ tp_virtual = None ;
+ tp_ret_type = Some ret_type ;
+ tp_args = ty_args; } in
let env2 =
- { e_globals = env.e_globals;
- e_funs = tproto::(env.e_funs);
- e_classes = env.e_classes; } in
+ { e_globals = env.e_globals;
+ e_funs = tproto::(env.e_funs);
+ e_classes = env.e_classes; } in
(* Build local env *)
let locales = List.fold_left (* tr = (ty,ref?) *)
- (fun envir (tr,i) -> Smap.add i tr envir)
- Smap.empty
- ty_args
+ (fun envir (tr,i) -> Smap.add i tr envir)
+ Smap.empty
+ ty_args
in (* contexte ds l'instruction *)
let contexte = { b_pe = env2; b_locals = locales; b_class = None } in
let tb = get_block ret_type contexte b in (* vérif instructions typées*)
@@ -546,168 +546,168 @@ let get_fun env p b = (* p : proto b : block -> tp, tb, env2*)
(* Déclarations de classes *)
let compute_tclass env c =
- let cls_name = c.c_name in
- ty_assert (not (Smap.mem cls_name env.e_classes)) ("Redeclaration of class " ^cls_name^".");
- (* artifice pour que la classe en train d'être définie puisse être utilisée par elle-même *)
- let forward_def = {tc_name = cls_name; tc_size = 0; tc_super = None; tc_members = Smap.empty; tc_methods = []; tc_vtable = [] } in
- let forward_env = {
- e_globals = env.e_globals;
- e_funs = env.e_funs;
- e_classes = (Smap.add cls_name forward_def env.e_classes); } in
-
- let super, vtable, used = match c.c_supers with
- | Some [] | None -> None, ref [], 0
- | Some [n] ->
- begin try let c = get_c env n in
- Some n, ref c.tc_vtable, c.tc_size (* copy parent vtable, will be modified when redefined members *)
- with Not_found -> ty_error ("Super " ^ n ^ " does not exist or is not a class.")
- end
- | _ -> ty_error "Intentionnal sacrifice : multiple inheritance not supported."
- in
- let used = (if used = 0 then 4 else used) in (* If no supers, reserve space for vtable pointer *)
- let (mem, mem_u), meth = List.fold_left
- (fun ((mem, mem_u), meth) n -> match n with
- | CVar(t, i) ->
- let t, r = build_type_or_ref t in
- ty_assert (not r) "Class members cannot be references.";
- ty_assert (bf forward_env t) ("Malformed type for member " ^ i ^ ".");
- ty_assert (t <> TClass(cls_name)) "Class cannot contain itself as a member.";
- ty_assert (not (Smap.mem i mem)) ("Redefinition of class member " ^ i ^ " in class " ^ cls_name ^ ".");
- let size = type_size env t in
- ((Smap.add i (t, mem_u) mem, mem_u + size), meth)
- | CMethod(proto, virt) ->
- let m = err_add_loc proto.p_loc (fun () ->
- ty_assert (proto.p_class = None) "Overqualification in prototype.";
- ty_assert (proto.p_ret_type <> None || proto.p_name = cls_name) "Invalid name for constructor";
- (* Make sure prototype is well formed *)
- let args = parse_args forward_env proto.p_args in
- (* Make sure method is compatible with other declarations in this class *)
- ty_assert (not (List.exists
- (fun p -> p.tp_name = proto.p_name && (List.map fst p.tp_args) = (List.map fst args)) meth))
- ("Redefinition of function " ^ proto.p_name ^ " with same argument types.");
- (* Check return type *)
- let ret_type = match proto.p_ret_type with
- | Some k -> Some (build_type_or_ref k)
- | None -> None in
- (* If method is redefined from a virtual method of a parent class, it becomes virtual with same offset
- Else if method is virtual, it gets new offset !
- Else method is not virtual, everything is simple. *)
- let rec check_super = function
- | None -> None
- | Some(n) -> let c = get_c env n in
- try let proto = List.find
- (fun p -> p.tp_name = proto.p_name && p.tp_virtual <> None && (List.map fst p.tp_args) = (List.map fst args))
- c.tc_methods
- in Some (proto)
- with Not_found -> check_super (c.tc_super)
- in
- let vproto_in_super = check_super super in
- let virtl = match vproto_in_super with
- | Some(k) -> k.tp_virtual
- | None ->
- if not virt then None
- else (* allocate new spot in vtable *)
- Some (List.fold_left (fun n (x, _) -> max n (x+4)) 0 !vtable)
- in
- (* Build proto *)
- let tproto =
- { tp_virtual = virtl;
- tp_loc = proto.p_loc;
- tp_name = proto.p_name;
- tp_unique_ident = proto.p_name ^ (tproto_unique_number()) ;
- tp_class = Some(cls_name);
- tp_ret_type = ret_type;
- tp_args = args;
- } in
- (* Add to vtable *)
- begin match virtl with
- | None -> ()
- | Some i ->
- vtable := (i, tproto)::(List.remove_assoc i !vtable)
- end;
- tproto) in
- (mem, mem_u), m::meth
- ) ((Smap.empty, used), []) c.c_members in
- { tc_name = cls_name;
- tc_vtable = !vtable;
- tc_size = mem_u;
- tc_super = super;
- tc_members = mem;
- tc_methods = meth; }
-
-let get_method env proto block = (* return : TDFunction *)
- match proto.p_class with
- | None -> assert false
- | Some(cls_name) ->
- try let c = get_c env cls_name in
- let args = parse_args env proto.p_args in
- let ret_type = match proto.p_ret_type with
- | Some k -> Some (build_type_or_ref k)
- | None -> None in
- (* Find prototype in class *)
- begin try let cproto = List.find
- (fun p -> p.tp_args = args && p.tp_ret_type = ret_type && p.tp_name = proto.p_name) c.tc_methods
- in
- let locals = List.fold_left
- (fun env (tr, i) -> Smap.add i tr env) Smap.empty args in
- let contexte = {
- b_pe = env;
- b_locals = locals;
- b_class = Some c; } in
- let tb = get_block (match ret_type with | None -> T_Void, false | Some k -> k) contexte block in
- cproto, tb
- with
- | Not_found -> ty_error ("Implementation corresponds to no declared method of class " ^ cls_name)
- end
- with
- | Not_found -> ty_error (cls_name ^ " is not defined.")
-
+ let cls_name = c.c_name in
+ ty_assert (not (Smap.mem cls_name env.e_classes)) ("Redeclaration of class " ^cls_name^".");
+ (* artifice pour que la classe en train d'être définie puisse être utilisée par elle-même *)
+ let forward_def = {tc_name = cls_name; tc_size = 0; tc_super = None; tc_members = Smap.empty; tc_methods = []; tc_vtable = [] } in
+ let forward_env = {
+ e_globals = env.e_globals;
+ e_funs = env.e_funs;
+ e_classes = (Smap.add cls_name forward_def env.e_classes); } in
+
+ let super, vtable, used = match c.c_supers with
+ | Some [] | None -> None, ref [], 0
+ | Some [n] ->
+ begin try let c = get_c env n in
+ Some n, ref c.tc_vtable, c.tc_size (* copy parent vtable, will be modified when redefined members *)
+ with Not_found -> ty_error ("Super " ^ n ^ " does not exist or is not a class.")
+ end
+ | _ -> ty_error "Intentionnal sacrifice : multiple inheritance not supported."
+ in
+ let used = (if used = 0 then 4 else used) in (* If no supers, reserve space for vtable pointer *)
+ let (mem, mem_u), meth = List.fold_left
+ (fun ((mem, mem_u), meth) n -> match n with
+ | CVar(t, i) ->
+ let t, r = build_type_or_ref t in
+ ty_assert (not r) "Class members cannot be references.";
+ ty_assert (bf forward_env t) ("Malformed type for member " ^ i ^ ".");
+ ty_assert (t <> TClass(cls_name)) "Class cannot contain itself as a member.";
+ ty_assert (not (Smap.mem i mem)) ("Redefinition of class member " ^ i ^ " in class " ^ cls_name ^ ".");
+ let size = type_size env t in
+ ((Smap.add i (t, mem_u) mem, mem_u + size), meth)
+ | CMethod(proto, virt) ->
+ let m = err_add_loc proto.p_loc (fun () ->
+ ty_assert (proto.p_class = None) "Overqualification in prototype.";
+ ty_assert (proto.p_ret_type <> None || proto.p_name = cls_name) "Invalid name for constructor";
+ (* Make sure prototype is well formed *)
+ let args = parse_args forward_env proto.p_args in
+ (* Make sure method is compatible with other declarations in this class *)
+ ty_assert (not (List.exists
+ (fun p -> p.tp_name = proto.p_name && (List.map fst p.tp_args) = (List.map fst args)) meth))
+ ("Redefinition of function " ^ proto.p_name ^ " with same argument types.");
+ (* Check return type *)
+ let ret_type = match proto.p_ret_type with
+ | Some k -> Some (build_type_or_ref k)
+ | None -> None in
+ (* If method is redefined from a virtual method of a parent class, it becomes virtual with same offset
+ Else if method is virtual, it gets new offset !
+ Else method is not virtual, everything is simple. *)
+ let rec check_super = function
+ | None -> None
+ | Some(n) -> let c = get_c env n in
+ try let proto = List.find
+ (fun p -> p.tp_name = proto.p_name && p.tp_virtual <> None && (List.map fst p.tp_args) = (List.map fst args))
+ c.tc_methods
+ in Some (proto)
+ with Not_found -> check_super (c.tc_super)
+ in
+ let vproto_in_super = check_super super in
+ let virtl = match vproto_in_super with
+ | Some(k) -> k.tp_virtual
+ | None ->
+ if not virt then None
+ else (* allocate new spot in vtable *)
+ Some (List.fold_left (fun n (x, _) -> max n (x+4)) 0 !vtable)
+ in
+ (* Build proto *)
+ let tproto =
+ { tp_virtual = virtl;
+ tp_loc = proto.p_loc;
+ tp_name = proto.p_name;
+ tp_unique_ident = proto.p_name ^ (tproto_unique_number()) ;
+ tp_class = Some(cls_name);
+ tp_ret_type = ret_type;
+ tp_args = args;
+ } in
+ (* Add to vtable *)
+ begin match virtl with
+ | None -> ()
+ | Some i ->
+ vtable := (i, tproto)::(List.remove_assoc i !vtable)
+ end;
+ tproto) in
+ (mem, mem_u), m::meth
+ ) ((Smap.empty, used), []) c.c_members in
+ { tc_name = cls_name;
+ tc_vtable = !vtable;
+ tc_size = mem_u;
+ tc_super = super;
+ tc_members = mem;
+ tc_methods = meth; }
+
+let get_method env proto block = (* return : TDFunction *)
+ match proto.p_class with
+ | None -> assert false
+ | Some(cls_name) ->
+ try let c = get_c env cls_name in
+ let args = parse_args env proto.p_args in
+ let ret_type = match proto.p_ret_type with
+ | Some k -> Some (build_type_or_ref k)
+ | None -> None in
+ (* Find prototype in class *)
+ begin try let cproto = List.find
+ (fun p -> p.tp_args = args && p.tp_ret_type = ret_type && p.tp_name = proto.p_name) c.tc_methods
+ in
+ let locals = List.fold_left
+ (fun env (tr, i) -> Smap.add i tr env) Smap.empty args in
+ let contexte = {
+ b_pe = env;
+ b_locals = locals;
+ b_class = Some c; } in
+ let tb = get_block (match ret_type with | None -> T_Void, false | Some k -> k) contexte block in
+ cproto, tb
+ with
+ | Not_found -> ty_error ("Implementation corresponds to no declared method of class " ^ cls_name)
+ end
+ with
+ | Not_found -> ty_error (cls_name ^ " is not defined.")
+
(* Partie générique *)
let compute_decl env d =
- err_add_loc (d.d_loc) (fun () ->
- match d.d_desc with
- | DGlobal(t,i) -> let tr, r = build_type_or_ref t in
- ty_assert (bf env tr) ("Malformed type for global var " ^ i);
- ty_assert (not r) "Global cannot be reference";
- ty_assert (not (Smap.mem i env.e_globals)) ("Redeclaration of " ^ i);
- ty_assert (not (List.exists (fun p -> p.tp_name = i) env.e_funs)) ("Redeclaration of: " ^ i ^ ", was previously a function");
- (TDGlobal(tr,i)) ,
- { e_globals = (Smap.add i tr env.e_globals);
- e_funs = env.e_funs;
- e_classes = env.e_classes }
- (* on voudrait une liste de ident pr decl plsr en meme temps *)
- | DFunction (p,b) ->
- ty_assert (not (Smap.mem p.p_name env.e_globals)) ("Redeclaration of: " ^ p.p_name ^ ", was previously a global variable");
- begin match p.p_class with
- | None ->
- let tp, tb, env2 = get_fun env p b in
- TDFunction(tp, tb), env2
- | Some _ ->
- let tp, tb = get_method env p b in
- (TDFunction(tp, tb)), env(* env is not modified *)
- end
- | DClass c ->
- let tc = compute_tclass env c in
- (TDClass tc),
- { e_globals = env.e_globals;
- e_funs = env.e_funs;
- e_classes = Smap.add c.c_name tc env.e_classes; }
- )
+ err_add_loc (d.d_loc) (fun () ->
+ match d.d_desc with
+ | DGlobal(t,i) -> let tr, r = build_type_or_ref t in
+ ty_assert (bf env tr) ("Malformed type for global var " ^ i);
+ ty_assert (not r) "Global cannot be reference";
+ ty_assert (not (Smap.mem i env.e_globals)) ("Redeclaration of " ^ i);
+ ty_assert (not (List.exists (fun p -> p.tp_name = i) env.e_funs)) ("Redeclaration of: " ^ i ^ ", was previously a function");
+ (TDGlobal(tr,i)) ,
+ { e_globals = (Smap.add i tr env.e_globals);
+ e_funs = env.e_funs;
+ e_classes = env.e_classes }
+ (* on voudrait une liste de ident pr decl plsr en meme temps *)
+ | DFunction (p,b) ->
+ ty_assert (not (Smap.mem p.p_name env.e_globals)) ("Redeclaration of: " ^ p.p_name ^ ", was previously a global variable");
+ begin match p.p_class with
+ | None ->
+ let tp, tb, env2 = get_fun env p b in
+ TDFunction(tp, tb), env2
+ | Some _ ->
+ let tp, tb = get_method env p b in
+ (TDFunction(tp, tb)), env(* env is not modified *)
+ end
+ | DClass c ->
+ let tc = compute_tclass env c in
+ (TDClass tc),
+ { e_globals = env.e_globals;
+ e_funs = env.e_funs;
+ e_classes = Smap.add c.c_name tc env.e_classes; }
+ )
let prog p =
let decls, env = (
List.fold_left
(fun (decls, env) decl ->
- let decl_p, env2 = compute_decl env decl in
- decl_p::decls, env2)
+ let decl_p, env2 = compute_decl env decl in
+ decl_p::decls, env2)
([],{ e_globals = Smap.empty; e_funs = []; e_classes = Smap.empty })
p
) in
ty_assert (List.exists
- (fun tp -> tp.tp_class = None && tp.tp_name = "main"
- && tp.tp_args = [] && tp.tp_ret_type = Some (T_Int,false))
- env.e_funs) "No 'int main()' function defined in program...";
+ (fun tp -> tp.tp_class = None && tp.tp_name = "main"
+ && tp.tp_args = [] && tp.tp_ret_type = Some (T_Int,false))
+ env.e_funs) "No 'int main()' function defined in program...";
{ prog_decls = List.rev decls; prog_env = env }