let rec checkAexp (ex: aexp) (dect: dec_table) (proct: proc_table) :sType = match ex with
N(_) -> DInt
| R(_) -> DFloat
| Var(i) -> let (_,_,t) = (getVarDeclaration i dect) in (getType t)
| Vec(i,x) -> if ((checkAexp x dect proct) = DInt) then (
let (_,_,t) = (getVarDeclaration i dect) in (getType t)
) else (
raise (SEMANTIC_ERROR "Invalid Index")
)
| Mat(i,x,y) -> if (((checkAexp x dect proct) = DInt) & ((checkAexp y dect proct) = DInt)) then (
let (_,_,t) = (getVarDeclaration i dect) in (getType t)
) else (
raise (SEMANTIC_ERROR "Invalid Index")
)
(** For now are only allowed arithmetical operations between int and int or float and float, not mixed operations*) |
| Sum(ex1,ex2) -> (
let t1 = (checkAexp ex1 dect proct) and
t2 = (checkAexp ex2 dect proct) in
match (t1,t2) with
(DInt, DInt) -> DInt
| (DFloat, DFloat) -> DFloat
| _ -> raise (SEMANTIC_ERROR "Different Types")
)
| Sub(ex1,ex2) -> (
let t1 = (checkAexp ex1 dect proct) and
t2 = (checkAexp ex2 dect proct) in
match (t1,t2) with
(DInt, DInt) -> DInt
| (DFloat, DFloat) -> DFloat
| _ -> raise (SEMANTIC_ERROR "Different Types")
)
| Mul(ex1,ex2) -> (
let t1 = (checkAexp ex1 dect proct) and
t2 = (checkAexp ex2 dect proct) in
match (t1,t2) with
(DInt, DInt) -> DInt
| (DFloat, DFloat) -> DFloat
| _ -> raise (SEMANTIC_ERROR "Different Types")
)
| Div(ex1,ex2) -> (
let t1 = (checkAexp ex1 dect proct) and
t2 = (checkAexp ex2 dect proct) in
match (t1,t2) with
(DInt, DInt) -> DInt
| (DFloat, DFloat) -> DFloat
| _ -> raise (SEMANTIC_ERROR "Different Types")
)
| FCall(i,el) -> (
let pten = (Hashtbl.find proct i) in match pten with
Building(t, plist) -> (
if (checkParTypes (List.rev plist) (List.rev el) dect proct)
then (
match t with
SRet(Int) -> DInt
| SRet(Float) -> DFloat
| Void -> raise (SEMANTIC_ERROR "Void function")
)
else raise (SEMANTIC_ERROR "Different Parameters Types")
)
| Subroutine(t,plist,_,_) -> (
if (checkParTypes (List.rev plist) (List.rev el) dect proct)
then (
match t with
SRet(Int) -> DInt
| SRet(Float) -> DFloat
| Void -> raise (SEMANTIC_ERROR "Void function")
)
else raise (SEMANTIC_ERROR "Different Parameters Types")
)
)
(** Checks the semantic type of a list of parameters @param plist The list of formal parameters @param el The list of actual parameters @param dect The declarations table @param proct The procedures table @return True if the formal parameters types match with the actual parameters type, False otherwise *) |
and checkParTypes (plist: dec list) (el: aexp list) (dect: dec_table) (proct: proc_table) = match (plist,el) with
([],[]) -> true
| ([x],[]) -> true
| (Dec(id,Basic(t))::ps,e::es) -> (
match t with
Int -> ((checkAexp e dect proct) = DInt) & checkParTypes ps es dect proct
| Float -> ((checkAexp e dect proct) = DFloat) & checkParTypes ps es dect proct
)
| _ -> raise (SEMANTIC_ERROR "Wrong Parameters Number")
(** Checks the semantic type of boolean operations (compare is only allowed betrween int and int or float and float, not mixed operations) @param b The boolean operation to check @param dect The declarations table @param proct The procedures table @return The sematic type of b *) |
and checkBool (b: bexp) (dect: dec_table) (proct: proc_table) = match b with
B(b) -> DBool
| Equ(ex1,ex2) -> (
let t1 = (checkAexp ex1 dect proct) and
t2 = (checkAexp ex2 dect proct) in
match (t1,t2) with
(DInt, DInt) -> DBool
| (DFloat, DFloat) -> DBool
| _ -> raise (SEMANTIC_ERROR "Different Types")
)
| LE(ex1,ex2) -> (
let t1 = (checkAexp ex1 dect proct) and
t2 = (checkAexp ex2 dect proct) in
match (t1,t2) with
(DInt, DInt) -> DBool
| (DFloat, DFloat) -> DBool
| _ -> raise (SEMANTIC_ERROR "Different Types")
)
| LT(ex1,ex2) -> (
let t1 = (checkAexp ex1 dect proct) and
t2 = (checkAexp ex2 dect proct) in
match (t1,t2) with
(DInt, DInt) -> DBool
| (DFloat, DFloat) -> DBool
| _ -> raise (SEMANTIC_ERROR "Different Types")
)
| Not(bx) -> if ((checkBool bx dect proct) = DBool) then DBool else raise (SEMANTIC_ERROR "Different Types")
| And(bx1,bx2) -> (
let t1 = (checkBool bx1 dect proct) and
t2 = (checkBool bx2 dect proct) in
match (t1,t2) with
(DBool, DBool) -> DBool
| _ -> raise (SEMANTIC_ERROR "Different Types")
)
| Or(bx1,bx2) -> (
let t1 = (checkBool bx1 dect proct) and
t2 = (checkBool bx2 dect proct) in
match (t1,t2) with
(DBool, DBool) -> DBool
| _ -> raise (SEMANTIC_ERROR "Different Types")
)