/* * @(#) $(JCGO)/jtrsrc/com/ivmaisoft/jcgo/InstanceOf.java -- * a part of JCGO translator. ** * Project: JCGO (http://www.ivmaisoft.com/jcgo/) * Copyright (C) 2001-2012 Ivan Maidanski <ivmai@mail.ru> * All rights reserved. */ /* * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. ** * This software is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License (GPL) for more details. ** * Linking this library statically or dynamically with other modules is * making a combined work based on this library. Thus, the terms and * conditions of the GNU General Public License cover the whole * combination. ** * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent * modules, and to copy and distribute the resulting executable under * terms of your choice, provided that you also meet, for each linked * independent module, the terms and conditions of the license of that * module. An independent module is a module which is not derived from * or based on this library. If you modify this library, you may extend * this exception to your version of the library, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. */ package com.ivmaisoft.jcgo; /** * Grammar production for the instanceof statement. ** * Format: RelationalExpression INSTANCEOF PrimitiveType/ClassOrIfaceType [Dims] */ final class InstanceOf extends LexNode { private int dims; private ClassDefinition cd; InstanceOf(Term a, Term c, Term d) { super(a, c, d); } void processPass1(Context c) { if (cd == null) { terms[0].processPass1(c); int s0 = terms[0].exprType().objectSize(); if (s0 >= Type.BOOLEAN && s0 <= Type.VOID) { fatalError(c, "Illegal type of expression for 'instanceof'"); } ClassDefinition oldTypeClassDefinition = c.typeClassDefinition; int oldTypeDims = c.typeDims; c.typeDims = 0; terms[2].processPass1(c); terms[1].processPass1(c); cd = c.typeClassDefinition; dims = c.typeDims; c.typeDims = oldTypeDims; c.typeClassDefinition = oldTypeClassDefinition; if (dims == 0 && cd.objectSize() <= Type.VOID) { fatalError(c, "Primitive type is not allowed in 'instanceof'"); return; } ExpressionType actualType0 = terms[0].actualExprType(); if (cd.isAssignableFrom(actualType0.signatureClass(), dims - actualType0.signatureDimensions(), c.forClass)) { cd = Main.dict.get(Names.JAVA_LANG_OBJECT); dims = 0; } cd.markForInstanceOf(dims > 0); } } void updateCondBranch(Context c, boolean forTrue) { assertCond(cd != null); VariableDefinition v; if (forTrue && (v = terms[0].getVariable(false)) != null) { ExpressionType actualType0 = c.getActualType(v); if (actualType0 == null) { actualType0 = v.actualExprType(); } ExpressionType exprType = cd.asExprType(dims); if (!ClassDefinition.isAssignableFrom(exprType, actualType0, c.forClass)) { c.setActualType(v, exprType); } c.setVarNotNull(v); } } ExpressionType exprType() { return Main.dict.classTable[Type.BOOLEAN]; } boolean isImmutable() { return terms[0].isImmutable(); } boolean isSafeExpr() { return terms[0].isSafeExpr(); } boolean isSafeWithThrow() { return terms[0].isSafeWithThrow(); } int tokenCount() { return terms[0].tokenCount() + 2; } boolean isAtomary() { return true; } void processOutput(OutputContext oc) { assertCond(cd != null); if (dims == 0 && cd.name().equals(Names.JAVA_LANG_OBJECT)) { oc.cPrint("("); terms[0].atomaryOutput(oc); oc.cPrint("!= "); oc.cPrint(LexTerm.NULL_STR); } else { boolean full = false; if (dims > 0) { if (cd.used()) { full = dims > 1 || cd.isInterface() || cd.objectSize() == Type.CLASSINTERFACE; } else { cd = Main.dict.classTable[Type.BOOLEAN]; dims = 0; } } else { if (cd.hasRealInstances()) { cd = cd.getRealOurClass(); full = cd.isInterface(); } else if (!cd.used() || cd.isInterface()) { cd = Main.dict.classTable[Type.BOOLEAN]; } } boolean simple = false; if (!full && !cd.hasInstantatedSubclasses(false) && terms[0].isNotNull()) { oc.cPrint("(JCGO_METHODS_OF("); terms[0].processOutput(oc); oc.cPrint(")->jcgo_typeid== "); simple = true; } else { oc.cPrint("jcgo_instanceOf"); if (!full) { oc.cPrint("0"); } oc.cPrint("("); } String cname = cd.castName(); oc.cPrint("OBJT_"); oc.cPrint(cname); if (dims > 0 && !full) { oc.cPrint("+OBJT_jarray"); } if (!simple) { oc.cPrint(", MAXT_"); oc.cPrint(cname); if (full) { oc.cPrint(", "); if (cd.isInterface()) { oc.cPrint("~"); } oc.cPrint(Integer.toString(dims)); } else if (dims > 0) { oc.cPrint("+OBJT_jarray"); } oc.cPrint(", ("); oc.cPrint(Type.cName[Type.CLASSINTERFACE]); oc.cPrint(")"); terms[0].atomaryOutput(oc); } } oc.cPrint(")"); } ExpressionType traceClassInit() { terms[0].traceClassInit(); return null; } }