001: /**************************************************************************/
002: /* N I C E */
003: /* A simple imperative object-oriented research language */
004: /* (c) Daniel Bonniot 1999 */
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: Create a multidimensional array.
018:
019: @author Daniel Bonniot
020: */
021:
022: public class MultiArrayNewProc extends gnu.mapping.ProcedureN implements
023: Inlineable {
024: /**
025: @param arrayType the type of the array
026: @param nbDimensions the number of dimensions to be allocated.
027: The corresponding number of integers are expected as arguments
028: of the procedure.
029: */
030: public MultiArrayNewProc(ArrayType arrayType, int nbDimensions) {
031: this .arrayType = arrayType;
032: this .nbDimensions = nbDimensions;
033: }
034:
035: private ArrayType arrayType;
036: private int nbDimensions;
037:
038: public void compile(ApplyExp exp, Compilation comp, Target target) {
039: Expression[] args = exp.getArgs();
040:
041: for (int i = 0; i < nbDimensions; i++)
042: args[i].compile(comp, Type.int_type);
043:
044: arrayType = creationType(arrayType, target, false);
045:
046: comp.getCode().emitNewArray(arrayType.getComponentType(),
047: nbDimensions);
048: target.compileFromStack(comp, arrayType);
049: }
050:
051: /** Decide the bytecode type to create a new array with,
052: given its computed type and the target.
053:
054: @param promote whether promotion of component types is desired.
055: */
056: static ArrayType creationType(ArrayType computedType,
057: Target target, boolean promote) {
058: if (target.getType() instanceof ArrayType) {
059: ArrayType targetType = (ArrayType) target.getType();
060: /*
061: By well-typing, we know the target type is a super-type of
062: the computed type.
063: If the target has primitive components, we might as well
064: use that type to produce better code, since subsumption would need
065: copying otherwise.
066: On the other hand, it would be incorrect (and useless) for
067: reference types, in case the arrays comes back in the value of
068: a function.
069: */
070: if (hasPrimitiveComponents(targetType))
071: return targetType;
072: }
073:
074: if (promote)
075: // We don't have information about the context. The sensible thing to do
076: // is to promote primitive types (those smaller than int).
077: return promoteComponent(computedType);
078: else
079: return computedType;
080: }
081:
082: private static boolean hasPrimitiveComponents(ArrayType array) {
083: Type componentType = array.getComponentType();
084:
085: return componentType instanceof ArrayType
086: || componentType instanceof PrimType;
087: }
088:
089: /** Recursively promote the component of the given array. */
090: private static ArrayType promoteComponent(ArrayType array) {
091: Type type = array.getComponentType();
092:
093: // Is the type subject to promotion?
094: Type promoted;
095:
096: if (type == Type.byte_type || type == Type.short_type)
097: promoted = Type.int_type;
098:
099: // If not directly, is it an array whose component type is?
100: else if (type.isArray())
101: promoted = promoteComponent((ArrayType) type);
102:
103: else
104: promoted = type;
105:
106: // If the component is changed, return a new array.
107: if (promoted != type)
108: return SpecialArray.create(promoted);
109:
110: return array;
111: }
112:
113: public Type getReturnType(Expression[] args) {
114: return arrayType;
115: }
116:
117: public Object applyN(Object[] args) {
118: throw new Error("Not implemented");
119: }
120: }
|