Пример #1
0
  /**
   * LambdaList constructor for {@link Subr}.
   *
   * @param reqCount Number of required parameters
   * @param optCount Number of optional parameters
   * @param rest if true, then a function uses rest parameter
   * @param keys List of keywords for keyword parameters
   * @param allowOtherKeys if true, then a function accepts a keyword not defined in <code>keys
   *     </code>
   */
  public LambdaList(int reqCount, int optCount, boolean rest, Object keys, boolean allowOtherKeys) {
    int keyCount = Lists.length(keys);

    // whole: not supported in SUBR
    this.whole = null;
    // req
    this.required = new Required[reqCount];
    for (int i = 0; i < reqCount; i++) {
      this.required[i] = new Required(genVar());
    }
    // opt
    this.optional = new Optional[optCount];
    for (int i = 0; i < optCount; i++) {
      this.optional[i] = new Optional(genVar(), Symbols.NIL, genVar());
    }
    // rest
    if (rest) {
      this.rest = new Rest(genVar());
    } else {
      this.rest = null;
    }
    // key
    this.keyword = new Keyword[keyCount];
    this.allowOtherKeys = false;
    for (int i = 0; i < keyCount; i++) {
      Symbol key = Data.symbol(Lists.car(keys));
      // System.out.println("key = "+key);
      // if (key == Symbols.LK_ALLOW_OTHER_KEYS) {
      //    //System.out.println("allowOtherKeys = true");
      //    this.allowOtherKeys = true;
      //    keys = Lists.cdr(keys);
      //    if (!Lists.isEnd(keys)) {
      //        throw new ProgramException
      //            ("no variable is allowed right after "+
      //             "&allow-other-keys: ~S.",
      //             Lists.list(keys));
      //    }
      // }
      // else {
      //    this.keyword[i] = new Keyword
      //        (genVar(), key, Symbols.NIL, genVar());
      //    keys = Lists.cdr(keys);
      // }
      this.keyword[i] = new Keyword(genVar(), key, Symbols.NIL, genVar());
      keys = Lists.cdr(keys);
    }
    //
    this.allowOtherKeys = allowOtherKeys;
    // aux: not supported in SUBR
    this.aux = new Aux[0];
  }
Пример #2
0
  /**
   * LambdaList constructor for {@link Expr}.
   *
   * @param params List which represents a LambdaList
   * @param env
   */
  public LambdaList(Object params, Env env) {
    // if (Logger.tracelevelp(env))
    //    Logger.trace("[lambdaList] params=~S",
    //                 Lists.list(params), env);
    if (params == null) throw new NullPointerException("params is null");
    if (env == null) throw new NullPointerException("env is null");
    this.params = params;

    /*
     * parse params
     */
    Object obj = null;
    Object var = null;
    Object initform = null;
    Symbol svar = null;
    Symbol key = null;
    ArrayList tmp = new ArrayList();
    int wholeCount = 0;
    int reqCount = 0;
    int optCount = 0;
    int restCount = 0;
    int keyCount = 0;
    int allowOtherKeysCount = 0;
    int auxCount = 0;
    int step = BEGIN;
    while (true) {
      switch (step) {
        case BEGIN:
          if (params == Symbols.NIL) {
            step = END;
          } else if (Data.isAtom(params)) {
            step = REST;
            params = Lists.list(params);
          } else {
            obj = Lists.car(params);
            if (obj == Symbols.LK_WHOLE) {
              step = WHOLE;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_OPTIONAL) {
              step = OPTIONAL;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_REST || obj == Symbols.LK_BODY) {
              step = REST;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_KEY) {
              step = KEYWORD;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_AUX) {
              step = AUX;
              params = Lists.cdr(params);
            } else {
              step = REQUIRED;
            }
          }
          break;
        case WHOLE:
          /*
           * params pattern:
           * [&whole var]
           */
          if (Lists.isEnd(params)) {
            throw new ProgramException("whole parameter not exists", Symbols.NIL);
          }
          obj = Lists.car(params);
          var = Data.isPair(obj) ? new LambdaList(obj, env) : obj;
          tmp.add(new Whole(var));
          wholeCount++;
          params = Lists.cdr(params);
          if (params == Symbols.NIL) {
            step = END;
          } else if (Data.isAtom(params)) {
            step = REST;
            params = Lists.list(params);
          } else {
            obj = Lists.car(params);
            if (obj == Symbols.LK_OPTIONAL) {
              step = OPTIONAL;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_REST || obj == Symbols.LK_BODY) {
              step = REST;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_KEY) {
              step = KEYWORD;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_AUX) {
              step = AUX;
              params = Lists.cdr(params);
            } else {
              step = REQUIRED;
            }
          }
          break;
        case REQUIRED:
          /*
           * params pattern:
           * {var}*
           */
          if (params == Symbols.NIL) {
            step = END;
          } else if (Data.isAtom(params)) {
            step = REST;
            params = Lists.list(params);
          } else {
            /* !Lists.isEnd(params) */
            obj = Lists.car(params);
            if (obj == Symbols.LK_OPTIONAL) {
              step = OPTIONAL;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_REST || obj == Symbols.LK_BODY) {
              step = REST;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_KEY) {
              step = KEYWORD;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_AUX) {
              step = AUX;
              params = Lists.cdr(params);
            } else {
              var = Data.isPair(obj) ? new LambdaList(obj, env) : obj;
              tmp.add(new Required(var));
              reqCount++;

              step = REQUIRED;
              params = Lists.cdr(params);
            }
          }
          break;
        case OPTIONAL:
          /*
           * params pattern:
           * [&optional {var | (var [initform [svar]])}*]
           */
          if (params == Symbols.NIL) {
            step = END;
          } else if (Data.isAtom(params)) {
            step = REST;
            params = Lists.list(params);
          } else {
            /* !Lists.isEnd(params) */
            obj = Lists.car(params);
            if (obj == Symbols.LK_REST || obj == Symbols.LK_BODY) {
              step = REST;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_KEY) {
              step = KEYWORD;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_AUX) {
              step = AUX;
              params = Lists.cdr(params);
            } else {
              if (Data.isSymbol(obj)) {
                /*
                 * obj pattern:
                 * var <symbol>
                 */
                var = Data.symbol(obj);
                initform = Symbols.NIL;
                svar = NOT_SPECIFIED;
              } else {
                /*
                 * obj pattern:
                 * (var [initform [svar]])
                 */
                var =
                    Data.isPair(Lists.car(obj))
                        ? new LambdaList(Lists.car(obj), env)
                        : Lists.car(obj);
                initform = Lists.cadr(obj);
                svar = Lists.isEnd(Lists.cddr(obj)) ? NOT_SPECIFIED : Data.symbol(Lists.caddr(obj));
              }
              tmp.add(new Optional(var, initform, svar));
              optCount++;
              step = OPTIONAL;
              params = Lists.cdr(params);
            }
          }
          break;
        case REST:
          /*
           * params pattern:
           * [&rest var]
           */
          if (Lists.isEnd(params)) {
            throw new ProgramException("rest parameter not exists", Symbols.NIL);
          }
          obj = Lists.car(params);
          var = Data.isPair(obj) ? new LambdaList(obj, env) : obj;
          tmp.add(new Rest(var));
          restCount++;
          params = Lists.cdr(params);
          if (Lists.isEnd(params)) {
            step = END;
          } else {
            obj = Lists.car(params);
            if (obj == Symbols.LK_KEY) {
              step = KEYWORD;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_AUX) {
              step = AUX;
              params = Lists.cdr(params);
            } else {
              throw new ProgramException(
                  "unacceptable variable: ~S" + " (expected: &key, &aux or empty)",
                  Lists.list(obj));
            }
          }
          break;
        case KEYWORD:
          /*
           * params pattern:
           * [&key {var | ({var | (keyword var)} [initform [svar]])}*]
           */
          if (Lists.isEnd(params)) {
            step = END;
          } else {
            obj = Lists.car(params);
            if (obj == Symbols.LK_ALLOW_OTHER_KEYS) {
              step = ALLOW_OTHER_KEYS;
              params = Lists.cdr(params);
            } else if (obj == Symbols.LK_AUX) {
              step = AUX;
              params = Lists.cdr(params);
            } else {
              if (Data.isSymbol(obj)) {
                /*
                 * obj pattern:
                 * var <symbol>
                 */
                var = Data.symbol(obj);
                initform = Symbols.NIL;
                svar = NOT_SPECIFIED;
                key = toKeyword(Data.symbol(var), env);
              } else {
                /*
                 * obj pattern:
                 * ({var | (keyword var)} [initform [svar]])
                 */
                var =
                    Data.isSymbol(Lists.car(obj))
                        ? Lists.car(obj)
                        : Data.isSymbol(Lists.cadar(obj))
                            ? Lists.cadar(obj)
                            : new LambdaList(Lists.cadar(obj), env);
                initform = Lists.cadr(obj);
                svar = Lists.isEnd(Lists.cddr(obj)) ? NOT_SPECIFIED : Data.symbol(Lists.caddr(obj));
                key =
                    Data.isSymbol(Lists.car(obj))
                        ? toKeyword(Data.symbol(var), env)
                        : Data.symbol(Lists.caar(obj));
              }
              tmp.add(new Keyword(var, key, initform, svar));
              keyCount++;
              step = KEYWORD;
              params = Lists.cdr(params);
            }
          }
          break;
        case ALLOW_OTHER_KEYS:
          // System.out.println("in ALLOW_OTHER_KEYS");
          allowOtherKeysCount++;
          if (Lists.isEnd(params)) {
            // System.out.println("-> END");
            step = END;
          } else {
            obj = Lists.car(params);
            // System.out.println("-> obj="+obj);
            if (obj == Symbols.LK_AUX) {
              step = AUX;
              params = Lists.cdr(params);
            } else {
              throw new ProgramException(
                  "unacceptable variable: ~S" + " (expected: &aux or empty)", Lists.list(obj));
            }
          }
          break;
        case AUX:
          /*
           * params pattern:
           * [&aux {var | (var [initform])}*]
           */
          if (Lists.isEnd(params)) {
            step = END;
          } else {
            obj = Lists.car(params);
            if (Data.isSymbol(obj)) {
              /*
               * obj pattern:
               * var <symbol>
               */
              var = Data.symbol(obj);
              initform = Symbols.NIL;
            } else {
              /*
               * obj pattern:
               * (var [initform])
               */
              var =
                  Data.isSymbol(Lists.car(obj))
                      ? Lists.car(obj)
                      : new LambdaList(Lists.car(obj), env);
              initform = Lists.cadr(obj);
            }
            tmp.add(new Aux(var, initform));
            auxCount++;
            step = AUX;
            params = Lists.cdr(params);
          }
          break;
        case END:
          Iterator it = tmp.iterator();
          this.required = new Required[reqCount];
          this.optional = new Optional[optCount];
          this.keyword = new Keyword[keyCount];
          this.aux = new Aux[auxCount];

          // fill whole param
          this.whole = (wholeCount > 0) ? (Whole) it.next() : null;
          // fill required params
          for (int i = 0; i < reqCount; i++) this.required[i] = (Required) it.next();
          // fill optional params
          for (int i = 0; i < optCount; i++) this.optional[i] = (Optional) it.next();
          // fill rest param
          this.rest = (restCount > 0) ? (Rest) it.next() : null;
          // fill keyword params
          for (int i = 0; i < keyCount; i++) this.keyword[i] = (Keyword) it.next();
          // fill allowOtherKeys flag
          this.allowOtherKeys = (allowOtherKeysCount > 0);
          // fill aux params
          for (int i = 0; i < auxCount; i++) this.aux[i] = (Aux) it.next();
          return;
        default:
          throw new NotReachedException("unacceptable step: " + step, Symbols.NIL);
      }
    }
  }