001: // Copyright (c) 2000, 2001, 2006 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.expr;
005:
006: import gnu.bytecode.*;
007: import gnu.kawa.reflect.OccurrenceType;
008: import gnu.kawa.reflect.SingletonType;
009:
010: /** The value in the result (as a sequence of values) is passed to a function.
011: */
012:
013: public class SeriesTarget extends Target {
014: /** Where to place each value. */
015: public Declaration param;
016:
017: /** A function to call (using jsr/jsr_w). */
018: public Label function;
019:
020: /** Where to go when done executing the Expression whose target this is.
021: * If null, execution should continue just after the Expression. */
022: public Label done;
023:
024: /** A surrounding Scope for local Variables.
025: * This Scope should include both any calls to compileFromStackSimple
026: * and the entirety of the 'function' subroutine. This is protect against
027: * where a variable logically goes out of scope, but we cannot re-use
028: * the local variable slot until we're past the 'function'. */
029: public Scope scope;
030:
031: public void compileFromStackSimple(Compilation comp, Type stackType) {
032: CodeAttr code = comp.getCode();
033: StackTarget.convert(comp, stackType, param.getType());
034: param.compileStore(comp);
035: code.emitJsr(function);
036: if (done != null && code.reachableHere())
037: code.emitGoto(done);
038: // Make sure we don't free the local variable slots for any variable
039: // slots prematurely. I.e. any local variables in use at this point
040: // must be protected from being re-used in the Jsr subroutine.
041: code.locals.preserveVariablesUpto(scope);
042: }
043:
044: public void compileFromStack(Compilation comp, Type stackType) {
045: CodeAttr code = comp.getCode();
046:
047: if (OccurrenceType.itemCountIsOne(stackType)) {
048: compileFromStackSimple(comp, stackType);
049: return;
050: }
051:
052: /* emit the following:
053: int index = 0;
054: for (;;)
055: {
056: int next = Values.nextIndex(values, index);
057: if (next < 0)
058: goto done;
059: Values.nextValue(values, index);
060: compileFromStackSimple(comp, Type.pointerType);
061: index = value;
062: }
063: */
064: Variable indexVar = code.addLocal(Type.int_type);
065: Variable valuesVar = code.addLocal(Type.pointer_type);
066: Variable nextVar = code.addLocal(Type.int_type);
067: Label doneLabel = done;
068: boolean doneGiven;
069: if (doneLabel == null) {
070: doneGiven = false;
071: doneLabel = new Label(code);
072: } else {
073: doneGiven = true;
074: done = null; // To suppress goto in compileFromStackSimple.
075: }
076: StackTarget.convert(comp, stackType, Type.pointer_type);
077: code.emitStore(valuesVar);
078: code.emitPushInt(0);
079: code.emitStore(indexVar);
080:
081: Label top = new Label(code);
082: top.define(code);
083: code.emitLoad(valuesVar);
084: code.emitLoad(indexVar);
085: code.emitInvokeStatic(Compilation.typeValues.getDeclaredMethod(
086: "nextIndex", 2));
087: code.emitDup(Type.int_type);
088: code.emitStore(nextVar);
089: code.emitGotoIfIntLtZero(doneLabel);
090: code.emitLoad(valuesVar);
091: code.emitLoad(indexVar);
092: code.emitInvokeStatic(Compilation.typeValues.getDeclaredMethod(
093: "nextValue", 2));
094: compileFromStackSimple(comp, SingletonType.getInstance());
095: code.emitLoad(nextVar);
096: code.emitStore(indexVar);
097: code.emitGoto(top);
098: if (doneGiven)
099: done = doneLabel;
100: else
101: doneLabel.define(code);
102:
103: /*
104: if (stackType is singleton type)
105: compileFromStackSimple(comp, stackType);
106: else
107: {
108: code.emitDup(stackType);
109: emit[if TOP instanceof Values];
110: emit loop [Values, get, ...];
111: code.emitElse();
112: compileFromStackSimple(comp, stackType);
113: code.emitFi();
114: }
115: */
116: }
117:
118: public String toString() {
119: return "SeriesTarget[param: " + param + "; func:" + function
120: + " done:" + done + "]";
121: }
122:
123: public Type getType() {
124: return Type.pointer_type;
125: }
126: }
|