public Type getImplementationType() {
   return ClassType.make("gnu.kawa.xml.KProcessingInstruction");
 }
 public StaticFieldLocation(String cname, String fname) {
   super(null, ClassType.make(cname), fname);
 }
 static {
   typeProcessingInstructionType = ClassType.make("gnu.kawa.xml.ProcessingInstructionType");
   coerceMethod = typeProcessingInstructionType.getDeclaredMethod("coerce", 2);
   coerceOrNullMethod = typeProcessingInstructionType.getDeclaredMethod("coerceOrNull", 2);
 }
 public static void emitLoadModuleMethod(LambdaExp paramLambdaExp, Compilation paramCompilation)
 {
   Object localObject3 = paramLambdaExp.nameDecl;
   Object localObject1;
   CodeAttr localCodeAttr;
   Object localObject2;
   label61:
   label129:
   label150:
   label178:
   int i;
   if (localObject3 == null)
   {
     localObject1 = paramLambdaExp.getName();
     localCodeAttr = null;
     localObject2 = localCodeAttr;
     if (paramCompilation.immediate)
     {
       localObject2 = localCodeAttr;
       if (localObject1 != null)
       {
         localObject2 = localCodeAttr;
         if (localObject3 != null)
         {
           localObject3 = Environment.getCurrent();
           if (!(localObject1 instanceof Symbol)) {
             break label353;
           }
           localObject2 = (Symbol)localObject1;
           localObject3 = ((Environment)localObject3).get((Symbol)localObject2, paramCompilation.getLanguage().getEnvPropertyFor(paramLambdaExp.nameDecl), null);
           localObject2 = localCodeAttr;
           if ((localObject3 instanceof ModuleMethod)) {
             localObject2 = (ModuleMethod)localObject3;
           }
         }
       }
     }
     localCodeAttr = paramCompilation.getCode();
     localObject3 = Compilation.typeModuleMethod;
     if (localObject2 != null) {
       break label369;
     }
     localCodeAttr.emitNew((ClassType)localObject3);
     localCodeAttr.emitDup(1);
     localObject2 = "<init>";
     localObject3 = ((ClassType)localObject3).getDeclaredMethod((String)localObject2, 4);
     if (!paramLambdaExp.getNeedsClosureEnv()) {
       break label385;
     }
     localObject2 = paramLambdaExp.getOwningLambda();
     if ((!(localObject2 instanceof ClassExp)) || (((LambdaExp)localObject2).staticLinkField == null)) {
       break label393;
     }
     localCodeAttr.emitLoad(localCodeAttr.getCurrentScope().getVariable(1));
     localCodeAttr.emitPushInt(paramLambdaExp.getSelectorValue(paramCompilation));
     paramCompilation.compileConstant(localObject1, Target.pushObject);
     int j = paramLambdaExp.min_args;
     if (paramLambdaExp.keywords != null) {
       break label583;
     }
     i = paramLambdaExp.max_args;
     label215:
     localCodeAttr.emitPushInt(i << 12 | j);
     localCodeAttr.emitInvoke((Method)localObject3);
     if (paramLambdaExp.properties == null) {
       return;
     }
     j = paramLambdaExp.properties.length;
     i = 0;
     label252:
     if (i >= j) {
       return;
     }
     localObject2 = paramLambdaExp.properties[i];
     if ((localObject2 != null) && (localObject2 != PropertySet.nameKey))
     {
       localObject1 = paramLambdaExp.properties[(i + 1)];
       localCodeAttr.emitDup(1);
       paramCompilation.compileConstant(localObject2);
       localObject2 = Target.pushObject;
       if (!(localObject1 instanceof Expression)) {
         break label589;
       }
       ((Expression)localObject1).compile(paramCompilation, (Target)localObject2);
     }
   }
   for (;;)
   {
     localCodeAttr.emitInvokeVirtual(ClassType.make("gnu.mapping.PropertySet").getDeclaredMethod("setProperty", 2));
     i += 2;
     break label252;
     localObject1 = ((Declaration)localObject3).getSymbol();
     break;
     label353:
     localObject2 = Symbol.make("", localObject1.toString().intern());
     break label61;
     label369:
     paramCompilation.compileConstant(localObject2, Target.pushValue((Type)localObject3));
     localObject2 = "init";
     break label129;
     label385:
     localObject2 = paramCompilation.getModule();
     break label150;
     label393:
     if ((!(localObject2 instanceof ModuleExp)) || ((paramCompilation.moduleClass == paramCompilation.mainClass) && (!paramCompilation.method.getStaticFlag())))
     {
       localCodeAttr.emitPushThis();
       break label178;
     }
     if (paramCompilation.moduleInstanceVar == null)
     {
       paramCompilation.moduleInstanceVar = localCodeAttr.locals.current_scope.addVariable(localCodeAttr, paramCompilation.moduleClass, "$instance");
       if ((paramCompilation.moduleClass == paramCompilation.mainClass) || (paramCompilation.isStatic())) {
         break label571;
       }
       localCodeAttr.emitNew(paramCompilation.moduleClass);
       localCodeAttr.emitDup(paramCompilation.moduleClass);
       localCodeAttr.emitInvokeSpecial(paramCompilation.moduleClass.constructor);
       paramCompilation.moduleInstanceMainField = paramCompilation.moduleClass.addField("$main", paramCompilation.mainClass, 0);
       localCodeAttr.emitDup(paramCompilation.moduleClass);
       localCodeAttr.emitPushThis();
       localCodeAttr.emitPutField(paramCompilation.moduleInstanceMainField);
     }
     for (;;)
     {
       localCodeAttr.emitStore(paramCompilation.moduleInstanceVar);
       localCodeAttr.emitLoad(paramCompilation.moduleInstanceVar);
       break;
       label571:
       localCodeAttr.emitGetStatic(paramCompilation.moduleInstanceMainField);
     }
     label583:
     i = -1;
     break label215;
     label589:
     paramCompilation.compileConstant(localObject1, (Target)localObject2);
   }
 }
Beispiel #5
0
  static void compile(ApplyExp exp, Compilation comp, Target target, boolean checkInlineable) {
    int args_length = exp.args.length;
    Expression exp_func = exp.func;
    LambdaExp func_lambda = null;
    String func_name = null;
    Declaration owner = null;
    Object quotedValue = null;
    if (exp_func instanceof LambdaExp) {
      func_lambda = (LambdaExp) exp_func;
      func_name = func_lambda.getName();
      if (func_name == null) func_name = "<lambda>";
    } else if (exp_func instanceof ReferenceExp) {
      ReferenceExp func_ref = (ReferenceExp) exp_func;
      owner = func_ref.contextDecl();
      Declaration func_decl = func_ref.binding;
      while (func_decl != null && func_decl.isAlias() && func_decl.value instanceof ReferenceExp) {
        func_ref = (ReferenceExp) func_decl.value;
        if (owner != null || func_decl.needsContext() || func_ref.binding == null) break;
        func_decl = func_ref.binding;
        owner = func_ref.contextDecl();
      }
      if (!func_decl.getFlag(Declaration.IS_UNKNOWN)) {
        Expression value = func_decl.getValue();
        func_name = func_decl.getName();
        if (value != null && value instanceof LambdaExp) func_lambda = (LambdaExp) value;
        if (value != null && value instanceof QuoteExp) quotedValue = ((QuoteExp) value).getValue();
      }
    } else if (exp_func instanceof QuoteExp) {
      quotedValue = ((QuoteExp) exp_func).getValue();
    }
    if (checkInlineable && quotedValue instanceof Procedure) {
      Procedure proc = (Procedure) quotedValue;
      if (target instanceof IgnoreTarget && proc.isSideEffectFree()) {
        for (int i = 0; i < args_length; i++) exp.args[i].compile(comp, target);
        return;
      }
      try {
        if (inlineCompile(proc, exp, comp, target)) return;
      } catch (Throwable ex) {
        comp.getMessages()
            .error('e', "caught exception in inline-compiler for " + quotedValue + " - " + ex, ex);
        return;
      }
    }

    gnu.bytecode.CodeAttr code = comp.getCode();
    Method method;

    if (func_lambda != null) {
      if ((func_lambda.max_args >= 0 && args_length > func_lambda.max_args)
          || args_length < func_lambda.min_args)
        // This is supposed to get caught by InlineCalls.
        throw new Error("internal error - wrong number of parameters for " + func_lambda);
      int conv = func_lambda.getCallConvention();
      // Mostly duplicates logic with LambdaExp.validateApply.
      // See comment there.
      if (comp.inlineOk(func_lambda)
          && (conv <= Compilation.CALL_WITH_CONSUMER
              || (conv == Compilation.CALL_WITH_TAILCALLS && !exp.isTailCall()))
          && (method = func_lambda.getMethod(args_length)) != null) {
        PrimProcedure pproc = new PrimProcedure(method, func_lambda);
        boolean is_static = method.getStaticFlag();
        boolean extraArg = false;
        // ?? Procedure.checkArgCount(this, args.length); // FIXME
        if (!is_static || func_lambda.declareClosureEnv() != null) {
          if (is_static) extraArg = true;
          if (comp.curLambda == func_lambda) // Recursive call.
          code.emitLoad(
                func_lambda.closureEnv != null ? func_lambda.closureEnv : func_lambda.thisVariable);
          else if (owner != null) owner.load(null, 0, comp, Target.pushObject);
          else func_lambda.getOwningLambda().loadHeapFrame(comp);
        }

        pproc.compile(extraArg ? Type.voidType : null, exp, comp, target);
        return;
      }
    }

    /*
       if (comp.usingCPStyle())
         {
      {
        Label l = new Label(code);
        gnu.bytecode.SwitchState fswitch = comp.fswitch;
        int pc = fswitch.getMaxValue() + 1;
        fswitch.addCase(pc, code, l);
               exp_func.compile(comp, new StackTarget(Compilation.typeProcedure));
        comp.loadCallContext();

        // Emit: context->pc = pc.
        comp.loadCallContext();
        code.emitPushInt(pc);
        code.emitPutField(Compilation.pcCallContextField);
        code.emitInvokeVirtual(Compilation.applyCpsMethod);

        // emit[save java stack, if needed]
        Type[] stackTypes = code.saveStackTypeState(false);
        java.util.Stack stackFields = new java.util.Stack();
        if (stackTypes != null)
          {
    	for (int i = stackTypes.length;  --i >= 0; )
    	  {
    	    Field fld = comp.allocLocalField (stackTypes[i], null);
    	    code.emitPushThis();
    	    code.emitSwap();
    	    code.emitPutField(fld);
    	    stackFields.push(fld);
    	  }
          }

        code.emitReturn();
        l.define(code);

        // emit[restore java stack, if needed]
        if (stackTypes != null)
          {
    	for (int i = stackTypes.length;  --i >= 0; )
    	  {
    	    Field fld = (Field) stackFields.pop();
    	    code.emitPushThis();
    	    code.emitGetField(fld);
    	    comp.freeLocalField(fld);
    	  }
          }

        // FIXME
        // Load result from stack.value to target.
        comp.loadCallContext();
        code.emitGetField(comp.valueCallContextField);
        target.compileFromStack(comp, Type.pointer_type);
      }
    return;
         }
       */

    // Check for tail-recursion.
    boolean tail_recurse = exp.isTailCall() && func_lambda != null && func_lambda == comp.curLambda;

    if (func_lambda != null
        && func_lambda.getInlineOnly()
        && !tail_recurse
        && func_lambda.min_args == args_length) {
      pushArgs(func_lambda, exp.args, null, comp);
      if (func_lambda.getFlag(LambdaExp.METHODS_COMPILED)) {
        popParams(code, func_lambda, null, false);
        code.emitTailCall(false, func_lambda.getVarScope());
        return;
      }
      func_lambda.flags |= LambdaExp.METHODS_COMPILED;
      LambdaExp saveLambda = comp.curLambda;
      comp.curLambda = func_lambda;
      func_lambda.allocChildClasses(comp);
      func_lambda.allocParameters(comp);
      popParams(code, func_lambda, null, false);
      func_lambda.enterFunction(comp);
      func_lambda.body.compileWithPosition(comp, target);
      func_lambda.compileEnd(comp);
      func_lambda.generateApplyMethods(comp);
      code.popScope();
      comp.curLambda = saveLambda;
      return;
    }

    if (comp.curLambda.isHandlingTailCalls()
        && (exp.isTailCall() || target instanceof ConsumerTarget)
        && !comp.curLambda.getInlineOnly()) {
      ClassType typeContext = Compilation.typeCallContext;
      exp_func.compile(comp, new StackTarget(Compilation.typeProcedure));
      // evaluate args to frame-locals vars;  // may recurse!
      if (args_length <= 4) {
        for (int i = 0; i < args_length; ++i)
          exp.args[i].compileWithPosition(comp, Target.pushObject);
        comp.loadCallContext();
        code.emitInvoke(
            Compilation.typeProcedure.getDeclaredMethod("check" + args_length, args_length + 1));
      } else {
        compileToArray(exp.args, comp);
        comp.loadCallContext();
        code.emitInvoke(Compilation.typeProcedure.getDeclaredMethod("checkN", 2));
      }
      if (exp.isTailCall()) {
        code.emitReturn();
      } else if (((ConsumerTarget) target).isContextTarget()) {
        comp.loadCallContext();
        code.emitInvoke(typeContext.getDeclaredMethod("runUntilDone", 0));
      } else {
        comp.loadCallContext();
        code.emitLoad(((ConsumerTarget) target).getConsumerVariable());
        code.emitInvoke(typeContext.getDeclaredMethod("runUntilValue", 1));
      }
      return;
    }

    if (!tail_recurse) exp_func.compile(comp, new StackTarget(Compilation.typeProcedure));

    boolean toArray =
        (tail_recurse ? func_lambda.min_args != func_lambda.max_args : args_length > 4);
    int[] incValues = null; // Increments if we can use iinc.
    if (toArray) {
      compileToArray(exp.args, comp);
      method = Compilation.applyNmethod;
    } else if (tail_recurse) {
      incValues = new int[exp.args.length];
      pushArgs(func_lambda, exp.args, incValues, comp);
      method = null;
    } else {
      for (int i = 0; i < args_length; ++i) {
        exp.args[i].compileWithPosition(comp, Target.pushObject);
        if (!code.reachableHere()) break;
      }
      method = Compilation.applymethods[args_length];
    }
    if (!code.reachableHere()) {
      comp.error('e', "unreachable code");
      return;
    }
    if (tail_recurse) {
      popParams(code, func_lambda, incValues, toArray);
      code.emitTailCall(false, func_lambda.getVarScope());
      return;
    }
    code.emitInvokeVirtual(method);
    target.compileFromStack(comp, Type.pointer_type);
  }
/** A type that matches some number of repetitions of a basetype. */
public class OccurrenceType extends ObjectType implements Externalizable, TypeValue {
  Type base;
  int minOccurs;
  int maxOccurs;

  public Type getBase() {
    return base;
  }

  public int minOccurs() {
    return minOccurs;
  }

  public int maxOccurs() {
    return maxOccurs;
  }

  public OccurrenceType(Type base, int minOccurs, int maxOccurs) {
    this.base = base;
    this.minOccurs = minOccurs;
    this.maxOccurs = maxOccurs;
  }

  public static Type getInstance(Type base, int minOccurs, int maxOccurs) {
    if (minOccurs == 1 && maxOccurs == 1) return base;
    if (minOccurs == 0
        && maxOccurs < 0
        && (base == SingletonType.instance || base == Type.pointer_type)) return Type.pointer_type;
    return new OccurrenceType(base, minOccurs, maxOccurs);
  }

  public static final Type emptySequenceType =
      OccurrenceType.getInstance(SingletonType.instance, 0, 0);

  public Type getImplementationType() {
    return Type.pointer_type;
  }

  public int compare(Type other) {
    if (other instanceof OccurrenceType) {
      OccurrenceType occOther = (OccurrenceType) other;
      if (minOccurs == occOther.minOccurs && maxOccurs == occOther.maxOccurs)
        return base.compare(occOther.getBase());
    }
    /*
    Type primeThis = itemPrimeType(getBase());
    Type primeOther = itemPrimeType(other);
    FIXME: Compare primThis with primOther AND the occurrence numbers.
    */
    return -2;
  }

  public Object coerceFromObject(Object obj) {
    if (obj instanceof Values) {
    } else {
      // Assumes that base is an item type.  FIXME.
      if (minOccurs <= 1 && maxOccurs != 0) return base.coerceFromObject(obj);
    }
    // FIXME
    if (!isInstance(obj)) throw new ClassCastException();
    return obj;
  }

  public boolean isInstance(Object obj) {
    if (obj instanceof Values) {
      Values vals = (Values) obj;
      int pos = vals.startPos();
      int n = 0;
      if (base instanceof ItemPredicate) {
        ItemPredicate pred = (ItemPredicate) base;
        for (; ; ) {
          boolean matches;
          matches = pred.isInstancePos(vals, pos);
          pos = vals.nextPos(pos);
          if (pos == 0) {
            return n >= minOccurs && (maxOccurs < 0 || n <= maxOccurs);
          }
          if (!matches) return false;
          n++;
        }
      } else {

        for (; ; ) {
          pos = vals.nextPos(pos);
          if (pos == 0) {
            return n >= minOccurs && (maxOccurs < 0 || n <= maxOccurs);
          }
          Object value = vals.getPosPrevious(pos);
          if (!base.isInstance(value)) return false;
          n++;
        }
      }
    } else {
      if (minOccurs > 1 || maxOccurs == 0) return false;
      return base.isInstance(obj);
    }
  }

  public void emitTestIf(Variable incoming, Declaration decl, Compilation comp) {
    CodeAttr code = comp.getCode();
    if (incoming != null) code.emitLoad(incoming);
    if (decl != null) {
      code.emitDup();
      decl.compileStore(comp);
    }
    comp.compileConstant(this);
    code.emitSwap();
    code.emitInvokeVirtual(isInstanceMethod);
    code.emitIfIntNotZero();
  }

  public void emitIsInstance(Variable incoming, Compilation comp, Target target) {
    gnu.kawa.reflect.InstanceOf.emitIsInstance(this, incoming, comp, target);
  }

  public Expression convertValue(Expression value) {
    return null;
  }

  public Procedure getConstructor() {
    return null;
  }

  /**
   * Return a conservative estimage on the min/max number of items of a type.
   *
   * @return {@code maxCount << 12 | minCount & 0xFFF}, where a {@code maxCount} of -1 means
   *     unbounded.
   */
  public static int itemCountRange(Type type) {
    if (type instanceof SingletonType) return (1 << 12) | 1;
    if (type instanceof OccurrenceType) {
      OccurrenceType occ = (OccurrenceType) type;
      int min = occ.minOccurs();
      int max = occ.maxOccurs();
      int bnum = itemCountRange(occ.getBase());
      if ((min == 1 && max == 1) || bnum == 0) return bnum;
      if (max > 0xfffff) max = -1;
      if (max == 0) return 0;
      int bmin = bnum & 0xfff;
      int bmax = bnum >> 12;
      if (bnum != 0x1001) {
        if (min > 0xfff) min = 0xfff;
        min = min * bmin;
        if (min > 0xfff) min = 0xfff;
        if (max < 0 || bmax < 0) max = -1;
        else max = max * bmax;
        if (max > 0xfffff) max = -1;
      }
      return (max << 12) | min;
    }
    if (type instanceof PrimType) return type.isVoid() ? 0 : 0x1001;
    if (type instanceof ArrayType) return 0x1001;
    if (type instanceof ObjectType) {
      int cmp = type.compare(Compilation.typeValues);
      if (cmp == -3) return 0x1001;
    }
    return -1 << 12;
  }

  /**
   * Returna a quantifer kind for a sequence type.
   *
   * @return '0' if type is known to be a void (0-item) type; '1' if type is known to be a
   *     single-item type; '?' if type matches a sequence of 0 or 1 items; '+' if type matches a
   *     sequence of 1 or more items; '*' otherwise.
   */
  public static char itemCountCode(Type type) {
    int num = itemCountRange(type);
    int min = num & 0xFFF;
    int max = num >> 12;
    return max == 0 ? '0' : min == 0 ? (max == 1 ? '?' : '*') : min == 1 && max == 1 ? '1' : '+';
  }

  public static boolean itemCountIsZeroOrOne(Type type) {
    // cute hack for: max == 0 || max == 1.
    return (itemCountRange(type) >> 13) == 0;
  }

  public static boolean itemCountIsOne(Type type) {
    return itemCountRange(type) == 0x1001;
  }

  /** QUery formal semantics "prime type" */
  public static Type itemPrimeType(Type type) {
    while (type instanceof OccurrenceType) type = ((OccurrenceType) type).getBase();
    return itemCountIsOne(type) ? type : SingletonType.instance;
  }

  public void writeExternal(ObjectOutput out) throws IOException {
    out.writeObject(base);
    out.writeInt(minOccurs);
    out.writeInt(maxOccurs);
  }

  public String toString() {
    String b = base.toString();
    boolean parens = b == null || b.indexOf(' ') >= 0;
    StringBuffer sbuf = new StringBuffer();
    if (parens) sbuf.append('(');
    sbuf.append(b);
    if (parens) sbuf.append(')');
    if (minOccurs == 1 && maxOccurs == 1) ;
    else if (minOccurs == 0 && maxOccurs == 1) sbuf.append('?');
    else if (minOccurs == 1 && maxOccurs == -1) sbuf.append('+');
    else if (minOccurs == 0 && maxOccurs == -1) sbuf.append('*');
    else {
      sbuf.append('{');
      sbuf.append(minOccurs);
      sbuf.append(',');
      if (maxOccurs >= 0) sbuf.append(maxOccurs);
      else sbuf.append('*');
      sbuf.append('}');
    }
    return sbuf.toString();
  }

  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    base = (Type) in.readObject();
    minOccurs = in.readInt();
    maxOccurs = in.readInt();
  }

  public static final ClassType typeOccurrenceType =
      ClassType.make("gnu.kawa.reflect.OccurrenceType");
  static final Method isInstanceMethod = typeOccurrenceType.getDeclaredMethod("isInstance", 1);
}
 public Expression rewrite(Object paramObject, Translator paramTranslator) {
   Object[] arrayOfObject = new Object[4];
   if (this.op_code == 0) {
     if (!pattern3.match(paramObject, arrayOfObject, 1)) {}
   } else {
     while (pattern4.match(paramObject, arrayOfObject, 0)) {
       if ((arrayOfObject[3] instanceof LList)) {
         break;
       }
       return paramTranslator.syntaxError("missing/invalid parameter list in " + getName());
     }
   }
   return paramTranslator.syntaxError(
       "wrong number of arguments to " + getName() + "(opcode:" + this.op_code + ")");
   Object localObject1 = (LList) arrayOfObject[3];
   int j = ((LList) localObject1).size();
   Type[] arrayOfType = new Type[j];
   int i = 0;
   while (i < j) {
     localObject1 = (Pair) localObject1;
     arrayOfType[i] = paramTranslator.exp2Type((Pair) localObject1);
     localObject1 = (LList) ((Pair) localObject1).getCdr();
     i += 1;
   }
   Type localType = paramTranslator.exp2Type(new Pair(arrayOfObject[2], null));
   if (this.op_code == 0) {
     paramObject =
         new PrimProcedure(((Number) arrayOfObject[1]).intValue(), localType, arrayOfType);
   }
   for (; ; ) {
     return new QuoteExp(paramObject);
     Object localObject2 = null;
     paramObject = paramTranslator.exp2Type((Pair) paramObject);
     localObject1 = paramObject;
     if (paramObject != null) {
       localObject1 = ((Type) paramObject).getImplementationType();
     }
     paramObject = localObject2;
     try {
       localObject1 = (ClassType) localObject1;
       paramObject = localObject1;
       ((ClassType) localObject1).getReflectClass();
       paramObject = localObject1;
       if ((arrayOfObject[1] instanceof Pair)) {
         paramTranslator = (Pair) arrayOfObject[1];
         if (paramTranslator.getCar() == "quote") {
           arrayOfObject[1] = ((Pair) paramTranslator.getCdr()).getCar();
         }
       }
       paramObject =
           new PrimProcedure(
               this.op_code,
               (ClassType) paramObject,
               arrayOfObject[1].toString(),
               localType,
               arrayOfType);
     } catch (Exception localException) {
       if (paramObject != null) {
         break label403;
       }
     }
   }
   char c = 'e';
   for (; ; ) {
     paramTranslator.error(c, "unknown class: " + arrayOfObject[0]);
     break;
     label403:
     c = 'w';
     ((ClassType) paramObject).setExisting(false);
   }
 }