module til-typecheck-var
imports til-typecheck-exp
strategies

  typecheck-declaration = 
    ?Declaration(x)
    ; rules( TypeOf+x : x -> TypeName("int") )

  typecheck-declaration = 
    ?DeclarationTyped(x, t)
    ; rules( TypeOf+x : x -> t )
 
  TypecheckVar :
    Var(x) -> Var(x){t}
    where <TypeOf> x => t

  TypecheckAssign :
    Assign(x, e) -> Assign(x, e){TypeName("void")}
    where <typeof> e => t
    	; <TypeOf> x => t
    
strategies // expressions with variables and calls

  typecheck-exp = 
    typecheck-exp(TypecheckVar <+ typecheck-funcall)
    
  typecheck-funcall = 
    TypecheckRead <+ TypecheckS2I <+ TypecheckI2S <+ TypecheckB2S
    
  typecheck-proccall =
    TypecheckWrite
	
strategies // built-in functions
 
  TypecheckS2I :
    FunCall("string2int", [e]) -> FunCall("string2int", [e]){TypeName("int")}
    where <typeof> e => TypeName("string")
    
  TypecheckI2S :
    FunCall("int2string", [e]) -> FunCall("int2string", [e]){TypeName("string")}
    where <typeof> e => TypeName("int")
    
  TypecheckB2S :
    FunCall("bool2string", [e]) -> FunCall("bool2string", [e]){TypeName("string")}
    where <typeof> e => TypeName("bool")
    
  TypecheckRead :
    FunCall("read", []) -> FunCall("read", []){TypeName("string")}
    
  TypecheckRead :
    FunCall("readint", []) -> FunCall("readint", []){TypeName("int")}

strategies // built-in procedures

  TypecheckWrite :
    ProcCall("write", [e]) -> ProcCall("write", [e]){TypeName("void")}
    where <typeof> e => TypeName("string")

  TypecheckWrite :
    ProcCall("writeint", [e]) -> ProcCall("writeint", [e]){TypeName("void")}
    where <typeof> e => TypeName("int")