From 0119a154bf824eedd5e2f3890ec1f8b6b865efa1 Mon Sep 17 00:00:00 2001 From: fiplox Date: Thu, 27 Jan 2022 16:31:58 +0100 Subject: [PATCH] backup --- .gitignore | 3 + .merlin | 1 + README.md | 51 +++++++++++ ast.ml | 209 +++++++++++++++++++++++++++++++++++++++++++++ baselib.ml | 188 ++++++++++++++++++++++++++++++++++++++++ build.sh | 10 +++ compiler.ml | 140 ++++++++++++++++++++++++++++++ lexer.mll | 92 ++++++++++++++++++++ mips.ml | 147 ++++++++++++++++++++++++++++++++ parser.mly | 217 +++++++++++++++++++++++++++++++++++++++++++++++ semantics.ml | 157 ++++++++++++++++++++++++++++++++++ simplifier.ml | 77 +++++++++++++++++ t.s | 0 test.ml | 39 +++++++++ tests/0.test | 2 + tests/1.test | 1 + tests/10.test | 7 ++ tests/11.test | 11 +++ tests/12.test | 10 +++ tests/13.test | 11 +++ tests/14.test | 15 ++++ tests/15.test | 12 +++ tests/16.test | 13 +++ tests/17.test | 12 +++ tests/18.test | 24 ++++++ tests/19.test | 12 +++ tests/2.test | 1 + tests/20.test | 10 +++ tests/3.test | 1 + tests/4.test | 7 ++ tests/5.test | 3 + tests/6.test | 3 + tests/7.test | 3 + tests/8.test | 3 + tests/9.test | 3 + tests/game.test | 23 +++++ tests/newt.test | 18 ++++ tests/puiss.test | 23 +++++ tests/tmp.test | 7 ++ 39 files changed, 1566 insertions(+) create mode 100644 .gitignore create mode 100644 .merlin create mode 100644 README.md create mode 100644 ast.ml create mode 100644 baselib.ml create mode 100755 build.sh create mode 100644 compiler.ml create mode 100644 lexer.mll create mode 100644 mips.ml create mode 100644 parser.mly create mode 100644 semantics.ml create mode 100644 simplifier.ml create mode 100644 t.s create mode 100644 test.ml create mode 100644 tests/0.test create mode 100644 tests/1.test create mode 100644 tests/10.test create mode 100644 tests/11.test create mode 100644 tests/12.test create mode 100644 tests/13.test create mode 100644 tests/14.test create mode 100644 tests/15.test create mode 100644 tests/16.test create mode 100644 tests/17.test create mode 100644 tests/18.test create mode 100644 tests/19.test create mode 100644 tests/2.test create mode 100644 tests/20.test create mode 100644 tests/3.test create mode 100644 tests/4.test create mode 100644 tests/5.test create mode 100644 tests/6.test create mode 100644 tests/7.test create mode 100644 tests/8.test create mode 100644 tests/9.test create mode 100644 tests/game.test create mode 100644 tests/newt.test create mode 100644 tests/puiss.test create mode 100644 tests/tmp.test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..67573f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +_build/ +*.byte +*.~* diff --git a/.merlin b/.merlin new file mode 100644 index 0000000..1a1fd25 --- /dev/null +++ b/.merlin @@ -0,0 +1 @@ +B _build diff --git a/README.md b/README.md new file mode 100644 index 0000000..0b8cc10 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# MiniC + +## Fonctionnalités + +* Declaration des types de bases (int, char, float, bool) +* Declaration des fonctions +* Conditions if, else, else if +* Boucle while +* Fonctions natives : + * `_add` + * `_sub` + * `_mul` + * `_div` + * `_add` + * `_sub` + * `_mul` + * `_div` + * `_xor` + * `_or ` + * `_and` + * `_seq` + * `_sne` + * `_sge` + * `_sgt` + * `_sle` + * `_slt` + * `_mod` + * `_neg` + * `_not` + * `puts` + * `puti` + * `geti` + +## Tests + +### Test game (not really) +```sh +$ ocamlbuild -use-menhir test.byte +$ ./test.byte tests/game.test > t.s +$ spim t.s +(spim) load "t.s" +(spim) run +``` + +### Autres tests (sans user input) +```sh +$ ./build.sh newt +``` +```sh +$ ./build.sh puiss +``` diff --git a/ast.ml b/ast.ml new file mode 100644 index 0000000..a71a76c --- /dev/null +++ b/ast.ml @@ -0,0 +1,209 @@ +type type_t = + | Int_t + | Float_t + | Char_t + | Str_t + | Void_t + | Bool_t + | Func_t of type_t * type_t list + | Point_t of type_t + (* | Array_t of int * type_t *) + +let rec string_of_type_t t = + match t with + | Int_t -> "int" + | Float_t -> "float" + | Char_t -> "char" + | Str_t -> "string" + | Void_t -> "void" + | Bool_t -> "bool" + (* | Array_t (n, t) -> string_of_type_t t *) + | Point_t t -> string_of_type_t t + | Func_t (r, a) -> + (if List.length a > 1 then "(" else "") + ^ String.concat ", " (List.map string_of_type_t a) + ^ (if List.length a > 1 then ")" else "") + ^ " -> " + ^ string_of_type_t r +;; + +module Syntax = struct + type ident = string + + type expr = + | Int of + { value : int + ; pos : Lexing.position + } + | Float of + { value : float + ; pos : Lexing.position + } + | Char of + { value : string + ; pos : Lexing.position + } + | Str of + { value : string + ; pos : Lexing.position + } + (* | Array of *) + (* { value : expr list *) + (* ; cap : int option *) + (* ; pos : Lexing.position *) + (* } *) + | Bool of + { value : bool + ; pos : Lexing.position + } + | Var of + { name : ident + ; pos : Lexing.position + } + | Call of + { func : ident + ; args : expr list + ; pos : Lexing.position + } + + type instr = + | Assign of + { var : ident + ; expr : expr + ; pos : Lexing.position + } + | Decl of + { var : ident + ; typ : type_t + ; pos : Lexing.position + } + | Expr of + { expr : expr + ; pos : Lexing.position + } + | Return of + { expr : expr + ; pos : Lexing.position + } + | Cond of + { expr : expr + ; blockt : block + ; blockf : block + ; pos : Lexing.position + } + | Loop of + { expr : expr + ; block : block + ; pos : Lexing.position + } + + and block = instr list + + type def = + | Func of + { typ : type_t + ; name : ident + ; args : (type_t * ident) list + ; block : block + ; pos : Lexing.position + } + + type prog = def list +end + +module IR = struct + type ident = string + + type expr = + | Int of int + | Float of float + | Char of char + | Str of string + | Void + | Bool of bool + (* | Array of int * expr list *) + | Var of ident + | Call of ident * expr list + + type instr = + | Decl of ident + | Expr of expr + | Assign of ident * expr + | Return of expr + | Cond of expr * block * block + | Loop of expr * block + + and block = instr list + + type def = Func of ident * ident list * block + type prog = def list + + let string_of_ir ast = + let rec fmt_e = function + | Int n -> "Int " ^ string_of_int n + | Float n -> "Float " ^ string_of_float n + | Char c -> "Char " ^ String.make 1 c + | Str s -> "Str \"" ^ s ^ "\"" + (* | Array (n, e) -> "Array (" ^ string_of_int n ^ ", " ^ String.concat " ; " (List.map fmt_e e) ^ ")" *) + | Void -> "Void" + | Bool b -> "Bool " ^ string_of_bool b + | Var v -> "Var \"" ^ v ^ "\"" + | Call (f, a) -> + "Call (\"" ^ f ^ "\", [ " ^ String.concat " ; " (List.map fmt_e a) ^ " ])" + and fmt_i = function + | Decl v -> "Decl \"" ^ v ^ "\"" + | Assign (v, e) -> "Assign (\"" ^ v ^ "\", " ^ fmt_e e ^ ")" + | Expr e -> "Expr (" ^ fmt_e e ^ ")" + | Return e -> "Return (" ^ fmt_e e ^ ")" + | Cond (e, bt, bf) -> "Cond (" ^ fmt_e e ^ ", " ^ fmt_b bt ^ "\n, " ^ fmt_b bf ^ ")" + | Loop (e, b) -> "Loop (" ^ fmt_e e ^ ",\n" ^ fmt_b b ^ ")" + and fmt_b b = "\t[ " ^ String.concat "\n\t; " (List.map fmt_i b) ^ " ]" + and fmt_arg a = "\"" ^ a ^ "\"" + and fmt_d = function + | Func (name, args, b) -> + "[ Func (\"" + ^ name + ^ "\", " + ^ "[ " + ^ String.concat " ; " (List.map fmt_arg args) + ^ " ],\n" + ^ fmt_b b + ^ ")" + ^ "]" + and fmt_p p = "[\n " ^ String.concat "\n " (List.map fmt_d p) ^ "\n]" in + fmt_p ast + ;; +end + +module IR2 = struct + type ident = string + + type value = + | Nil + | Bool of bool + | Int of int + | Float of float + | Char of char + | Data of string + + type expr = + | Value of value + | Var of ident + | Call of ident * expr list + + (* type lvalue = *) + (* | LVar of ident *) + (* | LAddr of expr *) + type instr = + | Decl of ident + | Return of expr + | Expr of expr + | Assign of expr * expr + | Cond of expr * block * block + | Loop of expr * block + + and block = instr list + + type def = Func of ident * ident list * block + type prog = def list +end diff --git a/baselib.ml b/baselib.ml new file mode 100644 index 0000000..828b137 --- /dev/null +++ b/baselib.ml @@ -0,0 +1,188 @@ +open Ast +module Env = Map.Make (String) + +let native_func_names = + [ "_add" + ; "_sub" + ; "_mul" + ; "_div" + ; "_adds" + ; "_subs" + ; "_muls" + ; "_divs" + ; "_xor" + ; "_or" + ; "_and" + ; "_seq" + ; "_sne" + ; "_sge" + ; "_sgt" + ; "_sle" + ; "_slt" + ; "_mod" + ; "_neg" + ; "_not" + ; "puts" + ; "puti" + ; "geti" + ] +;; + +let native_asmdx = Func_t (Int_t, [ Int_t; Int_t ]) +let native_asmdfloat = Func_t (Float_t, [ Float_t; Float_t ]) +let native_eq = Func_t (Int_t, [ Int_t; Int_t ]) +let native_not = Func_t (Int_t, [ Int_t ]) +let native_neg = Func_t (Int_t, [ Int_t ]) +let native_puts = Func_t (Void_t, [ Str_t ]) +let native_puti = Func_t (Void_t, [ Int_t ]) +let native_geti = Func_t (Int_t, []) + +let native_funcs = + [ native_asmdx (* "_add" *) + ; native_asmdx (* "_sub" *) + ; native_asmdx (* "_mul" *) + ; native_asmdx (* "_div" *) + ; native_asmdfloat (* "_adds" *) + ; native_asmdfloat (* "_subs" *) + ; native_asmdfloat (* "_muls" *) + ; native_asmdfloat (* "_divs" *) + ; native_asmdx (* "_xor" *) + ; native_asmdx (* "_or" *) + ; native_asmdx (* "_and" *) + ; native_eq (* "_seq" *) + ; native_eq (* "_sne" *) + ; native_eq (* "_sge" *) + ; native_eq (* "_sgt" *) + ; native_eq (* "_sle" *) + ; native_eq (* "_slt" *) + ; native_asmdx (* "_mod" *) + ; native_neg (* "_neg" *) + ; native_not (* "_not" *) + ; native_puts (* "puts" *) + ; native_puti (* "puti" *) + ; native_geti (* "geti" *) + ] +;; + +let add_funcs env name func = Env.add name func env +let _baselib_ = List.fold_left2 add_funcs Env.empty native_func_names native_funcs + +open Mips + +let builtins = + [ Label "_add" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Add (V0, T0, T1) + ; Jr RA + ; Label "_sub" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Sub (V0, T0, T1) + ; Jr RA + ; Label "_div" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Div (V0, T0, T1) + ; Jr RA + ; Label "_mul" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Mul (V0, T0, T1) + ; Jr RA + ; Label "_adds" + ; Ls (F1, Mem (SP, 0)) + ; Ls (F2, Mem (SP, 4)) + ; Adds (F0, F1, F2) + ; Jr RA + ; Label "_subs" + ; Ls (F1, Mem (SP, 0)) + ; Ls (F2, Mem (SP, 4)) + ; Subs (F0, F1, F2) + ; Jr RA + ; Label "_divs" + ; Ls (F1, Mem (SP, 0)) + ; Ls (F2, Mem (SP, 4)) + ; Divs (F0, F1, F2) + ; Jr RA + ; Label "_muls" + ; Ls (F1, Mem (SP, 0)) + ; Ls (F2, Mem (SP, 4)) + ; Muls (F0, F1, F2) + ; Jr RA + ; Label "_xor" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Xor (V0, T0, T1) + ; Jr RA + ; Label "_or" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Or (V0, T0, T1) + ; Jr RA + ; Label "_and" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; And (V0, T0, T1) + ; Jr RA + ; Label "_seq" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Seq (V0, T0, T1) + ; Jr RA + ; Label "_sne" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Sne (V0, T0, T1) + ; Jr RA + ; Label "_sge" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Sge (V0, T0, T1) + ; Jr RA + ; Label "_sgt" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Sgt (V0, T0, T1) + ; Jr RA + ; Label "_sle" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Sle (V0, T0, T1) + ; Jr RA + ; Label "_slt" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Slt (V0, T0, T1) + ; Jr RA + ; Label "_mod" + ; Lw (T0, Mem (SP, 0)) + ; Lw (T1, Mem (SP, 4)) + ; Div (V0, T0, T1) + ; Mfhi V0 + ; Jr RA + ; Label "_not" + ; Lw (T0, Mem (SP, 0)) + ; Seq (V0, T0, Zero) + ; Jr RA + ; Label "_neg" + ; Lw (T0, Mem (SP, 0)) + ; Sub (V0, T0, Zero) + ; Jr RA + ; Label "puti" + ; Lw (A0, Mem (SP, 0)) + ; Li (V0, Syscall.print_int) + ; Syscall + ; Jr RA + ; Label "geti" + ; Lw (A0, Mem (SP, 0)) + ; Li (V0, Syscall.read_int) + ; Syscall + ; Jr RA + ; Label "puts" + ; Lw (A0, Mem (SP, 0)) + ; Li (V0, Syscall.print_str) + ; Syscall + ; Jr RA + ] +;; diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..103ef37 --- /dev/null +++ b/build.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +ocamlbuild -use-menhir test.byte +./test.byte tests/$1.test > t.s +# echo 'load "t.s"' | spim +# spim +cat < [ Li (V0, 0) ] + | Bool b -> [ Li (V0, if b then 1 else 0) ] + | Int n -> [ Li (V0, n) ] + | Float f -> [ Lis (F0, f) ] + | Char c -> [ Li (V0, int_of_char c) ] + | Data l -> [ La (V0, Lbl l) ] + + +let rec compile_expr e env = + match e with + | Value v -> compile_v v + | Var v -> [ Lw (V0, Env.find v env) ] + | Call (f, args) -> + let ca = + List.map + (fun a -> compile_expr a env @ [ Addi (SP, SP, -4); Sw (V0, Mem (SP, 0)) ]) + args + in + List.flatten ca @ [ Jal f; Addi (SP, SP, 4 * List.length args) ] +;; + +let rec compile_instr i info = + match i with + | Decl v -> + { info with env = Env.add v (Mem (FP, -info.fpo)) info.env; fpo = info.fpo + 4 } + | Return e -> + { info with code = info.code @ compile_expr e info.env @ [ B info.return ] } + | Expr e -> { info with code = info.code @ compile_expr e info.env } + | Assign (lv, e) -> + { info with + code = + (info.code + @ compile_expr e info.env + @ + match lv with + | Var v -> [ Sw (V0, Env.find v info.env) ] + | _ -> failwith "WTF???") + } +(* | LVar v -> [ Sw (V0, Env.find v info.env) ] *) +(* | LAddr a -> [] *) +(* @ [ Addi (SP, SP, -4) *) +(* ; Sw (V0, Mem (SP, 0)) ] *) +(* @ compile_expr a info.env *) +(* @ [ Lw (T0, Mem (SP, 0)) *) +(* ; Addi (SP, SP, 4) *) +(* ; Sw (T0, Mem (V0, 0)) ]) } *) +| Cond (c, t, e) -> + let uniq = string_of_int info.counter in + let ct = compile_block t { info with code = [] + ; counter = info.counter + 1 } in + let ce = compile_block e { info with code = [] + ; counter = ct.counter } in + { info with + code = info.code + @ compile_expr c info.env + @ [ Beqz (V0, "else" ^ uniq) ] + @ ct.code + @ [ B ("endif" ^ uniq) + ; Label ("else" ^ uniq) ] + @ ce.code + @ [ Label ("endif" ^ uniq) ] + ; counter = ce.counter } +| Loop (c, t) -> + let uniq = string_of_int info.counter in + let ct = compile_block t { info with code = [] + ; counter = info.counter + 1 } in + { info with + code = info.code + @ [ Label ("loop" ^ uniq) ] + @ compile_expr c info.env + @ [ Beqz (V0, "endloop" ^ uniq) ] + @ ct.code + @ [ J ("loop" ^ uniq) ] + @ [ Label ("endloop" ^ uniq) ] + ; counter = ct.counter } + +and compile_block b info = + match b with + | [] -> info + | i :: r -> compile_block r (compile_instr i info) +;; + +let compile_def (Func (name, args, b)) counter = + let cb = + compile_block + b + { code = [] + ; env = + List.fold_left + (fun e (i, a) -> Env.add a (Mem (FP, 4 * i)) e) + Env.empty + (List.mapi (fun i a -> i + 1, a) args) + ; fpo = 8 + ; counter = counter + 1 + ; return = "ret" ^ string_of_int counter + } + in + ( cb.counter + , [] + @ [ Label name + ; Addi (SP, SP, -cb.fpo) + ; Sw (RA, Mem (SP, cb.fpo - 4)) + ; Sw (FP, Mem (SP, cb.fpo - 8)) + ; Addi (FP, SP, cb.fpo - 4) + ] + @ cb.code + @ [ Label cb.return + ; Addi (SP, SP, cb.fpo) + ; Lw (RA, Mem (FP, 0)) + ; Lw (FP, Mem (FP, -4)) + ; Jr RA + ] ) +;; + +let rec compile_prog p counter = + match p with + | [] -> [] + | d :: r -> + let new_counter, cd = compile_def d counter in + cd @ compile_prog r new_counter +;; + +let compile (code, data) = + { text = Baselib.builtins @ compile_prog code 0 + ; data = List.map (fun (l, s) -> l, Asciiz s) data + } +;; diff --git a/lexer.mll b/lexer.mll new file mode 100644 index 0000000..9f83fed --- /dev/null +++ b/lexer.mll @@ -0,0 +1,92 @@ +{ + open Lexing + open Parser + + exception Error of char + exception ErrorStr of string + let keywords = + [ + ("void", Lvoid_kw); + ("int", Lint_kw); + ("char", Lchar_kw); + ("float", Lfloat_kw); + ("bool", Lbool_kw); + ("return", Lreturn); + ("puts", Lputs); + ("puti", Lputi); + ("geti", Lgeti); + ("if", Lif); + ("else", Lelse); + (* ("for", Lfor); *) + (* ("do", Ldo); *) + ("while", Lwhile); + (* ("break", Lbreak); *) + (* ("continue", Lcontinue) *) + ] + let find_kw s = + match List.assoc_opt s keywords with + | Some kw -> kw + | None -> Lvar s +} + +let alpha = ['a'-'z' 'A'-'Z'] +let num = ['0'-'9'] +let numf = (num)+ '.' (num)+ +let identifier = alpha (alpha | num | '-' | '_')* +let character = (_ | '\\'['a' 'b' 't' 'n' 'v' 'f' 'r' '0' '\\' ''']) +let boo = ("true" | "false") + + +rule token = parse +| eof { Lend } +| [ ' ' '\t' ] { token lexbuf } +| '\n' { Lexing.new_line lexbuf; token lexbuf } +| "//" { comment lexbuf } +| "/*" { multiline_comment lexbuf } +| ('-')? numf as n { Lfloat (float_of_string n) } +| ('-')? num+ as n { Lint (int_of_string n) } +| boo as b { Lbool (bool_of_string b) } +| "'" character"'" as c { Lchar c } +| '"' { Lstr (str lexbuf) } +| "(" { Lopar } +| ")" { Lcpar } +(* | "[" { Lob } *) +(* | "]" { Lcb } *) +| ";" { Lsc } +| "*" { Lmul } +| "+" { Ladd } +| "/" { Ldiv } +| "%" { Lmod } +| "^" { Lxor } +| "&" { Land } +| "|" { Lor } +| "-" { Lsub } +| "=" { Lassign } +| "==" { Leq } +| "!=" { Lneq } +| ">=" { Lge } +| ">" { Lgt } +| "<=" { Lle } +| "<" { Llt } +| "," { Lcomma } +| "{" { Lobr } +| "}" { Lcbr } +| "!" { Lnot } +| identifier as i { find_kw i } +| _ as c { raise (Error c) } + +and comment = parse +| eof { Lend } +| '\n' { Lexing.new_line lexbuf; token lexbuf } +| _ { comment lexbuf } + +and multiline_comment = parse +| eof { Lend } +| '\n' { Lexing.new_line lexbuf; multiline_comment lexbuf } +| "*/" { token lexbuf } +| _ { multiline_comment lexbuf } + +and str = parse +| eof { raise (ErrorStr "Unexpected EOF") } +| '"' { "" } +| _ as c { (String.make 1 c) ^ (str lexbuf) } diff --git a/mips.ml b/mips.ml new file mode 100644 index 0000000..6eb2de1 --- /dev/null +++ b/mips.ml @@ -0,0 +1,147 @@ +type reg = + | Zero + | SP + | RA + | FP + | V0 + | F0 + | F1 + | F2 + | A0 + | A1 + | T0 + | T1 + (* | FF *) + +type label = string + +type loc = + | Lbl of label + | Mem of reg * int + +type instr = + | Label of label + | Li of reg * int + | Lis of reg * float + | La of reg * loc + | Sw of reg * loc + | Lw of reg * loc + | Ls of reg * loc + | Sb of reg * loc + | Lb of reg * loc + | Move of reg * reg + | Addi of reg * reg * int + | Add of reg * reg * reg + | Sub of reg * reg * reg + | Div of reg * reg * reg + | Mflo of reg + | Mfhi of reg + | Xor of reg * reg * reg + | Or of reg * reg * reg + | Nor of reg * reg * reg + | And of reg * reg * reg + | Mul of reg * reg * reg + | Seq of reg * reg * reg + | Sne of reg * reg * reg + | Sge of reg * reg * reg + | Sgt of reg * reg * reg + | Sle of reg * reg * reg + | Slt of reg * reg * reg + | Adds of reg * reg * reg + | Subs of reg * reg * reg + | Muls of reg * reg * reg + | Divs of reg * reg * reg + | Andi of reg * reg * int + | Not of reg * reg + | Syscall + | B of label + | Beqz of reg * label + | Jal of label + | Jr of reg + | J of label + +type directive = + | Asciiz of string + +type decl = label * directive + +type asm = { text: instr list ; data: decl list } + +module Syscall = struct + let print_int = 1 + let print_str = 4 + let read_int = 5 + let read_str = 8 + let sbrk = 9 +end + +let ps = Printf.sprintf (* alias raccourci *) + +let fmt_reg = function + | Zero -> "$zero" + | SP -> "$sp" + | FP -> "$fp" + | RA -> "$ra" + | V0 -> "$v0" + | F0 -> "$f0" + | F1 -> "$f1" + | F2 -> "$f2" + | A0 -> "$a0" + | A1 -> "$a1" + | T0 -> "$t0" + | T1 -> "$t1" + (* | FF -> "0x00ff" *) + +let fmt_loc = function + | Lbl (l) -> l + | Mem (r, o) -> ps "%d(%s)" o (fmt_reg r) + +let fmt_instr = function + | Label (l) -> ps "%s:" l + | Li (r, i) -> ps " li %s, %d" (fmt_reg r) i + | Lis (r, i) -> ps " li.s %s, %f" (fmt_reg r) i + | La (r, a) -> ps " la %s, %s" (fmt_reg r) (fmt_loc a) + | Sw (r, a) -> ps " sw %s, %s" (fmt_reg r) (fmt_loc a) + | Lw (r, a) -> ps " lw %s, %s" (fmt_reg r) (fmt_loc a) + | Ls (r, a) -> ps " l.s %s, %s" (fmt_reg r) (fmt_loc a) + | Sb (r, a) -> ps " sb %s, %s" (fmt_reg r) (fmt_loc a) + | Lb (r, a) -> ps " lb %s, %s" (fmt_reg r) (fmt_loc a) + | Move (rd, rs) -> ps " move %s, %s" (fmt_reg rd) (fmt_reg rs) + | Addi (rd, rs, i) -> ps " addi %s, %s, %d" (fmt_reg rd) (fmt_reg rs) i + | Add (rd, rs, rt) -> ps " add %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Sub (rd, rs, rt) -> ps " sub %s, %s, %s" (fmt_reg rd)(fmt_reg rt) (fmt_reg rs) + | Div (rd, rs, rt) -> ps " div %s, %s, %s" (fmt_reg rd) (fmt_reg rt) (fmt_reg rs) + | Mflo rd -> ps " mflo %s" (fmt_reg rd) + | Mfhi rd -> ps " mfhi %s" (fmt_reg rd) + | Xor (rd, rs, rt) -> ps " xor %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Or (rd, rs, rt) -> ps " or %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Nor (rd, rs, rt) -> ps " nor %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | And (rd, rs, rt) -> ps " and %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Mul (rd, rs, rt) -> ps " mul %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Seq (rd, rs, rt) -> ps " seq %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Sne (rd, rs, rt) -> ps " sne %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Sge (rd, rt, rs) -> ps " sge %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Sgt (rd, rt, rs) -> ps " sgt %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Sle (rd, rt, rs) -> ps " sle %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Slt (rd, rt, rs) -> ps " slt %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Adds (rd, rt, rs) -> ps " add.s %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Subs (rd, rt, rs) -> ps " sub.s %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Muls (rd, rt, rs) -> ps " mul.s %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Divs (rd, rt, rs) -> ps " div.s %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) + | Andi (rd, rs, i) -> ps " and %s, %s, %d" (fmt_reg rd) (fmt_reg rs) i + | Not (rd, rs) -> ps " not %s, %s" (fmt_reg rd) (fmt_reg rs) + | Syscall -> ps " syscall" + | B (l) -> ps " b %s" l + | Beqz (r, l) -> ps " beqz %s, %s" (fmt_reg r) l + | Jal (l) -> ps " jal %s" l + | Jr (r) -> ps " jr %s" (fmt_reg r) + | J (l) -> ps " j %s" l + +let fmt_dir = function + | Asciiz (s) -> ps ".asciiz \"%s\"" s + +let print_asm oc asm = + Printf.fprintf oc ".text\n.globl main\n" ; + List.iter (fun i -> Printf.fprintf oc "%s\n" (fmt_instr i)) asm.text ; + Printf.fprintf oc "\n.data\n" ; + List.iter (fun (l, d) -> Printf.fprintf oc "%s: %s\n" l (fmt_dir d)) asm.data diff --git a/parser.mly b/parser.mly new file mode 100644 index 0000000..e3879f7 --- /dev/null +++ b/parser.mly @@ -0,0 +1,217 @@ +%{ + open Ast + open Ast.Syntax +%} + +%token Lint +%token Lfloat +%token Lvar +%token Lchar +%token Lstr +%token Lbool +%token Lint_kw Lfloat_kw Lchar_kw Lvoid_kw Lbool_kw +%token Ladd Lsub Lmul Ldiv Lmod Lxor Lor Land Leq Lneq Lge Lgt Lle Llt Lnot +%token Lopar Lcpar Lputs Lputi Lgeti +%token Lreturn Lassign Lsc Lend Lif Lelse Lwhile +%token Lcomma Lobr Lcbr (* Lob Lcb *) + +%left Ladd Lsub +%left Lmul Ldiv +%left Lmod Lxor Lor Land +%left Leq Lneq Lge Lgt Lle Llt Lnot +%left Lputs Lputi Lgeti Lrand + +%start prog + +%type prog + +%% + +prog: +| d = def; p = prog { + d :: p +} +| Lend { [] } +; + +def: +| t = typ; id = Lvar; Lopar; a = args; Lcpar; Lobr; b = block; Lcbr { + Func { typ = t; name = id; args = a; block = b; pos = $startpos(t) } +} +; + +arg: +| t = typ; id = Lvar { + t, id +} +; + +args: +| { [] } +| a = arg { a :: [] } +| a = arg; Lcomma; r = args { + a :: r +} +; + +block: +| { [] } +| Lreturn; e = expr; Lsc; b = block { + Return { expr = e; pos = $startpos($1) } + :: b +} +| v = Lvar; Lassign; e = expr; Lsc; b = block { + Assign { var = v; expr = e; pos = $startpos($2) } + :: b +} +| t = typ; v = Lvar; Lsc; b = block { + Decl { var = v; typ = t; pos = $startpos(t) } + :: b +} +| t = typ; Lmul; v = Lvar; Lsc; b = block { + Decl { var = v; typ = Point_t(t); pos = $startpos(t) } + :: b +} +| t = typ; v = Lvar; Lassign; e = expr; Lsc; b = block { + Decl { var = v; typ = t; pos = $startpos(t) } + :: Assign { var = v; expr = e; pos = $startpos($3) } + :: b +} +| e = expr; Lsc; b = block { + Expr { expr = e; pos = $startpos(e) } + :: b +} +| Lwhile; e = expr; Lobr; bl = block; Lcbr; b = block { + Loop { expr = e; block = bl; pos = $startpos($1) } + :: b +} +| c = cond; b = block { + c :: b +} +; + +cond: +| Lif; e = expr; Lobr; bt = block; Lcbr { + Cond { expr = e; blockt = bt; blockf = []; pos = $startpos($1) } +} +| Lif; e = expr; Lobr; bt = block; Lcbr; Lelse; Lobr; be = block; Lcbr { + Cond { expr = e; blockt = bt; blockf = be; pos = $startpos($1) } +} +| Lif; e = expr; Lobr; bt = block; Lcbr; Lelse; bf = cond { + Cond { expr = e; blockt = bt; blockf = [bf]; pos = $startpos($1) } +} +; + + +par: +| { [] } +| e = expr { + e :: [] +} +| e = expr; Lcomma; p = par { + e :: p +} + +expr: +| Lopar; e = expr; Lcpar { + e +} +| n = Lfloat { + Float { value = n; pos = $startpos(n) } +} +| c = Lchar { + Char { value = c; pos = $startpos(c) } +} +| s = Lstr { + Str { value = s; pos = $startpos(s) } +} +| n = Lint { + Int { value = n; pos = $startpos(n) } +} +| b = Lbool { + Bool { value = b; pos = $startpos(b) } +} +| v = Lvar { + Var { name = v; pos = $startpos(v) } +} +| id = Lvar; Lopar; p = par; Lcpar; { + Call { func = id; args = p; pos = $startpos(id) } +} +| Lnot; a = expr; { + Call { func = "_not"; args = [ a ]; pos = $startpos($1) } +} +| Lsub; a = expr; { + Call { func = "_neg"; args = [ a ]; pos = $startpos($1) } +} +| a = expr; Lmul; b = expr { + Call { func = "_mul"; args = [ a ; b ]; pos = $startpos($2) } +} +| a = expr; Ladd; b = expr { + Call { func = "_add"; args = [ a ; b ]; pos = $startpos($2) } +} +| a = expr; Lsub; b = expr { + Call { func = "_sub"; args = [ a ; b ]; pos = $startpos($2) } +} +| a = expr; Ldiv; b = expr { + Call { func = "_div"; args = [ a ; b ]; pos = $startpos($2) } +} +| a = expr; Lmod; b = expr { + Call { func = "_mod"; args = [ a ; b ]; pos = $startpos($2) } +} +| a = expr; n = nat; b = expr { + Call { func = n; args = [ a ; b ]; pos = $startpos(n) } +} +| n = nat; Lopar; e = expr; Lcpar; { + Call { func = n; args = [ e ]; pos = $startpos(n) } +} +| n = nat; Lopar; Lcpar; { + Call { func = n; args = [ ]; pos = $startpos(n) } +} +; + +nat: +| Lxor { + "_xor" +} +| Lor { + "_or" +} +| Land { + "_and" +} +| Lputs { + "puts" +} +| Lputi { + "puti" +} +| Lgeti { + "geti" +} +| Lneq { + "_sne" +} +| Leq { + "_seq" +} +| Lge { + "_sge" +} +| Lgt { + "_sgt" +} +| Lle { + "_sle" +} +| Llt { + "_slt" +} +; + +typ: +| Lint_kw { Int_t } +| Lchar_kw { Char_t } +| Lfloat_kw { Float_t } +| Lbool_kw { Bool_t } +| Lvoid_kw { Void_t } +; diff --git a/semantics.ml b/semantics.ml new file mode 100644 index 0000000..f557339 --- /dev/null +++ b/semantics.ml @@ -0,0 +1,157 @@ +open Ast +open Ast.IR +open Baselib + +exception Error of string * Lexing.position + +(* fonctions d'aide à la gestion des erreurs *) + +let expr_pos expr = + match expr with + | Syntax.Int n -> n.pos + | Syntax.Float n -> n.pos + | Syntax.Char c -> c.pos + | Syntax.Str s -> s.pos + | Syntax.Bool b -> b.pos + | Syntax.Var v -> v.pos + | Syntax.Call c -> c.pos +;; + +let errt expected given pos = + raise + (Error + ( Printf.sprintf + "expected %s but given %s" + (string_of_type_t expected) + (string_of_type_t given) + , pos )) +;; + +(* analyse sémantique *) + +let rec analyze_expr expr env = + match expr with + | Syntax.Int n -> Int n.value, Int_t + | Syntax.Float n -> Float n.value, Float_t (* TODO: Should be Float_t *) + | Syntax.Char c -> Char c.value.[0], Char_t + | Syntax.Str s -> Str s.value, Str_t + | Syntax.Bool b -> Bool b.value, Bool_t + | Syntax.Var va -> + (match Env.find_opt va.name env with + | Some v -> Var va.name, v + | _ -> raise (Error (Printf.sprintf "unbound variable '%s'" va.name, va.pos))) + | Syntax.Call c -> + (match Env.find_opt c.func env with + | Some (Func_t (rt, at)) -> + if List.length at != List.length c.args + then + raise + (Error + ( Printf.sprintf + "expected %d arguments but given %d" + (List.length at) + (List.length c.args) + , c.pos )); + let args = + List.map2 + (fun eat a -> + let aa, at = analyze_expr a env in + if at = eat then aa else errt eat at (expr_pos a)) + at + c.args + in + Call (c.func, args), rt + | Some _ -> raise (Error (Printf.sprintf "'%s' is not a function" c.func, c.pos)) + | None -> raise (Error (Printf.sprintf "undefined function '%s'" c.func, c.pos))) +;; + +let rec analyze_instr instr env = + match instr with + | Syntax.Assign a -> + let t = + match Env.find_opt a.var env with + | Some ty -> ty + | _ -> raise (Error (Printf.sprintf "undeclared variable '%s'" a.var, a.pos)) + in + let ae, et = analyze_expr a.expr env in + if t = et + then Assign (a.var, ae), Env.add a.var et env + else + raise + (Error + ( Printf.sprintf + "changing type of variable '%s' %s -> %s" + a.var + (string_of_type_t t) + (string_of_type_t et) + , a.pos )) + | Syntax.Decl d -> + if Env.mem d.var env + then raise (Error (Printf.sprintf "redefinition of '%s'" d.var, d.pos)) + else Decl d.var, Env.add d.var d.typ env + | Syntax.Expr e -> + let ae, t = analyze_expr e.expr env in + Expr ae, env + | Syntax.Return r -> + let ae, _ = analyze_expr r.expr env in + Return ae, env + | Syntax.Cond c -> + let ae, et = analyze_expr c.expr env in + if et <> Int_t && et <> Bool_t + then raise (Error (Printf.sprintf "not a boolean expression", c.pos)) + else ( + let abt, nenv = analyze_block c.blockt env in + let abf, new_env = analyze_block c.blockf nenv in + Cond (ae, abt, abf), new_env) + | Syntax.Loop l -> + let ae, et = analyze_expr l.expr env in + if et <> Int_t && et <> Bool_t + then raise (Error (Printf.sprintf "not a boolean expression", l.pos)) + else ( + let ab, nenv = analyze_block l.block env in + Loop (ae, ab), nenv) + +and analyze_block block env = + match block with + | [] -> [], env + | instr :: rest -> + let ai, new_env = analyze_instr instr env in + let ab, nenv = analyze_block rest new_env in + ai :: ab, nenv +;; + +let rec add_arg_env args env = + match args with + | [] -> env + | (ty, arg) :: rest -> add_arg_env rest (Env.add arg ty env) +;; + +let rec analyze_def def env = + match def with + | Syntax.Func f -> + if Env.mem f.name env + then raise (Error (Printf.sprintf "redefinition of function '%s'" f.name, f.pos)) + else ( + let at, args = List.split f.args in + let nenv = add_arg_env f.args (Env.add f.name (Func_t (f.typ, at)) env) in + let b, new_env = analyze_block f.block nenv in + Func (f.name, args, b), Env.add f.name (Func_t (f.typ, at)) env) +;; + +let print_env key v = print_endline (key ^ " " ^ string_of_type_t v) + +let rec analyze_prog defs env = + match defs with + | [] -> [], env + | def :: rest -> + let ad, new_env = analyze_def def env in + let ap, nenv = analyze_prog rest new_env in + ad :: ap, nenv +;; + +let analyze parsed = + let a, env = analyze_prog parsed Baselib._baselib_ in + (* Env.iter print_env env; *) + (* print_endline ("a" ^ " " ^ (string_of_type_t (Env.find "a" env))); *) + a +;; diff --git a/simplifier.ml b/simplifier.ml new file mode 100644 index 0000000..c22526b --- /dev/null +++ b/simplifier.ml @@ -0,0 +1,77 @@ +open Ast +module Env = Map.Make (String) + +let collect_constant_strings code = + let counter = ref 0 in + let env = ref Env.empty in + let rec ccs_expr = function + | IR.Void -> IR2.Value (IR2.Nil), [] + | IR.Bool b -> IR2.Value (IR2.Bool b), [] + | IR.Int n -> IR2.Value (IR2.Int n), [] + | IR.Char c -> IR2.Value (IR2.Char c), [] + | IR.Float f -> IR2.Value (IR2.Float f), [] + | IR.Str s -> + (match Env.find_opt s !env with + | Some l -> IR2.Value (IR2.Data l), [] + | None -> + incr counter; + let l = "str" ^ string_of_int !counter in + env := Env.add s l !env; + IR2.Value (IR2.Data l), [ l, s ]) + | IR.Var v -> IR2.Var v, [] + | IR.Call (f, args) -> + let args2 = List.map ccs_expr args in + let ccs = List.flatten (List.map (fun (_, s) -> s) args2) in + IR2.Call (f, List.map (fun (e, _) -> e) args2), ccs + in + (* let ccs_lvalue = function *) + (* | IR.LVar v -> *) + (* IR2.LVar v, [] *) + (* | IR.LAddr a -> *) + (* let a2, ccs = ccs_expr a in *) + (* IR2.LAddr a2, ccs *) + (* in *) + let rec ccs_instr = function + | IR.Decl v -> IR2.Decl v, [] + | IR.Return e -> + let e2, ccs = ccs_expr e in + IR2.Return e2, ccs + | IR.Expr e -> + let e2, ccs = ccs_expr e in + IR2.Expr e2, ccs + | IR.Assign (lv, e) -> + let lv2, ccs_lv = ccs_expr (IR.Var lv) in + let e2, ccs_e = ccs_expr e in + IR2.Assign (lv2, e2), List.flatten [ ccs_lv; ccs_e ] + | IR.Cond (t, y, n) -> + let t2, ccs_t = ccs_expr t in + let y2, ccs_y = ccs_block y in + let n2, ccs_n = ccs_block n in + IR2.Cond (t2, y2, n2), List.flatten [ ccs_t; ccs_y; ccs_n ] + | IR.Loop (e, b) -> + let e2, ccs_e = ccs_expr e in + let b2, ccs_b = ccs_block b in + IR2.Loop (e2, b2), List.flatten [ ccs_e; ccs_b ] + and ccs_block = function + | [] -> [], [] + | i :: r -> + let i2, ccs_i = ccs_instr i in + let r2, ccs_r = ccs_block r in + i2 :: r2, List.flatten [ ccs_i; ccs_r ] + in + let ccs_def = function + | IR.Func (name, args, body) -> + let body2, ccs = ccs_block body in + IR2.Func (name, args, body2), ccs + in + let rec ccs_prog = function + | [] -> [], [] + | d :: r -> + let d2, ccs_d = ccs_def d in + let r2, ccs_r = ccs_prog r in + d2 :: r2, List.flatten [ ccs_d; ccs_r ] + in + ccs_prog code +;; + +let simplify code = collect_constant_strings code diff --git a/t.s b/t.s new file mode 100644 index 0000000..e69de29 diff --git a/test.ml b/test.ml new file mode 100644 index 0000000..fdcbf47 --- /dev/null +++ b/test.ml @@ -0,0 +1,39 @@ +(* ocamlbuild -use-menhir test.byte *) + +open Lexing +open Ast +open Ast.IR + +let err msg pos = + Printf.eprintf + "Error on line %d col %d: %s.\n" + pos.pos_lnum + (pos.pos_cnum - pos.pos_bol) + msg; + exit 1 +;; + +let () = + if Array.length Sys.argv != 2 + then ( + Printf.eprintf "Usage: %s \n" Sys.argv.(0); + exit 1); + let f = open_in Sys.argv.(1) in + let buf = Lexing.from_channel f in + try + let parsed = Parser.prog Lexer.token buf in + close_in f; + let ast = Semantics.analyze parsed in + let simplified = Simplifier.simplify ast in + (* print_endline (IR.string_of_ir ast); *) + let compiled = Compiler.compile simplified in + Mips.print_asm Stdlib.stdout compiled + (* print_endline (IR.string_of_ir ast) *) + with + | Match_failure (m, _, _) -> Printf.eprintf "Vous devez compléter le module %s.\n" m + | Lexer.Error c -> + err (Printf.sprintf "unrecognized char '%c'" c) (Lexing.lexeme_start_p buf) + | Parser.Error -> err "syntax error" (Lexing.lexeme_start_p buf) + | Semantics.Error (msg, pos) -> err msg pos + | _ -> failwith "WTF?" +;; diff --git a/tests/0.test b/tests/0.test new file mode 100644 index 0000000..67cf767 --- /dev/null +++ b/tests/0.test @@ -0,0 +1,2 @@ +1312 +# fichier vide diff --git a/tests/1.test b/tests/1.test new file mode 100644 index 0000000..38c48a9 --- /dev/null +++ b/tests/1.test @@ -0,0 +1 @@ +return 1312; diff --git a/tests/10.test b/tests/10.test new file mode 100644 index 0000000..5fc1077 --- /dev/null +++ b/tests/10.test @@ -0,0 +1,7 @@ +char a = 'A'; +a = 'B'; +char b; +b = 'a'; +/* b = 1; // it should fail */ +int c = 1 + 10; +return a; diff --git a/tests/11.test b/tests/11.test new file mode 100644 index 0000000..8d1484b --- /dev/null +++ b/tests/11.test @@ -0,0 +1,11 @@ +int main(int argc, char argv) +{ + int c = 1; + return 0; +} + +int add(int a, int b) +{ + /* int d = c; // should fail */ + return a + b; +} diff --git a/tests/12.test b/tests/12.test new file mode 100644 index 0000000..7493816 --- /dev/null +++ b/tests/12.test @@ -0,0 +1,10 @@ +int add(int a, int b) +{ + return a + b; +} + +int main() +{ + int a = 12; + return a; +} diff --git a/tests/13.test b/tests/13.test new file mode 100644 index 0000000..5099df4 --- /dev/null +++ b/tests/13.test @@ -0,0 +1,11 @@ +int add(int a, int b) +{ + return a + b; +} + +int main() +{ + int a; // test of scope + + return 0; +} diff --git a/tests/14.test b/tests/14.test new file mode 100644 index 0000000..0997c0e --- /dev/null +++ b/tests/14.test @@ -0,0 +1,15 @@ +int foo(int a, int b) +{ + return a + b; +} + +int main() +{ + int a = 1; + int b = 2; + foo(a, b); + int c = foo(a,b); + bool f = true; + + return 0; +} diff --git a/tests/15.test b/tests/15.test new file mode 100644 index 0000000..6a5b8d0 --- /dev/null +++ b/tests/15.test @@ -0,0 +1,12 @@ +int foo(int a, int b) +{ + return a + b; +} + +int main() +{ + int a = geti(); + int b = geti(); + puti(foo(a, b)); + return 0; +} diff --git a/tests/16.test b/tests/16.test new file mode 100644 index 0000000..fbf2253 --- /dev/null +++ b/tests/16.test @@ -0,0 +1,13 @@ +int add_int(int a, int b) +{ + return a + b; +} + +int main() +{ + int a = 2; + int b = 2; + + puti(a + 5 * b); + return 0; +} diff --git a/tests/17.test b/tests/17.test new file mode 100644 index 0000000..563b94d --- /dev/null +++ b/tests/17.test @@ -0,0 +1,12 @@ +int main() +{ + int a = 3; + int b = 4; + if (a == b) { + puts("true"); + } else { + puts("false"); + } + + return 0; +} diff --git a/tests/18.test b/tests/18.test new file mode 100644 index 0000000..690f8e4 --- /dev/null +++ b/tests/18.test @@ -0,0 +1,24 @@ +int main() +{ + int b = 5; + char a = 'a'; + bool c = true; + float fp = 123.123; + while (c) { + b = b - 1; + puti(b); + puts("\n"); + if (b <= 0) { + c = false; + } else if (b == 1) { + puts("elif1\n"); + } else if (b == 2) { + puts("elif2\n"); + } else if (b == 3) { + puts("elif3\n"); + } + } + puts("false\n"); + + return 0; +} diff --git a/tests/19.test b/tests/19.test new file mode 100644 index 0000000..d9596f0 --- /dev/null +++ b/tests/19.test @@ -0,0 +1,12 @@ +int main() +{ + int a = -1; + if (1) { + puts("yep\n"); + puti(-(a + 1)); + puts("\n"); + } + puti(!0); + + return 0; +} diff --git a/tests/2.test b/tests/2.test new file mode 100644 index 0000000..023bbf2 --- /dev/null +++ b/tests/2.test @@ -0,0 +1 @@ +return 21 * 2; diff --git a/tests/20.test b/tests/20.test new file mode 100644 index 0000000..f8e00a0 --- /dev/null +++ b/tests/20.test @@ -0,0 +1,10 @@ +int main() +{ + if (!1) { + puts("1\n"); + } + if (!0) { + puts("2\n"); + } + return 0; +} diff --git a/tests/3.test b/tests/3.test new file mode 100644 index 0000000..3147961 --- /dev/null +++ b/tests/3.test @@ -0,0 +1 @@ +x = 42; diff --git a/tests/4.test b/tests/4.test new file mode 100644 index 0000000..59b8556 --- /dev/null +++ b/tests/4.test @@ -0,0 +1,7 @@ +x = -42; +/*rsiaters +iaresnies +arisetn +airsetn +*/ +return x; diff --git a/tests/5.test b/tests/5.test new file mode 100644 index 0000000..e85e97e --- /dev/null +++ b/tests/5.test @@ -0,0 +1,3 @@ +x = 500 + 150 + 6; +y = x * 2; +return y; diff --git a/tests/6.test b/tests/6.test new file mode 100644 index 0000000..de2e04d --- /dev/null +++ b/tests/6.test @@ -0,0 +1,3 @@ +x = 2 * (2 + 6) + 2; +y = x * 2; +return y; diff --git a/tests/7.test b/tests/7.test new file mode 100644 index 0000000..cccba69 --- /dev/null +++ b/tests/7.test @@ -0,0 +1,3 @@ +x = 2.0 * (2.2 + 6.1) + 2.1; +#y = x * 2; +return x; diff --git a/tests/8.test b/tests/8.test new file mode 100644 index 0000000..8c8032b --- /dev/null +++ b/tests/8.test @@ -0,0 +1,3 @@ +x = 'A'; +x = '\''; +return x; diff --git a/tests/9.test b/tests/9.test new file mode 100644 index 0000000..003f308 --- /dev/null +++ b/tests/9.test @@ -0,0 +1,3 @@ +a = "Hello, world!"; +b = ""; +return a; diff --git a/tests/game.test b/tests/game.test new file mode 100644 index 0000000..6c462b7 --- /dev/null +++ b/tests/game.test @@ -0,0 +1,23 @@ +// NOTE: DO NOT TEST WITH build.sh because geti (input) +void guessing_game(int n) +{ + int x = 4; // no syscall for rand in spim -_- + int res = -1; + while (res != x) { + puts("Guess the number\n"); + res = geti(); + if (res < x) { + puts("Too little\n"); + } else if (res > x) { + puts("Too big\n"); + } + } + puts("Bravo, you guessed!\n"); +} + +int main() +{ + puts("Hello, enter a max for guessing game\n"); + guessing_game(10); + return 0; +} diff --git a/tests/newt.test b/tests/newt.test new file mode 100644 index 0000000..821b745 --- /dev/null +++ b/tests/newt.test @@ -0,0 +1,18 @@ +int fact(int n) +{ + int result; + if (n == 0) { + result = 1; + } else { + result = n * fact((n - 1)); + } + return result; +} + +int main() +{ + puts("\n"); + puti(fact(12)); + puts("\n"); + return 0; +} diff --git a/tests/puiss.test b/tests/puiss.test new file mode 100644 index 0000000..51c9508 --- /dev/null +++ b/tests/puiss.test @@ -0,0 +1,23 @@ +int puiss(int n, int x) +{ + int res = 1; + if (n == 0) { + return res; + } + if (n == 1) { + return x; + } + while (n > 0) { + res = res * x; + n = n - 1; + } + return res; +} + +int main() +{ + int x = 3; + int n = 5; + puti(puiss(x,n)); // 3 ^ 5 + return 0; +} diff --git a/tests/tmp.test b/tests/tmp.test new file mode 100644 index 0000000..abdab5d --- /dev/null +++ b/tests/tmp.test @@ -0,0 +1,7 @@ +int main() +{ + if (1) { + puts("Hello, world!"); + } + return 0; +}