|
|
@@ -11,20 +11,25 @@ open Stringify
|
|
|
* - The number of array indices must match the number of array dimensions.
|
|
|
* x The type on the right-hand side of an assignment must match the type on
|
|
|
* the left-hand side.
|
|
|
- * - The number of arguments used for a function call must match the number of
|
|
|
+ * x The number of arguments used for a function call must match the number of
|
|
|
* parameters for that function.
|
|
|
- * - The types of the function arguments must match the types of parameters.
|
|
|
+ * x The types of the function arguments must match the types of parameters.
|
|
|
* x The operands of a unary or binary operation must have valid types.
|
|
|
* x The predicate expression of an if, while, or do-while statement must be
|
|
|
* a boolean.
|
|
|
* x Only values having a basic type can be type cast.
|
|
|
*)
|
|
|
|
|
|
+let spec = function
|
|
|
+ | ArrayDec (ctype, dims) -> ArraySpec (ctype, list_size dims)
|
|
|
+ | ctype -> ctype
|
|
|
+
|
|
|
let check_type ?(msg="") expected = function
|
|
|
- | Type (node, got) when got != expected ->
|
|
|
+ | Type (node, got) when (spec got) <> (spec expected) ->
|
|
|
let msg = match msg with
|
|
|
| "" -> sprintf "expected type %s, got %s"
|
|
|
(type2str expected) (type2str got)
|
|
|
+ (*(type2str (spec expected)) (type2str (spec got))*)
|
|
|
| _ -> msg
|
|
|
in
|
|
|
raise (NodeError (node, msg))
|
|
|
@@ -53,11 +58,29 @@ let check_type_op allowed_types desc = function
|
|
|
| _ -> raise InvalidNode
|
|
|
|
|
|
let rec typecheck node = match node with
|
|
|
- | BoolConst (value, _) -> Type (node, Bool)
|
|
|
- | IntConst (value, _) -> Type (node, Int)
|
|
|
- | FloatConst (value, _) -> Type (node, Float)
|
|
|
- | VarUse (_, ctype, _) -> Type (node, ctype)
|
|
|
- | FunUse (_, ret_type, _) -> Type (node, ret_type)
|
|
|
+ | BoolConst (value, _) -> Type (node, Bool)
|
|
|
+ | IntConst (value, _) -> Type (node, Int)
|
|
|
+ | FloatConst (value, _) -> Type (node, Float)
|
|
|
+ | VarUse (_, ctype, _) -> Type (node, ctype)
|
|
|
+
|
|
|
+ | FunUse (FunCall (_, args, _), FunDef (_, ftype, name, params, _, _), _) ->
|
|
|
+ (match (list_size args, list_size params) with
|
|
|
+ | (nargs, nparams) when nargs != nparams ->
|
|
|
+ let msg =
|
|
|
+ sprintf "function \"%s\" expects %d arguments, got %d"
|
|
|
+ name nparams nargs
|
|
|
+ in
|
|
|
+ raise (NodeError (node, msg))
|
|
|
+ | _ ->
|
|
|
+ let check_arg_type arg param =
|
|
|
+ check_type (ctypeof param) (typecheck arg);
|
|
|
+ in
|
|
|
+ List.iter2 check_arg_type args params;
|
|
|
+ Type (node, ftype)
|
|
|
+ )
|
|
|
+
|
|
|
+ | Arg (Type (_, vtype)) -> Type (node, vtype)
|
|
|
+ | Arg value -> typecheck (Arg (typecheck value))
|
|
|
|
|
|
| Monop (op, (Type (_, vtype) as value), _) ->
|
|
|
let desc = sprintf "unary operator \"%s\"" (op2str op) in
|
|
|
@@ -78,11 +101,11 @@ let rec typecheck node = match node with
|
|
|
check_type ttype fexpr;
|
|
|
Type (node, ttype)
|
|
|
|
|
|
- | VarLet (_, (Type (_, vtype) as value), dec_type, depth) ->
|
|
|
+ | VarLet (Assign (_, (Type _ as value), _), dec_type, depth) ->
|
|
|
check_type dec_type value;
|
|
|
- Type (node, vtype)
|
|
|
- | VarLet (assign, value, dec_type, depth) ->
|
|
|
- typecheck (VarLet (assign, typecheck value, dec_type, depth))
|
|
|
+ node
|
|
|
+ | VarLet (assign, dec_type, depth) ->
|
|
|
+ typecheck (VarLet (typecheck assign, dec_type, depth))
|
|
|
|
|
|
| TypeCast (ctype, (Type _ as value), loc) ->
|
|
|
check_type_op [Bool; Int; Float] "typecast" value;
|
|
|
@@ -90,10 +113,8 @@ let rec typecheck node = match node with
|
|
|
| TypeCast (ctype, value, loc) ->
|
|
|
typecheck (TypeCast (ctype, typecheck value, loc))
|
|
|
|
|
|
- | Return (Type _, _) ->
|
|
|
- node
|
|
|
- | Return (value, loc) ->
|
|
|
- typecheck (Return (typecheck value, loc))
|
|
|
+ | Return (Type _, _) -> node
|
|
|
+ | Return (value, loc) -> typecheck (Return (typecheck value, loc))
|
|
|
|
|
|
| FunDef (export, ret_type, name, params, body, loc) ->
|
|
|
let params = transform_all typecheck params in
|