summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser.mly3
-rw-r--r--src/typing.ml61
2 files changed, 46 insertions, 18 deletions
diff --git a/src/parser.mly b/src/parser.mly
index 0cf545d..2b50797 100644
--- a/src/parser.mly
+++ b/src/parser.mly
@@ -55,7 +55,6 @@
%left LT LE GT GE
%left PLUS MINUS
%left TIMES DIV MOD
-%nonassoc LPAREN
%start <Ast.program> prog
@@ -245,7 +244,6 @@ expression:
expression_desc:
| e1 = expression ASSIGN e2 = expression { EAssign(e1, e2) }
| a = expression b = binop c = expression { EBinary(a, b, c) }
-| a = expression LPAREN arg = separated_list(COMMA, expression) RPAREN { ECall(a, arg) }
| NEW c = TIDENT LPAREN args = separated_list(COMMA, expression) RPAREN { ENew(c, args) }
;
@@ -282,6 +280,7 @@ primary_desc:
{ EMember(
{ e_loc = $startpos, $endpos; e_desc = EUnary(Deref, a)}
, b) }
+| a = primary LPAREN arg = separated_list(COMMA, expression) RPAREN { ECall(a, arg) }
| a = primary DOT b = IDENT
{ EMember(a, b) }
;
diff --git a/src/typing.ml b/src/typing.ml
index 8f042f1..a87bf16 100644
--- a/src/typing.ml
+++ b/src/typing.ml
@@ -44,7 +44,9 @@ and texpr_desc =
| TEIdent of ident
| TEAssign of texpression * texpression
| TECallFun of ident * texpression list (* changé : te -> ident *)
- | TECallMethod of texpression * 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 *)
+ | TECallVirtual of texpression * ident * texpression list (* TODO (c'est le bazar) *)
| TEUnary of unop * texpression
| TEBinary of texpression * binop * texpression
| TEMember of texpression * ident
@@ -78,6 +80,7 @@ and tproto = {
tp_virtual : bool; (* only used for class methods *)
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;
@@ -90,6 +93,12 @@ and tcls = {
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
+
type env = {
e_globals : typ Smap.t;
e_funs : tproto list;
@@ -292,10 +301,14 @@ and compute_type env e =
closest_proto env.b_pe args_types candidates
in
let l_te = List.map fst args_values in
+ let l_te = match obj with
+ | None -> l_te
+ | Some(obj_e) -> obj_e :: l_te 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
- TECallFun(name,l_te),(ty,b,false)
+ ty_assert (not tproto.tp_virtual) "Virtual methods not implemented yet.";
+ TECallFun(tproto.tp_unique_ident,l_te),(ty,b,false)
| EMember (e, id) ->
let e, (ty, r, l) = get_expr0 env e in
begin match ty with
@@ -392,17 +405,6 @@ and compute_type_stm ret_type env s = match s.s_desc with (* statement -> ts_des
b_locals = Smap.add i (ty,b) env.b_locals;
b_class = env.b_class } in
TSDeclareAssignExpr( (ty,b) ,i,te) , env0
- | 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
- in
- TSWriteCout(args) , env
| SDeclareAssignConstructor(vt,i,ti,e_l) ->
let ty, b = build_type_or_ref vt in
ty_assert (bf env.b_pe ty) "Malformed type";
@@ -421,8 +423,23 @@ and compute_type_stm ret_type env s = match s.s_desc with (* statement -> ts_des
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
- TSDeclareAssignConstructor(ty, i, Some p, ti, l_te), env
+ 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
+ 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 =
@@ -468,8 +485,14 @@ let get_fun env p b = (* p : proto b : block -> tp, tb, env2*)
| 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_class = None ; tp_virtual = false ;
- tp_ret_type = Some ret_type ; tp_args = ty_args; } in
+ let tproto = {
+ tp_loc = p.p_loc ;
+ tp_name = name ;
+ tp_unique_ident = name ^ (tproto_unique_number());
+ tp_class = None ;
+ tp_virtual = false ;
+ tp_ret_type = Some ret_type ;
+ tp_args = ty_args; } in
let env2 =
{ e_globals = env.e_globals;
e_funs = tproto::(env.e_funs);
@@ -531,6 +554,7 @@ and build_method env cls_name cls_mems virt proto =
{ tp_virtual = virt;
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;
@@ -559,6 +583,7 @@ let get_method env proto block = (* return : TDFunction *)
{ tp_virtual = cproto.tp_virtual;
tp_loc = proto.p_loc;
tp_name = proto.p_name;
+ tp_unique_ident = proto.p_name ^ (tproto_unique_number()) ;
tp_class = proto.p_class;
tp_ret_type = ret_type;
tp_args = args }, tb
@@ -610,6 +635,10 @@ let prog p =
([],{ 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...";
{ prog_decls = decls; prog_env = env }