/tmp/mosstmp/csu00097/comp-proof.sml

signature SMALL =
sig
type var=string ;
datatype IExpr= 
                PLUS of IExpr*IExpr 
               |MINUS of IExpr*IExpr
               |MULT of IExpr*IExpr
               |DIV of IExpr*IExpr
               |MOD of IExpr*IExpr
               |LET of IExpr*IExpr*IExpr
               |ERR of IExpr  
               |VAR of var| INT of int ;

type Env= (var * int) list ;

exception  UNDECLAREDVARIABLE ;
val reduce: (IExpr*Env) -> IExpr 
val proof: ( IExpr * Env * ((Env*IExpr*IExpr*string) list)) ->  (Env*IExpr*IExpr*string) list  ; 
  
end ;

structure SSTEP: SMALL =

struct

type var=string ;
datatype IExpr=
                PLUS of IExpr*IExpr
               |MINUS of IExpr*IExpr
               |MULT of IExpr*IExpr
               |DIV of IExpr*IExpr
               |MOD of IExpr*IExpr
               |LET of IExpr*IExpr*IExpr
               |ERR of IExpr
               |VAR of var| INT of int ;

type Env= (var * int) list ;

exception  UNDECLAREDVARIABLE ;


(* independent *)

fun equal(x:var,y:var)=
  let
    
    fun eq([],[])=true 
        |eq(a::x,[])=false 
        |eq([],b::y)=false 
        |eq(a::x,b::y)= if (a=b) then eq(x,y) else false ;
   in
     eq(explode(x),explode(y)) 
  end 

   
(* independent *)

fun find(x:var,[])= raise UNDECLAREDVARIABLE    
| find(x,y::E)=
        let 
          

val (a,b)=y ;
        
in
    if equal(x,a) then INT(b) else find(x,E) 
 end
 

(* independent *)

fun upd(E,x,n)=
let 

fun up_iter(left,[],(x,n))=left@(x,n)::[]
    |up_iter(left,y::right,(x,n))=
      let
        val (a,b)=y ;
      in
    if equal(x,a) then left@(x,n)::right 
    else up_iter(left@y::[],right,(x,n))
end

in

up_iter([],E,(x,n)) 
end


(* independent *)

fun reduce(INT(n),E)=INT(n)
|reduce(ERR(e),E)=ERR(e) 
|reduce(PLUS(INT(n1),INT(n2)),E)=INT(n1+n2) 
|reduce(VAR(x),E)= find(x,E)
|reduce(PLUS(ERR(e1),e2),E)=ERR(e1)
|reduce(PLUS(INT(n),ERR(e)),E)=ERR(e)
|reduce(PLUS(INT(n),e),E)=PLUS(INT(n),reduce(e,E)) 
|reduce(PLUS(e1,e2),E)=PLUS(reduce(e1,E),e2) 

|reduce(MINUS(INT(n1),INT(n2)),E)=INT(n1-n2)
|reduce(MINUS(ERR(e1),e2),E)=ERR(e1) 
|reduce(MINUS(INT(n),ERR(e)),E)=ERR(e)
|reduce(MINUS(INT(n),e),E)=MINUS(INT(n),reduce(e,E))
|reduce(MINUS(e1,e2),E)=MINUS(reduce(e1,E),e2)

|reduce(MULT(INT(n1),INT(n2)),E)=INT(n1*n2)
|reduce(MULT(ERR(e1),e2),E)=ERR(e1) 
|reduce(MULT(INT(n),ERR(e)),E)=ERR(e)
|reduce(MULT(INT(n),e),E)=MULT(INT(n),reduce(e,E))
other|reduce(MULT(e1,e2),E)=MULT(reduce(e1,E),e2)

|reduce(DIV(INT(n1),INT(n2)),E)=if (n2=0) then ERR(DIV(INT(n1),INT(n2)))
                            else INT(n1 div n2)
|reduce(DIV(ERR(e1),e2),E)=ERR(e1) 
|reduce(DIV(INT(n),ERR(e)),E)=ERR(e)
|reduce(DIV(INT(n),e),E)=DIV(INT(n),reduce(e,E))
|reduce(DIV(e1,e2),E)=DIV(reduce(e1,E),e2)

