the example Paintit package works
authorThomas Walker Lynch <xtujpz@reasoningtechnology.com>
Fri, 11 Oct 2024 01:32:18 +0000 (01:32 +0000)
committerThomas Walker Lynch <xtujpz@reasoningtechnology.com>
Fri, 11 Oct 2024 01:32:18 +0000 (01:32 +0000)
45 files changed:
developer/javac/AriadneGraph.java [deleted file]
developer/javac/Black.java [new file with mode: 0644]
developer/javac/Blue.java [new file with mode: 0644]
developer/javac/Graph.java [new file with mode: 0644]
developer/javac/Green.java [new file with mode: 0644]
developer/javac/PaintItBlack.java [deleted file]
developer/jvm/.gitignore [new file with mode: 0644]
developer/shell/.githolder [new file with mode: 0644]
developer/shell/black [new file with mode: 0755]
developer/shell/blue [new file with mode: 0755]
developer/shell/green [new file with mode: 0755]
developer/tool/#make_PaintIt# [new file with mode: 0755]
developer/tool/env_build
developer/tool/make [new file with mode: 0755]
developer/tool/make.sh [deleted file]
developer/tool/make_PaintIt [new file with mode: 0755]
document/directory_naming.html [new file with mode: 0644]
document/directory_structure_description.html [deleted file]
release_candidate/AriadneGraph$_all_DAG_DF_closure10.class [deleted file]
release_candidate/AriadneGraph$_all_DAG_DF_closure7.class [deleted file]
release_candidate/AriadneGraph$_all_DAG_DF_closure8.class [deleted file]
release_candidate/AriadneGraph$_all_DAG_DF_closure9.class [deleted file]
release_candidate/AriadneGraph$_good_dependency_q_closure10.class [deleted file]
release_candidate/AriadneGraph$_good_dependency_q_closure11.class [deleted file]
release_candidate/AriadneGraph$_mark_node_form_closure3.class [deleted file]
release_candidate/AriadneGraph$_mark_node_form_closure4.class [deleted file]
release_candidate/AriadneGraph$_markup_graph_f_descend_closure4.class [deleted file]
release_candidate/AriadneGraph$_markup_graph_f_descend_closure5.class [deleted file]
release_candidate/AriadneGraph$_markup_graph_f_descend_closure6.class [deleted file]
release_candidate/AriadneGraph$_markup_graph_f_descend_closure7.class [deleted file]
release_candidate/AriadneGraph$_newer_than_all_closure11.class [deleted file]
release_candidate/AriadneGraph$_newer_than_all_closure12.class [deleted file]
release_candidate/AriadneGraph$_run_build_scripts_f_closure12.class [deleted file]
release_candidate/AriadneGraph$_run_build_scripts_f_closure13.class [deleted file]
release_candidate/AriadneGraph$_run_build_scripts_f_closure14.class [deleted file]
release_candidate/AriadneGraph$_run_build_scripts_f_closure15.class [deleted file]
release_candidate/AriadneGraph$_wellformed_q_closure1.class [deleted file]
release_candidate/AriadneGraph$_wellformed_q_closure2.class [deleted file]
release_candidate/AriadneGraph$_wellformed_q_closure3.class [deleted file]
release_candidate/AriadneGraph.class [deleted file]
release_candidate/build [deleted file]
tool/env_administrator [new file with mode: 0644]
tool/env_dev [deleted file]
tool/env_developer [new file with mode: 0644]
tool/env_pm [deleted file]

