|
|
@@ -172,31 +172,29 @@ let rec typecheck node =
|
|
|
| Dim (name, ann) ->
|
|
|
(Dim (name, Type Int :: ann), [])
|
|
|
|
|
|
- (* Void functions may have no return statement, other functions must have a
|
|
|
- * return statement of valid type *)
|
|
|
+ (* Void functions may have a return statement without a value, other functions
|
|
|
+ * must have a return statement of a valid type *)
|
|
|
| FunDef (export, ret_type, name, params, body, ann) ->
|
|
|
let params, perr = err_map typecheck params in
|
|
|
let body, berr = typecheck body in
|
|
|
- let rec find_return = function
|
|
|
- | [] -> None
|
|
|
- | [Return (value, _) as ret] -> Some (ret, typeof value)
|
|
|
- | hd :: tl -> find_return tl
|
|
|
+ let rec check_types = function
|
|
|
+ | Return (Some _, _) as ret when ret_type = Void ->
|
|
|
+ ret, [NodeMsg (ret, "void function should not have a return value")]
|
|
|
+
|
|
|
+ | Return (Some value, _) as ret when typeof value <> ret_type ->
|
|
|
+ ret, [NodeMsg (ret, sprintf
|
|
|
+ "function \"%s\" has return type %s, got %s"
|
|
|
+ name (type2str ret_type) (type2str (typeof value)))]
|
|
|
+
|
|
|
+ | node -> traverse_list check_types node
|
|
|
in
|
|
|
let err =
|
|
|
- match (ret_type, find_return (block_body body)) with
|
|
|
- | (Void, Some (ret, _)) ->
|
|
|
- [NodeMsg (ret, "void function should not have a return value")]
|
|
|
-
|
|
|
- | ((Bool | Int | Float), None) ->
|
|
|
+ snd (check_types body) @
|
|
|
+ match last_if_return body with
|
|
|
+ | None when ret_type <> Void ->
|
|
|
[NodeMsg (node, sprintf
|
|
|
- "expected return value of type %s for function \"%s\""
|
|
|
+ "function \"%s\" must end with a return of type %s"
|
|
|
(type2str ret_type) name)]
|
|
|
-
|
|
|
- | ((Bool | Int | Float), Some (ret, t)) when t != ret_type ->
|
|
|
- [NodeMsg (ret, sprintf
|
|
|
- "function \"%s\" has return type %s, got %s"
|
|
|
- name (type2str ret_type) (type2str t))]
|
|
|
-
|
|
|
| _ -> []
|
|
|
in
|
|
|
(FunDef (export, ret_type, name, params, body, ann), perr @ berr @ err)
|