Command line parsing of anon args.
authorRichard W.M. Jones <rjones@redhat.com>
Sun, 22 Dec 2019 18:17:06 +0000 (18:17 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Sun, 22 Dec 2019 18:17:06 +0000 (18:17 +0000)
src/Makefile.in
src/ast.mli
src/eval.ml [new file with mode: 0644]
src/eval.mli [new file with mode: 0644]
src/main.ml

index 1b838b1..d3e21fc 100644 (file)
@@ -22,6 +22,7 @@ OBJECTS = \
        parser.cmx \
        lexer.cmx \
        parse.cmx \
+       eval.cmx \
        main.cmx
 
 all: goals
@@ -32,17 +33,18 @@ clean:
        rm -f parser.ml parser.mli lexer.ml parser.conflicts stamp-parser
        rm -f goals
 
-goals: $(OBJECTS)
-       @OCAMLFIND@ opt $^ -o $@
-
+OCAMLPACKAGES = -package str,unix
 OCAMLFLAGS = -g -safe-string -warn-error CDEFLMPSUVYZX+52-3
 
+goals: $(OBJECTS)
+       @OCAMLFIND@ opt $(OCAMLFLAGS) $(OCAMLPACKAGES) -linkpkg $^ -o $@
+
 %.cmi: %.mli
-       @OCAMLFIND@ c $(OCAMLFLAGS) -c $< -o $@
+       @OCAMLFIND@ c $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
 %.cmo: %.ml
-       @OCAMLFIND@ c $(OCAMLFLAGS) -c $< -o $@
+       @OCAMLFIND@ c $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
 %.cmx: %.ml
-       @OCAMLFIND@ opt $(OCAMLFLAGS) -c $< -o $@
+       @OCAMLFIND@ opt $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
 
 parser.ml parser.mli: stamp-parser
 stamp-parser: parser.mly
index 6179fb4..e2189cf 100644 (file)
 
 type file = stmt list
 and stmt =
-  (* let id = expr *)
+  (** let id = expr *)
   | Let of id * expr
-  (* goal id (params) = patterns : exprs = code *)
+  (** goal id (params) = patterns : exprs = code *)
   | Goal of id * id list * pattern list * expr list * code option
 and pattern =
-  (* match tactic such as file ("filename") *)
+  (** match tactic such as file ("filename") *)
   | PTactic of id * substs list
-  (* match named variable, which must be a string or list *)
+  (** match named variable, which must be a string or list *)
   | PVarSubst of id
 and expr =
-  (* goalname (params), tactic (params) etc. *)
+  (** goalname (params), tactic (params) etc. *)
   | ECall of id * expr list
-  (* variable *)
+  (** variable *)
   | EVar of id
-  (* string with %-substitutions *)
+  (** string with %-substitutions *)
   | EString of substs
-  (* list *)
+  (** list *)
   | EList of expr list
 and id = string
 and code = substs
 and substs = subst list
 and subst =
-  (* String literal part. *)
+  (** String literal part. *)
   | SString of string
-  (* %-substitution. *)
+  (** %-substitution. *)
   | SVar of id
 
-(* This is used for incrementally building Ast.substs in the parser. *)
+(** This is used for incrementally building Ast.substs in the parser. *)
 module Substs : sig
   type t
   val create : unit -> t
diff --git a/src/eval.ml b/src/eval.ml
new file mode 100644 (file)
index 0000000..1df1a17
--- /dev/null
@@ -0,0 +1,21 @@
+(* Goalfile evaluation
+ * Copyright (C) 2019 Richard W.M. Jones
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+let evaluate file vars exprs =
+  ()
diff --git a/src/eval.mli b/src/eval.mli
new file mode 100644 (file)
index 0000000..2e55981
--- /dev/null
@@ -0,0 +1,22 @@
+(* Goalfile evaluation
+ * Copyright (C) 2019 Richard W.M. Jones
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+val evaluate : Ast.file -> (string, Ast.expr) Hashtbl.t -> Ast.expr list -> unit
+(** This drives evaluation of the list of expressions (in parallel)
+    until they are complete or we reach an error. *)
index be1baff..2685160 100644 (file)
@@ -21,11 +21,14 @@ open Printf
 
 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).
 
@@ -52,28 +55,56 @@ let main () =
   (* 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 ()