My ultimate goal here is to making binding work easier for SDL programmers by using a file motif, like, eg, rm below.

Suggested Code with testing

// run via
//
//   vmake -results
//
// testing string to binding
// and related funcs

// (setq indent-tabs-mode nil)

{


// functions like these should probaby eventually wind up in generics
//  . ++= generics();




  // from /vesta/beta.vestasys.org/bridges/make_compat/latest/build.ves
  // latest -> 6/
  //
  // split like perl
  /**nocache**/
  split_text(sep:text, intext:text)
  {
    pos = _find(intext, sep);
    return if pos == -1 then <intext>
    else {
      start = _sub(intext, 0, pos);
      rest = _sub(intext, pos+1);
      value <start>+split_text(sep, rest);
    };
  };

  // with default sep, and trim meaning dont return "" for leading or trailing sep
  /**nocache**/
  split(intext:text, sep:text = "/", trim = FALSE, err = "error in split")
  {
    rtn = split_text(sep, intext);
    rtn = if trim
          then {
            rtn_trimmed = < >;
            foreach elem in rtn do {
              rtn_trimmed += if elem == "" then < > else <elem>;
            };
            return rtn_trimmed;
          } else rtn;
    return rtn;
  };



  // john's code
  // turns "a/b/c" into [ a = [ b = [ c = 1 ] ]
  /**nocache**/
  string_to_binding(intext:text, sep:text = "/") : binding
  {
    pos = _find(intext, sep);
    res = if pos == -1
                   then [ $intext = 1 ]
                   else {
                     elem = _sub(intext, 0, pos);
                     rest = _sub(intext, pos+1);
                     value [ $elem = string_to_binding(rest, sep) ];
                   };
    return res;
  };


  // from /vesta/beta.vestasys.org/bridges/make_compat/latest/build.ves
  // latest -> 6/
  //
  // given list of strings, recursively look up that binding
  /**nocache**/
  lookup_path_l(b: binding, l: list(text), err: any = []): any {
    res = if _length(l) == 0 then b else {
      n = _head(l);
      value if (_is_binding(b) && b!$n)
      then lookup_path_l(b/$n, _tail(l), err)
      else err;
    };
    return res;
  };

  // from /vesta/beta.vestasys.org/bridges/make_compat/latest/build.ves
  // latest -> 6/
  //
  // given "a/b/c" look that up in root (by using split text then calling path-value)
  /**nocache**/
  lookup_path_t(b : binding, path : text, err : any = [ ]) : binding {
    arc_list = split_text("/", path);
    return lookup_path_l(b, arc_list, err);
  };













  // from : /vesta/vestasys.org/vesta/repos/latest/src/progs.ves
  // latest -> 57/
  //
  // Extract a value on a path from a binding, if present, or return
  // "err" if not.
  // orig
  /**nocache**/
  lookup_path_b_orig(b: binding, p: any, err: any = []): any {
     res = if !_is_binding(p) then b else {
      n = _n(_head(p));
      value if (_is_binding(b) && b!$n)
      then lookup_path_b(b/$n, _v(_head(p)), err)
      else err;
    };
     return res;
  };

  // jvk modified
  /**nocache**/
  lookup_path_b(b: binding, p: any, err: any = []): any {
     res = if !_is_binding(p)
           then b
           else if _length(p) != 1
                then err
                else {
                  n = _n(_head(p));
                  value if (b!$n)  // dont have to redundantly check whether b _is_binding
                        then lookup_path_b(b/$n, _v(_head(p)), err)
                        else err;
                };
     return res;
  };





  // john's combo
  /**nocache**/
  lookup_path(b: binding, query: any, err : any = [ ]) : binding {
    return if _is_binding(query)
           then lookup_path_b(b, query, err)
           else if _is_list(query)
                then lookup_path_l(b, query, err)
                else if _is_text(query)
                     then lookup_path_t(b, query, err)
                     else err;
  };



  // adapted from lookup_path_l
  /**nocache**/
  rm_l(b: binding, path: list(text), err: any = []): binding {
    _=_assert(_length(path) >= 1, "list got to zero in rm_l");
    n = _head(path);
    rtn = [ ];
    foreach [ nam = val ] in b do {
      rtn += if nam == n
             then if _length(path) == 1 
                  then [ ]
                  else [ $nam = rm_l (val, _tail(path), err) ]
             else [ $nam = val ];
    };
    return rtn;
  };
  /**nocache**/
  rm(b: binding, path: text, err: any = []): bool {
    return rm_l(b, split(path, "/", TRUE), err);
  };

  // return a function that calls f1 and f2  
  /**nocache**/
  append_func(f1_in, f2_in) {
    appf() {
      return f1_in()
          ++ f2_in()
        ;
    };
    return appf;
  };
  /**nocache**/
  append_func_nocache(f1_in, f2_in) {
    /**nocache**/
    appf_nc() {
      return f1_in()
          ++ f2_in()
        ;
    };
    return appf_nc;
  };

  ////////////////////////////////////////////
  // results and test

  chk (a, b, msg = "error") {
    return if a == b then TRUE else {
      _=_print("error: ");
      _=_print(msg);
      _=_print("a != b:");
      _=_print([a]);
      _=_print([b]);
      return FALSE;
    }
    
  };



  cume = [ ];




  /**nocache**/ 
  f1(){
    _=_print("f1");
    return [ f1 = 1 ];
  };
  /**nocache**/ 
  f2(){
    _=_print("f2");
    return [ f2 = 2 ];
  };
  /**nocache**/ 
  f1_for_nc(){
    _=_print("f1_nc");
    return [ f1_nc = 3 ];
  };
  /**nocache**/ 
  f2_for_nc(){
    _=_print("f2_nc");
    return [ f2_nc = 4 ];
  };


  bnd = [ a = [
               1 = [ i = 1,
                    ii = 2,
                    ],
               2 = [ i = 3,
                    ii = 4,
                    iii = 5,
                    ],
               3 = [ i = 6,
                    ],
               4 = [
                    ],
               ],
        b = [
             1 = [ i = 7,
                  ii = 8,
                  iii = 9,
                  iv = 10,
                  ],
             2 = [ i = 11,
                  ],
             3 = [ i = 12,
                  ii = 14,
                  ],
             ],
        ];

  //
  // test rm
  //
  b2 = [ dir0/dir1/file1 = "c" ]
    ++ [ dir0/dir1/file2 = "c" ]
    ++ [ dir0/dir2/file3 = "c" ]
    ++ [ dir0/dir2/file4 = "c" ]
    ++ [ dir0/dir3/file5 = "c" ]
    ++ [ dir0/dir3/file6 = "c" ]
    ;
  str = "dir0/dir1/file2";
  res = [ $str = rm (b2, str) ];
  _=chk(res, [ $str = [ dir0/dir1/file1 = "c" ]
                   ++ [ dir0/dir2/file3 = "c" ]
                   ++ [ dir0/dir2/file4 = "c" ]
                   ++ [ dir0/dir3/file5 = "c" ]
                   ++ [ dir0/dir3/file6 = "c" ] ], "wrong value");
  cume ++= res;


  str = "dir0/dir3";
  res = [ $str = rm (b2, str) ];
  _=chk(res, [ $str = [ dir0/dir1/file1 = "c" ]
                   ++ [ dir0/dir1/file2 = "c" ]
                   ++ [ dir0/dir2/file3 = "c" ]
                   ++ [ dir0/dir2/file4 = "c" ] ], "wrong value");
  cume ++= res;



  // leading slash
  str = "/dir0/dir1/file2";
  res = [ $str = rm (b2, str) ];
  _=chk(res, [ $str = [ dir0/dir1/file1 = "c" ]
                   ++ [ dir0/dir2/file3 = "c" ]
                   ++ [ dir0/dir2/file4 = "c" ]
                   ++ [ dir0/dir3/file5 = "c" ]
                   ++ [ dir0/dir3/file6 = "c" ] ], "wrong value");
  cume ++= res;


  str = "/dir0/dir3";
  res = [ $str = rm (b2, str) ];
  _=chk(res, [ $str = [ dir0/dir1/file1 = "c" ]
                   ++ [ dir0/dir1/file2 = "c" ]
                   ++ [ dir0/dir2/file3 = "c" ]
                   ++ [ dir0/dir2/file4 = "c" ] ], "wrong value");
  cume ++= res;




  // trailing slash
  str = "/dir0/dir1/file2/";
  res = [ $str = rm (b2, str) ];
  _=chk(res, [ $str = [ dir0/dir1/file1 = "c" ]
                   ++ [ dir0/dir2/file3 = "c" ]
                   ++ [ dir0/dir2/file4 = "c" ]
                   ++ [ dir0/dir3/file5 = "c" ]
                   ++ [ dir0/dir3/file6 = "c" ] ], "wrong value");
  cume ++= res;


  str = "/dir0/dir3/";
  res = [ $str = rm (b2, str) ];
  _=chk(res, [ $str = [ dir0/dir1/file1 = "c" ]
                   ++ [ dir0/dir1/file2 = "c" ]
                   ++ [ dir0/dir2/file3 = "c" ]
                   ++ [ dir0/dir2/file4 = "c" ] ], "wrong value");
  cume ++= res;




  //
  // test append_func
  //
  test_appf = append_func(f1, f2);
  res = [ append_f1_f2 = test_appf ];
  // can't chk
  cume ++= res;
  res =      [ append_f1_f2_rtn = test_appf() ];
  _=chk(res, [ append_f1_f2_rtn = [ f1 = 1,  f2 = 2 ] ], "append_func check error");
  cume ++= res;

  // this commnent is a trivial change to cache miss model file
  test_appf_nc = append_func_nocache(f1_for_nc, f2_for_nc);
  res = [ append_f1_f2_nc = test_appf_nc ];
  // can't chk
  cume ++= res;
  res =      [ append_f1_f2_nc_rtn = test_appf_nc() ];
  _=chk(res, [ append_f1_f2_nc_rtn = [ f1_nc = 3,  f2_nc = 4 ] ], "append_func_nocache check error");
  cume ++= res;


  //
  // test split
  //
  str = "a/b/c";
  res = [ $str = split (str)];
  _=chk(res, [ $str = <"a", "b", "c"> ], "wrong value");
  cume ++= res;


  str = "a/b/c/";
  res = [ $str = split (str)];
  _=chk(res, [ $str = <"a", "b", "c", ""> ], "wrong value");
  cume ++= res;

  str = "/a/b/c";
  res = [ $str = split (str)];
  _=chk(res, [ $str = <"", "a", "b", "c"> ], "wrong value");
  cume ++= res;


  str = "a/b/c";
  res =      [ $(str + " trimmed") = split (str, "/", TRUE)];
  _=chk(res, [ $(str + " trimmed") = <"a", "b", "c"> ], "wrong value");
  cume ++= res;

  str = "a/b/c/";
  res =      [ $(str + " trimmed") = split (str, "/", TRUE)];
  _=chk(res, [ $(str + " trimmed") = <"a", "b", "c"> ], "wrong value");
  cume ++= res;

  str = "/a/b/c";
  res =      [ $(str + " trimmed") = split (str, "/", TRUE)];
  _=chk(res, [ $(str + " trimmed") = <"a", "b", "c"> ], "wrong value");
  cume ++= res;


  //
  // test lookup_path
  //
  func = lookup_path;

  str = "a/1/i";
  res = [ $str = func(bnd, str) ];
  _=chk(res, [ $str = 1 ], "wrong value");
  cume ++= res;

  str = [ a/1/ii = 1 ];
  res = [ a_1_ii_binding = func(bnd, str) ];
  _=chk(res, [ a_1_ii_binding = 2 ], "wrong value");
  cume ++= res;

  str = < "b", "1", "iv" >;
  res = [ b_1_iv_list = func(bnd, str) ];
  _=chk(res, [ b_1_iv_list = 10 ], "wrong value");
  cume ++= res;

  str = "b/3/ii";
  res = [ $str = func(bnd, str) ];
  _=chk(res, [ $str = 14 ], "wrong value");
  cume ++= res;

  str = "/b/3/ii";
  res = [ $str = func(bnd, str) ];
  _=chk(res, [ $str = 14 ], "wrong value");
  cume ++= res;

  str = "b/2";
  res = [ $str = func(bnd, str) ];
  _=chk(res, [ $str = [ i = 11 ] ], "wrong value");
  cume ++= res;

  str = [ a/3 = 1 ];
  res = [ a_3_binding = func(bnd, str) ];
  _=chk(res, [ a_3_binding = [ i =6 ] ], "wrong value");
  cume ++= res;

  str =  <"b","1">;
  res = [ b_1_list = func(bnd, str) ];
  _=chk(res, [ b_1_list = [ i = 7 , ii = 8, iii = 9, iv = 10 ] ], "wrong value");
  cume ++= res;

  str = "blah";
  res = [ $str = func(bnd, str, "blah_error") ];
  cume ++= res;
  _=chk(res, [ $str = "blah_error" ], "wrong value");
  str = "b/blah";
  res = [ $str = func(bnd, str, "didnt work") ];
  _=chk(res, [ $str = "didnt work" ], "wrong value");
  cume ++= res;
  str = "a/2/blah";
  res = [ $str = func(bnd, str, "9999") ];
  _=chk(res, [ $str = "9999" ], "wrong value");
  cume ++= res;
  str = "b/blah/3";
  res = [ $str = func(bnd, str, [result = "error"]) ];
  _=chk(res, [ $str = [result = "error"] ], "wrong value");
  cume ++= res;

  str = [ oops = 1 ];
  res = [ oops_binding = func(bnd, str, "oops") ];
  _=chk(res, [ oops_binding = "oops" ], "wrong value");
  cume ++= res;
  str = <"b", "nonex">;
  res = [ nonex_list = func(bnd, str, "didnt work nonex") ];
  _=chk(res, [ nonex_list = "didnt work nonex" ], "wrong value");
  cume ++= res;

  stb = string_to_binding("string/to/bindg");
  res = [ stb ];
  _=chk(res, [ stb = [ string = [ to = [ bindg = 1 ] ] ] ], "wrong value");
  cume ++= res;

  return cume;

}

