feat(library/init/lean/compiler/ir/checker): improve IR checker

This commit is contained in:
Leonardo de Moura 2019-05-08 05:47:25 -07:00
parent a24a8361f5
commit 74fb8e627a
3 changed files with 50 additions and 6 deletions

View file

@ -80,6 +80,8 @@ def IRType.beq : IRType → IRType → Bool
| IRType.tobject IRType.tobject := true
| _ _ := false
instance IRType.HasBeq : HasBeq IRType := ⟨IRType.beq⟩
def IRType.isScalar : IRType → Bool
| IRType.float := true
| IRType.uint8 := true
@ -89,7 +91,10 @@ def IRType.isScalar : IRType → Bool
| IRType.usize := true
| _ := false
instance IRType.HasBeq : HasBeq IRType := ⟨IRType.beq⟩
def IRType.isObj : IRType → Bool
| IRType.object := true
| IRType.tobject := true
| _ := false
/- Arguments to applications, constructors, etc.
We use `irrelevant` for Lean types, propositions and proofs that have been erased.

View file

@ -30,8 +30,41 @@ match a with
def checkArgs (as : Array Arg) : M Unit :=
as.mfor checkArg
def checkExpr : Expr → M Unit
| e := pure ()
@[inline] def checkType (ty : IRType) (p : IRType → Bool) : M Unit :=
unless (p ty) $ throw ("unexpected type")
def checkObjType (ty : IRType) : M Unit := checkType ty IRType.isObj
def checkScalarType (ty : IRType) : M Unit := checkType ty IRType.isScalar
@[inline] def checkVarType (x : VarId) (p : IRType → Bool) : M Unit :=
do ctx ← read,
match ctx.getType x with
| some ty := checkType ty p
| none := throw ("unknown variable '" ++ toString x ++ "'")
def checkObjVar (x : VarId) : M Unit :=
checkVarType x IRType.isObj
def checkScalarVar (x : VarId) : M Unit :=
checkVarType x IRType.isScalar
def checkExpr (ty : IRType) : Expr → M Unit
| (Expr.pap _ ys) := checkObjType ty *> checkArgs ys -- partial applications should always produce a closure object
| (Expr.ap x ys) := checkObjVar x *> checkArgs ys
| (Expr.fap c ys) := checkArgs ys
| (Expr.ctor c ys) := when (!c.isScalar) (checkObjType ty) *> checkArgs ys
| (Expr.reset x) := checkObjVar x *> checkObjType ty
| (Expr.reuse x i u ys) := checkObjVar x *> checkArgs ys *> checkObjType ty
| (Expr.box xty x) := checkObjType ty *> checkScalarVar x *> checkVarType x (==xty)
| (Expr.unbox x) := checkScalarType ty *> checkObjVar x
| (Expr.proj _ x) := checkObjVar x *> checkObjType ty
| (Expr.uproj _ x) := checkObjVar x *> checkType ty (==IRType.usize)
| (Expr.sproj _ _ x) := checkObjVar x *> checkScalarType ty
| (Expr.isShared x) := checkObjVar x *> checkType ty (==IRType.uint8)
| (Expr.isTaggedPtr x) := checkObjVar x *> checkType ty (==IRType.uint8)
| (Expr.lit (LitVal.str _)) := checkObjType ty
| (Expr.lit _) := pure ()
@[inline] def withParams (ps : Array Param) (k : M Unit) : M Unit :=
do ctx ← read,
@ -44,7 +77,7 @@ local attribute [instance] monadInhabited
partial def checkFnBody : FnBody → M Unit
| (FnBody.vdecl x t v b) := do
checkExpr v,
checkExpr t v,
ctx ← read,
when (ctx.contains x.idx) $ throw ("invalid variable declaration, shadowing is not allowed"),
adaptReader (λ ctx : Context, ctx.addLocal x t v) (checkFnBody b)
@ -73,7 +106,7 @@ end Checker
def Decl.check (d : Decl) : IO Unit :=
match Checker.checkDecl d {} with
| Except.error msg := throw (IO.userError ("IR check failed at '" ++ toString d.id ++ "'"))
| Except.error msg := throw (IO.userError ("IR check failed at '" ++ toString d.id ++ "', error: " ++ msg))
| other := pure ()
end IR

View file

@ -118,7 +118,13 @@ std::string decl_to_string(decl const & d) {
void test(decl const & d) {
inc(d.raw());
object * r = test_core(d.raw(), io_mk_world());
dec(r);
if (io_result_is_error(r)) {
io_result_show_error(r);
dec(r);
throw exception("IR test error");
} else {
dec(r);
}
}
}