This commit is contained in:
Dmitry Boulytchev 2020-02-16 01:21:27 +03:00
parent 61296c51e7
commit 3b9fac8e9a
3 changed files with 43 additions and 15 deletions

2
.gitignore vendored
View file

@ -2,3 +2,5 @@
*.cmi *.cmi
*.cmx *.cmx
*.o *.o
version.ml

View file

@ -41,16 +41,32 @@ class options args =
let rec fix f = f (fix f) in let rec fix f = f (fix f) in
let dump_ast = 1 in let dump_ast = 1 in
let dump_sm = 2 in let dump_sm = 2 in
let help_string =
"Lama compiler. (C) JetBrains Reserach, 2017-2020.\n" ^
"Usage: lamac <options> <input file>\n\n" ^
"When no options specified, builds the source file into executable.\n" ^
"Options:\n" ^
" -c --- compile into object file\n" ^
" -I <path> --- add <path> into unit search path list\n" ^
" -i --- interpret on a source-level interpreter\n" ^
" -s --- compile into stack machine code and interpret on the stack machine initerpreter\n" ^
" -dp --- dump AST (the output will be written into .ast file)\n" ^
" -ds --- dump stack machine code (the output will be written into .sm file; has no\n" ^
" effect if -i option is specfied)\n" ^
" -v --- show version\n" ^
" -h --- show this help\n"
in
object (self) object (self)
val i = ref 1 val version = ref false
val infile = ref (None : string option) val help = ref false
val paths = ref [X86.get_std_path ()] val i = ref 1
val mode = ref (`Default : [`Default | `Eval | `SM | `Compile ]) val infile = ref (None : string option)
val paths = ref [X86.get_std_path ()]
val mode = ref (`Default : [`Default | `Eval | `SM | `Compile ])
(* Workaround until Ostap starts to memoize properly *) (* Workaround until Ostap starts to memoize properly *)
val const = ref false val const = ref false
(* end of the workaround *) (* end of the workaround *)
val dump = ref 0 val dump = ref 0
val help = ref false
initializer initializer
let rec loop () = let rec loop () =
match self#peek with match self#peek with
@ -60,15 +76,16 @@ class options args =
| "-w" -> self#set_workaround | "-w" -> self#set_workaround
(* end of the workaround *) (* end of the workaround *)
| "-c" -> self#set_mode `Compile | "-c" -> self#set_mode `Compile
| "-I" -> (match self#peek with None -> raise (Commandline_error "path expected after '-I' specifier") | Some path -> self#add_include_path path) | "-I" -> (match self#peek with None -> raise (Commandline_error "Path expected after '-I' specifier") | Some path -> self#add_include_path path)
| "-s" -> self#set_mode `SM | "-s" -> self#set_mode `SM
| "-i" -> self#set_mode `Eval | "-i" -> self#set_mode `Eval
| "-ds" -> self#set_dump dump_sm | "-ds" -> self#set_dump dump_sm
| "-dp" -> self#set_dump dump_ast | "-dp" -> self#set_dump dump_ast
| "-h" -> self#set_help | "-h" -> self#set_help
| "-v" -> self#set_version
| _ -> | _ ->
if opt.[0] = '-' if opt.[0] = '-'
then raise (Commandline_error (Printf.sprintf "invalid command line specifier ('%s')" opt)) then raise (Commandline_error (Printf.sprintf "Invalid command line specifier ('%s')" opt))
else self#set_infile opt else self#set_infile opt
); );
loop () loop ()
@ -79,28 +96,29 @@ class options args =
method private set_workaround = method private set_workaround =
const := true const := true
(* end of the workaround *) (* end of the workaround *)
method private set_help = help := true
method private set_version = version := true
method private set_dump mask = method private set_dump mask =
dump := !dump lor mask dump := !dump lor mask
method private set_infile name = method private set_infile name =
match !infile with match !infile with
| None -> infile := Some name | None -> infile := Some name
| Some name' -> raise (Commandline_error (Printf.sprintf "input file ('%s') already specified" name')) | Some name' -> raise (Commandline_error (Printf.sprintf "Input file ('%s') already specified" name'))
method private add_include_path path = method private add_include_path path =
paths := path :: !paths paths := path :: !paths
method private set_mode s = method private set_mode s =
match !mode with match !mode with
| `Default -> mode := s | `Default -> mode := s
| _ -> raise (Commandline_error "extra compilation mode specifier") | _ -> raise (Commandline_error "Extra compilation mode specifier")
method private peek = method private peek =
let j = !i in let j = !i in
if j < n if j < n
then (incr i; Some (args.(j))) then (incr i; Some (args.(j)))
else None else None
method private set_help = help := true
method get_mode = !mode method get_mode = !mode
method get_infile = method get_infile =
match !infile with match !infile with
| None -> raise (Commandline_error "input file not specified") | None -> raise (Commandline_error "Input file not specified")
| Some name -> name | Some name -> name
method get_help = !help method get_help = !help
method get_include_paths = !paths method get_include_paths = !paths
@ -122,11 +140,15 @@ class options args =
if (!dump land dump_sm) > 0 if (!dump land dump_sm) > 0
then self#dump_file "sm" (SM.show_prg sm) then self#dump_file "sm" (SM.show_prg sm)
else () else ()
method greet =
if !version then Printf.printf "%s\n" Version.version;
if !help then Printf.printf "%s" help_string
end end
let main = let main =
try try
let cmd = new options Sys.argv in let cmd = new options Sys.argv in
cmd#greet;
match (try parse cmd with Language.Semantic_error msg -> `Fail msg) with match (try parse cmd with Language.Semantic_error msg -> `Fail msg) with
| `Ok prog -> | `Ok prog ->
cmd#dump_AST (snd prog); cmd#dump_AST (snd prog);
@ -150,5 +172,6 @@ let main =
List.iter (fun i -> Printf.printf "%d\n" i) output List.iter (fun i -> Printf.printf "%d\n" i) output
) )
| `Fail er -> Printf.eprintf "Error: %s\n" er | `Fail er -> Printf.eprintf "Error: %s\n" er
with Language.Semantic_error msg -> Printf.printf "Error: %s\n" msg with
| Language.Semantic_error msg -> Printf.printf "Error: %s\n" msg
| Commandline_error msg -> Printf.printf "%s\n" msg

