⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 valuesmap.java

📁 A framework written in Java for implementing high-level and dynamic languages, compiling them into J
💻 JAVA
字号:
// Copyright (c) 2001, 2003, 2004  Per M.A. Bothner and Brainfood Inc.// This is free software;  for terms and warranty disclaimer see ./COPYING.package gnu.kawa.functions;import gnu.lists.*;import gnu.mapping.*;import gnu.bytecode.*;import gnu.expr.*;import gnu.math.IntNum;/** Map a function over a value sequence, yielding a new sequence. * Normally, the function takes one argument, the item in the sequence. * If startCounter is non-negative, a position index is also passed. * Used to implement XQuery's 'for' form. */public class ValuesMap extends MethodProc implements CanInline, Inlineable{  public static final ValuesMap valuesMap = new ValuesMap(-1);  public static final ValuesMap valuesMapWithPos = new ValuesMap(1);  private ValuesMap (int startCounter)  {    this.startCounter = startCounter;  }  /** If non-negative also define a counter variable.   * Used for XQuery's 'at' clause in a FLWOR expression. */  private final int startCounter;  public int numArgs() { return 0x2002; }  public void apply (CallContext ctx) throws Throwable  {    Procedure proc = (Procedure) ctx.getNextArg();    Consumer out = ctx.consumer;    Object val = ctx.getNextArg();    Procedure.checkArgCount(proc, 1);    if (val instanceof Values)      {	int ipos = 0;	int count = startCounter;	Values values = (Values) val;	while ((ipos = values.nextPos(ipos)) != 0)	  {	    Object v = values.getPosPrevious(ipos);	    if (startCounter >= 0)	      proc.check2(v, IntNum.make(count++), ctx);	    else	      proc.check1(v, ctx);	    ctx.runUntilDone();	  }      }    else      {	if (startCounter >= 0)	  proc.check2(val, IntNum.make(startCounter), ctx);	else	  proc.check1(val, ctx);	ctx.runUntilDone();      }  }  /** If we can inline, return LambdaExp for first arg; otherwise null. */  private LambdaExp canInline (ApplyExp exp)  {    Expression[] args = exp.getArgs();    Expression arg0;    // FIXME Could if needed wrap expr in LambdaExp:    if (args.length == 2 && (arg0 = args[0]) instanceof LambdaExp)      {	LambdaExp lexp = (LambdaExp) arg0;	if (lexp.min_args == lexp.max_args	    && 	lexp.min_args == (startCounter >= 0 ? 2 : 1))	  return lexp;      }    return null;  }  public Expression inline (ApplyExp exp, ExpWalker walker)  {    LambdaExp lexp = canInline(exp);    if (lexp != null)      {	lexp.setInlineOnly(true);	lexp.returnContinuation = exp;      }    return exp;  }  public void compile (ApplyExp exp, Compilation comp, Target target)  {    LambdaExp lambda = canInline(exp);    if (lambda == null)      {	ApplyExp.compile(exp, comp, target);	return;      }    Expression[] args = exp.getArgs();    if (! (target instanceof IgnoreTarget	   || target instanceof ConsumerTarget	   || target instanceof SeriesTarget))      {	ConsumerTarget.compileUsingConsumer(exp, comp, target);	return;      }    Expression vals = args[1];    compileInlined(lambda, vals, startCounter, null, comp, target);  }  public static void compileInlined(LambdaExp lambda, Expression vals,                                    int startCounter, Method matchesMethod,                                    Compilation comp, Target target)  {    Declaration param = lambda.firstDecl();    CodeAttr code = comp.getCode();    SeriesTarget starget = new SeriesTarget();    starget.scope = code.pushScope();    Variable counter;    Declaration counterDecl;    if (startCounter >= 0)      {	counter = starget.scope.addVariable(code, Type.int_type, "position");	code.emitPushInt(startCounter);	code.emitStore(counter);        counterDecl = new Declaration(counter);      }    else      {        counter = null;        counterDecl = null;      }    starget.function = new Label(code);    if (target instanceof SeriesTarget)      starget.done = ((SeriesTarget) target).done;    else      starget.done = new Label(code);    // If the param Declaration is captured, then it gets messy initializing    // it.  So just cheat and create a helper variable.    if (param.isSimple())      param.allocateVariable(code);    else      param = new Declaration(code.addLocal(param.getType(), param.getName()));    starget.param = param;    Type retAddrType = Type.pointer_type;    Variable retAddr = code.addLocal(retAddrType);    vals.compileWithPosition(comp, starget);    starget.function.define(code);    code.pushType(retAddrType);    code.emitStore(retAddr);    Expression[] args;    if (startCounter >= 0)      {	args = new Expression[] { new ReferenceExp(param),                                  new ReferenceExp(counterDecl) };      }    else      args = new Expression[] { new ReferenceExp(param) };    Expression app = new ApplyExp(lambda, args);    if (matchesMethod != null)      {        // Major kludge - used by ValuesFilter.        if (app.getType().getImplementationType() != Type.boolean_type)          app = new ApplyExp(matchesMethod,                             new Expression[] {                               app,                               new ReferenceExp(counterDecl) });        app = new IfExp(app, new ReferenceExp(param), QuoteExp.voidExp);      }    if (target instanceof SeriesTarget)      {        SeriesTarget atarget = (SeriesTarget) target;        Label done = atarget.done;        atarget.done = null;        app.compile(comp, target);        atarget.done = done;      }    else      app.compile(comp, target);    if (startCounter >= 0)      {	code.emitInc(counter, (short) 1);      }    code.emitRet(retAddr);    code.popScope();    if (! (target instanceof SeriesTarget))      starget.done.define(code);  }  public Type getReturnType (Expression[] args)  {    return Type.pointer_type;  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -