All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.dev.compiler.java.ArrayExpression Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */


package com.tangosol.dev.compiler.java;


import com.tangosol.dev.assembler.CodeAttribute;
import com.tangosol.dev.assembler.Op;
import com.tangosol.dev.assembler.Iconst;
import com.tangosol.dev.assembler.Dup;
import com.tangosol.dev.assembler.Znewarray;
import com.tangosol.dev.assembler.Bnewarray;
import com.tangosol.dev.assembler.Cnewarray;
import com.tangosol.dev.assembler.Snewarray;
import com.tangosol.dev.assembler.Inewarray;
import com.tangosol.dev.assembler.Lnewarray;
import com.tangosol.dev.assembler.Fnewarray;
import com.tangosol.dev.assembler.Dnewarray;
import com.tangosol.dev.assembler.Anewarray;
import com.tangosol.dev.assembler.Bastore;
import com.tangosol.dev.assembler.Castore;
import com.tangosol.dev.assembler.Sastore;
import com.tangosol.dev.assembler.Iastore;
import com.tangosol.dev.assembler.Lastore;
import com.tangosol.dev.assembler.Fastore;
import com.tangosol.dev.assembler.Dastore;
import com.tangosol.dev.assembler.Aastore;
import com.tangosol.dev.assembler.ClassConstant;


import com.tangosol.dev.compiler.CompilerException;
import com.tangosol.dev.compiler.Context;

import com.tangosol.dev.component.DataType;

import com.tangosol.util.ErrorList;

import java.util.Set;
import java.util.Map;


/**
* Implements the array ({}) expression used in array initializers and array
* allocation expressions.
*
* @version 1.00, 10/05/98
* @author  Cameron Purdy
*/
public class ArrayExpression extends Expression
    {
    // ----- construction ---------------------------------------------------

    /**
    * Construct a ArrayExpression.
    *
    * @param block     the containing block
    * @param tokFirst  the first token ({)
    * @param tokLast   the last token (})
    * @param aexpr     an array of expressions
    */
    public ArrayExpression(Block block, Token tokFirst, Token tokLast, Expression[] aexpr)
        {
        super(block, tokFirst, tokLast);

        this.aexpr = aexpr;
        }


    // ----- code generation ------------------------------------------------

    /**
    * Perform semantic checks, parse tree re-organization, name binding,
    * and optimizations.
    *
    * @param ctx        the compiler context
    * @param setUVars   the set of potentially unassigned variables
    * @param setFVars   the set of potentially assigned final variables
    * @param mapThrown  the set of potentially thrown checked exceptions
    * @param errlist    the error list
    *
    * @return the resulting language element (typically this)
    *
    * @exception CompilerException  thrown if an error occurs that should
    *            stop the compilation process
    */
    protected Element precompile(Context ctx, DualSet setUVars, DualSet setFVars, Map mapThrown, ErrorList errlist)
            throws CompilerException
        {
        // unlike other expressions, the array expression does not determine
        // its own type; by this point, the type should have been supplied
        if (getType() == UNKNOWN)
            {
            logError(ERROR, ARRAY_UNEXPECTED, null, errlist);
            return this;
            }

        DataType dtElement = getElementType();
        char     chType    = dtElement.getTypeString().charAt(0);

        Expression[] aexpr = this.aexpr;
        int          cexpr = aexpr.length;

        for (int i = 0; i < cexpr; ++i)
            {
            Expression expr = aexpr[i];

            if (expr instanceof ArrayExpression)
                {
                if (dtElement.isArray())
                    {
                    expr.setType(dtElement);
                    }
                else
                    {
                    logError(ERROR, BAD_INITIALIZER, new String[] {dtElement.toString()}, errlist);
                    continue;
                    }
                }

            expr = (Expression) expr.precompile(ctx, setUVars, setFVars, mapThrown, errlist);
            if (expr.checkAssignable(ctx, dtElement, errlist))
                {
                expr = expr.convertAssignable(ctx, dtElement);
                }
            aexpr[i] = expr;
            }

        // store expressions
        this.aexpr = aexpr;

        return this;
        }

    /**
    * Perform final optimizations and code generation.
    *
    * @param ctx       the compiler context
    * @param code      the assembler code attribute to compile to
    * @param fReached  true if this language element is reached (JLS 14.19)
    * @param errlist   the error list to log errors to
    *
    * @return true if the element can complete normally (JLS 14.1)
    *
    * @exception CompilerException  thrown if an error occurs that should
    *            stop the compilation process
    */
    protected boolean compile(Context ctx, CodeAttribute code, boolean fReached, ErrorList errlist)
            throws CompilerException
        {
        // compilation for "{e0, e1, ..., en}":
        //
        //      iconst n
        //      ?newarray
        //
        // for element e at index i:
        //
        //      dup
        //      iconst i
        //      [e]
        //      ?astore

        DataType dtElement = getElementType();
        char     chType    = dtElement.getTypeString().charAt(0);

        Expression[] aexpr = this.aexpr;
        int          cexpr = aexpr.length;

        // size of array to create
        code.add(new Iconst(cexpr));

        // array creation
        Op opNew = null;
        switch (chType)
            {
            case 'Z':
                opNew = new Znewarray();
                break;
            case 'B':
                opNew = new Bnewarray();
                break;
            case 'C':
                opNew = new Cnewarray();
                break;
            case 'S':
                opNew = new Snewarray();
                break;
            case 'I':
                opNew = new Inewarray();
                break;
            case 'J':
                opNew = new Lnewarray();
                break;
            case 'F':
                opNew = new Fnewarray();
                break;
            case 'D':
                opNew = new Dnewarray();
                break;
            case 'N':
            case 'L':
            case 'R':
            case '[':
                opNew = new Anewarray(dtElement.getClassConstant());
                break;
            default:
                throw new IllegalStateException();
            }
        code.add(opNew);

        boolean fDebug = ctx.isDebug();
        for (int i = 0; i < cexpr; ++i)
            {
            Expression expr   = aexpr[i];
            boolean    fNoOpt = fDebug || !expr.isConstant();

            Op opStore = null;
            switch (chType)
                {
                case 'Z':
                    if (fNoOpt || ((Boolean) expr.getValue()).booleanValue() != false)
                        {
                        opStore = new Bastore();
                        }
                    break;
                case 'B':
                    if (fNoOpt || ((Number) expr.getValue()).byteValue() != (byte) 0)
                        {
                        opStore = new Bastore();
                        }
                    break;
                case 'C':
                    if (fNoOpt || (char) ((Number) expr.getValue()).intValue() != '\0')
                        {
                        opStore = new Castore();
                        }
                    break;
                case 'S':
                    if (fNoOpt || ((Number) expr.getValue()).shortValue() != (short) 0)
                        {
                        opStore = new Sastore();
                        }
                    break;
                case 'I':
                    if (fNoOpt || ((Number) expr.getValue()).intValue() != 0)
                        {
                        opStore = new Iastore();
                        }
                    break;
                case 'J':
                    if (fNoOpt || ((Number) expr.getValue()).longValue() != 0L)
                        {
                        opStore = new Lastore();
                        }
                    break;
                case 'F':
                    if (fNoOpt || ((Number) expr.getValue()).floatValue() != 0.0F)
                        {
                        opStore = new Fastore();
                        }
                    break;
                case 'D':
                    if (fNoOpt || ((Number) expr.getValue()).doubleValue() != 0.0)
                        {
                        opStore = new Dastore();
                        }
                    break;
                case 'N':
                case 'L':
                case 'R':
                case '[':
                    if (fNoOpt || expr.getValue() != null)
                        {
                        opStore = new Aastore();
                        }
                    break;
                default:
                    throw new IllegalStateException();
                }

            // set element  value at index 
            if (opStore != null)
                {
                code.add(new Dup());
                code.add(new Iconst(i));
                expr.compile(ctx, code, fReached, errlist);
                code.add(opStore);
                }
            }

        return fReached;
        }


    // ----- accessors ------------------------------------------------------

    /**
    * Determine the contents of the array expression.
    *
    * @return the array of expressions
    */
    public Expression[] getElements()
        {
        return aexpr;
        }

    /**
    * Determine the type of the contents of the array.
    *
    * @return the declared type of the array elements
    */
    public DataType getElementType()
        {
        return getType().getElementType();
        }


    // ----- Expression methods ---------------------------------------------

    /**
    * Determine if the expression has a constant value.
    *
    * @return true if the expression results in a constant value
    */
    public boolean isConstant()
        {
        // constant iff all expressions are constant
        Expression[] aexpr = this.aexpr;
        int          cexpr = aexpr.length;
        for (int i = 0; i < cexpr; ++i)
            {
            if (!aexpr[i].isConstant())
                {
                return false;
                }
            }

        return true;
        }

    /**
    * Determine the constant value of the expression.
    *
    * @return the constant value of the expression
    */
    public Object getValue()
        {
        Expression[] aexpr = this.aexpr;
        int          cexpr = aexpr.length;

        Object[] aval = new Object[cexpr];
        for (int i = 0; i < cexpr; ++i)
            {
            aval[i] = aexpr[i].getValue();
            }

        return aval;
        }


    // ----- Element methods ------------------------------------------------

    /**
    * Print the element information.
    *
    * @param sIndent
    */
    public void print(String sIndent)
        {
        out(sIndent + toString());

        Expression[] aexpr = this.aexpr;
        int          cexpr = aexpr.length;
        for (int i = 0; i < cexpr; ++i)
            {
            out(sIndent + "  [" + i + "]");
            aexpr[i].print(sIndent + "    ");
            }
        }


    // ----- data members ---------------------------------------------------

    /**
    * The class name.
    */
    private static final String CLASS = "ArrayExpression";

    /**
    * Unknown data type.
    */
    private static final DataType UNKNOWN = DataType.UNKNOWN;

    /**
    * Null data type.
    */
    private static final DataType NULL = DataType.NULL;

    /**
    * The array of expressions.
    */
    private Expression[] aexpr;
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy