open Utils
+(* See also "let id" in [lexer.mll]. *)
+let var_regexp = Str.regexp "\\([a-zA-Z_][a-zA-Z0-9_]*\\)=\\(.*\\)"
+
let usage =
"\
goals: Build software.
- goals [-f Goalfile] ['var = value' ...] ['target' ...]
+ goals [-f Goalfile] ['var=value' ...] ['target' ...]
For detailed help see goals(1).
(* Parse the input file. *)
let file = Parse.parse_goalfile filename in
- Ast.print_file stdout file;
-
- (* Find the target(s) to execute first. *)
- let initial_targets = ref [] in
- (* XXX Parse command line anon args here. XXX *)
+ (* Parse the command line anon args. Each parameter has the
+ * form "name=<expr>" to assign a value to a variable, or
+ * "<expr>" to indicate a target to build.
+ *)
+ let assignments = ref [] in
+ let targets = ref [] in
+ List.iter (
+ fun arg ->
+ if Str.string_match var_regexp arg 0 then ( (* assignment *)
+ let name = Str.matched_group 1 arg in
+ let expr = Parse.parse_cli_expr (Str.matched_group 2 arg) in
+ assignments := Ast.Let (name, expr) :: !assignments
+ )
+ else ( (* target *)
+ let expr = Parse.parse_cli_expr arg in
+ targets := expr :: !targets
+ )
+ ) !args;
- (* If no initial target set on the command line, find
+ (* If no target was set on the command line, find
* the first goal in the file.
*)
- List.iter (
- function
- | Ast.Goal (name, [], _, _, _) ->
- if !initial_targets = [] then
- initial_targets := Ast.ECall (name, []) :: !initial_targets
- | Ast.Goal (name, _, _, _, _) ->
- if !initial_targets = [] then
+ if !targets = [] then (
+ try
+ let first_goal =
+ List.find (function Ast.Goal _ -> true | _ -> false) file in
+ match first_goal with
+ | Ast.Goal (name, [], _, _, _) ->
+ targets := [Ast.ECall (name, [])]
+ | Ast.Goal (name, _, _, _, _) ->
failwithf "%s: first target ā%sā has parameters and so cannot be used as the default target"
filename name
- | _ -> ()
- ) file;
+ | _ -> assert false
+ with
+ (* Actually this is fine. If there are no goals we'll do nothing. *)
+ Not_found -> ()
+ );
+
+ let targets = List.rev !targets in
+
+ (* Assignments are simply treated as statements added to the end of
+ * the file (so they override earlier assignments to the same variable,
+ * if any).
+ *)
+ let file = file @ List.rev !assignments in
+
+ (* We start with an empty symbol table. *)
+ let vars = Hashtbl.create 13 in
- let initial_targets = List.rev !initial_targets in
- ignore initial_targets
+ (* Evaluate the target expressions in turn. *)
+ Eval.evaluate file vars targets
let () = main ()