Compleating assignment for interpreter, modified grammars, fixed tests

This commit is contained in:
elvis
2024-11-16 15:40:00 +01:00
parent 40055899c9
commit 9e599cc018
24 changed files with 593 additions and 1238 deletions

View File

@ -8,3 +8,21 @@
(package miniFun)
(modes byte exe)
)
(executable
(name miniFunInterpreter)
(public_name miniFunInterpreter)
(libraries miniFun
clap)
(package miniFun)
(modes byte exe)
)
(executable
(name miniImpInterpreter)
(public_name miniImpInterpreter)
(libraries miniImp
clap)
(package miniImp)
(modes byte exe)
)

View File

@ -0,0 +1,15 @@
lambda n: int -> int =>
let fib = lambda f : (int -> int) -> int -> int =>
\ n : int -> int =>
if n == 0 then 0
else if n == 1 then 1
else f (n - 1) + f (n - 2)
in
let rec fix f : ((int -> int) -> int -> int) -> int -> int =
\ x : int -> int =>
f (fix f) x
in
fix fib n

25
bin/miller-rabin.miniimp Normal file
View File

@ -0,0 +1,25 @@
def main with input n output result as
if (n % 2) == 0 then result := 1
else (
result := 0;
s := 0;
while (0 == ((n - 1) / (2 ^ s)) % 2) do (
s := s + 1
);
d := ((n - 1) / 2 ^ s);
for (i := 20, i > 0, i := i - 1) do (
a := rand(n - 4) + 2;
x := powmod(a, d, n);
for (j := 0, j < s, j := j+1) do (
y := powmod(x, 2, n);
if (y == 1 && (not x == 1) && (not x == n - 1)) then
result := 1;
else
skip;
x := y;
);
if not y == 1 then result := 1;
else skip;
)
)

100
bin/miniFunInterpreter.ml Normal file
View File

@ -0,0 +1,100 @@
open MiniFun
open Lexing
(* -------------------------------------------------------------------------- *)
(* Command Arguments *)
let () =
Clap.description "Interpreter for MiniFun language.";
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 inputval = Clap.optional_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'
()
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 (inval: 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 _ =
match TypeChecker.typecheck program with
| Ok _ -> ()
| Error (`AbsentAssignment msg)
| Error (`WrongTypeSpecification msg)
| Error (`WrongType msg) ->
Printf.fprintf stderr "%s\n" msg;
exit (-1)
in
let return_value =
match Semantics.reduce program inval with
Ok o -> o
| Error (`AbsentAssignment msg)
| Error (`DivisionByZero msg)
| Error (`WrongType msg) ->
Printf.fprintf stderr "%s\n" msg;
exit (-1)
in
Printf.fprintf outch "%d\n" return_value
in
let inx = In_channel.open_text input in
let outx = match output with
None -> stdout
| Some f -> Out_channel.open_text f
in
let inputval = match inputval with
None -> (
Printf.fprintf stdout "Provide the input: ";
read_int ()
)
| Some o -> o
in
interpret_file inx inputval outx;

91
bin/miniImpInterpreter.ml Normal file
View File

@ -0,0 +1,91 @@
open MiniImp
open Lexing
(* -------------------------------------------------------------------------- *)
(* Command Arguments *)
let () =
Clap.description "Interpreter for MiniImp language.";
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 inputval = Clap.optional_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'
()
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 (inval: 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 =
match Semantics.reduce program inval with
Ok o -> o
| Error (`AbsentAssignment msg)
| Error (`DivisionByZero msg)
| Error (`WrongType msg) ->
Printf.fprintf stderr "%s\n" msg;
exit (-1)
in
Printf.fprintf outch "%d\n" return_value
in
let inx = In_channel.open_text input in
let outx = match output with
None -> stdout
| Some f -> Out_channel.open_text f
in
let inputval = match inputval with
None -> (
Printf.fprintf stdout "Provide the input: ";
read_int ()
)
| Some o -> o
in
interpret_file inx inputval outx;

8
bin/sum.miniimp Normal file
View File

@ -0,0 +1,8 @@
def main with input in output out as
x := in;
out := 0;
while not x < 0 do (
out := out + x;
x := x - 1;
);
skip