7 |
* check for unreachable code and prune it (see simplify/simplify.sml) |
* check for unreachable code and prune it (see simplify/simplify.sml) |
8 |
* error recovery so that we can detect multiple errors in a single compile |
* error recovery so that we can detect multiple errors in a single compile |
9 |
* check that functions have a return on all paths |
* check that functions have a return on all paths |
10 |
* check that strands have at least one output variable. |
* check that the args of strand creation have the same type and number as the params |
11 |
*) |
*) |
12 |
|
|
13 |
structure Typechecker : sig |
structure Typechecker : sig |
771 |
(* check the strand parameters *) |
(* check the strand parameters *) |
772 |
val (params, env) = checkParams (env, cxt, params) |
val (params, env) = checkParams (env, cxt, params) |
773 |
(* check the strand state variable definitions *) |
(* check the strand state variable definitions *) |
774 |
val (vds, env) = let |
val (vds, hasOutput, env) = let |
775 |
fun checkStateVar ((isOut, vd), (vds, env)) = let |
fun checkStateVar ((isOut, vd), (vds, hasOut, env)) = let |
776 |
val kind = if isOut then AST.StrandOutputVar else AST.StrandStateVar |
val kind = if isOut then AST.StrandOutputVar else AST.StrandStateVar |
777 |
val (x, x', e') = checkVarDecl (env, cxt, kind, vd) |
val (x, x', e') = checkVarDecl (env, cxt, kind, vd) |
778 |
in |
in |
784 |
]) |
]) |
785 |
else (); |
else (); |
786 |
checkForRedef (env, cxt, x); |
checkForRedef (env, cxt, x); |
787 |
(AST.VD_Decl(x', e')::vds, insertLocal(env, cxt, x, x')) |
(AST.VD_Decl(x', e')::vds, hasOut orelse isOut, insertLocal(env, cxt, x, x')) |
788 |
end |
end |
789 |
val (vds, env) = List.foldl checkStateVar ([], env) state |
val (vds, hasOutput, env) = List.foldl checkStateVar ([], false, env) state |
790 |
in |
in |
791 |
(List.rev vds, env) |
(List.rev vds, hasOutput, env) |
792 |
end |
end |
793 |
(* check the strand methods *) |
(* check the strand methods *) |
794 |
val methods = List.map (fn m => checkMethod (env, cxt, m)) methods |
val methods = List.map (fn m => checkMethod (env, cxt, m)) methods |
799 |
then methods |
then methods |
800 |
else methods @ [AST.M_Method(StrandUtil.Stabilize, AST.S_Block[])] |
else methods @ [AST.M_Method(StrandUtil.Stabilize, AST.S_Block[])] |
801 |
in |
in |
802 |
|
(* FIXME: once there are global outputs, then it should be okay to have not strand outputs! *) |
803 |
|
(* check that there is at least one output variable *) |
804 |
|
if not hasOutput |
805 |
|
then err(cxt, [S "strand ", A name, S " does not have any outputs"]) |
806 |
|
else (); |
807 |
(* FIXME: should check for duplicate method definitions *) |
(* FIXME: should check for duplicate method definitions *) |
808 |
if not(List.exists (fn StrandUtil.Update => true | _ => false) methodNames) |
if not(List.exists (fn StrandUtil.Update => true | _ => false) methodNames) |
809 |
then err(cxt, [S "strand ", A name, S " is missing an update method"]) |
then err(cxt, [S "strand ", A name, S " is missing an update method"]) |
815 |
| checkCreate (env, cxt, PT.C_Create(strand, args)) = let |
| checkCreate (env, cxt, PT.C_Create(strand, args)) = let |
816 |
val (args, tys) = checkExprList (env, cxt, args) |
val (args, tys) = checkExprList (env, cxt, args) |
817 |
in |
in |
818 |
(* FIXME: check against strand definition *) |
(* FIXME: check args against strand definition *) |
819 |
AST.C_Create(strand, args) |
AST.C_Create(strand, args) |
820 |
end |
end |
821 |
|
|