Results

My running of this returned

% vesta -result /vesta/twd1.shr.intel.com/play/jvkumpf/test/jvkumpf_test_pkg/checkout/19/56/build.12.string_to_binding.and.lookup_path.johns.versions.ves
Vesta evaluator, version eval/72

"f1_nc"
"f2_nc"

Return value of `/vesta/twd1.shr.intel.com/play/jvkumpf/test/jvkumpf_test_pkg/checkout/19/56/build.12.string_to_binding.and.lookup_path.johns.versions.ves':
[ "dir0/dir1/file2"=
  [ dir0=
    [ dir1=
      [ file1="c" ],
      dir2=
      [ file3="c",
        file4="c" ],
      dir3=
      [ file5="c",
        file6="c" ] ] ],
  "dir0/dir3"=
  [ dir0=
    [ dir1=
      [ file1="c",
        file2="c" ],
      dir2=
      [ file3="c",
        file4="c" ] ] ],
  "/dir0/dir1/file2"=
  [ dir0=
    [ dir1=
      [ file1="c" ],
      dir2=
      [ file3="c",
        file4="c" ],
      dir3=
      [ file5="c",
        file6="c" ] ] ],
  "/dir0/dir3"=
  [ dir0=
    [ dir1=
      [ file1="c",
        file2="c" ],
      dir2=
      [ file3="c",
        file4="c" ] ] ],
  "/dir0/dir1/file2/"=
  [ dir0=
    [ dir1=
      [ file1="c" ],
      dir2=
      [ file3="c",
        file4="c" ],
      dir3=
      [ file5="c",
        file6="c" ] ] ],
  "/dir0/dir3/"=
  [ dir0=
    [ dir1=
      [ file1="c",
        file2="c" ],
      dir2=
      [ file3="c",
        file4="c" ] ] ],
  append_f1_f2=<Closure>,
  append_f1_f2_rtn=
  [ f1=1,
    f2=2 ],
  append_f1_f2_nc=<Closure>,
  append_f1_f2_nc_rtn=
  [ f1_nc=3,
    f2_nc=4 ],
  "a/b/c"=
  < "a",
    "b",
    "c" >,
  "a/b/c/"=
  < "a",
    "b",
    "c",
    "" >,
  "/a/b/c"=
  < "",
    "a",
    "b",
    "c" >,
  "a/b/c trimmed"=
  < "a",
    "b",
    "c" >,
  "a/b/c/ trimmed"=
  < "a",
    "b",
    "c" >,
  "/a/b/c trimmed"=
  < "a",
    "b",
    "c" >,
  "a/1/i"=1,
  a_1_ii_binding=2,
  b_1_iv_list=10,
  "b/3/ii"=14,
  "/b/3/ii"=
  [  ],
  "b/2"=
  [ i=11 ],
  a_3_binding=
  [ i=6 ],
  b_1_list=
  [ i=7,
    ii=8,
    iii=9,
    iv=10 ],
  blah="blah_error",
  "b/blah"="didnt work",
  "a/2/blah"="9999",
  "b/blah/3"=
  [ result="error" ],
  oops_binding="oops",
  nonex_list="didnt work nonex",
  stb=
  [ string=
    [ to=
      [ bindg=1 ] ] ] ]