|reduce(MOD(INT(n1),INT(n2)),E)=INT(n1 mod n2)
|reduce(MOD(ERR(e1),e2),E)=ERR(e1) 
|reduce(MOD(INT(n),ERR(e)),E)=ERR(e)
|reduce(MOD(INT(n),e),E)=MOD(INT(n),reduce(e,E))
other|reduce(MOD(e1,e2),E)=MOD(reduce(e1,E),e2)  

|reduce(LET(VAR(x), INT(n1), INT(n2)),E)= INT(n2) 
|reduce(LET(VAR(x), INT(n1), e2),E)=
       LET(VAR(x),INT(n1),reduce(e2,upd(E,x,n1))) 

|reduce(LET(VAR(x),e1,e2),E)=LET(VAR(x),reduce(e1,E),e2) ;



fun  proof(INT(n:int),E:Env,[]:(Env*IExpr*IExpr*string) list )=(E,INT(n),INT(n),"zero")::[]  
|proof(INT(n:int),E:Env,L:(Env*IExpr*IExpr*string) list )= rev(L)
|proof(ERR(e:IExpr),E,[])=(E,ERR(e),ERR(e),"zero")::[]
|proof(ERR(e:IExpr),E,L)=rev(L)
|proof(PLUS(INT(n1),INT(n2)),E,L)=proof(reduce(PLUS(INT(n1),INT(n2)),E),E,(E,PLUS(INT(n1),INT(n2)),reduce(PLUS(INT(n1),INT(n2)),E),"add0")::L)

 
|proof(VAR(x),E,L)= proof(reduce(VAR(x),E),E,(E,VAR(x),reduce(VAR(x),E),"vbl")::L)
|proof(PLUS(ERR(e1),e2),E,L)=proof(reduce(PLUS(ERR(e1),e2),E),E,(E,PLUS(ERR(e1),e2),reduce(PLUS(ERR(e1),e2),E),"err0")::L)

|proof(PLUS(INT(n),ERR(e)),E,L)=proof(reduce(PLUS(INT(n),ERR(e)),E),E,(E,PLUS(INT(n),ERR(e)),reduce(PLUS(INT(n),ERR(e)),E),"err0")::L)

|proof(PLUS(INT(n),e),E,L)=proof(PLUS(INT(n),reduce(e,E)),E,(E,PLUS(INT(n),e),reduce(PLUS(INT(n),e),E),"addr")::L) 
|proof(PLUS(e1,e2),E,L)=proof(reduce(e1,E),E,(E,PLUS(e1,e2),reduce(PLUS(e1,e2),E),"addl")::L)

|proof(MINUS(INT(n1),INT(n2)),E,L)=proof(reduce(MINUS(INT(n1),INT(n2)),E),E,(E,MINUS(INT(n1),INT(n2)),reduce(MINUS(INT(n1),INT(n2)),E),"sub0")::L)
|proof(MINUS(ERR(e1),e2),E,L)=proof(reduce(MINUS(ERR(e1),e2),E),E,(E,MINUS(ERR(e1),e2),reduce(MINUS(ERR(e1),e2),E),"err0")::L)
|proof(MINUS(INT(n),ERR(e)),E,L)=proof(reduce(MINUS(INT(n),ERR(e)),E),E,(E,MINUS(INT(n),ERR(e)),reduce(MINUS(INT(n),ERR(e)),E),"err0")::L)
|proof(MINUS(INT(n),e),E,L)=proof(reduce(e,E),E,(E,MINUS(INT(n),e),reduce(MINUS(INT(n),e),E),"subr")::L)
|proof(MINUS(e1,e2),E,L)=proof(reduce(e1,E),E,(E,MINUS(e1,e2),reduce(MINUS(e1,e2),E),"subl")::L)

|proof(MULT(INT(n1),INT(n2)),E,L)=proof(reduce(MULT(INT(n1),INT(n2)),E),E,(E,MULT(INT(n1),INT(n2)),reduce(MULT(INT(n1),INT(n2)),E),"mult0")::L)
|proof(MULT(ERR(e1),e2),E,L)=proof(reduce(MULT(ERR(e1),e2),E),E,(E,MULT(ERR(e1),e2),reduce(MULT(ERR(e1),e2),E),"err0")::L)
|proof(MULT(INT(n),ERR(e)),E,L)=proof(reduce(MULT(INT(n),ERR(e)),E),E,(E,MULT(INT(n),ERR(e)),reduce(MULT(INT(n),ERR(e)),E),"err0")::L)
|proof(MULT(INT(n),e),E,L)=proof(reduce(e,E),E,(E,MULT(INT(n),e),reduce(MULT(INT(n),e),E),"multr")::L)
|proof(MULT(e1,e2),E,L)=proof(reduce(e1,E),E,(E,MULT(e1,e2),reduce(MULT(e1,e2),E),"multl")::L)

|proof(DIV(INT(n1),INT(n2)),E,L)=proof(reduce(DIV(INT(n1),INT(n2)),E),E,(E,DIV(INT(n1),INT(n2)),reduce(DIV(INT(n1),INT(n2)),E),"div0")::L)
|proof(DIV(ERR(e1),e2),E,L)=proof(reduce(DIV(ERR(e1),e2),E),E,(E,DIV(ERR(e1),e2),reduce(DIV(ERR(e1),e2),E),"err0")::L) 
|proof(DIV(INT(n),ERR(e)),E,L)=proof(reduce(DIV(INT(n),ERR(e)),E),E,(E,DIV(INT(n),ERR(e)),reduce(DIV(INT(n),ERR(e)),E),"err0")::L)
|proof(DIV(INT(n),e),E,L)=proof(reduce(e,E),E,(E,DIV(INT(n),e),reduce(DIV(INT(n),e),E),"divr")::L)
|proof(DIV(e1,e2),E,L)=proof(reduce(e1,E),E,(E,DIV(e1,e2),reduce(DIV(e1,e2),E),"divl")::L)

|proof(MOD(INT(n1),INT(n2)),E,L)=proof(reduce(MOD(INT(n1),INT(n2)),E),E,(E,MOD(INT(n1),INT(n2)),reduce(MOD(INT(n1),INT(n2)),E),"mod0")::L)
|proof(MOD(ERR(e1),e2),E,L)=proof(reduce(MOD(ERR(e1),e2),E),E,(E,MOD(ERR(e1),e2),reduce(MOD(ERR(e1),e2),E),"err0")::L)
|proof(MOD(INT(n),ERR(e)),E,L)=proof(reduce(MOD(INT(n),ERR(e)),E),E,(E,MOD(INT(n),ERR(e)),reduce(MOD(INT(n),ERR(e)),E),"err0")::L)
|proof(MOD(INT(n),e),E,L)=proof(reduce(e,E),E,(E,MOD(INT(n),e),reduce(MOD(INT(n),e),E),"modr")::L)
|proof(MOD(e1,e2),E,L)=proof(reduce(e1,E),E,(E,MOD(e1,e2),reduce(MOD(e1,e2),E),"modl")::L)

|proof(LET(VAR(x), INT(n1), INT(n2)),E,L)=proof(reduce(LET (VAR(x), INT(n1), INT(n2)),E),E,(E,LET(VAR(x), INT(n1), INT(n2)),reduce(LET(VAR(x), INT(n1), INT(n2)),E),"let0")::L) 

|proof(LET(VAR(x), INT(n1), e2),E,L)= proof(reduce(e2,upd(E,x,n1)),upd(E,x,n1),(E,LET(VAR(x), INT(n1), e2),reduce(LET(VAR(x), INT(n1), e2),E),"letR")::L)

|proof(LET(VAR(x),e1,e2),E,L)=proof(reduce(e1,E),E,(E,LET(VAR(x),e1,e2),reduce(LET(VAR(x),e1,e2),E),"letL")::L) ;








 






end ;
open SSTEP ;