diff --git a/.gitignore b/.gitignore index b0a833a..a1de90b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ src/parser.ml *.mli src/**/*.cmi comp +*/**/*.output # Tests out tests/out/ diff --git a/README.md b/README.md index bb2bf86..3d5f79e 100644 --- a/README.md +++ b/README.md @@ -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! diff --git a/src/Makefile b/src/Makefile index 5c4c317..43621e7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 \ No newline at end of file diff --git a/src/lexer.mll b/src/lexer.mll new file mode 100644 index 0000000..deb988b --- /dev/null +++ b/src/lexer.mll @@ -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 } diff --git a/src/parser.mly b/src/parser.mly new file mode 100644 index 0000000..ad03eed --- /dev/null +++ b/src/parser.mly @@ -0,0 +1,200 @@ +%{ +open Lang +%} + +%token IDENTIFIER +%token LITCONSTANT +%token STRINGCONSTANT +%token TP +%token BCONSTANT +%token INTCONSTANT +%token 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 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) +*/ diff --git a/src/typing.ml b/src/typing.ml index a47fb87..f32633d 100644 --- a/src/typing.ml +++ b/src/typing.ml @@ -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 = *) -(* 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 = *) + + + +(* 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 = +*) + +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 = +*) + + + +(* 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 = +*) + +let addEnv_fun (fun_decl: fundecl) (env: environment) = { + localvars=(env.localvars); + funbind=(fun_decl::(env.funbind)) +};; +(* val addEnv_fun : + Lang.fundecl -> environment + -> environment = +*) + + + +(* 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 = +*) + +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 = +*) + + + +(* 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 = *) + + + +(* ----- 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 - | BinOp(op, expr1, expr2) -> - | CondE(expr1, expr2, expr3) -> - | CallE(functionName, exprList) -> *) + | 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) -> + 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 = +*) + +(* - 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 \ No newline at end of file + + +(* ----- 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 = +*) + +(* - 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 = +*) + +(* - 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 = +*) + +(* - 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 +;; \ No newline at end of file diff --git a/src/use.ml b/src/use.ml index 16880ca..76cf849 100644 --- a/src/use.ml +++ b/src/use.ml @@ -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";; *) diff --git a/tests/progsimple.c b/tests/progsimple.c new file mode 100644 index 0000000..af4358d --- /dev/null +++ b/tests/progsimple.c @@ -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; +} +