mirror of
https://github.com/LucasVbr/postscript-compiler.git
synced 2026-05-14 01:31:59 +00:00
@@ -8,6 +8,7 @@ src/parser.ml
|
|||||||
*.mli
|
*.mli
|
||||||
src/**/*.cmi
|
src/**/*.cmi
|
||||||
comp
|
comp
|
||||||
|
*/**/*.output
|
||||||
|
|
||||||
# Tests out
|
# Tests out
|
||||||
tests/out/
|
tests/out/
|
||||||
|
|||||||
@@ -8,13 +8,18 @@
|
|||||||
|
|
||||||
> Compilateur du langage Postscript en Ocaml
|
> 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**
|
👤 **Lucas VABRE**
|
||||||
|
|
||||||
* Github: [@LucasVbr](https://github.com/LucasVbr)
|
* Github: [@LucasVbr](https://github.com/LucasVbr)
|
||||||
* LinkedIn: [@lucasvbr](https://linkedin.com/in/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
|
# Compile
|
||||||
all: lib comp clean
|
all: comp
|
||||||
|
|
||||||
# Compilation of Ocaml files
|
# Compilation of Ocaml files
|
||||||
# Attention: order of object files important
|
# 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
|
# ocaml lexer and parser
|
||||||
|
|
||||||
# Comment in for your own lexer
|
# Comment in for your own lexer
|
||||||
# lexer.ml: lexer.mll lang.cmo
|
lexer.ml: lexer.mll lang.cmo
|
||||||
# ocamllex $<
|
ocamllex $<
|
||||||
|
|
||||||
# Comment in for your own parser
|
# Comment in for your own parser
|
||||||
# parser.ml parser.mli: parser.mly lang.cmo
|
parser.ml parser.mli: parser.mly lang.cmo
|
||||||
# ocamlyacc $<
|
ocamlyacc $<
|
||||||
|
|
||||||
lexer.cmo: lexer.ml parser.cmo
|
lexer.cmo: lexer.ml parser.cmo
|
||||||
ocamlc -c $<
|
ocamlc -c $<
|
||||||
@@ -51,10 +51,14 @@ parser.cmo: parser.ml parser.cmi lang.cmo
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
### Import files from /lib
|
### Import files from /lib (temporarly)
|
||||||
lib:
|
# lib:
|
||||||
cp ../lib/* ./
|
# cp ../lib/* ./
|
||||||
|
|
||||||
## Remove compiled modules and lib
|
## Remove compiled modules and lib
|
||||||
clean:
|
clean:
|
||||||
rm -f lexer.ml parser.ml *.mli *.cmi *.cmo
|
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)
|
||||||
|
*/
|
||||||
+402
-25
@@ -1,38 +1,415 @@
|
|||||||
(* Typechecking of source programs *)
|
(* Typechecking of source programs *)
|
||||||
|
|
||||||
open Lang
|
open Lang;;
|
||||||
|
|
||||||
(* Environments *)
|
(* Environments *)
|
||||||
type environment = {
|
type environment = {
|
||||||
localvars: (vname * tp) list;
|
localvars: (vname * tp) list;
|
||||||
funbind: fundecl list
|
funbind: fundecl list
|
||||||
}
|
};;
|
||||||
|
|
||||||
let find_var (var: vname) (env: environment) =
|
(* Fonction sur les listes de declarations de variables *)
|
||||||
let rec aux local_vars =
|
let rec count_same_var_name (name: string) (var_decl_list: vardecl list) =
|
||||||
match local_vars with
|
match var_decl_list with
|
||||||
| [] -> failwith "Variable inconnue"
|
| [] -> 0
|
||||||
| tete::reste ->
|
| Vardecl(var_tp, var_name)::reste ->
|
||||||
let (name, _) = tete in
|
(count_same_var_name name reste)
|
||||||
if name = var
|
+ if name = var_name then 1 else 0
|
||||||
then tete
|
|
||||||
else aux reste
|
|
||||||
in aux (env.localvars)
|
|
||||||
;;
|
;;
|
||||||
|
(* 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
|
match expression with
|
||||||
| Const(const) ->
|
| Const(const) -> (
|
||||||
match const with
|
match const with
|
||||||
| BoolV(_) -> BoolT
|
| BoolV _ -> BoolT
|
||||||
| FloatV(_) -> FloatT
|
| FloatV _ -> FloatT
|
||||||
| IntV(_) -> IntT
|
| IntV _ -> IntT
|
||||||
| LitV(_) -> LitT
|
| LitV _ -> LitT
|
||||||
| StringV(_) -> StringT
|
| StringV _ -> StringT
|
||||||
| VarE(var) -> tp_expr (find_var var env) env
|
)
|
||||||
| BinOp(op, expr1, expr2) ->
|
| VarE(var) -> (
|
||||||
| CondE(expr1, expr2, expr3) ->
|
let var_value = (findEnv_var var env) in
|
||||||
| CallE(functionName, exprList) -> *)
|
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) ->
|
||||||
|
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:
|
(* For using the parser:
|
||||||
|
|
||||||
- Evaluate this file (use.ml)
|
- Evaluate this file (use.ml)
|
||||||
- parse "Tests/rectangles.c" ;;
|
- parse "../Tests/progsimple.c" ;;
|
||||||
|
|
||||||
* For code generation:
|
* For code generation:
|
||||||
|
|
||||||
- Evaluate this file (use.ml)
|
- 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