diff --git a/developer/javac/AriadneGraph.java b/developer/javac/AriadneGraph.java
deleted file mode 100644 (file)
index 711c144..0000000
+++ /dev/null
@@ -1,683 +0,0 @@
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-
-public class AriadneGraph {
-
-  /*--------------------------------------------------------------------------------
-   type aliases
-  */
-  public class TokenSet extends HashSet<Token>{}
-  public class LabelList extends ArrayList<Label> {}
-  public interface Node extends Map<Label, Object>{}
-  public interface NodeList extends List<Node>{}
-  public interface RecognizerF extends Function<Label, Node>{}
-  public interface RecognizerFList extends List<RecognizerF>{}
-
-
-  /*--------------------------------------------------------------------------------
-   instance data 
-  */
-
-  private static Boolean debug = true;
-  private Map<Label, Node> node_map;
-  private RecognizerFList recognizer_f_list;
-
-  /*--------------------------------------------------------------------------------
-    constructors
-  */
-
-  public AriadneGraph(Map<Label, Node> node_map, RecognizerFList recognizer_f_list) {
-    if (node_map == null && recognizer_f_list == null) {
-      System.err.println("AriadneGraph: requires one or both of 'node_map' as Map, and 'recognizer_f_list' as List.");
-      System.exit(1);
-    }
-
-    // Initialize node_map and recognizer_f_list to empty collections if they are null
-    this.node_map = (node_map != null) ? node_map : new HashMap<Label, Node>();
-    this.recognizer_f_list = (recognizer_f_list != null) ? recognizer_f_list : new ArrayList<RecognizerF>();
-  }
-
-  /*--------------------------------------------------------------------------------
-   file utilities
-  */
-
-  public static Map<String ,String> unpack_file_path(String file_fp){
-    if(debug) System.out.println("unpack_file_path::file_fp: " + file_fp);
-
-    File file = new File(file_fp);
-    String parent_dp = (file.getParent() != null) ? file.getParent() : "";
-
-    if( !parent_dp.isEmpty() && !parent_dp.endsWith(File.separator) ){
-      parent_dp += File.separator;
-    }
-
-    String file_fn = file.getName();
-    String file_fn_base = file_fn;
-    String file_fn_ext = "";
-
-    int last_index = file_fn.lastIndexOf('.');
-    if(last_index > 0){
-      file_fn_base = file_fn.substring(0 ,last_index);
-      if( last_index + 1 < file_fn.length() ){
-        file_fn_ext = file_fn.substring(last_index + 1);
-      }
-    }
-
-    Map<String ,String> ret_val = new HashMap<>();
-    ret_val.put("dp" ,parent_dp);
-    ret_val.put("fn" ,file_fn);
-    ret_val.put("fn_base" ,file_fn_base);
-    ret_val.put("fn_ext" ,file_fn_ext);
-
-    if(debug) System.out.println("unpack_file_path::ret_val: " + ret_val);
-
-    return ret_val;
-  }
-
-  public static boolean file_exists_q(Label node_label){
-    Path node_path = Paths.get(node_label);
-    return Files.exists(node_path);
-  }
-
-  /*--------------------------------------------------------------------------------
-    About nodes
-
-    A leaf type node specifies a path to a file that should not be deleted by
-    in clean operations. Typically this is the source code. We could add a
-    tool to lock permissions on these before a build, so that the build
-    scripts will also not mess with them (unless they change permissions).
-
-    If the user has multiple dependency graphs defined, a node with no
-    dependencies in one graph, might have dependencies in another.
-
-    An error type node, is one that was found to not have a type, or
-    was constructed by the tool to be a place older, perhaps for a
-    node label that was not found.
-
-  */
-  public static TokenSet all_node_type_set = new TokenSet();
-  static {
-    all_node_type_set.add(new Token("symbol"));
-    all_node_type_set.add(new Token("path"));
-    all_node_type_set.add(new Token("leaf"));
-    all_node_type_set.add(new Token("error"));
-  }
-
-  public static TokenSet persistent_node_mark_set = new TokenSet();
-  static {
-    persistent_node_mark_set.add(new Token("cycle_member"));
-    persistent_node_mark_set.add(new Token("wellformed"));
-    persistent_node_mark_set.add(new Token("build_failed"));
-    persistent_node_mark_set.add(new Token("null_node"));
-  }
-
-  public static boolean leaf_q(Node node){
-    return node != null && "leaf".equals(node.get("type"));
-  }
-
-  public static boolean has_mark(Node node){
-    return node != null && node.get("mark") != null && !( (TokenSet)node.get("mark") ).isEmpty();
-  }
-
-  public static void set_mark(Node node ,Token mark){
-    if( node.get("mark") == null ){
-      node.put("mark" ,new HashTokenSet());
-    }
-    ( (TokenSet)node.get("mark") ).add(mark);
-  }
-
-  public static void clear_mark(Node node ,Token mark){
-    if( node != null && node.get("mark") != null ){
-      ( (TokenSet) node.get("mark") ).remove(mark);
-    }
-  }
-
-  public static boolean marked_good_q(Node node){
-    return node != null && node.get("mark") != null
-      && ( (TokenSet)node.get("mark") ).contains("wellformed")
-      && !( (TokenSet)node.get("mark") ).contains("cycle_member")
-      && !( (TokenSet)node.get("mark") ).contains("build_failed");
-  }
-
-
-  /*--------------------------------------------------------------------------------
-   Well-formed Node Check
-  */
-
-  public static TokenSet form_condition_set = new TokenSet();
-  static {
-    form_condition_set.add(new Token("no_node"));
-    form_condition_set.add(new Token("node_must_have_label"));
-    form_condition_set.add(new Token("label_must_be_string"));
-    form_condition_set.add(new Token("node_must_have_type"));
-    form_condition_set.add(new Token("bad_node_type"));
-    form_condition_set.add(new Token("neighbor_value_must_be_list"));
-    form_condition_set.add(new Token("neighbor_reference_must_be_string"));
-    form_condition_set.add(new Token("neighbor_label_not_in_graph"));
-    form_condition_set.add(new Token("mark_property_value_must_be_set"));
-    form_condition_set.add(new Token("unregistered_mark"));
-    form_condition_set.add(new Token("missing_required_build_code"));
-    form_condition_set.add(new Token("leaf_given_neighbor_property"));
-    form_condition_set.add(new Token("leaf_given_build_property"));
-  }
-
-  // given a node, collects a description of its form, returns a set form condition tokens
-  public static TokenSet wellformed_node_q(Node node){
-    TokenSet form_error_set = new HashSet<>();
-
-    if(node == null){
-      form_error_set.add("null_node");
-      return form_error_set;
-    }
-
-    if( !node.containsKey("label") )
-      form_error_set.add("node_must_have_label");
-    else if( !(node.get("label") instanceof Label) )
-      form_error_set.add("label_must_be_string");
-
-    if( !node.containsKey("type") )
-      form_error_set.add("node_must_have_type");
-    else if( !(node.get("type") instanceof String) || !all_node_type_set.contains(node.get("type")) )
-      form_error_set.add("bad_node_type");
-
-    if( node.containsKey("neighbor") ){
-      if( !(node.get("neighbor") instanceof List) )
-        form_error_set.add("neighbor_value_must_be_list");
-      else if( !((List<?>) node.get("neighbor")).stream().allMatch(it -> it instanceof Label) )
-        form_error_set.add("neighbor_reference_must_be_string");
-    }
-
-    if( node.containsKey("mark") ){
-      if( !(node.get("mark") instanceof Set) )
-        form_error_set.add("mark_property_value_must_be_set");
-      else if( !((Set<?>) node.get("mark")).stream().allMatch(it -> persistent_node_mark_set.contains(it)) )
-        form_error_set.add("unregistered_mark");
-    }
-
-    if( "path".equals(node.get("type")) && (!node.containsKey("build") || !(node.get("build") instanceof Runnable)) )
-      form_error_set.add("missing_required_build_code");
-
-    if( "leaf".equals(node.get("type")) ){
-      if( node.containsKey("neighbor") ) form_error_set.add("leaf_given_neighbor_property");
-      if( node.containsKey("build") ) form_error_set.add("leaf_given_build_property");
-    }
-
-    return form_error_set;
-  }
-
-  // given a node, potentially marks it as wellformed, returns one of 'wellformed' or 'malformed'
-  public static Token wellformed_mark_node(Node node ,boolean verbose){
-    if(debug){
-      if(node != null){
-        System.out.println("wellformed_mark_node::node: " + node);
-      }else{
-        System.out.println("wellformed_mark_node given a null node");
-      }
-    }
-
-    TokenSet form_errors = wellformed_node_q(node);
-    if( form_errors.isEmpty() ){
-      set_mark( node ,"wellformed" );
-      return "wellformed";
-    }
-
-    // At this point we know that form_errors is not empty
-    if(verbose){
-      if( node != null && node.get("label") != null && ((Label)node.get("label")).length() > 0 ){
-        System.out.print( "node " + node.get("label") + " is malformed due to:" );
-      }else{
-        System.out.print("anonymous node is malformed due to:");
-      }
-      for(Token error : form_errors){
-        System.out.print(" " + error);
-      }
-      System.out.println("");
-    }
-
-    return "malformed";
-  }
-  public Token wellformed_mark_node(Node node){
-    return wellformed_mark_node(node ,true);
-  }
-
-  // given a node_label, potentially marks the corresponding node as 'wellformed', returns a token set.
-  // Tokens included "undefined_node", "malformed", and "defactor_leaf".
-  public TokenSet wellformed_mark_node_label(Label node_label ,boolean verbose){
-    TokenSet ret_value = new HashSet<>();
-    Node node = lookup(node_label);
-    if(node == null){
-      ret_value.add("undefined_node");
-      return ret_value;
-    }
-    if( "malformed".equals(wellformed_mark_node(node ,verbose)) ){
-      ret_value.add("malformed");
-    }
-    if( ((List<?>)node.get("neighbor")).isEmpty() ){
-      ret_value.add("defacto_leaf"); // might not be `type:leaf`
-    }
-    return ret_value;
-  }
-  public TokenSet wellformed_mark_node_label(Label node_label){
-    return wellformed_mark_node_label(node_label, true);
-  }
-
-
-  /*--------------------------------------------------------------------------------
-   A well formed graph checker.  Traverses entire graph and marks nodes
-   that are not well formed or that are part of a cycle.
-
-   This must be run on the graph for `lookup_marked_good` to work.
-
-   Each node_label must be a string and not empty.
-
-   Subleties here because we have not yet determined if the nodes we are
-   wellformed (after all ,that is what we are determining here).
-
-   If we want to attempt to build 'islands' of things that might be located on
-   the far side of cycles ,then modify the cycle finder to return a list of
-   cycles (i.e. a list of lists) ,then use each of cycle definition (a list) as
-   the root nodes for further search.
-
-   `path_stack` is a stack of LabelList. The first entry is a clone of the list of
-   root nodes, referenced by label. Each subsequent list is a clone of the
-   neighbor list of the leftmost node of the prior entry.
-
-   `path` is a list of the left most nodes, referenced by label, of the entries
-   on the path stack. This is the path to our current location in the tree.
-  */
-
-
-  private boolean find_and_remove_cycle(List<LabelList> path_stack ,LabelList path ,boolean verbose){
-
-    if( path.size() <= 1 ) return false; // 0 or 1 length path can't have a cycle
-
-    // we want to know if the most recent node added to the path occurs at a point earlier
-    // in the path.
-    int rightmost_index = path.size() - 1;
-    Label recent_node_label = path.get( rightmost_index );
-    int cycle_start_index = path.indexOf(recent_node_label);
-    if( cycle_start_index == -1 ){
-      System.err.println("find_and_remove_cycle:: indexOf does not find index of known list member");
-      return false;
-    }
-    Boolean has_cycle =  cycle_start_index < rightmost_index;
-    if(!has_cycle) return false;
-
-    if(verbose) System.out.print("mark_form_graph_descend:: dependency cycle found:");
-    for( Label cycle_node_label : path.subList(cycle_start_index ,path.size()) ){
-      if(verbose) System.out.print(" " + cycle_node_label);
-      Node cycle_node = lookup(cycle_node_label);
-      if( cycle_node.get("mark") == null ){
-        cycle_node.put( "mark" ,new HashTokenSet() );
-      }
-      ( (TokenSet)cycle_node.get("mark") ).add("cycle_member");
-    }
-    if(verbose) System.out.println("");
-
-    // We cannot continue searching after the loop, so we pop back to treat
-    // the first node in the loop as though a leaf node.
-    path_stack.subList( cycle_start_index + 1 ,path_stack.size() ).clear();
-
-    return true;
-  }
-
-  private static TokenSet mark_form_graph_descend_set = new TokenSet();
-  static {
-    mark_form_graph_descend_set.add(new Token("empty_path_stack"));
-    mark_form_graph_descend_set.add(new Token("cycle_found"));
-    mark_form_graph_descend_set.add(new Token("undefined_node"));
-    mark_form_graph_descend_set.add(new Token("exists_malformed"));
-    mark_form_graph_descend_set.add(new Token("defacto_leaf"));
-  }
-
-  private TokenSet mark_form_graph_descend( List<LabelList> path_stack ,boolean verbose ){
-    TokenSet ret_value = new HashSet<>();
-    if(path_stack.isEmpty()){
-      if(verbose) System.out.println( "mark_form_graph_descend:: given empty path_stack to descend from" );
-      ret_value.add( "empty_path_stack" );
-      return ret_value;
-    }
-
-    LabelList local_path = new ArrayList<>();
-    for(LabelList path : path_stack){
-      local_path.add( path.get(0) );
-    }
-    Label local_node_label = local_path.get( local_path.size() - 1 );
-  
-    do{
-      
-      if( find_and_remove_cycle(path_stack ,local_path ,verbose) ){
-        ret_value.add("cycle_found");
-        return ret_value;
-      }
-
-      TokenSet wellformed_mark_node_label_result = wellformed_mark_node_label(local_node_label ,verbose);
-      ret_value.addAll( wellformed_mark_node_label_result );
-      if( 
-         wellformed_mark_node_label_result.contains("undefined_node") 
-         || wellformed_mark_node_label_result.contains("defacto_leaf") 
-      ){
-        return ret_value;
-      }
-
-      // Descend further into the tree.
-      path_stack.add( new ArrayList<>((LabelList) lookup(local_node_label).get("neighbor")) );
-      local_node_label = (LabelList)lookup(local_node_label).get("neighbor").get(0);
-      local_path.add(local_node_label);
-
-    }while(true);
-  }
-
-   
-  /*
-    Given root_node_label_list, marks up the graph and returns a set possibly
-    containing 'all_wellformed' and 'cycles_exist'.
-
-    Marks potentially added to each node include 'cycle_member' and 'wellformed'.
-    Note that these marks are independent.
-  */
-  public TokenSet mark_form_graph(LabelList root_node_label_list, boolean verbose){
-    TokenSet ret_value = new HashSet<>();
-    boolean exists_malformed = false;
-    TokenSet result; // used variously
-
-    if( root_node_label_list.isEmpty() ) return ret_value;
-
-    // Initialize the DFS tree iterator.
-    List<LabelList> path_stack = new ArrayList<>();
-    path_stack.add( new ArrayList<>(root_node_label_list) );
-
-    // iterate over left side tree descent, not ideal as it starts at the
-    // root each time, but avoids complexity in the cycle detection logic.
-    do{
-      result = mark_form_graph_descend(path_stack, verbose);
-      if( result.contains("cycle_found") ) ret_value.add("cycle_exists");
-      if( result.contains("undefined_node") ) exists_malformed = true;
-      if( result.contains("exists_malformed") ) exists_malformed = true;
-
-      // increment the iterator to the next leftmost path
-      LabelList top_list = path_stack.get( path_stack.size() - 1 );
-      top_list.remove(0);
-      if( top_list.isEmpty() ) path_stack.remove( path_stack.size() - 1 );
-
-    }while( !path_stack.isEmpty() );
-
-    if( !exists_malformed ) ret_value.add("all_wellformed");
-
-    if( verbose ){
-      if( exists_malformed ) System.out.println("one or more malformed nodes were found");
-      boolean exists_cycle = ret_value.contains("cycle_exists");
-      if( exists_cycle ) System.out.println("one or more cyclic dependency loop found");
-      if( exists_malformed || exists_cycle ) System.out.println("will attempt to build unaffected nodes");
-    }
-
-    return ret_value;
-  }
-  public TokenSet mark_form_graph(LabelList root_node_label_list){
-    return mark_form_graph(root_node_label_list, true);
-  }
-
-
-  /*--------------------------------------------------------------------------------
-    Graph traversal
-  */
-
-  // Given a node label, looks it up in the dependency graph, returns the node or null
-  public Node lookup(Label node_label, boolean verbose){
-    if(node_label == null || node_label.isEmpty()){
-      if(verbose) System.out.println("lookup:: given node_label is null or an empty string");
-      return null;
-    }
-
-    // Try the map
-    Node node = this.node_map.get(node_label);
-    if(node != null){
-      node.put("label", node_label);
-      if(verbose) System.out.println("lookup:: found from map: " + node);
-      return node;
-    }
-    // At this point, node will be null
-
-    // The map lookup failed, let's try the function recognizer list
-    Node match_result = null;
-    for (RecognizerF func : this.recognizer_f_list) {
-      Node match_result = func.apply(node_label); 
-      if("matched".equals(match_result.get("status"))){
-        node = match_result;
-        break;
-      }
-    }
-
-    if(verbose){
-      if(node != null) System.out.println("lookup:: found from recognizer function: " + node);
-      else System.out.println("lookup:: failed to find label: " + node_label);
-    }
-
-    return node;
-  }
-  public Node lookup(Label node_label){
-    return lookup(node_label, true);
-  }
-
-  // Mark aware lookup function
-  public Node lookup_marked_good(Label node_label, boolean verbose){
-    Node node = lookup(node_label, verbose);
-    if(node != null && marked_good_q(node)) return node;
-    return null;
-  }
-  public Node lookup_marked_good(Label node_label){
-    return lookup_marked_good(node_label, true);
-  }
-
-  /*
-    Given `root_node_label_list` of a DAG, applies `node_function` to each node in a
-    depth-first traversal order. Returns a set of error tokens encountered
-    during traversal.
-
-    `mark_form_graph` must be run on the DAG before this function is called, or
-    `lookup_marked_good` will not function correctly.
-  */
-  public TokenSet all_DAG_DF(LabelList root_node_label_list, BiConsumer<Node ,TokenSet> node_function, boolean verbose) {
-    if(verbose) System.out.println("all_DAG_DF::");
-
-    TokenSet error_token_set = new HashSet<>();
-
-    boolean accept_arg_list = true;
-    if(node_function == null) {
-      error_token_set.add("null_node_function");
-      accept_arg_list = false;
-    }
-    if(!(node_function instanceof BiFunction)) {
-      error_token_set.add("node_function_not_a_function");
-      accept_arg_list = false;
-    }
-    if(root_node_label_list == null) {
-      error_token_set.add("null_root_node_label_list");
-      accept_arg_list = false;
-    }
-    if(root_node_label_list.isEmpty()) {
-      error_token_set.add("empty_root_node_label_list");
-      accept_arg_list = false;
-    }
-    if(!accept_arg_list) return error_token_set;
-
-    TokenSet visited = new HashSet<>();
-    List<Node> in_traversal_order = new ArrayList<>();
-
-    Stack<Label> stack = new Stack<>();
-    root_node_label_list.forEach(stack::push);
-
-    while( !stack.isEmpty() ){
-      Label node_label = stack.pop();
-
-      Node node = lookup_marked_good(node_label, verbose);
-      if(node == null) {
-        error_token_set.add("lookup_fail");
-        continue;
-      }
-
-      if(visited.contains(node.get("label"))) continue;
-      visited.add((Label)node.get("label"));
-
-      in_traversal_order.add(node);
-
-      stack.addAll( (LabelList)node.get("neighbor") );
-    }
-
-    Collections.reverse(in_traversal_order);
-    for(Node node : in_traversal_order) {
-      node_function.apply(node, error_token_set);
-    }
-
-    return error_token_set;
-  }
-  public TokenSet all_DAG_DF(LabelList root_node_label_list, BiConsumer<Node ,TokenSet> node_function){
-    return all_DAG_DF(root_node_label_list, node_function, true);
-  }
-
-  /*--------------------------------------------------------------------------------
-    run the build scripts
-    depends upon is_acyclic having already marked up the graph.
-  */
-
-  // A dependency is "good" if it is marked good, and for leaf or path, if the
-  // corresponding file exists
-  public boolean good_dependency_q(LabelList node_labels){
-    return node_labels.stream().allMatch(node_label -> {
-        Node node = lookup_marked_good(node_label);
-        if( node == null ) return false;
-        if(
-          ("path".equals(node.get("type")) || "leaf".equals(node.get("type")) )
-          && !file_exists_q( (Label) node.get("label") )
-        ){
-          return false;
-        }
-        return true;
-      });
-  }
-
-  /*
-    Given a node label and a list of node labels, returns true if the file at the
-    node label in the first argument is newer than all the files at the
-    corresponding node labels in the second list.
-  */
-  public boolean newer_than_all(Label node_label, LabelList node_label_list) throws IOException {
-    Path node_path = Paths.get(node_label);
-    if (!Files.exists(node_path)) return false;
-
-    long node_last_modified = Files.getLastModifiedTime(node_path).toMillis();
-
-    return node_label_list.stream().allMatch(label -> {
-        try {
-          Path path = Paths.get(label);
-          if (!Files.exists(path)) return false;
-          long last_modified = Files.getLastModifiedTime(path).toMillis();
-          return node_last_modified > last_modified;
-        } catch (IOException e) {
-          return false;
-        }
-      });
-  }
-
-  public boolean can_be_built_q(Node node) {
-    if( !marked_good_q(node) ) return false;
-    if(
-       ( "symbol".equals(node.get("type")) || "path".equals(node.get("type")) )
-        && !good_dependency_q( (LabelList)node.get("neighbor") ) 
-    ){
-      return false;
-    }
-    if( 
-       "leaf".equals( node.get("type") ) 
-       && !file_exists_q( (Label)node.get("label") )
-    ){
-      return false;
-    }
-    return true;
-  }
-
-  // `can_be_build_q` must be true for this to be meaningful:
-  public boolean should_be_built_q(Node node, boolean verbose) throws IOException {
-    if ("leaf".equals(node.get("type"))) return false;
-    if ("symbol".equals(node.get("type"))) return true;
-    if ("path".equals(node.get("type"))) return !newer_than_all((Label) node.get("label"), (LabelList) node.get("neighbor"));
-    
-    if (verbose) {
-      System.out.println("should_be_build_q:: unrecognized node type, so assuming it should not be built.");
-    }
-    return false;
-  }
-  public boolean should_be_built_q(Node node) throws IOException {
-    return should_be_built_q(node, true);
-  }
-
-  /*
-    Runs the build scripts, assuming the graph has been marked up already.
-  */
-  public void run_build_scripts_f(LabelList root_node_label_list, boolean verbose) throws IOException {
-
-    if(root_node_label_list.isEmpty()) return;
-
-    TokenSet error_token_set = new HashSet<>(); // used to catch return values
-
-    System.out.println("run_build_script:: Checking if graph is well formed.");
-    error_token_set = mark_form_graph(root_node_label_list);
-    if(error_token_set != null && !error_token_set.isEmpty()) {
-      System.out.println("Graph is not well-formed. Expect build problems. Errors:");
-      error_token_set.forEach(token -> System.out.println("  - " + token));
-    } else {
-      System.out.println("Graph is well-formed. Proceeding with build.");
-    }
-
-    // Define the node function
-    BiConsumer<Node, TokenSet> node_function = (node, error_token_set_2) -> {
-      if(!can_be_built_q(node)) {
-        System.out.println("run_build_scripts_f:: Skipping build for " + node.get("label") + " due to problems with dependencies.");
-        return;
-      }
-      if(!should_be_built_q(node)) {
-        if(verbose) System.out.println("run_build_scripts_f:: " + node.get("label") + " already up to date");
-        return;
-      }
-
-      // Build the target
-      System.out.println("run_build_scripts_f:: Running build script for " + node.get("label"));
-      // Assuming node.build() is a method in the Map or a related object
-      // Replace this with the actual build function for the node
-      // node.build();
-
-      // For path nodes, check if the build updated the target path
-      if("path".equals(node.get("type")) && should_be_built_q(node)) {
-        System.out.println("run_build_scripts_f:: Build failed for " + node.get("label"));
-        set_mark(node, "build_failed");
-      }
-    };
-
-    System.out.println("run_build_scripts_f:: running ...");
-    error_token_set = all_DAG_DF(root_node_label_list, node_function, verbose);
-    if(error_token_set != null) {
-      error_token_set.forEach(error -> System.out.println("run_build_scripts_f::all_DAG_DF:: " + error));
-    }
-  }
-  public void run_build_scripts_f(LabelList root_node_label_list) throws IOException {
-    run_build_scripts_f(root_node_label_list, true);
-  }
-
-}
diff --git a/developer/javac/Black.java b/developer/javac/Black.java
new file mode 100644 (file)
index 0000000..d669ac3
--- /dev/null
@@ -0,0 +1,7 @@
+package com.ReasoningTechnology.PaintIt;
+
+public class Black {
+  public static void main(String[] args) {
+    System.out.println("Paint it black.");
+  }
+}
diff --git a/developer/javac/Blue.java b/developer/javac/Blue.java
new file mode 100644 (file)
index 0000000..c6c7a0a
--- /dev/null
@@ -0,0 +1,10 @@
+package com.ReasoningTechnology.PaintIt;
+
+public class Blue {
+  public static void print(){
+    System.out.println("Paint it blue.");
+  }
+  public static void main(String[] args) {
+    print();
+  }
+}
diff --git a/developer/javac/Graph.java b/developer/javac/Graph.java
new file mode 100644 (file)
index 0000000..573c3e8
--- /dev/null
@@ -0,0 +1,683 @@
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+
+public class Graph {
+
+  /*--------------------------------------------------------------------------------
+   type aliases
+  */
+  public class TokenSet extends HashSet<Token>{}
+  public class LabelList extends ArrayList<Label> {}
+  public interface Node extends Map<Label ,Object>{}
+  public interface NodeList extends List<Node>{}
+  public interface RecognizerF extends Function<Label ,Node>{}
+  public class RecognizerFList extends ArrayList<RecognizerF> {}
+
+  /*--------------------------------------------------------------------------------
+   instance data 
+  */
+
+  private static boolean debug = true;
+  private Map<Label ,Node> node_map;
+  private RecognizerFList recognizer_f_list;
+
+  /*--------------------------------------------------------------------------------
+    constructors
+  */
+
+  public AriadneGraph(Map<Label ,Node> node_map ,RecognizerFList recognizer_f_list){
+    if (node_map == null && recognizer_f_list == null) {
+      System.err.println("AriadneGraph: At least one of 'node_map' (Map) or 'recognizer_f_list' (List) must be provided.");
+      System.exit(1);
+    }
+
+    // Initialize node_map and recognizer_f_list to empty collections if they are null
+    this.node_map = (node_map != null) ? node_map : new HashMap<Label ,Node>();
+
+    this.recognizer_f_list = (recognizer_f_list != null) ? recognizer_f_list : new RecognizerFList();
+  }
+
+  /*--------------------------------------------------------------------------------
+   file utilities
+  */
+
+  public static Map<String ,String> unpack_file_path(String file_fp){
+    if(debug) System.out.println("unpack_file_path::file_fp: " + file_fp);
+
+    File file = new File(file_fp);
+    String parent_dp = (file.getParent() != null) ? file.getParent() : "";
+
+    if( !parent_dp.isEmpty() && !parent_dp.endsWith(File.separator) ){
+      parent_dp += File.separator;
+    }
+
+    String file_fn = file.getName();
+    String file_fn_base = file_fn;
+    String file_fn_ext = "";
+
+    int last_index = file_fn.lastIndexOf('.');
+    if(last_index > 0){
+      file_fn_base = file_fn.substring(0 ,last_index);
+      if( last_index + 1 < file_fn.length() ){
+        file_fn_ext = file_fn.substring(last_index + 1);
+      }
+    }
+
+    Map<String ,String> ret_val = new HashMap<>();
+    ret_val.put("dp" ,parent_dp);
+    ret_val.put("fn" ,file_fn);
+    ret_val.put("fn_base" ,file_fn_base);
+    ret_val.put("fn_ext" ,file_fn_ext);
+
+    if(debug) System.out.println("unpack_file_path::ret_val: " + ret_val);
+
+    return ret_val;
+  }
+
+  public static boolean file_exists_q(Label node_label){
+    Path node_path = Paths.get(node_label);
+    return Files.exists(node_path);
+  }
+
+  /*--------------------------------------------------------------------------------
+    About nodes
+
+    A leaf type node specifies a path to a file that should not be deleted by
+    in clean operations. Typically this is the source code. We could add a
+    tool to lock permissions on these before a build, so that the build
+    scripts will also not mess with them (unless they change permissions).
+
+    If the user has multiple dependency graphs defined, a node with no
+    dependencies in one graph, might have dependencies in another.
+
+    An error type node, is one that was found to not have a type, or
+    was constructed by the tool to be a place older, perhaps for a
+    node label that was not found.
+
+  */
+  public static TokenSet all_node_type_set = new TokenSet();
+  static {
+    all_node_type_set.add(new Token("symbol"));
+    all_node_type_set.add(new Token("path"));
+    all_node_type_set.add(new Token("leaf"));
+    all_node_type_set.add(new Token("error"));
+  }
+
+  public static TokenSet persistent_node_mark_set = new TokenSet();
+  static {
+    persistent_node_mark_set.add(new Token("cycle_member"));
+    persistent_node_mark_set.add(new Token("wellformed"));
+    persistent_node_mark_set.add(new Token("build_failed"));
+    persistent_node_mark_set.add(new Token("null_node"));
+  }
+
+  public static boolean leaf_q(Node node){
+    return node != null && "leaf".equals(node.get("type"));
+  }
+
+  public static boolean has_mark(Node node){
+    return node != null && node.get("mark") != null && !( (TokenSet)node.get("mark") ).isEmpty();
+  }
+
+  public static void set_mark(Node node ,Token mark){
+    if( node.get("mark") == null ){
+      node.put("mark" ,new HashTokenSet());
+    }
+    ( (TokenSet)node.get("mark") ).add(mark);
+  }
+
+  public static void clear_mark(Node node ,Token mark){
+    if( node != null && node.get("mark") != null ){
+      ( (TokenSet) node.get("mark") ).remove(mark);
+    }
+  }
+
+  public static boolean marked_good_q(Node node){
+    return node != null && node.get("mark") != null
+      && ( (TokenSet)node.get("mark") ).contains("wellformed")
+      && !( (TokenSet)node.get("mark") ).contains("cycle_member")
+      && !( (TokenSet)node.get("mark") ).contains("build_failed");
+  }
+
+
+  /*--------------------------------------------------------------------------------
+   Well-formed Node Check
+  */
+
+  public static TokenSet form_condition_set = new TokenSet();
+  static {
+    form_condition_set.add(new Token("no_node"));
+    form_condition_set.add(new Token("node_must_have_label"));
+    form_condition_set.add(new Token("label_must_be_string"));
+    form_condition_set.add(new Token("node_must_have_type"));
+    form_condition_set.add(new Token("bad_node_type"));
+    form_condition_set.add(new Token("neighbor_value_must_be_list"));
+    form_condition_set.add(new Token("neighbor_reference_must_be_string"));
+    form_condition_set.add(new Token("neighbor_label_not_in_graph"));
+    form_condition_set.add(new Token("mark_property_value_must_be_set"));
+    form_condition_set.add(new Token("unregistered_mark"));
+    form_condition_set.add(new Token("missing_required_build_code"));
+    form_condition_set.add(new Token("leaf_given_neighbor_property"));
+    form_condition_set.add(new Token("leaf_given_build_property"));
+  }
+
+  // given a node, collects a description of its form, returns a set form condition tokens
+  public static TokenSet wellformed_node_q(Node node){
+    TokenSet form_error_set = new HashSet<>();
+
+    if(node == null){
+      form_error_set.add("null_node");
+      return form_error_set;
+    }
+
+    if( !node.containsKey("label") )
+      form_error_set.add("node_must_have_label");
+    else if( !(node.get("label") instanceof Label) )
+      form_error_set.add("label_must_be_string");
+
+    if( !node.containsKey("type") )
+      form_error_set.add("node_must_have_type");
+    else if( !(node.get("type") instanceof String) || !all_node_type_set.contains(node.get("type")) )
+      form_error_set.add("bad_node_type");
+
+    if( node.containsKey("neighbor") ){
+      if( !(node.get("neighbor") instanceof List) )
+        form_error_set.add("neighbor_value_must_be_list");
+      else if( !((List<?>) node.get("neighbor")).stream().allMatch(it -> it instanceof Label) )
+        form_error_set.add("neighbor_reference_must_be_string");
+    }
+
+    if( node.containsKey("mark") ){
+      if( !(node.get("mark") instanceof Set) )
+        form_error_set.add("mark_property_value_must_be_set");
+      else if( !((Set<?>) node.get("mark")).stream().allMatch(it -> persistent_node_mark_set.contains(it)) )
+        form_error_set.add("unregistered_mark");
+    }
+
+    if( "path".equals(node.get("type")) && (!node.containsKey("build") || !(node.get("build") instanceof Runnable)) )
+      form_error_set.add("missing_required_build_code");
+
+    if( "leaf".equals(node.get("type")) ){
+      if( node.containsKey("neighbor") ) form_error_set.add("leaf_given_neighbor_property");
+      if( node.containsKey("build") ) form_error_set.add("leaf_given_build_property");
+    }
+
+    return form_error_set;
+  }
+
+  // given a node, potentially marks it as wellformed, returns one of 'wellformed' or 'malformed'
+  public static Token wellformed_mark_node(Node node ,boolean verbose){
+    if(debug){
+      if(node != null){
+        System.out.println("wellformed_mark_node::node: " + node);
+      }else{
+        System.out.println("wellformed_mark_node given a null node");
+      }
+    }
+
+    TokenSet form_errors = wellformed_node_q(node);
+    if( form_errors.isEmpty() ){
+      set_mark( node ,"wellformed" );
+      return "wellformed";
+    }
+
+    // At this point we know that form_errors is not empty
+    if(verbose){
+      if( node != null && node.get("label") != null && ((Label)node.get("label")).length() > 0 ){
+        System.out.print( "node " + node.get("label") + " is malformed due to:" );
+      }else{
+        System.out.print("anonymous node is malformed due to:");
+      }
+      for(Token error : form_errors){
+        System.out.print(" " + error);
+      }
+      System.out.println("");
+    }
+
+    return "malformed";
+  }
+  public Token wellformed_mark_node(Node node){
+    return wellformed_mark_node(node ,true);
+  }
+
+  // given a node_label, potentially marks the corresponding node as 'wellformed', returns a token set.
+  // Tokens included "undefined_node", "malformed", and "defactor_leaf".
+  public TokenSet wellformed_mark_node_label(Label node_label ,boolean verbose){
+    TokenSet ret_value = new HashSet<>();
+    Node node = lookup(node_label);
+    if(node == null){
+      ret_value.add("undefined_node");
+      return ret_value;
+    }
+    if( "malformed".equals(wellformed_mark_node(node ,verbose)) ){
+      ret_value.add("malformed");
+    }
+    if( ((List<?>)node.get("neighbor")).isEmpty() ){
+      ret_value.add("defacto_leaf"); // might not be `type:leaf`
+    }
+    return ret_value;
+  }
+  public TokenSet wellformed_mark_node_label(Label node_label){
+    return wellformed_mark_node_label(node_label ,true);
+  }
+
+
+  /*--------------------------------------------------------------------------------
+   A well formed graph checker.  Traverses entire graph and marks nodes
+   that are not well formed or that are part of a cycle.
+
+   This must be run on the graph for `lookup_marked_good` to work.
+
+   Each node_label must be a string and not empty.
+
+   Subleties here because we have not yet determined if the nodes we are
+   wellformed (after all ,that is what we are determining here).
+
+   If we want to attempt to build 'islands' of things that might be located on
+   the far side of cycles ,then modify the cycle finder to return a list of
+   cycles (i.e. a list of lists) ,then use each of cycle definition (a list) as
+   the root nodes for further search.
+
+   `path_stack` is a stack of LabelList. The first entry is a clone of the list of
+   root nodes, referenced by label. Each subsequent list is a clone of the
+   neighbor list of the leftmost node of the prior entry.
+
+   `path` is a list of the left most nodes, referenced by label, of the entries
+   on the path stack. This is the path to our current location in the tree.
+  */
+
+
+  private boolean find_and_remove_cycle(List<LabelList> path_stack ,LabelList path ,boolean verbose){
+
+    if( path.size() <= 1 ) return false; // 0 or 1 length path can't have a cycle
+
+    // we want to know if the most recent node added to the path occurs at a point earlier
+    // in the path.
+    int rightmost_index = path.size() - 1;
+    Label recent_node_label = path.get( rightmost_index );
+    int cycle_start_index = path.indexOf(recent_node_label);
+    if( cycle_start_index == -1 ){
+      System.err.println("find_and_remove_cycle:: indexOf does not find index of known list member");
+      return false;
+    }
+    Boolean has_cycle =  cycle_start_index < rightmost_index;
+    if(!has_cycle) return false;
+
+    if(verbose) System.out.print("mark_form_graph_descend:: dependency cycle found:");
+    for( Label cycle_node_label : path.subList(cycle_start_index ,path.size()) ){
+      if(verbose) System.out.print(" " + cycle_node_label);
+      Node cycle_node = lookup(cycle_node_label);
+      if( cycle_node.get("mark") == null ){
+        cycle_node.put( "mark" ,new HashTokenSet() );
+      }
+      ( (TokenSet)cycle_node.get("mark") ).add("cycle_member");
+    }
+    if(verbose) System.out.println("");
+
+    // We cannot continue searching after the loop, so we pop back to treat
+    // the first node in the loop as though a leaf node.
+    path_stack.subList( cycle_start_index + 1 ,path_stack.size() ).clear();
+
+    return true;
+  }
+
+  private static TokenSet mark_form_graph_descend_set = new TokenSet();
+  static {
+    mark_form_graph_descend_set.add(new Token("empty_path_stack"));
+    mark_form_graph_descend_set.add(new Token("cycle_found"));
+    mark_form_graph_descend_set.add(new Token("undefined_node"));
+    mark_form_graph_descend_set.add(new Token("exists_malformed"));
+    mark_form_graph_descend_set.add(new Token("defacto_leaf"));
+  }
+
+  private TokenSet mark_form_graph_descend( List<LabelList> path_stack ,boolean verbose ){
+    TokenSet ret_value = new HashSet<>();
+    if(path_stack.isEmpty()){
+      if(verbose) System.out.println( "mark_form_graph_descend:: given empty path_stack to descend from" );
+      ret_value.add( "empty_path_stack" );
+      return ret_value;
+    }
+
+    LabelList local_path = new ArrayList<>();
+    for(LabelList path : path_stack){
+      local_path.add( path.get(0) );
+    }
+    Label local_node_label = local_path.get( local_path.size() - 1 );
+  
+    do{
+      
+      if( find_and_remove_cycle(path_stack ,local_path ,verbose) ){
+        ret_value.add("cycle_found");
+        return ret_value;
+      }
+
+      TokenSet wellformed_mark_node_label_result = wellformed_mark_node_label(local_node_label ,verbose);
+      ret_value.addAll( wellformed_mark_node_label_result );
+      if( 
+         wellformed_mark_node_label_result.contains("undefined_node") 
+         || wellformed_mark_node_label_result.contains("defacto_leaf") 
+      ){
+        return ret_value;
+      }
+
+      // Descend further into the tree.
+      path_stack.add( new ArrayList<>((LabelList) lookup(local_node_label).get("neighbor")) );
+      local_node_label = (LabelList)lookup(local_node_label).get("neighbor").get(0);
+      local_path.add(local_node_label);
+
+    }while(true);
+  }
+
+   
+  /*
+    Given root_node_label_list, marks up the graph and returns a set possibly
+    containing 'all_wellformed' and 'cycles_exist'.
+
+    Marks potentially added to each node include 'cycle_member' and 'wellformed'.
+    Note that these marks are independent.
+  */
+  public TokenSet mark_form_graph(LabelList root_node_label_list ,boolean verbose){
+    TokenSet ret_value = new HashSet<>();
+    boolean exists_malformed = false;
+    TokenSet result; // used variously
+
+    if( root_node_label_list.isEmpty() ) return ret_value;
+
+    // Initialize the DFS tree iterator.
+    List<LabelList> path_stack = new ArrayList<>();
+    path_stack.add( new ArrayList<>(root_node_label_list) );
+
+    // iterate over left side tree descent, not ideal as it starts at the
+    // root each time, but avoids complexity in the cycle detection logic.
+    do{
+      result = mark_form_graph_descend(path_stack ,verbose);
+      if( result.contains("cycle_found") ) ret_value.add("cycle_exists");
+      if( result.contains("undefined_node") ) exists_malformed = true;
+      if( result.contains("exists_malformed") ) exists_malformed = true;
+
+      // increment the iterator to the next leftmost path
+      LabelList top_list = path_stack.get( path_stack.size() - 1 );
+      top_list.remove(0);
+      if( top_list.isEmpty() ) path_stack.remove( path_stack.size() - 1 );
+
+    }while( !path_stack.isEmpty() );
+
+    if( !exists_malformed ) ret_value.add("all_wellformed");
+
+    if( verbose ){
+      if( exists_malformed ) System.out.println("one or more malformed nodes were found");
+      boolean exists_cycle = ret_value.contains("cycle_exists");
+      if( exists_cycle ) System.out.println("one or more cyclic dependency loop found");
+      if( exists_malformed || exists_cycle ) System.out.println("will attempt to build unaffected nodes");
+    }
+
+    return ret_value;
+  }
+  public TokenSet mark_form_graph(LabelList root_node_label_list){
+    return mark_form_graph(root_node_label_list ,true);
+  }
+
+
+  /*--------------------------------------------------------------------------------
+    Graph traversal
+  */
+
+  // Given a node label, looks it up in the dependency graph, returns the node or null
+  public Node lookup(Label node_label ,boolean verbose){
+    if(node_label == null || node_label.isEmpty()){
+      if(verbose) System.out.println("lookup:: given node_label is null or an empty string");
+      return null;
+    }
+
+    // Try the map
+    Node node = this.node_map.get(node_label);
+    if(node != null){
+      node.put("label" ,node_label);
+      if(verbose) System.out.println("lookup:: found from map: " + node);
+      return node;
+    }
+    // At this point, node will be null
+
+    // The map lookup failed, let's try the function recognizer list
+    Node match_result = null;
+    for (RecognizerF func : this.recognizer_f_list){
+      Node match_result = func.apply(node_label); 
+      if("matched".equals(match_result.get("status"))){
+        node = match_result;
+        break;
+      }
+    }
+
+    if(verbose){
+      if(node != null) System.out.println("lookup:: found from recognizer function: " + node);
+      else System.out.println("lookup:: failed to find label: " + node_label);
+    }
+
+    return node;
+  }
+  public Node lookup(Label node_label){
+    return lookup(node_label ,true);
+  }
+
+  // Mark aware lookup function
+  public Node lookup_marked_good(Label node_label ,boolean verbose){
+    Node node = lookup(node_label ,verbose);
+    if(node != null && marked_good_q(node)) return node;
+    return null;
+  }
+  public Node lookup_marked_good(Label node_label){
+    return lookup_marked_good(node_label ,true);
+  }
+
+  /*
+    Given `root_node_label_list` of a DAG, applies `node_function` to each node in a
+    depth-first traversal order. Returns a set of error tokens encountered
+    during traversal.
+
+    `mark_form_graph` must be run on the DAG before this function is called, or
+    `lookup_marked_good` will not function correctly.
+  */
+  public TokenSet all_DAG_DF(LabelList root_node_label_list ,BiConsumer<Node ,TokenSet> node_function ,boolean verbose){
+    if(verbose) System.out.println("all_DAG_DF::");
+
+    TokenSet error_token_set = new HashSet<>();
+
+    boolean accept_arg_list = true;
+    if(node_function == null){
+      error_token_set.add("null_node_function");
+      accept_arg_list = false;
+    }
+    if(!(node_function instanceof BiFunction)){
+      error_token_set.add("node_function_not_a_function");
+      accept_arg_list = false;
+    }
+    if(root_node_label_list == null){
+      error_token_set.add("null_root_node_label_list");
+      accept_arg_list = false;
+    }
+    if(root_node_label_list.isEmpty()){
+      error_token_set.add("empty_root_node_label_list");
+      accept_arg_list = false;
+    }
+    if(!accept_arg_list) return error_token_set;
+
+    TokenSet visited = new HashSet<>();
+    List<Node> in_traversal_order = new ArrayList<>();
+
+    Stack<Label> stack = new Stack<>();
+    root_node_label_list.forEach(stack::push);
+
+    while( !stack.isEmpty() ){
+      Label node_label = stack.pop();
+
+      Node node = lookup_marked_good(node_label ,verbose);
+      if(node == null){
+        error_token_set.add("lookup_fail");
+        continue;
+      }
+
+      if(visited.contains(node.get("label"))) continue;
+      visited.add((Label)node.get("label"));
+
+      in_traversal_order.add(node);
+
+      stack.addAll( (LabelList)node.get("neighbor") );
+    }
+
+    Collections.reverse(in_traversal_order);
+    for(Node node : in_traversal_order){
+      node_function.apply(node ,error_token_set);
+    }
+
+    return error_token_set;
+  }
+  public TokenSet all_DAG_DF(LabelList root_node_label_list ,BiConsumer<Node ,TokenSet> node_function){
+    return all_DAG_DF(root_node_label_list ,node_function ,true);
+  }
+
+  /*--------------------------------------------------------------------------------
+    run the build scripts
+    depends upon is_acyclic having already marked up the graph.
+  */
+
+  // A dependency is "good" if it is marked good, and for leaf or path, if the
+  // corresponding file exists
+  public boolean good_dependency_q(LabelList node_labels){
+    return node_labels.stream().allMatch(node_label -> {
+        Node node = lookup_marked_good(node_label);
+        if( node == null ) return false;
+        if(
+          ("path".equals(node.get("type")) || "leaf".equals(node.get("type")) )
+          && !file_exists_q( (Label) node.get("label") )
+        ){
+          return false;
+        }
+        return true;
+      });
+  }
+
+  /*
+    Given a node label and a list of node labels, returns true if the file at the
+    node label in the first argument is newer than all the files at the
+    corresponding node labels in the second list.
+  */
+  public boolean newer_than_all(Label node_label ,LabelList node_label_list) throws IOException {
+    Path node_path = Paths.get(node_label);
+    if (!Files.exists(node_path)) return false;
+
+    long node_last_modified = Files.getLastModifiedTime(node_path).toMillis();
+
+    return node_label_list.stream().allMatch(label -> {
+        try {
+          Path path = Paths.get(label);
+          if (!Files.exists(path)) return false;
+          long last_modified = Files.getLastModifiedTime(path).toMillis();
+          return node_last_modified > last_modified;
+        } catch (IOException e){
+          return false;
+        }
+      });
+  }
+
+  public boolean can_be_built_q(Node node){
+    if( !marked_good_q(node) ) return false;
+    if(
+       ( "symbol".equals(node.get("type")) || "path".equals(node.get("type")) )
+        && !good_dependency_q( (LabelList)node.get("neighbor") ) 
+    ){
+      return false;
+    }
+    if( 
+       "leaf".equals( node.get("type") ) 
+       && !file_exists_q( (Label)node.get("label") )
+    ){
+      return false;
+    }
+    return true;
+  }
+
+  // `can_be_build_q` must be true for this to be meaningful:
+  public boolean should_be_built_q(Node node ,boolean verbose) throws IOException {
+    if ("leaf".equals(node.get("type"))) return false;
+    if ("symbol".equals(node.get("type"))) return true;
+    if ("path".equals(node.get("type"))) return !newer_than_all((Label) node.get("label") ,(LabelList) node.get("neighbor"));
+    
+    if (verbose){
+      System.out.println("should_be_build_q:: unrecognized node type, so assuming it should not be built.");
+    }
+    return false;
+  }
+  public boolean should_be_built_q(Node node) throws IOException {
+    return should_be_built_q(node ,true);
+  }
+
+  /*
+    Runs the build scripts, assuming the graph has been marked up already.
+  */
+  public void run_build_scripts_f(LabelList root_node_label_list ,boolean verbose) throws IOException {
+
+    if(root_node_label_list.isEmpty()) return;
+
+    TokenSet error_token_set = new HashSet<>(); // used to catch return values
+
+    System.out.println("run_build_script:: Checking if graph is well formed.");
+    error_token_set = mark_form_graph(root_node_label_list);
+    if(error_token_set != null && !error_token_set.isEmpty()){
+      System.out.println("Graph is not well-formed. Expect build problems. Errors:");
+      error_token_set.forEach(token -> System.out.println("  - " + token));
+    } else {
+      System.out.println("Graph is well-formed. Proceeding with build.");
+    }
+
+    // Define the node function
+    BiConsumer<Node ,TokenSet> node_function = (node ,error_token_set_2) -> {
+      if(!can_be_built_q(node)){
+        System.out.println("run_build_scripts_f:: Skipping build for " + node.get("label") + " due to problems with dependencies.");
+        return;
+      }
+      if(!should_be_built_q(node)){
+        if(verbose) System.out.println("run_build_scripts_f:: " + node.get("label") + " already up to date");
+        return;
+      }
+
+      // Build the target
+      System.out.println("run_build_scripts_f:: Running build script for " + node.get("label"));
+      // Assuming node.build() is a method in the Map or a related object
+      // Replace this with the actual build function for the node
+      // node.build();
+
+      // For path nodes, check if the build updated the target path
+      if("path".equals(node.get("type")) && should_be_built_q(node)){
+        System.out.println("run_build_scripts_f:: Build failed for " + node.get("label"));
+        set_mark(node ,"build_failed");
+      }
+    };
+
+    System.out.println("run_build_scripts_f:: running ...");
+    error_token_set = all_DAG_DF(root_node_label_list ,node_function ,verbose);
+    if(error_token_set != null){
+      error_token_set.forEach(error -> System.out.println("run_build_scripts_f::all_DAG_DF:: " + error));
+    }
+  }
+  public void run_build_scripts_f(LabelList root_node_label_list) throws IOException {
+    run_build_scripts_f(root_node_label_list ,true);
+  }
+
+}
diff --git a/developer/javac/Green.java b/developer/javac/Green.java
new file mode 100644 (file)
index 0000000..cf16a88
--- /dev/null
@@ -0,0 +1,7 @@
+package com.ReasoningTechnology.PaintIt;
+
+public class Green extends Blue  {
+  public static void print(){
+    System.out.println("Paint it green.");
+  }
+}
diff --git a/developer/javac/PaintItBlack.java b/developer/javac/PaintItBlack.java
deleted file mode 100644 (file)
index 7f41717..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-import com.ReasoningTechnology.Ariadna.*;
-
-public class PaintItBlack {
-  public static void main(String[] args) {
-    System.out.println("Paint it black.");
-  }
-}
diff --git a/developer/jvm/.gitignore b/developer/jvm/.gitignore
new file mode 100644 (file)
index 0000000..120f485
--- /dev/null
@@ -0,0 +1,2 @@
+*
+!/.gitignore
diff --git a/developer/shell/.githolder b/developer/shell/.githolder
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/developer/shell/black b/developer/shell/black
new file mode 100755 (executable)
index 0000000..d94d9cb
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Black
diff --git a/developer/shell/blue b/developer/shell/blue
new file mode 100755 (executable)
index 0000000..387f82a
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Blue
diff --git a/developer/shell/green b/developer/shell/green
new file mode 100755 (executable)
index 0000000..9611a51
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Green
diff --git a/developer/tool/#make_PaintIt# b/developer/tool/#make_PaintIt#
new file mode 100755 (executable)
index 0000000..dbd9959
--- /dev/null
@@ -0,0 +1,70 @@
+#!/bin/env bash
+
+if [ -z "$ENV_DEV" ]; then
+  echo "make_PaintIt:: script can only be run from the developer environment"
+  return 1
+fi
+
+# Ensure we are in the right directory
+cd "$REPO_HOME"/developer
+
+# Start with a fresh scratch_pad and remove a prior jvm
+# Depending, this is unnecessary and might even be undesirable.
+# Better to clean up the stuff we will rewrite instead of everything.
+# But for testing and in an unstable environment, this is probably best.
+echo "Starting with a clean scratch_pad and jvm directories..."
+rm -rf scratch_pad/*
+rm -rf jvm/PaintIt.jar
+
+# Compile all files (Black.java and Blue.java) with the correct package
+echo "Compiling files..."
+javac -d scratch_pad javac/Black.java javac/Blue.java javac/Green.java
+
+if [ $? -ne 0 ]; then
+  echo "Compilation failed."
+  exit 1
+fi
+
+# Create a JAR file from the compiled class files with correct package structure
+echo "Creating JAR file..."
+mkdir -p jvm
+jar cf jvm/PaintIt.jar -C scratch_pad .
+
+if [ $? -eq 0 ]; then
+  echo "JAR file created successfully: jvm/PaintIt.jar"
+else
+  echo "Failed to create JAR file."
+  exit 1
+fi
+
+# cleanup the scratch_pad
+# Depending, this is unnecessary and might even be undesirable.
+# Would be better to clean up the stuff we wrote instead of everything.
+# But for testing and in an unstable environment, this is probably best.
+echo "Starting with a clean scratch_pad and jvm directories..."
+rm -rf scratch_pad/*
+
+# Create shell wrappers in developer/shell for easy execution
+echo "Creating shell wrappers..."
+mkdir -p shell
+
+cat > shell/black << EOL
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Black
+EOL
+chmod +x shell/black
+
+cat > shell/blue << EOL
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Blue
+EOL
+chmod +x shell/blue
+
+cat > shell/green << EOL
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Green
+EOL
+chmod +x shell/green
+
+echo "Shell wrappers created successfully: black, blue, green"
+
index a651d09..2f35259 100644 (file)
@@ -15,21 +15,28 @@ if [ "$env_error" = true ]; then
   return 1
 fi
 
-export JAVA_HOME="$REPO_HOME/tool/jdk-11"
-export GROOVY_HOME="$REPO_HOME/tool/groovy-4.0.9"
+# goovy use has been deprecated
+# export GROOVY_HOME="$REPO_HOME/tool_shared/third_party/groovy-4.0.9"
 
+# third party tools we will use
+export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-11"
 export PATH=\
-"$REPO_HOME"/developer/shell\
-:"$JAVA_HOME"/bin\
-:"$GROOVY_HOME"/bin\
+"$JAVA_HOME"/bin\
 :"$PATH"
 
+# where the tool build finds its class files:
 export CLASSPATH=\
 "$REPO_HOME"/developer/jvm\
+:"$REPO_HOME"/developer/jvm/PaintIt.jar\
 :"$REPO_HOME"/developer/jvm/Ariadne.jar\
 :"$JAVA_HOME"/lib\
-:"$GROOVY_HOME"/lib\
 :"$CLASSPATH"
 
+# after we building the tool we might want to run it
+# the shell directory holds the bash UI wrappers
+export PATH=\
+"$REPO_HOME"/developer/shell\
+:"$PATH"
+
 export ENV_DEV_BUILD=true
 echo "${BASH_SOURCE[0]}" "complete"
diff --git a/developer/tool/make b/developer/tool/make
new file mode 100755 (executable)
index 0000000..b87d6c3
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/env bash
+
+if [ -z "$ENV_DEV" ]; then
+  echo "make.sh:: script can only be run from the developer environment"
+  return 1
+fi
+
+# Ensure we are in the right directory
+cd "$REPO_HOME"/developer
+
+# Clean the scratch_pad and jvm directories
+echo "Cleaning scratch_pad and jvm directories..."
+rm -rf scratch_pad/*
+rm -rf jvm/*
+
+# Compile all files
+echo "Compiling files..."
+javac -sourcepath javac:java_namespace -d scratch_pad javac/Black.java
+
+if [ $? -ne 0 ]; then
+  echo "Compilation failed."
+  exit 1
+fi
+
+# Create a JAR file from the compiled class files
+echo "Creating JAR file..."
+mkdir -p jvm
+jar cf jvm/Ariadne.jar -C scratch_pad .
+
+if [ $? -eq 0 ]; then
+  echo "JAR file created successfully: jvm/Ariadne.jar"
+else
+  echo "Failed to create JAR file."
+  exit 1
+fi
diff --git a/developer/tool/make.sh b/developer/tool/make.sh
deleted file mode 100755 (executable)
index 37ff783..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/env bash
-
-if [ -z "$ENV_DEV" ]; then
-  echo "make.sh:: script can only be run from the developer environment"
-  return 1
-fi
-
-# Ensure we are in the right directory
-cd "$REPO_HOME"/developer
-
-# Clean the scratch_pad and jvm directories
-echo "Cleaning scratch_pad and jvm directories..."
-rm -rf scratch_pad/*
-rm -rf jvm/*
-
-# Compile all files
-echo "Compiling files..."
-javac javac/*.java -d scratch_pad
-
-if [ $? -ne 0 ]; then
-  echo "Compilation failed."
-  exit 1
-fi
-
-# Create a JAR file from the compiled class files
-echo "Creating JAR file..."
-mkdir -p jvm
-jar cf jvm/Ariadne.jar -C scratch_pad .
-
-if [ $? -eq 0 ]; then
-  echo "JAR file created successfully: jvm/Ariadne.jar"
-else
-  echo "Failed to create JAR file."
-  exit 1
-fi
diff --git a/developer/tool/make_PaintIt b/developer/tool/make_PaintIt
new file mode 100755 (executable)
index 0000000..177dd1c
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/env bash
+
+if [ -z "$ENV_DEV" ]; then
+  echo "make_PaintIt:: script can only be run from the developer environment"
+  return 1
+fi
+
+# Ensure we are in the right directory
+cd "$REPO_HOME"/developer
+
+# Start with a fresh scratch_pad and remove a prior jvm
+# Depending, this is unnecessary and might even be undesirable.
+# Better to clean up the stuff we will rewrite instead of everything.
+# But for testing and in an unstable environment, this is probably best.
+echo "Starting with a clean scratch_pad and jvm directories..."
+rm -rf scratch_pad/*
+rm -rf jvm/PaintIt.jar
+
+# Compile all files (Black.java and Blue.java) with the correct package
+echo "Compiling files..."
+javac -d scratch_pad javac/Black.java javac/Blue.java javac/Green.java
+
+if [ $? -ne 0 ]; then
+  echo "Compilation failed."
+  exit 1
+fi
+
+# Create a JAR file from the compiled class files with correct package structure
+echo "Creating JAR file..."
+mkdir -p jvm
+jar cf jvm/PaintIt.jar -C scratch_pad .
+
+if [ $? -eq 0 ]; then
+  echo "JAR file created successfully: jvm/PaintIt.jar"
+else
+  echo "Failed to create JAR file."
+  exit 1
+fi
+
+# cleanup the scratch_pad
+# Depending, this is unnecessary and might even be undesirable.
+# Would be better to clean up the stuff we wrote instead of everything.
+# But for testing and in an unstable environment, this is probably best.
+echo "Starting with a clean scratch_pad and jvm directories..."
+rm -rf scratch_pad/*
+
+# Create shell wrappers in developer/shell for easy execution
+echo "Creating shell wrappers..."
+mkdir -p shell
+
+cat > shell/black << EOL
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Black
+EOL
+chmod +x shell/black
+
+cat > shell/blue << EOL
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Blue
+EOL
+chmod +x shell/blue
+
+cat > shell/green << EOL
+#!/bin/bash
+java com/ReasoningTechnology/PaintIt/Green
+EOL
+chmod +x shell/green
+
+
+echo "Shell wrappers created successfully: black, blue, green"
+
diff --git a/document/directory_naming.html b/document/directory_naming.html
new file mode 100644 (file)
index 0000000..105bbc3
--- /dev/null
@@ -0,0 +1,169 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Directory Structure Description</title>
+  <style>
+    body {
+      background-color: hsl(0, 0%, 0%);
+      color: hsl(42, 100%, 80%);
+      font-family: monospace;
+      padding: 20px;
+      margin: 0;
+    }
+    .page {
+      padding: 20px;
+      margin: 20px auto;
+      max-width: 800px;
+      background-color: hsl(0, 0%, 10%);
+      box-shadow: 0 0 10px hsl(42, 100%, 50%);
+    }
+    ul, li {
+      list-style-type: none;
+    }
+    li::before {
+      content: "📁 ";
+      margin-right: 5px;
+    }
+    li {
+      margin-bottom: 5px;
+    }
+    .description {
+      margin-left: 10px;
+      color: hsl(42, 100%, 60%);
+    }
+    h1 {
+      text-align: center;
+      color: hsl(42, 100%, 80%);
+      text-transform: uppercase;
+      margin-bottom: 20px;
+    }
+    h2 {
+      color: hsl(42, 100%, 80%);
+      text-transform: uppercase;
+      margin-top: 40px;
+    }
+    p {
+      color: hsl(42, 100%, 70%);
+      margin-bottom: 20px;
+    }
+  </style>
+</head>
+<body>
+
+  <div class="page">
+    <h1>Directory Naming</h1>
+
+    <h2>Reference</h2>
+
+    <ul>
+      <li>/var/user_data/Thomas-developer/Ariadne</li>
+      <ul>
+        <li>developer/ <span class="description">The workspace for developers to organize source code, build scripts, and development-specific tools.</span></li>
+        <ul>
+          <li>deprecated/ <span class="description">Archived files and older versions no longer in active use.</span></li>
+          <li>document/ <span class="description">Developer-level documentation for building and understanding the project.</span></li>
+          <li>javac/ <span class="description">Java source files prepared for compilation.</span></li>
+          <li>jvm/ <span class="description">Compiled Java bytecode files for the project.</span></li>
+          <li>scratch_pad/ <span class="description">Temporary storage for intermediate files during development.</span></li>
+          <li>shell/ <span class="description">Shell scripts intended to be part of the project release or build automation.</span></li>
+          <li>tool/ <span class="description">Developer-specific tools used for building or managing development tasks.</span></li>
+        </ul>
+        <li>document/ <span class="description">Top-level project documentation for project managers or contributors.</span></li>
+        <li>release_candidate/ <span class="description">Builds and packages ready for testing and release preparation.</span></li>
+        <li>scratch_pad/ <span class="description">Temporary storage for project management tasks.</span></li>
+        <li>tester/ <span class="description">Files and tools for managing and running test environments.</span></li>
+        <ul>
+          <li>document/ <span class="description">Test-specific documentation for procedures and setups.</span></li>
+          <li>test0/ <span class="description">Test case 0 environment and associated scripts.</span></li>
+          <li>test1/ <span class="description">Test case 1 environment and associated scripts.</span></li>
+          <li>test2/ <span class="description">Test case 2 environment and associated scripts.</span></li>
+          <li>tool/ <span class="description">Tools needed for testing and managing the test environment.</span></li>
+        </ul>
+        <li>tool/ <span class="description">Project management/administration specific tools.</span></li>
+        <li>tool_shared/ <span class="description">Tools shared across project roles.</span></li>
+        <ul>
+          <li>bespoke/ <span class="description">Tools developed specifically for this project.</span></li>
+          <li>customized/ <span class="description">Modified versions of third-party tools adapted for the project.</span></li>
+          <li>document/ <span class="description">Documentation related to shared tools and setup.</span></li>
+          <li>third_party/ <span class="description">Tools sourced from third-party vendors or open-source projects.</span></li>
+        </ul>
+        <li>LICENSE.txt <span class="description">The project license detailing usage and distribution terms.</span></li>
+        <li>README.md <span class="description">A general overview and introduction to the project.</span></li>
+      </ul>
+    </ul>
+
+
+    <h2>Name origin and rationale</h2>
+
+    <p>Typically, developers and project administrators do not employ a semantic
+      system for naming directories, but more commonly use conventional
+      placeholder names. The intended purpose of files in a directory with a
+      placeholder name then must be inferred from experience or inspection of
+      the files, or learned from other people or from documents.</p>
+
+    <p>For example, a directory named 'exe/' probably derives its name from the
+      fact that the contained files have their executable permission bit set;
+      however, such a directory will not contain all such files.  There might
+      even be some files in an `exe/` directory that do not have their
+      executable permission bit set. The two concepts being an `exe/` file
+      (i.e. being a file in an `exe/` directory) and being an executable file
+      are not identical. The actual intended meaning of being an `exe/` file
+      will sometimes be that the contained files are applications available to a
+      user, or that they are tools available for use in a project.
+    </p>
+
+    <p>The directory names in this project resulted from an exploration of a
+      property-based file system. In such a system a number of files and
+      agents are defined. Then we can ask questions about their relationships.
+      Files with a relationship to the developer are collected, and this
+      becomes the `developer/` directory. In a similar manner we get the
+      directories, `tester/', and `javac/`.  In this latter case the
+      agent is a compiler rather than a role.
+      </p>
+      
+    <p>However, when attempting applying this method in practice it became
+      apparent that the recognition of relationships was insufficient.  Consider
+      the directories `deprecated` and `scratch_pad`. There is no
+      'Mr. Deprecated' or 'Mr. Scratch_Pad' who the contained files are
+      for. (And this conclusion is not for the lack of trying. Even mythological
+      beings did not suffice as agents.) Rather than saying a file has a
+      relationship with an agent, these properties (directory names) are states
+      imposed by decree by an agent on a file.  Perhaps the developer, has
+      decreed that a file is now deprecated, or a build script has decreed that
+      it is a scratch_pad file. Such decrees are typically more dynamic than the
+      relationship properties. Also, these properties are disconnected from the
+      contents of the file.  When, for example, we say a file is for the java
+      compiler we can surmise something about its contents. However when we say
+      a file is `deprecated` we can surmise nothing about its contents.
+      </p>
+
+    <p>To understand a directory name within this system, one can imagine
+      reading said name as part of a sentence that integrates the
+      property. Consider two property names: 'is-a' and 'is-for'. For example,
+      "Each file in the <code>document/</code> directory is a document," or
+      "Each file in the <code>developer/</code> directory is for the developer."
+      Although the property name is not carried over to the conventional file
+      system, we can typically infer what it must be. It is beyond the scope of
+      discussion here, but in actuality, our collections are defined by
+      predicates that are given a file's properties and relationships as
+      arguments, where the predicate resolves to true if and only if the file
+      belongs to the collection. Now wouldn't that be interesting if we
+      instead derived a probability?
+    </p>
+
+    <p>It is uncommon for a property value to be plural. While it is not
+      disallowed, it rarely occurs in practice. This is true independent of
+      whether we are discussing a relationship property or a state
+      property. Hence when we make a file collection based on a shared property,
+      then carry that over as a directory name in a conventional file system,
+      the resulting directory name will often be singular.  This pattern can be
+      observed in the case of the `document/` directory, as shown in the prior
+      paragraph.
+    </p>
+
+  </div>
+
+</body>
+</html>
diff --git a/document/directory_structure_description.html b/document/directory_structure_description.html
deleted file mode 100644 (file)
index cbe1950..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="UTF-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <title>Directory Structure Description</title>
-  <style>
-    body {
-      background-color: hsl(0, 0%, 0%);
-      color: hsl(42, 100%, 80%);
-      font-family: monospace;
-      padding: 20px;
-      margin: 0;
-    }
-    .page {
-      padding: 20px;
-      margin: 20px auto;
-      max-width: 800px;
-      background-color: hsl(0, 0%, 10%);
-      box-shadow: 0 0 10px hsl(42, 100%, 50%);
-    }
-    ul, li {
-      list-style-type: none;
-    }
-    li::before {
-      content: "📁 ";
-      margin-right: 5px;
-    }
-    li {
-      margin-bottom: 5px;
-    }
-    .description {
-      margin-left: 10px;
-      color: hsl(42, 100%, 60%);
-    }
-    h1 {
-      text-align: center;
-      color: hsl(42, 100%, 80%);
-      text-transform: uppercase;
-      margin-bottom: 20px;
-    }
-    h2 {
-      color: hsl(42, 100%, 80%);
-      text-transform: uppercase;
-      margin-top: 40px;
-    }
-    p {
-      color: hsl(42, 100%, 70%);
-      margin-bottom: 20px;
-    }
-  </style>
-</head>
-<body>
-
-  <div class="page">
-    <h1>Directory Structure Description</h1>
-
-    <h2>Reference</h2>
-
-    <ul>
-      <li>/var/user_data/Thomas-developer/Ariadne</li>
-      <ul>
-        <li>developer/ <span class="description">The workspace for developers to organize source code, build scripts, and development-specific tools.</span></li>
-        <ul>
-          <li>deprecated/ <span class="description">Archived files and older versions no longer in active use.</span></li>
-          <li>document/ <span class="description">Developer-level documentation for building and understanding the project.</span></li>
-          <li>javac/ <span class="description">Java source files prepared for compilation.</span></li>
-          <li>jvm/ <span class="description">Compiled Java bytecode files for the project.</span></li>
-          <li>scratch_pad/ <span class="description">Temporary storage for intermediate files during development.</span></li>
-          <li>shell/ <span class="description">Shell scripts intended to be part of the project release or build automation.</span></li>
-          <li>tool/ <span class="description">Developer-specific tools used for building or managing development tasks.</span></li>
-        </ul>
-        <li>document/ <span class="description">Top-level project documentation for project managers or contributors.</span></li>
-        <li>release_candidate/ <span class="description">Builds and packages ready for testing and release preparation.</span></li>
-        <li>scratch_pad/ <span class="description">Temporary storage for project management tasks.</span></li>
-        <li>tester/ <span class="description">Files and tools for managing and running test environments.</span></li>
-        <ul>
-          <li>document/ <span class="description">Test-specific documentation for procedures and setups.</span></li>
-          <li>test0/ <span class="description">Test case 0 environment and associated scripts.</span></li>
-          <li>test1/ <span class="description">Test case 1 environment and associated scripts.</span></li>
-          <li>test2/ <span class="description">Test case 2 environment and associated scripts.</span></li>
-          <li>tool/ <span class="description">Tools needed for testing and managing the test environment.</span></li>
-        </ul>
-        <li>tool/ <span class="description">Project management/administration specific tools.</span></li>
-        <li>tool_shared/ <span class="description">Tools shared across project roles.</span></li>
-        <ul>
-          <li>bespoke/ <span class="description">Tools developed specifically for this project.</span></li>
-          <li>customized/ <span class="description">Modified versions of third-party tools adapted for the project.</span></li>
-          <li>document/ <span class="description">Documentation related to shared tools and setup.</span></li>
-          <li>third_party/ <span class="description">Tools sourced from third-party vendors or open-source projects.</span></li>
-        </ul>
-        <li>LICENSE.txt <span class="description">The project license detailing usage and distribution terms.</span></li>
-        <li>README.md <span class="description">A general overview and introduction to the project.</span></li>
-      </ul>
-    </ul>
-
-
-    <h2>Name origin and rationale</h2>
-
-    <p>Typically, developers and project administrators do not employ a semantic
-      system for naming directories, but more commonly use conventional
-      placeholder names. The intended purpose of files in a directory with a
-      placeholder name then must be inferred from experience or inspection of
-      the files, or learned from other people or from documents.</p>
-
-    <p>For example, a directory named 'exe/' probably derives its name from the
-      fact that the contained files have their executable permission bit set;
-      however, such a directory will not contain all such files.  There might
-      even be some files in an `exe/` directory that do not have their
-      executable permission bit set. The two concepts being an `exe/` file
-      (i.e. being a file in an `exe/` directory) and being an executable file
-      are not identical. The actual intended meaning of being an `exe/` file
-      will sometimes be that the contained files are applications available to a
-      user, or that they are tools available for use in a project.
-    </p>
-
-    <p>The directory names in this project resulted from an exploration of a
-      property-based file system. In such a system a number of files and
-      agents are defined. Then we can ask questions about their relationships.
-      Files with a relationship to the developer are collected, and this
-      becomes the `developer/` directory. In a similar manner we get the
-      directories, `tester/', and `javac/`.  In this latter case the
-      agent is a compiler rather than a role.
-      </p>
-      
-    <p>However, when attempting this it became apparent that the recognition of
-      relationships was insufficient.  Consider the directories `deprecated` and
-      `scratch_pad`. There is no 'Mr. Deprecated' or 'Mr. Scratch_Pad' who the
-      contained files are for. (And this conclusion is not for the lack of
-      trying. Even mythological beings did not suffice as agents.) Rather than
-      saying a file has a relationship with an agent, these properties
-      (directory names) are states imposed by decree by an agent on a file.
-      Perhaps the developer, has decreed that a file is now deprecated, or a
-      build script has decreed that it is a scratch_pad file. Such decrees are
-      typically more dynamic than the relationship properties. Also, these
-      properties are also disconnected from the contents of the file.  When, for
-      example, we say a file is for the java compiler we can surmise something
-      about its contents. However when we say a file is `deprecated` we can
-      surmise nothing about its contents.
-      </p>
-
-    <p>To understand a directory name within this system, one can imagine
-      reading said name as part of a sentence that integrates the
-      property. Consider two property names: 'is-a' and 'is-for'. For example,
-      "Each file in the <code>document/</code> directory is a document," or
-      "Each file in the <code>developer/</code> directory is for the developer."
-      Although the property name is not carried over to the conventional file
-      system, we can typically infer what it must be. It is beyond the scope of
-      discussion here, but in actuality, our collections are defined by
-      predicates that are given a file's properties and relationships as
-      arguments, where the predicate resolves to true if and only if the file
-      belongs to the collection. Now wouldn't that be interesting if we
-      instead derived a probability?
-    </p>
-
-    <p>It is uncommon for a property value to be plural. While it is not
-      disallowed, it rarely occurs in practice. This is true independent of
-      whether we are discussing a relationship property or a state
-      property. Hence when we make a file collection based on a shared property,
-      then carry that over as a directory name in a conventional file system,
-      the resulting directory name will often be singular.  This pattern can be
-      observed in the case of the `document/` directory, as shown in the prior
-      paragraph.
-    </p>
-
-  </div>
-
-</body>
-</html>
diff --git a/release_candidate/AriadneGraph$_all_DAG_DF_closure10.class b/release_candidate/AriadneGraph$_all_DAG_DF_closure10.class
deleted file mode 100644 (file)
index ed70dc4..0000000
Binary files a/release_candidate/AriadneGraph$_all_DAG_DF_closure10.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_all_DAG_DF_closure7.class b/release_candidate/AriadneGraph$_all_DAG_DF_closure7.class
deleted file mode 100644 (file)
index f1873bb..0000000
Binary files a/release_candidate/AriadneGraph$_all_DAG_DF_closure7.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_all_DAG_DF_closure8.class b/release_candidate/AriadneGraph$_all_DAG_DF_closure8.class
deleted file mode 100644 (file)
index 89bfd7b..0000000
Binary files a/release_candidate/AriadneGraph$_all_DAG_DF_closure8.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_all_DAG_DF_closure9.class b/release_candidate/AriadneGraph$_all_DAG_DF_closure9.class
deleted file mode 100644 (file)
index c659646..0000000
Binary files a/release_candidate/AriadneGraph$_all_DAG_DF_closure9.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_good_dependency_q_closure10.class b/release_candidate/AriadneGraph$_good_dependency_q_closure10.class
deleted file mode 100644 (file)
index ac3b277..0000000
Binary files a/release_candidate/AriadneGraph$_good_dependency_q_closure10.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_good_dependency_q_closure11.class b/release_candidate/AriadneGraph$_good_dependency_q_closure11.class
deleted file mode 100644 (file)
index 85adf52..0000000
Binary files a/release_candidate/AriadneGraph$_good_dependency_q_closure11.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_mark_node_form_closure3.class b/release_candidate/AriadneGraph$_mark_node_form_closure3.class
deleted file mode 100644 (file)
index 3daa7a4..0000000
Binary files a/release_candidate/AriadneGraph$_mark_node_form_closure3.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_mark_node_form_closure4.class b/release_candidate/AriadneGraph$_mark_node_form_closure4.class
deleted file mode 100644 (file)
index add9310..0000000
Binary files a/release_candidate/AriadneGraph$_mark_node_form_closure4.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_markup_graph_f_descend_closure4.class b/release_candidate/AriadneGraph$_markup_graph_f_descend_closure4.class
deleted file mode 100644 (file)
index 4bd2cf5..0000000
Binary files a/release_candidate/AriadneGraph$_markup_graph_f_descend_closure4.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_markup_graph_f_descend_closure5.class b/release_candidate/AriadneGraph$_markup_graph_f_descend_closure5.class
deleted file mode 100644 (file)
index cb560b7..0000000
Binary files a/release_candidate/AriadneGraph$_markup_graph_f_descend_closure5.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_markup_graph_f_descend_closure6.class b/release_candidate/AriadneGraph$_markup_graph_f_descend_closure6.class
deleted file mode 100644 (file)
index 2e4ac45..0000000
Binary files a/release_candidate/AriadneGraph$_markup_graph_f_descend_closure6.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_markup_graph_f_descend_closure7.class b/release_candidate/AriadneGraph$_markup_graph_f_descend_closure7.class
deleted file mode 100644 (file)
index 1163929..0000000
Binary files a/release_candidate/AriadneGraph$_markup_graph_f_descend_closure7.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_newer_than_all_closure11.class b/release_candidate/AriadneGraph$_newer_than_all_closure11.class
deleted file mode 100644 (file)
index e895c0e..0000000
Binary files a/release_candidate/AriadneGraph$_newer_than_all_closure11.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_newer_than_all_closure12.class b/release_candidate/AriadneGraph$_newer_than_all_closure12.class
deleted file mode 100644 (file)
index 9a78dbf..0000000
Binary files a/release_candidate/AriadneGraph$_newer_than_all_closure12.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_run_build_scripts_f_closure12.class b/release_candidate/AriadneGraph$_run_build_scripts_f_closure12.class
deleted file mode 100644 (file)
index 4867af2..0000000
Binary files a/release_candidate/AriadneGraph$_run_build_scripts_f_closure12.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_run_build_scripts_f_closure13.class b/release_candidate/AriadneGraph$_run_build_scripts_f_closure13.class
deleted file mode 100644 (file)
index 1d0d9f0..0000000
Binary files a/release_candidate/AriadneGraph$_run_build_scripts_f_closure13.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_run_build_scripts_f_closure14.class b/release_candidate/AriadneGraph$_run_build_scripts_f_closure14.class
deleted file mode 100644 (file)
index 3536604..0000000
Binary files a/release_candidate/AriadneGraph$_run_build_scripts_f_closure14.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_run_build_scripts_f_closure15.class b/release_candidate/AriadneGraph$_run_build_scripts_f_closure15.class
deleted file mode 100644 (file)
index 54f1db3..0000000
Binary files a/release_candidate/AriadneGraph$_run_build_scripts_f_closure15.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_wellformed_q_closure1.class b/release_candidate/AriadneGraph$_wellformed_q_closure1.class
deleted file mode 100644 (file)
index e774627..0000000
Binary files a/release_candidate/AriadneGraph$_wellformed_q_closure1.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_wellformed_q_closure2.class b/release_candidate/AriadneGraph$_wellformed_q_closure2.class
deleted file mode 100644 (file)
index d029042..0000000
Binary files a/release_candidate/AriadneGraph$_wellformed_q_closure2.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph$_wellformed_q_closure3.class b/release_candidate/AriadneGraph$_wellformed_q_closure3.class
deleted file mode 100644 (file)
index 36db685..0000000
Binary files a/release_candidate/AriadneGraph$_wellformed_q_closure3.class and /dev/null differ
diff --git a/release_candidate/AriadneGraph.class b/release_candidate/AriadneGraph.class
deleted file mode 100644 (file)
index 8fd3e35..0000000
Binary files a/release_candidate/AriadneGraph.class and /dev/null differ
diff --git a/release_candidate/build b/release_candidate/build
deleted file mode 100755 (executable)
index f28d6ce..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env groovy
-
-// Function to load the graph class dynamically
-def include_a_class(a_class_fp) {
-  def class_loader = this.class.classLoader
-  def class_name = a_class_fp.replace('/', '.').replace('.class', '')
-  try {
-    return class_loader.loadClass(class_name)
-  } catch (Exception e) {
-    println "Error loading class '${class_name}': ${e.message}"
-    return null
-  }
-}
-
-/*
-// Function to load the graph class dynamically
-def include_a_class( a_class_fp ){
-  def class_loader = this.class.classLoader
-  try{
-    return class_loader.loadClass(a_class_fp)
-  } catch(Exception e){
-    return null
-  }
- }
- */
-
-// Shell User Interface to the build function
-def build(graph_definition_fp, root_node_labels){
-
-  // Print summary of what we are doing
-  println "build:: Building targets for graph '${graph_definition_fp}.class'"
-  if (root_node_labels.isEmpty()) {
-    println "No build targets specified. Please provide root node labels to build."
-    System.exit(0)
-  }
-  println "Building targets: ${root_node_labels.join(', ')}"
-
-  // Load the dependency graph class from arg[1]
-  def graph_definition_class = include_a_class(graph_definition_fp)
-  if(graph_definition_class){
-    println "build:: loaded ${graph_definition_fp}.class"
-  } else{
-    println "build:: failed to load ${graph_definition_fp}.class"
-    System.exit(1)
-  }
-
-  // Get the node_map and node_f_list from the graph class
-  def node_map = graph_definition_class.get_node_map()
-  def node_f_list = graph_definition_class.get_node_f_list()
-  println "node_map: ${node_map}"
-  println "node_f_list: ${node_f_list}"
-
-  // Create an instance of AriadneGraph, and run the build scripts
-  def graph = new AriadneGraph(node_map ,node_f_list)
-  graph.run_build_scripts_f(root_node_labels)
-}
-
-// Entry point for the script
-if(args.length == 0){
-  println "Usage: ./build <graph_definition.class> [root_node_labels...]"
-  System.exit(1)
-}
-
-// Get graph definition file and root node labels
-def graph_definition_fp = args[0]
-def root_node_labels = args.length > 1 ? args[1..-1] : []
-build(graph_definition_fp, root_node_labels)
-
diff --git a/tool/env_administrator b/tool/env_administrator
new file mode 100644 (file)
index 0000000..84ec125
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+
+# Ensure the script is sourced
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "This script must be sourced, not executed. Exiting."
+  return 1
+fi
+
+if [ -z "$ENV_BASE" ]; then
+  script_path="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
+  source "${script_path}/env_base"
+fi
+
+ENV_PM=true
+
+PROJECT="$PROJECT"_PMg
+
+export PATH=\
+"$REPO_HOME"/tool\
+:"$PATH"
+
+# no sneaky hidden files
+alias ls="ls -a"
+
+
+export ENV_PM=true
+echo "${BASH_SOURCE[0]}" "complete"
diff --git a/tool/env_dev b/tool/env_dev
deleted file mode 100644 (file)
index fa1076c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-
-# Ensure the script is sourced
-if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
-  echo "This script must be sourced, not executed. Exiting."
-  return 1
-fi
-
-if [ -z "$ENV_BASE" ]; then
-  script_path="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
-  source "${script_path}/env_base"
-fi
-
-export PATH="$REPO_HOME/developer/executable":"$PATH"
-
-# so the .gitignore files can be seen:
-alias ls="ls -a"
-
-cd "$REPO_HOME/developer"
-
-export ENV_DEV=true
-source "$REPO_HOME"/developer/executable/env_build
-echo "${BASH_SOURCE[0]}" "complete"
-
-
-
diff --git a/tool/env_developer b/tool/env_developer
new file mode 100644 (file)
index 0000000..7132218
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+# Ensure the script is sourced
+if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
+  echo "This script must be sourced, not executed. Exiting."
+  return 1
+fi
+
+if [ -z "$ENV_BASE" ]; then
+  script_path="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
+  source "${script_path}/env_base"
+fi
+
+PROJECT="$PROJECT"_DEVELOPER
+
+export PATH=\
+"$REPO_HOME/developer/tool"\
+:"$PATH"
+
+# so the .gitignore files can be seen:
+alias ls="ls -a"
+
+cd "$REPO_HOME/developer"
+
+export ENV_DEV=true
+source "$REPO_HOME"/developer/tool/env_build
+echo "${BASH_SOURCE[0]}" "complete"
+
+
+
diff --git a/tool/env_pm b/tool/env_pm
deleted file mode 100644 (file)
index 5f614d1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-
-# Ensure the script is sourced
-if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
-  echo "This script must be sourced, not executed. Exiting."
-  return 1
-fi
-
-if [ -z "$ENV_BASE" ]; then
-  script_path="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
-  source "${script_path}/env_base"
-fi
-
-ENV_PM=true
-
-PROJECT="$PROJECT"_PM
-
-export PATH=\
-"$REPO_HOME"/executor\
-:"$PATH"
-
-# no sneaky hidden files
-alias ls="ls -a"
-
-
-export ENV_PM=true
-echo "${BASH_SOURCE[0]}" "complete"