Implement tactics.
[goals.git] / src / main.ml
1 (* Goalfile parser
2  * Copyright (C) 2019 Richard W.M. Jones
3  * Copyright (C) 2019 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *)
19
20 open Printf
21
22 open Utils
23
24 (* See also "let id" in [lexer.mll]. *)
25 let var_regexp =
26   Str.regexp "\\([a-zA-Z_][a-zA-Z0-9_]*\\)[ \t]*=[ \t]*\\(.*\\)"
27
28 let usage =
29   "\
30 goals: Build software.
31
32  goals [-f Goalfile] ['var=value' ...] ['target' ...]
33
34 For detailed help see goals(1).
35
36 Options:"
37
38 let main () =
39   (* Command line arguments. *)
40   let args = ref [] in
41   let directory = ref "." in
42   let filename = ref "Goalfile" in
43
44   let argspec = [
45     "-C",          Arg.Set_string directory,
46                    "directory Change to directory before running";
47     "--directory", Arg.Set_string directory,
48                    "directory Change to directory before running";
49     "-f",          Arg.Set_string filename,
50                    "filename Set name of Goalfile";
51     "--file",      Arg.Set_string filename,
52                    "filename Set name of Goalfile";
53   ] in
54   let argspec = Arg.align argspec in
55   let anon_fun s = args := s :: !args in
56   Arg.parse argspec anon_fun usage;
57
58   let args = List.rev !args in
59   let directory = !directory in
60   let filename = !filename in
61
62   (* Parse the input file. *)
63   let env = Parse.parse_goalfile filename in
64
65   (* Now we've read the input, change directory. *)
66   Sys.chdir directory;
67
68   (* Parse the command line anon args.  Each parameter has the
69    * form "name=<expr>" to assign a value to a variable, or
70    * "<expr>" to indicate a target to build.
71    *)
72   let targets = ref [] in
73   let env = ref env in
74   List.iter (
75     fun arg ->
76       if Str.string_match var_regexp arg 0 then (
77         (* assignment *)
78         let name = Str.matched_group 1 arg in
79         let expr = Parse.parse_cli_expr (Str.matched_group 2 arg) in
80         env := Ast.Env.add name expr !env
81       )
82       else (
83         (* target *)
84         let expr = Parse.parse_cli_expr arg in
85         targets := expr :: !targets
86       )
87   ) args;
88   let targets = List.rev !targets and env = !env in
89
90   (* If no target was set on the command line, use "all ()". *)
91   let targets =
92     if targets <> [] then targets
93     else [Ast.ECallGoal (Ast.noloc, "all", [])] in
94
95   Ast.print_env stderr env;
96
97   (* Evaluate the target expressions in turn. *)
98   Eval.evaluate_targets env targets
99
100 let () =
101   try main ()
102   with
103     Failure msg -> prerr_endline msg; exit 1