001: /**************************************************************************/
002: /* N I C E */
003: /* A high-level object-oriented research language */
004: /* (c) Daniel Bonniot 2002 */
005: /* */
006: /* This program is free software; you can redistribute it and/or modify */
007: /* it under the terms of the GNU General Public License as published by */
008: /* the Free Software Foundation; either version 2 of the License, or */
009: /* (at your option) any later version. */
010: /* */
011: /**************************************************************************/package nice.tools.code;
012:
013: import gnu.expr.*;
014: import gnu.bytecode.*;
015:
016: /**
017: Creates a literal array constant.
018:
019: @author Daniel Bonniot
020: */
021:
022: public class LiteralArrayProc extends gnu.mapping.ProcedureN implements
023: Inlineable {
024: /**
025: @param arrayType the type of the array
026: @param nbElements the number of elements of the array
027: The corresponding number of elements are expected as arguments
028: of the procedure.
029: */
030: public LiteralArrayProc(ArrayType arrayType, int nbElements,
031: boolean wrapAsCollection) {
032: this .arrayType = arrayType;
033: this .nbElements = nbElements;
034: this .wrapAsCollection = wrapAsCollection;
035: }
036:
037: private ArrayType arrayType;
038: private int nbElements;
039: private boolean wrapAsCollection;
040:
041: public void compile(ApplyExp exp, Compilation comp, Target target) {
042: // The type was not specified explicitely, so we allow promotion.
043: arrayType = MultiArrayNewProc.creationType(arrayType, target,
044: true);
045:
046: Expression[] args = exp.getArgs();
047: CodeAttr code = comp.getCode();
048:
049: Type componentType = arrayType.getComponentType()
050: .getImplementationType();
051:
052: code.emitPushInt(nbElements);
053: code.emitNewArray(componentType);
054:
055: // Set a special type, not the legacy array type.
056: code.popType();
057: code.pushType(arrayType);
058:
059: /*
060: Optimization:
061: We need to keep the reference to the array.
062:
063: Instead of `dup'ing it before each use,
064: we `dup2' it every second iteration.
065:
066: This is better than producing all the references in advance,
067: which would make the stack grow unboundedly.
068:
069: This saves nbElements/2 bytecodes.
070: */
071:
072: if (nbElements > 0)
073: code.emitDup();
074:
075: for (int i = 0; i < nbElements; i++) {
076: // Duplicate the reference to the array, according to our future needs.
077: if (i % 2 == 0)
078: if (i < nbElements - 2)
079: code.emitDup(2);
080: else if (i == nbElements - 2)
081: code.emitDup();
082:
083: // Get the specific type for this rank of the array (useful for tuples)
084: Type specificType = Types.componentType(arrayType, i);
085: // Only use it if it is more specific than the expected type.
086: // For instance don't use int if we store it in an Object[] anyway.
087: if (!specificType.isAssignableTo(componentType))
088: specificType = componentType;
089:
090: code.emitPushInt(i);
091: args[i].compile(comp, specificType);
092: code.emitArrayStore(componentType);
093: }
094:
095: if (wrapAsCollection)
096: SpecialArray.emitCoerceToCollection(code);
097: else
098: target.compileFromStack(comp, code.topType());
099: }
100:
101: public Type getReturnType(Expression[] args) {
102: if (wrapAsCollection)
103: return ClassType.make("java.util.List");
104:
105: return arrayType;
106: }
107:
108: public Object applyN(Object[] args) {
109: throw new Error("Not implemented");
110: }
111: }
|