mirror of
https://github.com/LucasVbr/postscript-compiler.git
synced 2026-05-13 17:22:00 +00:00
@@ -8,6 +8,7 @@ src/parser.ml
|
||||
*.mli
|
||||
src/**/*.cmi
|
||||
comp
|
||||
*/**/*.output
|
||||
|
||||
# Tests out
|
||||
tests/out/
|
||||
|
||||
@@ -8,13 +8,18 @@
|
||||
|
||||
> Compilateur du langage Postscript en Ocaml
|
||||
|
||||
## Author
|
||||
## Authors
|
||||
|
||||
👤 **Laurian DUFRECHOU**
|
||||
|
||||
* Github: [@Laurian-Dufrechou](https://github.com/Laurian-Dufrechou)
|
||||
|
||||
👤 **Gaël BRUGUES**
|
||||
|
||||
* Github: [@Gagl08](https://github.com/Gagl08)
|
||||
|
||||
👤 **Lucas VABRE**
|
||||
|
||||
* Github: [@LucasVbr](https://github.com/LucasVbr)
|
||||
* LinkedIn: [@lucasvbr](https://linkedin.com/in/lucasvbr)
|
||||
|
||||
## Show your support
|
||||
|
||||
Give a ⭐️ if this project helped you!
|
||||
|
||||
+13
-9
@@ -1,5 +1,5 @@
|
||||
# Import lib + compile + clean folder
|
||||
all: lib comp clean
|
||||
# Compile
|
||||
all: comp
|
||||
|
||||
# Compilation of Ocaml files
|
||||
# Attention: order of object files important
|
||||
@@ -30,12 +30,12 @@ comp.cmo: comp.ml gen.cmo typing.cmo parser.cmo interf.cmo
|
||||
# ocaml lexer and parser
|
||||
|
||||
# Comment in for your own lexer
|
||||
# lexer.ml: lexer.mll lang.cmo
|
||||
# ocamllex $<
|
||||
lexer.ml: lexer.mll lang.cmo
|
||||
ocamllex $<
|
||||
|
||||
# Comment in for your own parser
|
||||
# parser.ml parser.mli: parser.mly lang.cmo
|
||||
# ocamlyacc $<
|
||||
parser.ml parser.mli: parser.mly lang.cmo
|
||||
ocamlyacc $<
|
||||
|
||||
lexer.cmo: lexer.ml parser.cmo
|
||||
ocamlc -c $<
|
||||
@@ -51,10 +51,14 @@ parser.cmo: parser.ml parser.cmi lang.cmo
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
### Import files from /lib
|
||||
lib:
|
||||
cp ../lib/* ./
|
||||
### Import files from /lib (temporarly)
|
||||
# lib:
|
||||
# cp ../lib/* ./
|
||||
|
||||
## Remove compiled modules and lib
|
||||
clean:
|
||||
rm -f lexer.ml parser.ml *.mli *.cmi *.cmo
|
||||
|
||||
## Run tests
|
||||
tests:
|
||||
./comp ./../tests/rectangles.c ./../tests/out/rectangles.ps
|
||||
@@ -0,0 +1,94 @@
|
||||
{
|
||||
open Lexing
|
||||
open Parser
|
||||
open Lang
|
||||
exception Lexerror
|
||||
|
||||
let pos lexbuf = (lexeme_start lexbuf, lexeme_end lexbuf)
|
||||
|
||||
let advance_line_pos pos =
|
||||
{ pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum; }
|
||||
|
||||
let advance_line lexbuf =
|
||||
lexbuf.lex_curr_p <- advance_line_pos lexbuf.lex_curr_p
|
||||
|
||||
}
|
||||
|
||||
let includeline = '#' [^ '\n']* '\n'
|
||||
let num = ['1'-'9']['0'-'9']*
|
||||
let num_virgule = ['1'-'9']['0'-'9']*'.'(['1'-'9']['0'-'9']*)?
|
||||
let alph = ['a'-'z''A'-'Z']
|
||||
let literal = '/'alph(alph|'-')*
|
||||
let str = '\"'alph(alph|'-'|'_'|num)*'\"'
|
||||
let blancs = [' ''\t']+
|
||||
let comment = '/' '*' (blancs|alph|num|num_virgule|'>'|'<')* '*' '/'
|
||||
|
||||
rule token = parse
|
||||
blancs
|
||||
{ token lexbuf } (* white space: recursive call of lexer *)
|
||||
|'\n'
|
||||
{advance_line lexbuf; token lexbuf } (* white space: recursive call of lexer *)
|
||||
| includeline
|
||||
{ advance_line lexbuf; token lexbuf } (* C include directives --> ignore *)
|
||||
| comment
|
||||
{ token lexbuf } (* comment --> ignore *)
|
||||
|
||||
|
||||
| "int" {TP(IntT)}
|
||||
| "bool" {TP(BoolT)}
|
||||
| "string" {TP(StringT)}
|
||||
| "float" {TP(FloatT)}
|
||||
| "void" {TP(VoidT)}
|
||||
| "lit" {TP(LitT)} (* faut demander *)
|
||||
|
||||
| '(' { LPAREN }
|
||||
| ')' { RPAREN }
|
||||
| '{' { LBRACE }
|
||||
| '}' { RBRACE }
|
||||
| "==" { BCEQ }
|
||||
| '=' { EQ }
|
||||
| '+' { PLUS }
|
||||
| '-' { MINUS }
|
||||
| '*' { TIMES }
|
||||
| '/' { DIV }
|
||||
| '%' { MOD }
|
||||
| '/' { DIV }
|
||||
| "<=" { BCLE }
|
||||
| ">=" { BCGE }
|
||||
| ">" { BCGT }
|
||||
| "<" { BCLT }
|
||||
| "!=" { BCNE }
|
||||
| "and" {BLAND}
|
||||
| "or" {BLOR}
|
||||
| "," {COMMA}
|
||||
| ";" {SEMICOLON}
|
||||
| ":" {COLON}
|
||||
| "?" {QMARK}
|
||||
|
||||
|
||||
| "return" {RETURN}
|
||||
|
||||
| "if" {IF}
|
||||
| "else" {ELSE}
|
||||
| "while" {WHILE}
|
||||
| "for" {FOR}
|
||||
|
||||
| "True" {BCONSTANT(true)}
|
||||
| "False" {BCONSTANT(false)}
|
||||
|
||||
|
||||
| eof {EOF}
|
||||
|
||||
| num_virgule as s {FLOATCONSTANT(float_of_string s)}
|
||||
| num as s {INTCONSTANT(int_of_string s)}
|
||||
| literal as l { LITCONSTANT l }
|
||||
| str as s { STRINGCONSTANT s }
|
||||
| alph alph* as i {IDENTIFIER i}
|
||||
|
||||
| _ {Printf.printf "ERROR: unrecogized symbol '%s'\n" (Lexing.lexeme lexbuf);
|
||||
raise Lexerror }
|
||||
|
||||
and
|
||||
ruleTail acc = parse
|
||||
| eof { acc }
|
||||
| _* as str { ruleTail (acc ^ str) lexbuf }
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
%{
|
||||
open Lang
|
||||
%}
|
||||
|
||||
%token <string> IDENTIFIER
|
||||
%token <string> LITCONSTANT
|
||||
%token <string> STRINGCONSTANT
|
||||
%token <Lang.tp> TP
|
||||
%token <bool> BCONSTANT
|
||||
%token <int> INTCONSTANT
|
||||
%token <float> FLOATCONSTANT
|
||||
%token PLUS MINUS TIMES DIV MOD FPLUS FMINUS FTIMES FDIV
|
||||
%token LPAREN RPAREN LBRACE RBRACE
|
||||
%token EQ COMMA SEMICOLON COLON QMARK
|
||||
%token IF ELSE WHILE FOR RETURN BCEQ BCGE BCGT BCLE BCLT BCNE BLAND BLOR
|
||||
%token EOF
|
||||
|
||||
%left QMARK COLON
|
||||
%left BLOR
|
||||
%left BLAND
|
||||
%left BCEQ BCNE
|
||||
%left BCGE BCGT BCLE BCLT
|
||||
%left PLUS MINUS FPLUS FMINUS
|
||||
%left TIMES DIV FDIV FTIMES MOD
|
||||
|
||||
|
||||
%right IF ELSE
|
||||
%left RPAREN
|
||||
%right LPAREN
|
||||
%left SEMICOLON
|
||||
|
||||
%start start
|
||||
%type <Lang.prog> start
|
||||
|
||||
%%
|
||||
|
||||
start: list_fundefn { Prog ([], $1) }
|
||||
;
|
||||
|
||||
list_fundefn:
|
||||
| {[]}
|
||||
| fundefn list_fundefn {$1 :: $2}
|
||||
;
|
||||
|
||||
fundefn: /* Compound-statement dans la doc --> 6.8.2 */
|
||||
/* d'apres la doc, on peut lui mettre --> LBRACE RBRACE {Skip} */
|
||||
|fundecl LBRACE block_item_list_opt RBRACE { Fundefn($1, $3) }
|
||||
// |fundecl LBRACE statement RBRACE { Fundefn($1, $3) }
|
||||
|
||||
;
|
||||
|
||||
fundecl: TP IDENTIFIER LPAREN vardecl_comma_list_opt RPAREN
|
||||
{ Fundecl($1, $2, $4) }
|
||||
;
|
||||
|
||||
vardecl_comma_list_opt:
|
||||
|TP IDENTIFIER COMMA vardecl_comma_list_opt {[Vardecl($1, $2)] @ $4} /* dans celle là c'est récursif*/
|
||||
|TP IDENTIFIER {[Vardecl($1, $2)]}
|
||||
|/* empty */{ [] }
|
||||
;
|
||||
|
||||
|
||||
constant:
|
||||
|LITCONSTANT{LitV($1) }
|
||||
|STRINGCONSTANT {StringV($1) }
|
||||
|BCONSTANT {BoolV($1) }
|
||||
|INTCONSTANT {IntV($1) }
|
||||
|FLOATCONSTANT {FloatV($1) }
|
||||
;
|
||||
|
||||
|
||||
expression: /* A.2.1 ---> 6.5.1 */
|
||||
|IDENTIFIER {VarE($1)}
|
||||
|constant {Const($1)}
|
||||
|LPAREN expression RPAREN {$2}
|
||||
|multiplicative_expression {$1}
|
||||
|additive_expression {$1}
|
||||
|relational_expression {$1}
|
||||
|equality_expression {$1}
|
||||
|logical_and_expression {$1}
|
||||
|logical_or_expression {$1}
|
||||
|conditional_expression {$1}
|
||||
|IDENTIFIER LPAREN expr_list RPAREN {CallE($1,$3)}
|
||||
;
|
||||
|
||||
|
||||
/*les calculs*/
|
||||
multiplicative_expression: /* 6.5.5 */
|
||||
|expression FTIMES expression {BinOp(BArith(BAfmul), $1, $3)}
|
||||
|expression TIMES expression {BinOp(BArith(BAmul), $1, $3)}
|
||||
|expression FDIV expression {BinOp(BArith(BAfdiv), $1, $3)}
|
||||
|expression DIV expression {BinOp(BArith(BAdiv), $1, $3)}
|
||||
|expression MOD expression {BinOp(BArith(BAmod), $1, $3)}
|
||||
;
|
||||
|
||||
additive_expression: /* 6.5.6 */
|
||||
|expression FPLUS expression {BinOp(BArith(BAfadd), $1, $3)}
|
||||
|expression FMINUS expression {BinOp(BArith(BAfsub), $1, $3)}
|
||||
|expression PLUS expression {BinOp(BArith(BAadd), $1, $3)}
|
||||
|expression MINUS expression {BinOp(BArith(BAsub), $1, $3)}
|
||||
;
|
||||
|
||||
/*les comparaisons*/
|
||||
relational_expression: /* 6.5.8 */
|
||||
|expression BCLT expression {BinOp(BCompar(BClt), $1, $3)}
|
||||
|expression BCGT expression {BinOp(BCompar(BCgt), $1, $3)}
|
||||
|expression BCLE expression {BinOp(BCompar(BCle), $1, $3)}
|
||||
|expression BCGE expression {BinOp(BCompar(BCge), $1, $3)}
|
||||
;
|
||||
equality_expression: /* 6.5.9 */
|
||||
|expression BCEQ expression {BinOp(BCompar(BCeq), $1, $3)}
|
||||
|expression BCNE expression {BinOp(BCompar(BCne), $1, $3)}
|
||||
;
|
||||
|
||||
/*les operateurs booleens */
|
||||
logical_and_expression:
|
||||
|expression BLAND expression {BinOp(BBool(BBand), $1, $3)} /* 6.5.13 */
|
||||
;
|
||||
|
||||
logical_or_expression:
|
||||
|expression BLOR expression {BinOp(BBool(BBor), $1, $3)} /* 6.5.14 */
|
||||
;
|
||||
|
||||
|
||||
conditional_expression: /* 6.5.16 */
|
||||
|expression QMARK expression COLON expression {CondE($1, $3, $5)}
|
||||
;
|
||||
|
||||
|
||||
/*///////////// FIN DES EXPRESSIONS ///////////////////*/
|
||||
|
||||
/*///////////// DEBUT DES STATEMENTS //////////////////*/
|
||||
|
||||
statement: /* A.2.3 ----> 6.8 */
|
||||
|compound_statement {$1} /* peut etre fundefn plutot vu que c'est le vrai compound_statement*/
|
||||
// |expression_statement {$1}
|
||||
|select_statement {$1} /*if et else*/
|
||||
|iteration_statement {$1} /*while et for*/
|
||||
|jump_statement SEMICOLON {$1} /*return et break*/
|
||||
|assignation SEMICOLON {$1}
|
||||
|IDENTIFIER LPAREN expr_list RPAREN {CallC($1,$3)}
|
||||
|
||||
// Faut faire l'appel à des foncttions avec CondC( fname * (expr_list ) )
|
||||
;
|
||||
|
||||
expr_list:
|
||||
| { [] }
|
||||
| expression expr_list{[$1] @ $2}
|
||||
;
|
||||
|
||||
compound_statement: /* 6.8.2 */
|
||||
|LBRACE block_item_list_opt RBRACE {$2}
|
||||
;
|
||||
|
||||
|
||||
block_item_list_opt: /* 6.8.2 */
|
||||
|statement block_item_list_opt {Seq($1,$2)} /* pas sur du tout */
|
||||
|{Skip}
|
||||
;
|
||||
|
||||
select_statement: /* 6.8.4 */
|
||||
|IF LPAREN expression RPAREN statement {CondC ($3, $5, Skip) }
|
||||
|IF LPAREN expression RPAREN statement ELSE statement {CondC ($3, $5, $7) }
|
||||
;
|
||||
|
||||
iteration_statement: /* 6.8.5 */
|
||||
|WHILE LPAREN expression RPAREN statement {Loop (Seq (CondC ( $3, Skip, Exit), $5))}
|
||||
|FOR LPAREN expression SEMICOLON expression SEMICOLON expression RPAREN statement {Loop (Seq (CondC ( $5, Skip, Exit), $9))} /*Absolument pas sur*/
|
||||
;
|
||||
|
||||
jump_statement: /* 6.8.6 */
|
||||
|RETURN expression {Return($2)}
|
||||
;
|
||||
|
||||
assignation: /* 6.5.17 */ /* dans la doc ça fait parti des expressions mais pg */
|
||||
|IDENTIFIER EQ expression {Assign($1, $3)}
|
||||
;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Dans ce qu'il y a marqué dans lang.ml, il manque
|
||||
|
||||
expr : CallE of fname * (expr list) ( call expression )
|
||||
|
||||
et
|
||||
|
||||
com : CallC of fname * (expr list) ( call statement )
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Demander au prof :
|
||||
|
||||
|
||||
---Comment ça marche pour appeler une fonction ou expressionn CallE et CallC ?
|
||||
|
||||
associativité des opérateurs ? (dans le pdf TP2 : introduction à YACC, partie 4 --> développons la grammaire ---> tirer 2)
|
||||
*/
|
||||
+400
-23
@@ -1,38 +1,415 @@
|
||||
(* Typechecking of source programs *)
|
||||
|
||||
open Lang
|
||||
open Lang;;
|
||||
|
||||
(* Environments *)
|
||||
type environment = {
|
||||
localvars: (vname * tp) list;
|
||||
funbind: fundecl list
|
||||
}
|
||||
};;
|
||||
|
||||
let find_var (var: vname) (env: environment) =
|
||||
let rec aux local_vars =
|
||||
match local_vars with
|
||||
| [] -> failwith "Variable inconnue"
|
||||
| tete::reste ->
|
||||
let (name, _) = tete in
|
||||
if name = var
|
||||
then tete
|
||||
else aux reste
|
||||
in aux (env.localvars)
|
||||
(* Fonction sur les listes de declarations de variables *)
|
||||
let rec count_same_var_name (name: string) (var_decl_list: vardecl list) =
|
||||
match var_decl_list with
|
||||
| [] -> 0
|
||||
| Vardecl(var_tp, var_name)::reste ->
|
||||
(count_same_var_name name reste)
|
||||
+ if name = var_name then 1 else 0
|
||||
;;
|
||||
(* val count_same_var_decl : string -> Lang.vardecl list -> int = <fun> *)
|
||||
|
||||
(* let rec tp_expr (expression: expr) (env: environment) =
|
||||
let rec valid_vardecl_list (var_decl_list: vardecl list) =
|
||||
match var_decl_list with
|
||||
| [] -> true
|
||||
| Vardecl(var_tp, var_name)::reste ->
|
||||
if (count_same_var_name var_name reste) = 0
|
||||
then valid_vardecl_list reste
|
||||
else false
|
||||
;;
|
||||
(* val valid_vardecl_list : Lang.vardecl list -> bool = <fun> *)
|
||||
|
||||
|
||||
|
||||
(* Recherche dans l'environement *)
|
||||
type 'a option = None| Some of 'a;;
|
||||
|
||||
let findEnv_var (name: vname) (env: environment) =
|
||||
let rec aux = function
|
||||
| [] -> None
|
||||
| (k, v)::reste ->
|
||||
if k = name then Some(v)
|
||||
else aux(reste)
|
||||
in aux(env.localvars)
|
||||
;;
|
||||
(* val findEnv_var :
|
||||
Lang.vname -> environment
|
||||
-> Lang.tp option = <fun>
|
||||
*)
|
||||
|
||||
let findEnv_fun (name: fname) (env: environment) =
|
||||
let rec aux = function
|
||||
| [] -> None
|
||||
| Fundecl(tp, fname, vars)::reste ->
|
||||
let f = (tp, fname, vars) in
|
||||
if fname = name then Some(f)
|
||||
else aux(reste)
|
||||
in aux(env.funbind)
|
||||
;;
|
||||
(* val findEnv_fun :
|
||||
Lang.fname -> environment
|
||||
-> (Lang.tp * Lang.fname * Lang.vardecl list) option = <fun>
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(* Ajout dans l'environnement *)
|
||||
let addEnv_var (var_decl: vardecl) (env: environment) =
|
||||
let Vardecl(var_decl_tp, var_decl_name) = var_decl
|
||||
in {
|
||||
localvars=(var_decl_name, var_decl_tp)::(env.localvars);
|
||||
funbind=env.funbind
|
||||
};;
|
||||
(* val addEnv_var :
|
||||
Lang.vardecl -> environment
|
||||
-> environment = <fun>
|
||||
*)
|
||||
|
||||
let addEnv_fun (fun_decl: fundecl) (env: environment) = {
|
||||
localvars=(env.localvars);
|
||||
funbind=(fun_decl::(env.funbind))
|
||||
};;
|
||||
(* val addEnv_fun :
|
||||
Lang.fundecl -> environment
|
||||
-> environment = <fun>
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(* Ajout dans l'environnement (récursif) *)
|
||||
let rec build_env_fun (env: environment) (fun_decl_list: fundecl list) =
|
||||
match fun_decl_list with
|
||||
| [] -> env
|
||||
| fun_decl::reste ->
|
||||
let Fundecl(fun_decl_tp,_,var_decl_list) = fun_decl
|
||||
in if valid_vardecl_list var_decl_list
|
||||
then addEnv_fun fun_decl env
|
||||
else raise (Failure "There is var declaration with the same name as arguments")
|
||||
;;
|
||||
(* val build_env_fun :
|
||||
environment -> Lang.fundecl list
|
||||
-> environment = <fun>
|
||||
*)
|
||||
|
||||
let rec build_env_var (env: environment) (var_decl_list: vardecl list) =
|
||||
match var_decl_list with
|
||||
| [] -> env
|
||||
| var_decl::reste -> build_env_var (addEnv_var var_decl env) reste
|
||||
;;
|
||||
(* val build_env_var :
|
||||
environment -> Lang.vardecl list
|
||||
-> environment = <fun>
|
||||
*)
|
||||
|
||||
|
||||
|
||||
(* Typage d'une declaration de variable *)
|
||||
let tp_vardecl (vdecl: vardecl) =
|
||||
let Vardecl(vdecl_tp, _) = vdecl
|
||||
in vdecl_tp
|
||||
;;
|
||||
(* val tp_vardecl : Lang.vardecl -> Lang.tp = <fun> *)
|
||||
|
||||
|
||||
|
||||
(* ----- Typage d'une expression ----- *)
|
||||
let rec tp_expr (env: environment) (expression: expr) =
|
||||
match expression with
|
||||
| Const(const) ->
|
||||
match const with
|
||||
| BoolV(_) -> BoolT
|
||||
| FloatV(_) -> FloatT
|
||||
| IntV(_) -> IntT
|
||||
| LitV(_) -> LitT
|
||||
| StringV(_) -> StringT
|
||||
| VarE(var) -> tp_expr (find_var var env) env
|
||||
| Const(const) -> (
|
||||
match const with
|
||||
| BoolV _ -> BoolT
|
||||
| FloatV _ -> FloatT
|
||||
| IntV _ -> IntT
|
||||
| LitV _ -> LitT
|
||||
| StringV _ -> StringT
|
||||
)
|
||||
| VarE(var) -> (
|
||||
let var_value = (findEnv_var var env) in
|
||||
match var_value with
|
||||
| Some(value) -> value
|
||||
| None -> raise (Failure "Unknown var")
|
||||
)
|
||||
| BinOp(op, expr1, expr2) ->
|
||||
let tp_expr1 = tp_expr env expr1
|
||||
and tp_expr2 = tp_expr env expr2 in
|
||||
if tp_expr1 = tp_expr2
|
||||
then (
|
||||
match op with
|
||||
| BArith(barith) -> (
|
||||
match barith with
|
||||
| BAadd -> IntT
|
||||
| BAsub -> IntT
|
||||
| BAmul -> IntT
|
||||
| BAdiv -> IntT
|
||||
| BAmod -> IntT
|
||||
| BAfadd -> FloatT
|
||||
| BAfsub -> FloatT
|
||||
| BAfmul -> FloatT
|
||||
| BAfdiv -> FloatT
|
||||
)
|
||||
| BBool(_) ->
|
||||
if tp_expr1 = BoolT && tp_expr2 = BoolT
|
||||
then BoolT
|
||||
else raise (Failure "Invalid Boolean operation")
|
||||
| BCompar(_) -> BoolT
|
||||
)
|
||||
else raise (Failure "Invalid type of Binary operation")
|
||||
| CondE(expr1, expr2, expr3) ->
|
||||
| CallE(functionName, exprList) -> *)
|
||||
let tp_expr1 = tp_expr env expr1
|
||||
and tp_expr2 = tp_expr env expr2
|
||||
and tp_expr3 = tp_expr env expr3
|
||||
in if tp_expr1 = BoolT && tp_expr2 = tp_expr3
|
||||
then tp_expr2
|
||||
else raise (Failure "Invalid type of Conditionnal Expression")
|
||||
| CallE(name, list_expr) ->
|
||||
match (findEnv_fun name env) with
|
||||
| Some(func) -> (
|
||||
let (func_tp, func_name, func_list_vardecl) = func in
|
||||
if (List.map (tp_expr env) list_expr) = (List.map tp_vardecl func_list_vardecl)
|
||||
then func_tp
|
||||
else raise (Failure "Invalid arguments")
|
||||
)
|
||||
| None -> raise (Failure "Unknown function in the environment")
|
||||
;;
|
||||
(* val tp_expr :
|
||||
environment -> Lang.expr
|
||||
-> Lang.tp = <fun>
|
||||
*)
|
||||
|
||||
(* - tp_expr: TESTS - *)
|
||||
let test_tp_expr =
|
||||
let function_to_test = tp_expr {
|
||||
localvars=[
|
||||
("i", IntT);
|
||||
("f", FloatT);
|
||||
("b", BoolT);
|
||||
("l", LitT);
|
||||
("s", StringT);
|
||||
];
|
||||
funbind=[
|
||||
Fundecl(BoolT, "fun1", [Vardecl(IntT, "a"); Vardecl(FloatT, "b")])
|
||||
]
|
||||
}
|
||||
and input_values = [
|
||||
Const(BoolV(true));
|
||||
Const(FloatV(10.98));
|
||||
Const(IntV(10));
|
||||
Const(LitV("l"));
|
||||
Const(StringV("Hello"));
|
||||
|
||||
VarE("b");
|
||||
VarE("f");
|
||||
VarE("i");
|
||||
VarE("l");
|
||||
VarE("s");
|
||||
|
||||
BinOp(BArith(BAadd), Const(IntV(5)), VarE("i"));
|
||||
BinOp(BArith(BAsub), Const(IntV(5)), VarE("i"));
|
||||
BinOp(BArith(BAmul), Const(IntV(5)), VarE("i"));
|
||||
BinOp(BArith(BAdiv), Const(IntV(5)), VarE("i"));
|
||||
BinOp(BArith(BAmod), Const(IntV(5)), VarE("i"));
|
||||
|
||||
BinOp(BArith(BAfadd), Const(FloatV(5.)), VarE("f"));
|
||||
BinOp(BArith(BAfsub), Const(FloatV(5.)), VarE("f"));
|
||||
BinOp(BArith(BAfmul), Const(FloatV(5.)), VarE("f"));
|
||||
BinOp(BArith(BAfdiv), Const(FloatV(5.)), VarE("f"));
|
||||
|
||||
BinOp(BCompar(BCeq), VarE("i"), VarE("i"));
|
||||
BinOp(BCompar(BCge), VarE("i"), VarE("i"));
|
||||
BinOp(BCompar(BCgt), VarE("i"), VarE("i"));
|
||||
BinOp(BCompar(BCle), VarE("i"), VarE("i"));
|
||||
BinOp(BCompar(BClt), VarE("i"), VarE("i"));
|
||||
BinOp(BCompar(BCne), VarE("i"), VarE("i"));
|
||||
|
||||
BinOp(BBool(BBand), VarE("b"), VarE("b"));
|
||||
BinOp(BBool(BBor), VarE("b"), VarE("b"));
|
||||
|
||||
(* (4 >= 5) ? 7 : 8 -> IntT *)
|
||||
CondE(
|
||||
BinOp(BCompar(BCge), Const(IntV(4)), Const(IntV(5))),
|
||||
Const(IntV(7)),
|
||||
Const(IntV(8))
|
||||
);
|
||||
|
||||
CallE("fun1", [VarE("i"); VarE("f")]);
|
||||
(* CallE("fun2", [VarE("i"); VarE("f")]); *)
|
||||
(* CallE("fun1", [VarE("b"); VarE("f")]); *)
|
||||
] and expected_result = [
|
||||
BoolT; FloatT; IntT; LitT; StringT;
|
||||
BoolT; FloatT; IntT; LitT; StringT;
|
||||
IntT; IntT; IntT; IntT; IntT;
|
||||
FloatT; FloatT; FloatT; FloatT;
|
||||
BoolT; BoolT; BoolT; BoolT; BoolT; BoolT;
|
||||
BoolT; BoolT;
|
||||
|
||||
IntT;
|
||||
BoolT;
|
||||
] in
|
||||
(List.map function_to_test input_values) = expected_result
|
||||
;;
|
||||
|
||||
let tp_prog (Prog (fundecls, fundefns)) = true
|
||||
|
||||
|
||||
(* ----- Typage d'une commande ----- *)
|
||||
let rec tp_cmd (env: environment) (cmd: com) =
|
||||
match cmd with
|
||||
| Skip -> VoidT
|
||||
| Exit -> VoidT
|
||||
| Assign(name, expr) -> VoidT
|
||||
| Seq(cmd1, cmd2) ->
|
||||
let tp_cmd1 = (tp_cmd env cmd1)
|
||||
and tp_cmd2 = (tp_cmd env cmd2)
|
||||
in if tp_cmd1 = VoidT
|
||||
then tp_cmd2
|
||||
else raise (Failure "Invalid type Sequence")
|
||||
| CondC(expr1, cmd1, cmd2) ->
|
||||
let tp_expr1 = tp_expr env expr1
|
||||
and tp_cmd1 = tp_cmd env cmd1
|
||||
and tp_cmd2 = tp_cmd env cmd2
|
||||
in
|
||||
if tp_expr1 = BoolT && tp_cmd1 = tp_cmd2
|
||||
then tp_cmd1
|
||||
else raise (Failure "Invalid type of Conditionnal Command")
|
||||
| Loop(cmd1) ->
|
||||
let _ = (tp_cmd env cmd1) in VoidT
|
||||
| CallC(name, list_expr) -> tp_expr env (CallE(name, list_expr))
|
||||
| Return(expr) -> (tp_expr env expr)
|
||||
;;
|
||||
(* val tp_cmd :
|
||||
environment -> Lang.com
|
||||
-> Lang.tp = <fun>
|
||||
*)
|
||||
|
||||
(* - tp_cmd: TESTS - *)
|
||||
let test_tp_cmd =
|
||||
let function_to_test = tp_cmd {
|
||||
localvars=[
|
||||
("i", IntT);
|
||||
("f", FloatT);
|
||||
];
|
||||
funbind=[
|
||||
Fundecl(BoolT, "fun1", [Vardecl(IntT, "a"); Vardecl(FloatT, "b")])
|
||||
]
|
||||
}
|
||||
and input_values = [
|
||||
Skip;
|
||||
Exit;
|
||||
Assign("test", Const(IntV(5)));
|
||||
Seq(Skip, Exit);
|
||||
Seq(Skip, Return(Const(FloatV(5.))));
|
||||
|
||||
CondC(
|
||||
BinOp(BCompar(BCge), Const(IntV(4)), Const(IntV(5))),
|
||||
Skip, Skip
|
||||
);
|
||||
Loop(Exit);
|
||||
|
||||
CallC("fun1", [VarE("i"); VarE("f")]);
|
||||
Return(Const(IntV(5)));
|
||||
]
|
||||
and expected_result = [
|
||||
VoidT;
|
||||
VoidT;
|
||||
VoidT;
|
||||
VoidT; FloatT;
|
||||
VoidT;
|
||||
VoidT;
|
||||
BoolT;
|
||||
IntT;
|
||||
] in
|
||||
(List.map function_to_test input_values) = expected_result
|
||||
;;
|
||||
|
||||
|
||||
|
||||
(* ----- Typage d'une définition de fonction ----- *)
|
||||
let tp_fundefn (env: environment) (fun_def: fundefn) =
|
||||
let Fundefn(fun_decl, cmd) = fun_def in
|
||||
let Fundecl(fun_decl_tp,_,var_decl_list) = fun_decl in
|
||||
let env1 = build_env_var env var_decl_list in
|
||||
let _ = tp_cmd env1 cmd
|
||||
in if valid_vardecl_list var_decl_list && (tp_cmd env1 cmd) = fun_decl_tp
|
||||
then fun_decl_tp
|
||||
else raise (Failure "Type return is not the same as the type of the function")
|
||||
;;
|
||||
(* val tp_fundefn :
|
||||
environment -> Lang.fundefn
|
||||
-> Lang.tp = <fun>
|
||||
*)
|
||||
|
||||
(* - tp_fundefn: TESTS - *)
|
||||
let test_tp_fundefn =
|
||||
let function_to_test = tp_fundefn {
|
||||
localvars=[];
|
||||
funbind=[
|
||||
Fundecl(BoolT, "fun1", [Vardecl(IntT, "x"); Vardecl(FloatT, "y")]);
|
||||
Fundecl(IntT, "fun2", [Vardecl(IntT, "x"); Vardecl(FloatT, "y")]);
|
||||
]
|
||||
}
|
||||
and input_values = [
|
||||
Fundefn(
|
||||
Fundecl(BoolT, "fun1", [Vardecl(IntT, "a"); Vardecl(FloatT, "b")]),
|
||||
Return(BinOp(BCompar(BCeq), Const(IntV(4)), Const(IntV(5))))
|
||||
);
|
||||
Fundefn(
|
||||
Fundecl(IntT, "fun2", [Vardecl(IntT, "a"); Vardecl(FloatT, "b")]),
|
||||
Return(VarE("a"))
|
||||
);
|
||||
]
|
||||
and expected_result = [
|
||||
BoolT;
|
||||
IntT;
|
||||
] in
|
||||
(List.map function_to_test input_values) = expected_result
|
||||
;;
|
||||
|
||||
|
||||
|
||||
(* ----- Typage d'un programme ----- *)
|
||||
let tp_prog (Prog (fundecls, fundefns)) =
|
||||
let env = build_env_fun {localvars=[];funbind=[]} fundecls in
|
||||
try (
|
||||
let _ = List.map (tp_fundefn env) fundefns
|
||||
in true
|
||||
) with _ -> false
|
||||
;;
|
||||
(* val tp_prog :
|
||||
Lang.prog
|
||||
-> bool = <fun>
|
||||
*)
|
||||
|
||||
(* - tp_prog: TESTS - *)
|
||||
let test_tp_prog =
|
||||
let function_to_test = tp_prog
|
||||
and input_values = [
|
||||
Prog(
|
||||
[
|
||||
Fundecl(BoolT, "fun1", [Vardecl(IntT, "x"); Vardecl(FloatT, "y")]);
|
||||
Fundecl(IntT, "fun2", [Vardecl(IntT, "x"); Vardecl(FloatT, "y")]);
|
||||
],
|
||||
[
|
||||
Fundefn(
|
||||
Fundecl(BoolT, "fun1", [Vardecl(IntT, "a"); Vardecl(FloatT, "b")]),
|
||||
Return(BinOp(BCompar(BCeq), Const(IntV(4)), Const(IntV(5))))
|
||||
);
|
||||
Fundefn(
|
||||
Fundecl(IntT, "fun2", [Vardecl(IntT, "a"); Vardecl(FloatT, "b")]),
|
||||
Return(VarE("a"))
|
||||
);
|
||||
]
|
||||
);
|
||||
]
|
||||
and expected_result = [
|
||||
true;
|
||||
] in
|
||||
(List.map function_to_test input_values) = expected_result
|
||||
;;
|
||||
+2
-2
@@ -13,12 +13,12 @@ open Instrs;;
|
||||
(* For using the parser:
|
||||
|
||||
- Evaluate this file (use.ml)
|
||||
- parse "Tests/rectangles.c" ;;
|
||||
- parse "../Tests/progsimple.c" ;;
|
||||
|
||||
* For code generation:
|
||||
|
||||
- Evaluate this file (use.ml)
|
||||
- run_test "Tests/rectangles.c" "Tests/rectangles.ps";;
|
||||
- run_test "../Tests/rectangles.c" "../Tests/rectangles.ps";;
|
||||
*)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
void yes( int yes){
|
||||
yes = 5;
|
||||
return yes;
|
||||
}
|
||||
|
||||
void main (string y, int x, int yooo) {
|
||||
x = 15;
|
||||
while (x < 20) {
|
||||
x = x + 1 -16;
|
||||
y = "hello";
|
||||
if (x == 17) {
|
||||
y = "world";
|
||||
}
|
||||
}
|
||||
|
||||
yooo = yes(5);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user