View file

@ -2,13 +2,16 @@ TOPFILE = lamac
OCAMLC = ocamlfind c OCAMLC = ocamlfind c
OCAMLOPT = ocamlfind opt OCAMLOPT = ocamlfind opt
OCAMLDEP = ocamlfind dep OCAMLDEP = ocamlfind dep
SOURCES = Language.ml SM.ml X86.ml Driver.ml SOURCES = Language.ml SM.ml X86.ml version.ml Driver.ml
CAMLP5 = -syntax camlp5o -package ostap.syntax,GT.syntax.all CAMLP5 = -syntax camlp5o -package ostap.syntax,GT.syntax.all
PXFLAGS = $(CAMLP5) PXFLAGS = $(CAMLP5)
BFLAGS = -rectypes -g BFLAGS = -rectypes -g
OFLAGS = $(BFLAGS) OFLAGS = $(BFLAGS)
all: .depend $(TOPFILE) all: version .depend $(TOPFILE)
version:
echo "let version = \"Version `git rev-parse --abbrev-ref HEAD`, `git rev-parse --short HEAD`, `git rev-parse --verify HEAD |git show --no-patch --no-notes --pretty='%cd'`\"" > version.ml
.depend: $(SOURCES) .depend: $(SOURCES)
$(OCAMLDEP) $(PXFLAGS) *.ml > .depend $(OCAMLDEP) $(PXFLAGS) *.ml > .depend