From 2560caab09ccedc18c63f65eafbf0a866a28ea4b Mon Sep 17 00:00:00 2001 From: mathis Date: Fri, 31 Dec 2021 22:43:17 +0100 Subject: [PATCH] check_expr_static_call --- doc/contextual_checks.md | 4 +- lib/astmanip.ml | 16 ++++++++ lib/contextual.ml | 31 ++++++++++++--- progs/ex1_ast.txt | 83 ---------------------------------------- 4 files changed, 44 insertions(+), 90 deletions(-) diff --git a/doc/contextual_checks.md b/doc/contextual_checks.md index c57cd74..9335310 100644 --- a/doc/contextual_checks.md +++ b/doc/contextual_checks.md @@ -49,8 +49,8 @@ * (Called method exists * Called method params are compatible with declaration -* (**Missing**) Called static method exists in static class -* (**Missing**) Called static method params are compatible with declaration +* Called static method exists in static class +* Called static method params are compatible with declaration * (**Missing**) Call to New exists * (**Missing**) Params in New call are compatible with ctor * (**Missing**) Numeric operators are used on Integer types diff --git a/lib/astmanip.ml b/lib/astmanip.ml index 64f2a9e..cf589ec 100644 --- a/lib/astmanip.ml +++ b/lib/astmanip.ml @@ -38,6 +38,22 @@ let rec find_method_opt decls name decl = in find_method_opt decls name superDecl ) +(** Get a static method declaration in a class with a given name. *) + +let get_static_method_opt name decl = + List.find_opt (fun (meth: methodDecl) -> meth.name = name) decl.body.staticMethods + +(** Get a static method declaration in a class with a given name. + @raise Not_found if the class has no such static method. *) + +let get_static_method name decl = + get_static_method_opt name decl + |> Optmanip.get_or_else (fun () -> + (* Printf.eprintf "[ERR] get_static_method_opt '%s' failed\n" name; *) + raise Not_found + ) + + (** Get the type of an attribute in a class declaration. *) let rec get_inst_attr_opt attrName decl = diff --git a/lib/contextual.ml b/lib/contextual.ml index 8e0ef01..8b6cbb5 100644 --- a/lib/contextual.ml +++ b/lib/contextual.ml @@ -36,7 +36,7 @@ let check_inheritance decls = ) in decls_with_super |> List.iter (fun (name, super) -> match find_class_opt decls super with - | None -> err (Printf.sprintf "class '%s' extends non-existing class '%s'" name super) + | None -> err (Printf.sprintf "class '%s' extends unknown class '%s'" name super) | _ -> () ) @@ -322,6 +322,9 @@ and check_expr_static_attr decls (t, name) = in if Option.is_none attr then err (Printf.sprintf "no static attribute named '%s' in class '%s'" name t) +(** Checks a function call expression. + @raise Contextual_error if a check fails. *) + and check_expr_call decls env (e, methName, args) = check_expr decls env e; let t = get_expr_type decls env e @@ -335,7 +338,7 @@ and check_expr_call decls env (e, methName, args) = | "String", _, _::_ -> err (Printf.sprintf "'%S::%s' expects no arguments" t methName) | "String", _, _ - | "Integer", _, _ -> err (Printf.sprintf "call to non-existing method '%s::%s'" t methName) + | "Integer", _, _ -> err (Printf.sprintf "call to unknown method '%s::%s'" t methName) | _ -> let decl = find_class decls t @@ -346,7 +349,24 @@ and check_expr_call decls env (e, methName, args) = ) in match meth with | Some(meth) -> check_call_args decls args meth - | None -> err (Printf.sprintf "call to non-existing method '%s::%s'" t methName) + | None -> err (Printf.sprintf "call to unknown method '%s::%s'" t methName) + +(** Checks a function call expression. + @raise Contextual_error if a check fails. *) + +and check_expr_static_call decls env (className, methName, args) = + let decl = find_class_opt decls className + in match decl with + | None -> err (Printf.sprintf "call to static method '%s' of unknown class '%s'" methName className) + | Some(decl) -> + let meth = get_static_method_opt methName decl + in let args = args |> List.map (fun e -> + check_expr decls env e; + get_expr_type decls env e + ) + in match meth with + | Some(meth) -> check_call_args decls args meth + | None -> err (Printf.sprintf "call to unknown static method '%s::%s'" className methName) (** Checks an expression. @raise Contextual_error if a check fails. *) @@ -357,10 +377,11 @@ and check_expr decls env expr = | Attr(e, name) -> check_expr_attr decls env (e, name) | StaticAttr(className, name) -> check_expr_static_attr decls (className, name) | UMinus e -> check_expr decls env e - | Call(e, methName, args) -> check_expr_call decls env (e, methName, args) | List le | New(_, le) -> List.iter (check_expr decls env) le + | Call(e, methName, args) -> check_expr_call decls env (e, methName, args) + | StaticCall(className, methName, args) -> check_expr_static_call decls env (className, methName, args) | BinOp(e1, _, e2) | StrCat(e1, e2) -> check_expr decls env e1; check_expr decls env e2 - | Cste _ | StaticCall _ | String _ -> () + | Cste _ | String _ -> () (* -------------------------------------------------------------------------- *) diff --git a/progs/ex1_ast.txt b/progs/ex1_ast.txt index 1b5c1e7..e84ce95 100644 --- a/progs/ex1_ast.txt +++ b/progs/ex1_ast.txt @@ -1,86 +1,3 @@ -(Ast.Attr ((Ast.Id "this"), "clone")) -(Ast.Attr ((Ast.Id "this"), "clone")) -(Ast.String "Inside Point::print") -(Ast.Attr ((Ast.Id "this"), "name")) -(Ast.Attr ((Ast.Id "this"), "x")) -(Ast.Attr ((Ast.Id "this"), "y")) -(Ast.StrCat ( - (Ast.StrCat ( - (Ast.StrCat ( - (Ast.StrCat ((Ast.String "= ("), - (Ast.Call ((Ast.Attr ((Ast.Id "this"), "x")), "toString", [])))), - (Ast.String ", "))), - (Ast.Call ((Ast.Attr ((Ast.Id "this"), "y")), "toString", [])))), - (Ast.String ")"))) -(Ast.Id "this") -(Ast.String "Inside Couleur::estGris") -(Ast.String "Inside Couleur::couleur") -(Ast.String "Inside PointColore::print") -(Ast.Id "super") -(Ast.Id "this") -(Ast.Call ((Ast.Id "this"), "couleur", [])) -(Ast.Call ((Ast.Call ((Ast.Id "this"), "couleur", [])), "name", - [(Ast.Cste 1)])) -(Ast.Attr ((Ast.Id "this"), "coul")) -(Ast.Attr ((Ast.Id "this"), "coul")) -(Ast.Id "p") -(Ast.Call ((Ast.Id "p"), "couleur", [])) -(Ast.Call ((Ast.Call ((Ast.Id "p"), "couleur", [])), "name", [(Ast.Cste 1)])) -(Ast.Id "p") -(Ast.Id "p2") -(Ast.String "Appel 1: ") -(Ast.Id "p2") -(Ast.String "Appel 2: ") -(Ast.Id "p3") -(Ast.String "Appel 3: ") -(Ast.Id "p3") -(Ast.String "Resultats de test: ") -(Ast.Id "c") -(Ast.String " ") -(Ast.Id "c2") -(Ast.String " ") -(Ast.Id "c3") -(Ast.String "") -(Ast.String "Debut du programme") -(Ast.Id "p1") -(Ast.Id "p2") -(Ast.Id "p2") -(Ast.Id "p1") -(Ast.Id "p1") -(Ast.Id "p2") -(Ast.Id "o") -(Ast.Id "o") -(Ast.Id "o") -(Ast.Id "p2") -(Ast.Id "p1") -(Ast.Id "p1") -(Ast.Id "p2") -(Ast.String "On va essayer le clonage:") -(Ast.Id "p1") -(Ast.Id "clone1") -(Ast.String "p1 isCloned: ") -(Ast.Id "p1") -(Ast.String "OK") -(Ast.String "KO") -(Ast.Id "clone1") -(Ast.Id "clone2") -(Ast.Call ((Ast.Id "clone2"), "move", - [(Ast.Cste 54); (Ast.Cste 36); (Ast.Cste 0)])) -(Ast.String "Impression de tous les clones de p1:") -(Ast.Id "p1") -(Ast.String "Fin de l'impression de tous les clones") -(Ast.String "Valeur du compteur de nombre de points: ") -(Ast.StaticCall ("Point", "howMany", [])) -(Ast.Call ((Ast.StaticCall ("Point", "howMany", [])), "toString", [])) -(Ast.Id "p1") -(Ast.Call ((Ast.Id "p1"), "clone", [])) -(Ast.Id "p1") -(Ast.Id "o") -(Ast.Call ((Ast.Id "o"), "clone", [])) -(Ast.String "test(Point, PointColore, PointNoir)") -(Ast.String "test(PointNoir, PointNoir, PointNoir)") -(Ast.String "test(PointNoir, PointNoir, PointNoir)") -(Ast.String "\nDone") { Ast.decls = [{ Ast.name = "Point"; ctorParams =