1 4 package gnu.kawa.functions; 5 import gnu.lists.*; 6 import gnu.mapping.*; 7 import gnu.bytecode.*; 8 import gnu.expr.*; 9 import gnu.math.IntNum; 10 11 16 17 public class ValuesMap extends MethodProc implements CanInline, Inlineable 18 { 19 public static final ValuesMap valuesMap = new ValuesMap(-1); 20 public static final ValuesMap valuesMapWithPos = new ValuesMap(1); 21 22 private ValuesMap (int startCounter) 23 { 24 this.startCounter = startCounter; 25 } 26 27 29 private final int startCounter; 30 31 public int numArgs() { return 0x2002; } 32 33 public void apply (CallContext ctx) throws Throwable 34 { 35 Procedure proc = (Procedure) ctx.getNextArg(); 36 Consumer out = ctx.consumer; 37 Object val = ctx.getNextArg(); 38 Procedure.checkArgCount(proc, 1); 39 if (val instanceof Values) 40 { 41 int ipos = 0; 42 int count = startCounter; 43 Values values = (Values) val; 44 while ((ipos = values.nextPos(ipos)) != 0) 45 { 46 Object v = values.getPosPrevious(ipos); 47 if (startCounter >= 0) 48 proc.check2(v, IntNum.make(count++), ctx); 49 else 50 proc.check1(v, ctx); 51 ctx.runUntilDone(); 52 } 53 } 54 else 55 { 56 if (startCounter >= 0) 57 proc.check2(val, IntNum.make(startCounter), ctx); 58 else 59 proc.check1(val, ctx); 60 ctx.runUntilDone(); 61 } 62 } 63 64 65 private LambdaExp canInline (ApplyExp exp) 66 { 67 Expression[] args = exp.getArgs(); 68 Expression arg0; 69 if (args.length == 2 && (arg0 = args[0]) instanceof LambdaExp) 71 { 72 LambdaExp lexp = (LambdaExp) arg0; 73 if (lexp.min_args == lexp.max_args 74 && lexp.min_args == (startCounter >= 0 ? 2 : 1)) 75 return lexp; 76 } 77 return null; 78 } 79 80 public Expression inline (ApplyExp exp, ExpWalker walker) 81 { 82 LambdaExp lexp = canInline(exp); 83 if (lexp != null) 84 { 85 lexp.setInlineOnly(true); 86 lexp.returnContinuation = exp; 87 } 88 return exp; 89 } 90 91 public void compile (ApplyExp exp, Compilation comp, Target target) 92 { 93 LambdaExp lambda = canInline(exp); 94 if (lambda == null) 95 { 96 ApplyExp.compile(exp, comp, target); 97 return; 98 } 99 Expression[] args = exp.getArgs(); 100 if (! (target instanceof IgnoreTarget 101 || target instanceof ConsumerTarget 102 || target instanceof SeriesTarget)) 103 { 104 ConsumerTarget.compileUsingConsumer(exp, comp, target); 105 return; 106 } 107 Expression vals = args[1]; 108 compileInlined(lambda, vals, startCounter, null, comp, target); 109 } 110 111 public static void compileInlined(LambdaExp lambda, Expression vals, 112 int startCounter, Method matchesMethod, 113 Compilation comp, Target target) 114 { 115 Declaration param = lambda.firstDecl(); 116 CodeAttr code = comp.getCode(); 117 SeriesTarget starget = new SeriesTarget(); 118 starget.scope = code.pushScope(); 119 Variable counter; 120 Declaration counterDecl; 121 if (startCounter >= 0) 122 { 123 counter = starget.scope.addVariable(code, Type.int_type, "position"); 124 code.emitPushInt(startCounter); 125 code.emitStore(counter); 126 counterDecl = new Declaration(counter); 127 } 128 else 129 { 130 counter = null; 131 counterDecl = null; 132 } 133 starget.function = new Label(code); 134 if (target instanceof SeriesTarget) 135 starget.done = ((SeriesTarget) target).done; 136 else 137 starget.done = new Label(code); 138 if (param.isSimple()) 141 param.allocateVariable(code); 142 else 143 param = new Declaration(code.addLocal(param.getType(), param.getName())); 144 starget.param = param; 145 Type retAddrType = Type.pointer_type; 146 Variable retAddr = code.addLocal(retAddrType); 147 vals.compileWithPosition(comp, starget); 148 149 starget.function.define(code); 150 code.pushType(retAddrType); 151 code.emitStore(retAddr); 152 Expression[] args; 153 if (startCounter >= 0) 154 { 155 args = new Expression[] { new ReferenceExp(param), 156 new ReferenceExp(counterDecl) }; 157 } 158 else 159 args = new Expression[] { new ReferenceExp(param) }; 160 Expression app = new ApplyExp(lambda, args); 161 if (matchesMethod != null) 162 { 163 if (app.getType().getImplementationType() != Type.boolean_type) 165 app = new ApplyExp(matchesMethod, 166 new Expression[] { 167 app, 168 new ReferenceExp(counterDecl) }); 169 app = new IfExp(app, new ReferenceExp(param), QuoteExp.voidExp); 170 } 171 if (target instanceof SeriesTarget) 172 { 173 SeriesTarget atarget = (SeriesTarget) target; 174 Label done = atarget.done; 175 atarget.done = null; 176 app.compile(comp, target); 177 atarget.done = done; 178 } 179 else 180 app.compile(comp, target); 181 if (startCounter >= 0) 182 { 183 code.emitInc(counter, (short) 1); 184 } 185 code.emitRet(retAddr); 186 code.popScope(); 187 if (! (target instanceof SeriesTarget)) 188 starget.done.define(code); 189 } 190 191 public Type getReturnType (Expression[] args) 192 { 193 return Type.pointer_type; 194 } 195 } 196 | Popular Tags |