Files
lci/bin/miniImpInterpreterReg.ml

147 lines
3.9 KiB
OCaml
Raw Normal View History

2025-01-11 20:32:11 +01:00
open MiniImp
open Lexing
(* -------------------------------------------------------------------------- *)
(* Command Arguments *)
let () =
2025-01-15 00:10:44 +01:00
Clap.description "Interpreter for MiniImp language to RISC code.";
2025-01-11 20:32:11 +01:00
let files = Clap.section ~description: "Files to consider." "FILES" in
let values = Clap.section ~description: "Input values." "VALUES" in
let input = Clap.mandatory_string
~description: "Input file."
~placeholder: "FILENAME"
~section: files
~long: "input"
~short: 'i'
()
in
let registers = Clap.default_int
~description: "Optional number of registers available."
~placeholder: "INT"
~section: values
~long: "registers"
~short: 'r'
4
in
let evalb = Clap.flag
~description: "Optional flag for evaluating the generated risc code."
~section: values
~set_long: "eval"
~set_short: 'e'
false
in
2025-01-15 00:10:44 +01:00
let checkundefined = Clap.flag
2025-01-26 21:47:05 +01:00
~description: "Optional flag for disabling the check for undefined \
variables."
2025-01-15 00:10:44 +01:00
~section: values
~unset_long: "undefined"
~unset_short: 'u'
true
in
let optimizereg = Clap.flag
2025-01-26 21:47:05 +01:00
~description: "Optional flag for disabling optimizing registers with \
liveness analysis."
2025-01-15 00:10:44 +01:00
~section: values
~unset_long: "liveness"
~unset_short: 'l'
true
in
2025-01-11 20:32:11 +01:00
let inputval = Clap.default_int
~description: "Optional input value to feed to the program. \
If not specified it is read from stdin."
~placeholder: "INT"
~section: values
~long: "value"
~short: 'v'
0
in
let output = Clap.optional_string
~description: "Output file. If not specified output is printed on stdout."
~placeholder: "FILENAME"
~section: files
~long: "output"
~long_synonyms: ["out"; "result"]
~short: 'o'
()
in
Clap.close ();
(* -------------------------------------------------------------------------- *)
(* Interpreter *)
let print_position outx lexbuf =
let pos = lexbuf.lex_curr_p in
Printf.fprintf outx "Encountered \"%s\" at %s:%d:%d"
(Lexing.lexeme lexbuf) pos.pos_fname
pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1)
in
let interpret_file inch (registers: int) outch =
let lexbuf = Lexing.from_channel inch in
let program =
try Parser.prg Lexer.read lexbuf with
| Lexer.LexingError msg ->
Printf.fprintf stderr "%a: %s\n" print_position lexbuf msg;
exit (-1)
| Parser.Error ->
Printf.fprintf stderr "%a: syntax error\n" print_position lexbuf;
exit (-1)
in
let return_value =
program |>
CfgImp.convert_io inputval |>
CfgRISC.convert
in
2025-01-15 00:10:44 +01:00
if checkundefined then (
2025-01-11 20:32:11 +01:00
match DefinedVariables.compute_defined_variables return_value |>
DefinedVariables.check_undefined_variables
with
| None -> ()
| Some l ->
Printf.printf "Error: undefined variables: %a\n"
DefinedVariables.Variable.pplist l;
exit (-1)
2025-01-15 00:10:44 +01:00
) else ();
let return_value =
if optimizereg then
return_value |>
LiveVariables.compute_live_variables |>
LiveVariables.optimize_cfg |>
LiveVariables.compute_cfg
else
return_value
in
2025-01-11 20:32:11 +01:00
let return_value =
return_value |>
ReduceRegisters.reduceregisters registers |>
RISC.convert
in
2025-01-26 21:47:05 +01:00
if evalb
then Printf.fprintf outch "%d\n" (RISCSemantics.reduce return_value)
else Printf.fprintf outch "%a\n" RISC.RISCAssembly.pp return_value
2025-01-11 20:32:11 +01:00
in
let inx = In_channel.open_text input in
let outx = match output with
None -> stdout
| Some f -> Out_channel.open_text f
in
interpret_file inx registers outx;
2025-01-17 00:46:51 +01:00
Out_channel.close outx