All Downloads are FREE. Search and download functionalities are using the official Maven repository.

water.rapids.ASTFun Maven / Gradle / Ivy

There is a newer version: 3.8.2.9
Show newest version
package water.rapids;

import water.util.SB;

import java.util.ArrayList;

/** Define a function
 *  Syntax: { ids... . expr }
 *  IDs are bound within expr
 */
public class ASTFun extends AST {
  final String[] _ids;          // Identifier names
  final AST _body;              // The function body

  // If this function is being evaluated, record the arguments and parent
  // lexical scope
  final Val[] _args;            // Evaluated arguments to a function
  final ASTFun _parent;         // Parent lexical scope

  protected ASTFun( Exec e ) { 
    e.xpeek('{');
    ArrayList ids = new ArrayList<>();
    ids.add("");                // 1-based ID list

    while( e.skipWS()!= '.' ) {
      String id = e.token();
      if( !Character.isJavaIdentifierStart(id.charAt(0)) ) throw new Exec.IllegalASTException("variable must be a valid Java identifier: "+id);
      for( char c : id.toCharArray() )
        if( !Character.isJavaIdentifierPart(c) ) throw new Exec.IllegalASTException("variable must be a valid Java identifier: "+id);
      ids.add(id);
    }
    e.xpeek('.');
    _ids = ids.toArray(new String[ids.size()]);
    _body = e.parse();
    _args = null;               // This is a template of an uncalled function
    _parent = null;
    e.skipWS();
    e.xpeek('}');
  }

  @Override public String str() { 
    SB sb = new SB().p('{');
    penv(sb);
    for( String id : _ids )
      sb.p(id).p(' ');
    sb.p(". ").p(_body.toString()).p('}');
    return sb.toString();
  }

  // Print environment
  private void penv( SB sb ) {
    if( _parent != null ) _parent.penv(sb);
    if( _args != null )
      for( int i=1; i<_ids.length; i++ )
        sb.p(_ids[i]).p('=').p(_args[i].toString()).p(' ');
  }

  // Function execution.  Just throw self on stack like a constant.  However,
  // capture the existing global scope.
  @Override public Val exec(Env env) { return new ValFun(new ASTFun(this,null,env._scope)); }

  // Expected argument count, plus self
  @Override int nargs() { return _ids.length; }

  // A function applied to arguments
  ASTFun( ASTFun fun, Val[] args, ASTFun parent ) {
    _ids = fun._ids;
    _body = fun._body;
    _parent = parent;
    _args = args;
  }

  // Do a ID lookup, returning the matching argument if found
  Val lookup( String id ) {
    for( int i=1; i<_ids.length; i++ )
      if( id.equals(_ids[i]) )
        return _args[i];        // Hit, return found argument
    return _parent == null ? null : _parent.lookup(id);
  }

  // Apply this function: evaluate all arguments, push a lexical scope mapping
  // the IDs to the ARGs, then evaluate the body.  After execution pop the
  // lexical scope and return the results.
  @Override
  public Val apply(Env env, Env.StackHelp stk, AST asts[]) {
    // Evaluation all arguments
    Val[] args = new Val[asts.length];
    for( int i=1; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy