This repository has been archived by the owner on Feb 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathkittylang.ml
171 lines (149 loc) · 4.38 KB
/
kittylang.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
(**
* ccmain.ml
* Part of Micro-JavaScript Compiler
*
* 3I018 Compilation
* Université Pierre et Marie Curie
*
*)
open Cmdliner
(*
type verbosity =
| Verbose
| Quiet
let string_of_verbosity = function
| Verbose -> "verbose"
| Quiet -> "quiet"
*)
let string_of_position lexbuf =
let open Lexing in
let pos = lexbuf.lex_curr_p in
Printf.sprintf "file: %s; line: %d; column: %d" pos.pos_fname
pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1)
let parse_with_error lexbuf =
try
let ast = Parser.program Lexer.read lexbuf in
match ast with
| Some prog -> `Ok prog
| None -> assert false (* Should not appear? *)
with
| Lexer.SyntaxError msg ->
`Error (string_of_position lexbuf, "SyntaxError")
| Parser.Error ->
`Error (string_of_position lexbuf, "ParserError")
let parse_file filename =
let in_file = Pervasives.open_in filename in
let lexbuf = Lexing.from_channel in_file in
Lexing.(lexbuf.lex_curr_p <- {
lexbuf.lex_curr_p with pos_fname = filename
});
let prog = parse_with_error lexbuf in
Pervasives.close_in in_file;
prog
(* `Ok ({ prog with Ast.filename = filename }) *)
let write_target filename code =
let out_file = Pervasives.open_out filename in
List.iter (fun s -> Pervasives.output_string out_file s) code;
Pervasives.close_out out_file
(*
let compile_prog prog =
Expander.expand_prog prog
|> Compiler.compile_prog (Prim.init_prim_env ())
*)
let result_string = Printf.sprintf
"\n===========================\n%s\n===========================\n"
let select_action parse compile expand =
if parse then
(fun prog ->
Ast.string_of_program prog
|> result_string
|> Printf.sprintf "Parsed program:%s")
else if expand then
failwith "-expand Not implemented"
(*
(fun prog ->
Expander.expand_prog prog
|> Kast.string_of_kprogram
|> result_string
|> P.sprintf "Kernal Abstract Syntax Tree:%s")
*)
else if compile then
failwith "-compile Not implemented"
(*
(fun prog ->
compile_prog prog
|> Bytecode.string_of_bytecode
|> result_string
|> P.sprintf "Bytecode:%s")
*)
else
failwith "Writing to file not implemented!"
(* (fun prog ->
expand_prog prog
|> compile_prog (init_prim_env ())
|> write_target filename)
*)
(**
* Command line Interface and Entry Point
*)
let cmicrojs parse expand compile filename =
let prog = parse_file filename in
match prog with
| `Ok prog ->
if (parse <> compile <> expand) then
let action = select_action parse compile expand in
`Ok (Printf.printf "%s" (action prog))
else
`Error (false, "Compile to bytecode not implemented.")
(* `Ok (compile_prog prog) *)
| `Error (where', msg) ->
`Error (false, Printf.sprintf "%s: at %s" msg where')
let file =
Arg.(required
& pos ~rev:true 0 (some string) None
& info [] ~docv:"SOURCE"
~doc:"Micro-JavaScript file(s) to process.")
let parse =
Arg.(value & flag & info ["p"; "parse"]
~docv:"PARSE"
~doc:"Parse and show parsed program." )
let expand =
Arg.(value & flag & info ["e"; "expand"]
~docv:"EXPAND"
~doc:"Parse, expand and show kernel abstract syntax tree")
let compile =
Arg.(value & flag & info ["c"; "compile"]
~docv:"COMPILE"
~doc:"Parse, compile and show the compiled code")
let run =
Arg.(value & flag & info ["r"; "run"]
~docv:"RUNNING"
~doc:"Compile and run program (debug mode)")
let generate =
Arg.(value & flag & info ["g"; "gen"]
~docv:"GENERATE"
~doc:"Compile and generate target (default mode)")
let dot_graph =
Arg.(value & flag & info ["astDot"]
~docv:"GENERATE"
~doc:"Compile and generate target (default mode)")
let verbosity =
let verbose =
Arg.info ["v"; "verbose"]
~doc:"Output full process on stdout" in
Arg.(value & flag & verbose)
let cmd =
(Term.(Term.ret(const cmicrojs $ parse $ expand $ compile $ file))
, Term.info "cmicrojs"
~version:"0.0.1"
~doc:"Microjs compiler in Ocaml"
~man:
[ `S "DESCRIPTION"
; `P "$(tname) is a compiler of Micro-Javascript language to\
NativeVM bytecode."
; `P "BUGS: Report bugs to <frederic dot pechansky at lip6 dot fr>."])
(* See cmicrojs for real entry point *)
let () =
match Term.eval cmd with
| `Error _ -> exit 1
| _ -> exit 0