forked from reactorlabs/sourir
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsourir.ml
125 lines (112 loc) · 4.03 KB
/
sourir.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
open Instr
let quiet = ref false
let autofix = ref false
let opts = ref []
let path = ref ""
let () =
let cmd_args = [
("--quiet", Arg.Set quiet, "quiet");
("--autofix", Arg.Set autofix, "automatically normalize graph");
("--opt", Arg.String (fun s -> opts := String.split_on_char ',' s), "Enable optimizations");
] in
Arg.parse cmd_args (fun s ->
if !path <> "" then raise (Arg.Bad ("Invalid argument "^s));
path := s) "options";
if !path = "" then (
Printf.eprintf
"You should provide a Sourir file to parse as command-line argument.\n\
Example: %s examples/sum.sou\n%!"
Sys.executable_name;
exit 1);
let program =
try Parse.program_of_file !path
with Parse.Error error ->
Parse.report_error error;
exit 2
in
let program =
if !autofix
then Transform.try_opt Transform.normalize_graph program
else program in
opts := if !opts = ["all"] then Transform.all_opts else !opts;
begin try Check.well_formed program with
| Check.MissingMain ->
Printf.eprintf "Program is missing an explicit or implicit main function\n";
exit 1
| Check.InvalidMain ->
Printf.eprintf "Main function cannot have arguments\n";
exit 1
| Check.DuplicateFunctionDeclaration f ->
Printf.eprintf "Duplicate function declaration %s\n" f;
exit 1
| Check.DuplicateVersion (f, v) ->
Printf.eprintf "Version %s in function %s is defined twice\n" v f;
exit 1
| Check.EmptyFunction f ->
Printf.eprintf "Function %s has no body\n" f;
exit 1
| Check.DuplicateParameter (f, x) ->
Printf.eprintf "Function %s : parameter %s is given twice\n" f x;
exit 1
| Check.ErrorAt (f, v, e) ->
Printf.eprintf "Error in function %s version %s: " f v;
begin match[@warning "-4"] e with
| Check.MissingReturn ->
Printf.eprintf "missing return statement\n";
| Check.FunctionDoesNotExist f' ->
Printf.eprintf "called function %s does not exist\n" f';
| Check.VersionDoesNotExist (f', v') ->
Printf.eprintf "osr target %s %s does not exist\n" f' v';
| Check.InvalidNumArgs pc ->
Printf.eprintf "at line %d: invalid number of arguments\n" (pc+1);
| Check.InvalidArgument (pc, expression) ->
Printf.eprintf "at line %d: invalid argument\n" (pc+1);
| Instr.Unbound_label (MergeLabel l) ->
Printf.eprintf "label %s does not exist\n" l;
| Instr.Unbound_label (BranchLabel l) ->
Printf.eprintf "label $%s does not exist\n" l;
| Instr.Unbound_osr_label l ->
Printf.eprintf "osr target %s does not exist\n" l;
| Check.BranchLabelReused pc ->
Printf.eprintf "label at line %d is used more than once\n" (pc+1);
| Check.FallthroughLabel pc ->
Printf.eprintf "fallthrough label at line %d is not allowed\n" (pc+1);
| Check.EntryPointIsLabel ->
Printf.eprintf "the first instruction cannot be a label\n";
| Check.DuplicateLabel l ->
Printf.eprintf "label %s used multiple times\n" l;
| _ -> assert(false)
end;
exit 1
end;
begin try Scope.check_program program with
| Scope.ScopeExceptionAt _ as exn ->
Printf.eprintf "Scope error in the source program:\n";
Scope.report_error program exn
end;
let program = try Transform.(try_opt (optimize !opts) program) with
| Transform.UnknownOptimization opt ->
Printf.eprintf "Unknown optimization %s.\nValid optimizers are %s\n"
opt (String.concat ", " Transform.all_opts);
exit 1
in
if not !quiet then begin
Printf.printf "After optimizations\n";
Disasm.disassemble_o stdout program
end;
begin try Scope.check_program program with
| Scope.ScopeExceptionAt _ as exn ->
Printf.eprintf "Scope error in the optimized program (%s):\n"
(String.concat ", " !opts);
Scope.report_error program exn
end;
let conf = Eval.run_interactive IO.stdin_input program in
let open Eval in
match conf.status with
| Running -> assert(false)
| Result (Int n) ->
exit n
| Result (Bool b) ->
exit (if b then 1 else 0)
| Result (Fun_ref _ | Array _ | Nil) ->
exit 0