Skip to content
Snippets Groups Projects
Commit 779d9ba9 authored by Per's avatar Per
Browse files

type check

parent 0a5e7d9c
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,8 @@ module Vm_Ex = Vm_ex__Vm_Ex
module Imp_Ex = Imp_ex__Imp_Ex
module State = State__State
module Imp = Imp__Imp
let () =
cmd; (* parse command line options and put into opt *)
......@@ -32,13 +34,17 @@ let () =
let lexbuf = Lexing.from_channel inBuffer in
lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = opt.infile };
try
let prog = Parser.prog Lexer.lex lexbuf in
let p = Parser.prog Lexer.lex lexbuf in
(* p_stdout ("Decl:" ^ nl ^ T_Dump.of_prog p); *)
let com = T_Check.tc_prog inBuffer p in
if opt.d_ast then
p_stderr ("Raw AST : \n" ^ of_com prog ^ nl);
p_stderr ("Raw AST:" ^ nl ^ Dump.of_com com ^ nl);
if opt.d_past then
p_stderr ("Pretty AST: \n" ^ pretty_of_com 0 prog ^ nl);
p_stderr ("Pretty AST:" ^ nl ^ Dump.pretty_of_com 0 com ^ nl);
let code = Compile.compile_program prog in
let code = Compile.compile_program com in
if opt.d_code then
p_stderr ("Raw Code : \n" ^ of_code false code ^ nl);
if opt.d_pcode then
......@@ -50,7 +56,7 @@ let () =
if opt.imp_ex then (
try
p_stdout ("Execute : imp_ex" );
let st_end = Imp_Ex.ceval_ex st_0 prog in
let st_end = Imp_Ex.ceval_ex st_0 com in
p_stdout ("ceval_ex" ^ nl ^ Env.to_string st_end ^ nl);
with
| _ -> p_stdout "ceval : Exited with an error\n";
......@@ -73,7 +79,9 @@ let () =
with
| Lexer.SyntaxError msg -> raise (CompilerError ("Syntax error. " ^ msg ^ parse_err_msg lexbuf));
| Parser.Error -> raise (CompilerError ("Parser error." ^ parse_err_msg lexbuf));
| Parser.Error ->
raise (CompilerError ("Parser error." ^ parse_err_msg lexbuf));
(* raise (CompilerError ("Parser error.")); *)
with
| CompilerError msg -> p_stderr msg;
| Failure msg -> p_stderr ("Failure (internal error): " ^ msg);
......
......@@ -20,6 +20,7 @@ let ecit = "\'"
(* Error handling *)
exception TypeError of string
exception CompilerError of string
exception UnMatched
......
......@@ -26,6 +26,7 @@ let digits = ['0'-'9']+
(* lexing rules *)
rule lex = parse
| "IF" { IF }
| "THEN" { THEN }
| "ELSE" { ELSE }
......@@ -41,8 +42,13 @@ rule lex = parse
| "=" { BEQ }
| "<=" { BLE }
| "SINT" { SINT }
| "UINT32" { UINT32 }
| ';' { SC }
| ':' { C }
| ":=" { ASSIGN }
| '+' { PLUS }
| "+u" { PLUSU }
| '-' { MINUS }
......@@ -56,6 +62,7 @@ rule lex = parse
| "(*" { set_info lexbuf; comments 0 lexbuf } (* nested comment *)
| '(' { LP } (* must come after comment *)
| ')' { RP }
| eof { EOF }
| _ { raise (SyntaxError("Unknown Symbol.")) }
......
......@@ -7,11 +7,21 @@
%token <int> INTVAL
%token IF THEN ELSE END WHILE DO DONE
%token TRUE FALSE AND NOT BEQ BLE
%token SC LP RP ASSIGN PLUS PLUSU MINUS
%token SINT UINT32
%token SC C LP RP
%token ASSIGN
%token PLUS PLUSU MINUS
%token EOF
(* precedence and associativity according to C/Java/Rust? *)
%left SC
%left AND
%left MINUS, PLUS, PLUSU
%left NOT
%{
open Imp__Imp
open T_Imp
open Common
open Env
open State__State
......@@ -19,34 +29,51 @@
%start prog
%type <Imp__Imp.com> prog
%type <T_Imp.prog> prog
%%
prog:
| com EOF { $1 }
| decl_span SC com_span EOF { Prog ($1, $3) }
decl_span:
| decl { ($1, ($startofs, $endofs)) }
decl:
| decl_span SC decl_span { Dseq ($1, $3) }
| ID C primtype { Ddecl ($1, $3) }
primtype:
| SINT { Tsint }
| UINT32 { Tuint32 }
com_span:
| com { ($1, ($startofs, $endofs)) }
com:
| com SC com { Cseq ($1, $3) }
| ID ASSIGN aexpr { Cassign ($1, $3) }
| IF bexpr THEN com ELSE com END { Cif ($2, $4, $6) }
| IF bexpr THEN com END { Cif ($2, $4, Cskip) }
| WHILE bexpr DO com DONE { Cwhile ($2, $4) }
| com_span SC com_span { Cseq ($1, $3) }
| ID ASSIGN aexpr_span { Cassign ($1, $3) }
| IF bexpr_span THEN com_span
ELSE com_span END { Cif ($2, $4, $6) }
| IF bexpr_span THEN com_span END { Cif ($2, $4, (Cskip, (0, 0))) }
| WHILE bexpr_span DO com_span DONE { Cwhile ($2, $4) }
bexpr_span:
| bexpr { ($1, ($startofs, $endofs)) }
bexpr:
| LP bexpr RP { $2 }
| TRUE { Btrue }
| FALSE { Bfalse }
| bexpr AND bexpr { Band ($1, $3) }
| NOT bexpr { Bnot ($2) }
| aexpr BEQ aexpr { Beq ($1, $3) }
| aexpr BLE aexpr { Ble ($1, $3) }
| bexpr_span AND bexpr_span { Band ($1, $3) }
| NOT bexpr_span { Bnot ($2) }
| aexpr_span BEQ aexpr_span { Beq ($1, $3) }
| aexpr_span BLE aexpr_span { Ble ($1, $3) }
aexpr_span:
| aexpr { ($1, ($startofs, $endofs)) }
aexpr:
| LP aexpr RP { $2 }
| INTVAL { Anum (Z.of_int $1) }
| ID { Avar $1 }
| aexpr PLUS aexpr { Aadd ($1, $3) }
| aexpr PLUSU aexpr { Aaddu ($1, $3) }
| aexpr MINUS aexpr { Asub ($1, $3) }
| aexpr_span PLUS aexpr_span { Aadd ($1, $3) }
| aexpr_span PLUSU aexpr_span { Aaddu ($1, $3) }
| aexpr_span MINUS aexpr_span { Asub ($1, $3) }
(* Copyright Per Lindgren 2016-2018, see the file "LICENSE" *)
(* for the full license governing this code. *)
(* type checker *)
open T_Imp
open T_Dump
open Common
open State__State
module Imp = Imp__Imp
let of_span inb (start, stop) =
let _ = seek_in inb start in
let s = really_input_string inb (stop - start) in
"<" ^ string_of_int start ^ ".." ^ string_of_int stop ^ "> " ^ s
let unique_id chan (id1, (t1, s1)) (id2, (t2, s2)) =
if id1 = id2 then
raise (CompilerError("Dupclicate variable definition: " ^
of_span chan s1 ^ " already declared at " ^ of_span chan s2))
else ()
let rec idt_acc ch sp acc = function
| Dseq (d1, d2) -> (idt_acc_span ch (idt_acc_span ch acc d1) d2)
| Ddecl (id, t) -> List.iter (unique_id ch (id, (t, sp))) acc;
(id, (t, sp)) :: acc
and idt_acc_span c acc (d, s) = idt_acc c s acc d
let of_idt ch (id, (t,s)) =
of_id id ^ ":" ^ of_types t ^ of_span ch s
let tc_unify ch t1 s1 t2 s2 : types =
match t1, t2 with
| Tsint, Tsint -> Tsint
| Tuint32, Tuint32 -> Tuint32
| Tint, t -> t
| t, Tint -> t
| _, _ ->
raise (TypeError(
"Type error: " ^
of_span ch s1 ^ " : " ^ of_types t1 ^ ", does not match " ^
of_span ch s2 ^ " : " ^ of_types t2 ))
let get_id_type itl (id : id) : types * span =
try
List.assoc id itl
with
_ -> raise (TypeError("Undeclared identifier: " ^ Dump.pretty_of_id id))
let rec tc_aexpr ch itl (a, span) : Imp.aexpr * types =
(* try *)
match a with
| Anum n -> (Imp.Anum n, Tint)
| Avar id ->
let (t, _ ) = get_id_type itl id in
(Imp.Avar id, t)
| Aadd ((a1, a1_span), (a2, a2_span)) ->
(* type check a1 against Tsint *)
let (ai1, t1) = tc_aexpr ch itl (a1, a1_span) in
let _ = tc_unify ch Tsint (0, 0) t1 a1_span in
(* type check a2 against Tsint *)
let (ai2, t2) = tc_aexpr ch itl (a2, a2_span) in
let _ = tc_unify ch Tsint (0, 0) t2 a2_span in
(Imp.Aadd(ai1, ai2), t1)
| Aaddu ((a1, a1_span), (a2, a2_span)) ->
(* type check a1 against Tuint32 *)
let (ai1, t1) = tc_aexpr ch itl (a1, a1_span) in
let _ = tc_unify ch Tuint32 (0, 0) t1 a1_span in
(* type check a2 against Tuint32 *)
let (ai2, t2) = tc_aexpr ch itl (a2, a2_span) in
let _ = tc_unify ch Tuint32 (0, 0) t2 a2_span in
(Imp.Aaddu(ai1, ai2), t1)
| Asub ((a1, a1_span), (a2, a2_span)) ->
(* type check a1 against Tsint *)
let (ai1, t1) = tc_aexpr ch itl (a1, a1_span) in
let _ = tc_unify ch Tsint (0, 0) t1 a1_span in
(* type check a2 against Tsint *)
let (ai2, t2) = tc_aexpr ch itl (a2, a2_span) in
let _ = tc_unify ch Tsint (0, 0) t2 a2_span in
(Imp.Asub(ai1, ai2), t1)
(* with
| TypeError msg -> raise (TypeError (msg ^ nl ^ "in expression:" ^ of_span ch span )) *)
let rec tc_bexpr ch itl (b, span) =
try
match b with
| Btrue -> Imp.Btrue
| Bfalse -> Imp.Bfalse
| Band (b1, b2) -> Imp.Band(tc_bexpr ch itl b1,tc_bexpr ch itl b2)
| Bnot b -> Imp.Bnot(tc_bexpr ch itl b)
| Beq ((a1, a1_span),(a2, a2_span)) ->
let (a1, t1) = tc_aexpr ch itl (a1, a1_span) in
let (a2, t2) = tc_aexpr ch itl (a2, a2_span) in
let _ = tc_unify ch t1 a1_span t2 a2_span in
Imp.Beq(a1, a2)
| Ble (a1, a2) -> Imp.Ble(imp_of_aexpr_span a1, imp_of_aexpr_span a2)
with
| TypeError msg -> raise (TypeError (msg ^ nl ^ "in expression:" ^ of_span ch span ))
let rec tc_com ch itl span com =
try
match com with
| Cseq (c1, c2) -> Imp.Cseq(tc_com_span ch itl c1, tc_com_span ch itl c2)
| Cassign (id, a) ->
let (_, a_span) = a in
let (a, ta) = tc_aexpr ch itl a in
let (tid, tid_span) = get_id_type itl id in
let _ = tc_unify ch ta a_span tid tid_span in
Imp.Cassign (id, a)
| Cif (b, c1, c2) -> Imp.Cif(tc_bexpr ch itl b, tc_com_span ch itl c1, tc_com_span ch itl c2)
| Cwhile (b, c) -> Imp.Cwhile(tc_bexpr ch itl b, tc_com_span ch itl c)
| Cskip -> Imp.Cskip
with
| TypeError msg -> raise (CompilerError (msg ^ nl ^ "in command: " ^ of_span ch span ))
and
tc_com_span ch itl (com, span) = tc_com ch itl span com
let tc_prog ch (Prog (decl, com)) =
let itl = idt_acc_span ch [] decl in
tc_com_span ch itl com
(* Copyright Per Lindgren 2016-2018, see the file "LICENSE" *)
(* for the full license governing this code. *)
open State__State
open Vm__Vm
open Env
open Common
open T_Imp
(* AST dump of T_Imp *)
let of_types = function
| Tsint -> "SINT"
| Tuint32 -> "UINT32"
| Tint -> "INT"
let of_id = function
| Id i -> "Id #" ^ Z.to_string i
let rec of_aexpr = function
| Anum v -> "Anum " ^ Z.to_string v
| Avar id -> "Avar " ^ of_id id
| Aadd (e1, e2) -> "Aadd (" ^ of_aexpr_span e1 ^ ") (" ^ of_aexpr_span e2 ^ ")"
| Aaddu (e1, e2) -> "Aaddu (" ^ of_aexpr_span e1 ^ ") (" ^ of_aexpr_span e2 ^")"
| Asub (e1, e2) -> "Asub (" ^ of_aexpr_span e1 ^ ") (" ^ of_aexpr_span e2 ^")"
and of_aexpr_span (e, (start, stop)) =
"< (" ^ string_of_int start ^ ", " ^ string_of_int stop ^
") " ^ of_aexpr e ^ ">"
let rec of_bexpr = function
| Btrue -> "Btrue"
| Bfalse -> "Bfalse"
| Band (b1, b2) -> "Band (" ^ of_bexpr_span b1 ^ ") (" ^ of_bexpr_span b2 ^ ")"
| Bnot b -> "Bnot (" ^ of_bexpr_span b ^ ")"
| Beq (e1, e2) -> "Beq (" ^ of_aexpr_span e1 ^ ") (" ^ of_aexpr_span e2 ^ ")"
| Ble (e1, e2) -> "Ble (" ^ of_aexpr_span e1 ^ ") (" ^ of_aexpr_span e2 ^ ")"
and of_bexpr_span (e, s) = of_bexpr e
let rec of_com = function
| Cskip -> "Cskip"
| Cassign (id, a) -> "Cassign " ^ of_id id ^ " " ^ of_aexpr_span a
| Cseq (c1, c2) -> "Cseq (" ^ of_com_span c1 ^ ") (" ^ of_com_span c2 ^ ")"
| Cif (b, c1, c2) -> "Cif (" ^ of_bexpr_span b ^ ") (" ^ of_com_span c1 ^ " " ^ of_com_span c2 ^ ")"
| Cwhile (b, c) -> "Cwhile (" ^ of_bexpr_span b ^ ") (" ^ of_com_span c ^ ")"
and of_com_span (c, (start, stop)) =
"< (" ^ string_of_int start ^ ", " ^ string_of_int stop ^
") " ^ of_com c ^ ">"
let rec of_decl = function
| Dseq (d1, d2) -> "Dseq (" ^ of_decl_span d1 ^ ", " ^ of_decl_span d2 ^ ")"
| Ddecl (id, t) -> "Ddecl (" ^ of_id id ^ ", " ^ of_types t ^ ")"
and of_decl_span (d,_) = of_decl d
let of_prog = function
| Prog (d, c) -> of_decl_span d ^ of_com_span c
T_Imp.ml 0 → 100644
module Imp = Imp__Imp
type types =
| Tsint
| Tuint32
| Tint (* int litterals can be coersed to both Tsint and Tuint32 *)
type span = int * int
type aexpr =
| Anum of (Z.t)
| Avar of State__State.id
| Aadd of aexpr_span * aexpr_span
| Aaddu of aexpr_span * aexpr_span
| Asub of aexpr_span * aexpr_span
and
aexpr_span = aexpr * span
type bexpr =
| Btrue
| Bfalse
| Band of bexpr_span * bexpr_span
| Bnot of bexpr_span
| Beq of aexpr_span * aexpr_span
| Ble of aexpr_span * aexpr_span
and bexpr_span = bexpr * span
type com =
| Cskip
| Cseq of com_span * com_span
| Cassign of State__State.id * aexpr_span
| Cif of bexpr_span * com_span * com_span
| Cwhile of bexpr_span * com_span
and com_span = com * span
type decl =
| Dseq of decl_span * decl_span
| Ddecl of State__State.id * types
and decl_span = decl * span
type prog = Prog of decl_span * com_span
(* Convert to Imp *)
let rec imp_of_aexpr = function
| Anum n -> Imp.Anum n
| Avar id -> Imp.Avar id
| Aadd (a1, a2) -> Imp.Aadd(imp_of_aexpr_span a1, imp_of_aexpr_span a2)
| Aaddu (a1, a2) -> Imp.Aaddu(imp_of_aexpr_span a1, imp_of_aexpr_span a2)
| Asub (a1, a2) -> Imp.Asub(imp_of_aexpr_span a1, imp_of_aexpr_span a2)
and
imp_of_aexpr_span (a, _) = imp_of_aexpr a
let rec imp_of_bexpr = function
| Btrue -> Imp.Btrue
| Bfalse -> Imp.Bfalse
| Band (b1, b2) -> Imp.Band(imp_of_bexpr_span b1,imp_of_bexpr_span b2)
| Bnot b -> Imp.Bnot(imp_of_bexpr_span b)
| Beq (a1, a2) -> Imp.Beq(imp_of_aexpr_span a1, imp_of_aexpr_span a2)
| Ble (a1, a2) -> Imp.Ble(imp_of_aexpr_span a1, imp_of_aexpr_span a2)
and
imp_of_bexpr_span (b, _) = imp_of_bexpr b
let rec imp_of_com = function
| Cskip -> Imp.Cskip
| Cseq (c1, c2) -> Imp.Cseq(imp_of_com_span c1,imp_of_com_span c2)
| Cassign (id, a) -> Imp.Cassign (id, imp_of_aexpr_span a)
| Cif (b, c1, c2) -> Imp.Cif(imp_of_bexpr_span b, imp_of_com_span c1, imp_of_com_span c2)
| Cwhile (b, c) -> Imp.Cwhile(imp_of_bexpr_span b, imp_of_com_span c)
and
imp_of_com_span (c, _) = imp_of_com c
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment