/* * @(#) $(JCGO)/jtrsrc/com/ivmaisoft/jcgo/BinaryOp.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 binary non-relational operators. ** * Formats: InclusiveOrExpression BITOR ExclusiveOrExpression * ExclusiveOrExpression XOR AndExpression AndExpression BITAND * EqualityExpression ShiftExpression FILLSHIFT_RIGHT AdditiveExpression * ShiftExpression SHIFT_RIGHT AdditiveExpression ShiftExpression SHIFT_LEFT * AdditiveExpression AdditiveExpression PLUS MultiplicativeExpression * AdditiveExpression MINUS MultiplicativeExpression MultiplicativeExpression * MOD UnaryExpression MultiplicativeExpression DIVIDE UnaryExpression * MultiplicativeExpression TIMES UnaryExpression */ final class BinaryOp extends LexNode { private ExpressionType exprType0; private ExpressionType exprType2; private int sym; private int strCnt0; private int strCnt2; private int rcvr; private boolean isString; private boolean t0IsLiteral; private boolean t0IsLiteralSet; private boolean t2IsLiteral; private boolean t2IsLiteralSet; private boolean asLiteral; private ConstValue constVal2; private LeftBrace noLeaksScope; private boolean isConditional; private boolean insideAssertStmt; private String stackObjCode; private boolean needsLocalVolatile; BinaryOp(Term a, Term b, Term c) { super(a, b, c); } boolean isJavaConstant(ClassDefinition ourClass) { return terms[0].isJavaConstant(ourClass) && terms[2].isJavaConstant(ourClass); } int getPrecedenceLevel() { int sym = terms[1].getSym(); return sym == LexTerm.BITOR ? 5 : sym == LexTerm.XOR ? 6 : sym == LexTerm.BITAND ? 7 : sym == LexTerm.FILLSHIFT_RIGHT || sym == LexTerm.SHIFT_LEFT || sym == LexTerm.SHIFT_RIGHT ? 10 : 11; } StringLiteral asStrLiteral() { return terms[1].getSym() == LexTerm.PLUS ? terms[2].asStrLiteral() : null; } boolean appendLiteralTo(Term t) { return terms[1].getSym() == LexTerm.PLUS && terms[0].appendLiteralTo(t) && terms[2].appendLiteralTo(t); } void processPass1(Context c) { if (exprType0 == null) { sym = terms[1].getSym(); if (sym == LexTerm.PLUS) { terms[2].appendLiteralTo(terms[0]); } BranchContext oldBranch = c.saveBranch(); terms[0].processPass1(c); oldBranch = c.swapBranch(oldBranch); exprType0 = terms[0].exprType(); terms[2].processPass1(c); c.unionBranch(oldBranch); exprType2 = terms[2].exprType(); assertCond(!terms[0].isType() && !terms[2].isType()); int s0; int s2; if (sym == LexTerm.PLUS && (exprType0.receiverClass().isStringOrNull() || exprType2 .receiverClass().isStringOrNull())) { if (exprType0.objectSize() == Type.VOID || exprType2.objectSize() == Type.VOID) { fatalError(c, "Inappropriate type of value in string concatenation"); } isString = true; insideAssertStmt = c.insideAssertStmt; strCnt0 = terms[0].countConcatStrs(); strCnt2 = terms[2].countConcatStrs(); if (strCnt2 > 1 && strCnt0 > 0) { strCnt2 = 1; } if (strCnt0 + strCnt2 == 1) { if (strCnt0 == 0) { if (exprType2.receiverClass().isStringOrNull() ? !terms[2] .isNotNull() : terms[2].actualExprType() .objectSize() == Type.CLASSINTERFACE) { strCnt0 = 1; } } else if (exprType0.receiverClass().isStringOrNull() ? !terms[0] .isNotNull() : terms[0].actualExprType() .objectSize() == Type.CLASSINTERFACE) { strCnt2 = 1; } } if (!exprType0.receiverClass().isStringOrNull()) { exprType0 = (terms[0] = wrapInValueOf(c, terms[0])) .exprType(); } if (!exprType2.receiverClass().isStringOrNull()) { exprType2 = (terms[2] = wrapInValueOf(c, terms[2])) .exprType(); } if (strCnt0 + strCnt2 > 2) { ClassDefinition cd = Main.dict .get(Names.JAVA_LANG_STRINGBUILDER); cd.define(c.forClass); cd.markMethod("<init>()"); cd.markMethod(Names.SIGN_APPEND_STRING); Main.dict.get(Names.JAVA_LANG_STRING).markMethod( Names.SIGN_INIT_STRINGBUILDER); } else { Main.dict.get(Names.JAVA_LANG_VMSYSTEM).markMethod( Names.SIGN_CONCAT0X); } isConditional = c.isConditional; noLeaksScope = c.localScope; } else if ((s0 = exprType0.objectSize()) == Type.BOOLEAN && exprType2.objectSize() == Type.BOOLEAN) { if (sym != LexTerm.XOR && sym != LexTerm.BITOR && sym != LexTerm.BITAND) { fatalError(c, "Illegal boolean logical operator"); } } else if (s0 >= Type.VOID || s0 <= Type.BOOLEAN || (s2 = exprType2.objectSize()) >= Type.VOID || s2 <= Type.BOOLEAN || ((s0 >= Type.FLOAT || s2 >= Type.FLOAT) && (sym == LexTerm.XOR || sym == LexTerm.BITOR || sym == LexTerm.BITAND || sym == LexTerm.FILLSHIFT_RIGHT || sym == LexTerm.SHIFT_RIGHT || sym == LexTerm.SHIFT_LEFT))) { fatalError(c, "Inappropriate type of value in numeric expression"); } constVal2 = terms[2].evaluateConstValue(); if (constVal2 == null && !isString && (sym == LexTerm.PLUS || sym == LexTerm.TIMES || sym == LexTerm.BITAND || sym == LexTerm.BITOR || sym == LexTerm.XOR) && (constVal2 = terms[0].evaluateConstValue()) != null) { Term t = terms[0]; terms[0] = terms[2]; terms[2] = t; ExpressionType exprType = exprType0; exprType0 = exprType2; exprType2 = exprType; } } } ConstValue evaluateConstValue() { assertCond(exprType0 != null); if (constVal2 == null || isString) return null; ConstValue constVal0 = terms[0].evaluateConstValue(); return constVal0 != null ? constVal0.arithmeticOp(constVal2, sym) : null; } boolean isFPZero() { assertCond(exprType0 != null); return sym != LexTerm.DIVIDE && sym != LexTerm.MOD && terms[0].isFPZero() && terms[2].isFPZero(); } ExpressionType exprType() { assertCond(exprType0 != null); int s0 = exprType0.objectSize(); int s2 = exprType2.objectSize(); if (isString) return Main.dict.get(Names.JAVA_LANG_STRING); if (s0 != Type.BOOLEAN || s2 != Type.BOOLEAN) { if (sym == LexTerm.FILLSHIFT_RIGHT || sym == LexTerm.SHIFT_RIGHT || sym == LexTerm.SHIFT_LEFT) return s0 >= Type.INT ? exprType0 : Main.dict.classTable[Type.INT]; if (s0 < Type.INT && s2 < Type.INT) return Main.dict.classTable[Type.INT]; if (s0 < s2) return exprType2; } return exprType0; } int countConcatStrs() { assertCond(exprType0 != null); return isString ? strCnt0 + strCnt2 : 1; } private boolean t0IsLiteral() { if (!t0IsLiteralSet) { t0IsLiteral = terms[0].isLiteral() && (!isString || exprType0.receiverClass().isStringOrNull()); t0IsLiteralSet = true; } return t0IsLiteral; } private boolean t2IsLiteral() { if (!t2IsLiteralSet) { t2IsLiteral = terms[2].isLiteral() && (!isString || exprType2.receiverClass().isStringOrNull()); t2IsLiteralSet = true; } return t2IsLiteral; } private boolean t2IsNonZeroLiteral() { return constVal2 != null && constVal2.isNonZero() && t2IsLiteral(); } boolean isLiteral() { assertCond(exprType0 != null); if (isString) return strCnt0 + strCnt2 <= 1 && t0IsLiteral() && t2IsLiteral(); if (sym == LexTerm.DIVIDE || sym == LexTerm.MOD) return exprType0.objectSize() < Type.FLOAT && exprType2.objectSize() < Type.FLOAT && t0IsLiteral() && t2IsNonZeroLiteral(); if (exprType0.objectSize() != Type.LONG || (sym != LexTerm.SHIFT_LEFT && sym != LexTerm.FILLSHIFT_RIGHT && sym != LexTerm.SHIFT_RIGHT)) return t0IsLiteral() && t2IsLiteral(); return constVal2 != null && t0IsLiteral() && t2IsLiteral() && terms[0].evaluateConstValue() != null; } boolean isImmutable() { assertCond(exprType0 != null); return isString ? strCnt0 + strCnt2 <= 1 && t0IsLiteral() && t2IsLiteral() : ((sym != LexTerm.DIVIDE && sym != LexTerm.MOD) || exprType0.objectSize() >= Type.FLOAT || exprType2.objectSize() >= Type.FLOAT ? terms[2] .isImmutable() : t2IsNonZeroLiteral()) && terms[0].isImmutable(); } boolean isSafeExpr() { assertCond(exprType0 != null); return ((sym != LexTerm.DIVIDE && sym != LexTerm.MOD) || exprType0.objectSize() >= Type.FLOAT || exprType2.objectSize() >= Type.FLOAT ? terms[2].isSafeExpr() : t2IsNonZeroLiteral()) && terms[0].isSafeExpr(); } boolean isSafeWithThrow() { return terms[0].isSafeWithThrow() && terms[2].isSafeWithThrow(); } int tokenCount() { return isString ? (strCnt0 + strCnt2 <= 1 ? 1 : strCnt0 == 0 ? terms[2] .tokenCount() : strCnt2 == 0 ? terms[0].tokenCount() : terms[0] .tokenCount() + terms[2].tokenCount() + 2) : constVal2 != null && terms[0].evaluateConstValue() != null ? 1 : terms[0] .tokenCount() + terms[2].tokenCount() + (terms[0].isSafeExpr() || terms[2].isSafeExpr() ? 1 : 2); } static boolean isRcvrNeeded(Term t0, Term t2) { return t0.isSafeExpr() ? !t2.isSafeWithThrow() && (t0.isFieldAccessed(null) || t2.isAnyLocalVarChanged(t0)) && !t0.isImmutable() : t0.isSafeWithThrow() ? !t2.isSafeExpr() : !t2.isImmutable() && (!t2.isSafeExpr() || t2.isFieldAccessed(null) || t0 .isAnyLocalVarChanged(t2)); } void allocRcvr(int[] curRcvrs) { assertCond(exprType0 != null); int[] curRcvrs2 = OutputContext.copyRcvrs(curRcvrs); terms[0].allocRcvr(curRcvrs); int s0; if (isRcvrNeeded(terms[0], terms[2])) { rcvr = ++curRcvrs2[!isString && (s0 = exprType0.objectSize()) < Type.VOID ? s0 : Type.NULLREF]; } terms[2].allocRcvr(curRcvrs2); OutputContext.joinRcvrs(curRcvrs, curRcvrs2); } boolean isNotNull() { return true; } String strLiteralValueGuess() { if (!isString) return null; String str0 = terms[0].strLiteralValueGuess(); String str2 = terms[2].strLiteralValueGuess(); return str0 != null ? (str2 != null ? str0 + str2 : str0) : str2; } void requireLiteral() { asLiteral = true; terms[0].requireLiteral(); terms[2].requireLiteral(); } void setStackObjVolatile() { if (!needsLocalVolatile) { needsLocalVolatile = true; if (isString) { if (strCnt0 + strCnt2 <= 2) { terms[0].setStackObjVolatile(); terms[2].setStackObjVolatile(); } else if (strCnt0 == 0) { terms[2].setStackObjVolatile(); } else if (strCnt2 == 0) { terms[0].setStackObjVolatile(); } } } } void setObjLeaks(VariableDefinition v) { if (isString) { if (strCnt0 + strCnt2 <= 2) { terms[0].setObjLeaks(v); terms[2].setObjLeaks(v); } else if (strCnt0 == 0) { terms[2].setObjLeaks(v); } else if (strCnt2 == 0) { terms[0].setObjLeaks(v); } if (strCnt0 > 1 && strCnt2 > 0) { noLeaksScope = VariableDefinition.addSetObjLeaksTerm( noLeaksScope, v, this, isConditional); } } } String writeStackObjDefn(OutputContext oc, boolean needsLocalVolatile) { assertCond(isString); return InstanceCreation.writeStackObjectDefn(oc, Main.dict.get(Names.JAVA_LANG_STRING), false, insideAssertStmt, needsLocalVolatile && Main.dict.allowConstStr <= 0); } void writeStackObjs(OutputContext oc, Term scopeTerm) { if (isString && strCnt0 > 1 && strCnt2 > 0) { terms[0].writeStackStrBufObj(oc, scopeTerm); if (noLeaksScope == scopeTerm) { assertCond(scopeTerm != null); stackObjCode = writeStackObjDefn(oc, needsLocalVolatile); } } else { terms[0].writeStackObjs(oc, scopeTerm); } terms[2].writeStackObjs(oc, scopeTerm); } void writeStackStrBufObj(OutputContext oc, Term scopeTerm) { assertCond(isString); if (strCnt0 == 0) { terms[2].writeStackStrBufObj(oc, scopeTerm); } else { if (strCnt2 == 0 || strCnt0 > 1) { terms[0].writeStackStrBufObj(oc, scopeTerm); } else { terms[0].writeStackObjs(oc, scopeTerm); if (noLeaksScope == scopeTerm) { assertCond(scopeTerm != null); stackObjCode = InstanceCreation.writeStackObjectDefn(oc, Main.dict.get(Names.JAVA_LANG_STRINGBUILDER), true, insideAssertStmt, false); } } terms[2].writeStackObjs(oc, scopeTerm); } } ExpressionType writeStackObjRetCode(OutputContext oc) { assertCond(isString && noLeaksScope == null); stackObjCode = MethodDefinition.STACKOBJ_RETNAME; oc.cPrint(Main.dict.get(Names.JAVA_LANG_STRING).cNewObjectCode()); return exprType(); } boolean isAtomary() { return isString || rcvr > 0 || sym == LexTerm.FILLSHIFT_RIGHT || sym == LexTerm.SHIFT_RIGHT || sym == LexTerm.SHIFT_LEFT; } static void outputDivShift(OutputContext oc, int sym, int s0) { if (sym == LexTerm.DIVIDE || sym == LexTerm.MOD) { oc.cPrint("jcgo_"); if (s0 == Type.LONG) { oc.cPrint("l"); } else if (s0 >= Type.FLOAT) { oc.cPrint("f"); } oc.cPrint(sym == LexTerm.DIVIDE ? "div" : "mod"); if (s0 == Type.FLOAT) { oc.cPrint("f"); } } else { oc.cPrint("JCGO_"); if (s0 == Type.LONG) { oc.cPrint("L"); } if (sym == LexTerm.FILLSHIFT_RIGHT) { oc.cPrint("U"); } oc.cPrint(sym == LexTerm.SHIFT_LEFT ? "SHL" : "SHR"); oc.cPrint("_F"); } oc.cPrint("("); } void parameterOutput(OutputContext oc, boolean asArg, int type) { assertCond(isString); if (strCnt0 == 0) { terms[2].parameterOutput(oc, asArg, type); } else if (strCnt2 == 0) { terms[0].parameterOutput(oc, asArg, type); } else { String rcvrStr = null; if (rcvr > 0) { rcvrStr = OutputContext.getRcvrName(rcvr, Type.CLASSINTERFACE); oc.cPrint("("); oc.cPrint(rcvrStr); oc.cPrint("= ("); oc.cPrint(Type.cName[Type.CLASSINTERFACE]); oc.cPrint(")"); ExpressionType oldAssignmentRightType = oc.assignmentRightType; oc.assignmentRightType = null; if (strCnt0 > 1) { terms[0].parameterOutput(oc, asArg, type); } else { terms[0].atomaryOutput(oc); } oc.assignmentRightType = oldAssignmentRightType; oc.cPrint(", "); } ClassDefinition cd = Main.dict.get(Names.JAVA_LANG_STRINGBUILDER); MethodDefinition md = cd.getMethod(Names.SIGN_APPEND_STRING); oc.cPrint(md != null ? md.routineCName() : MethodDefinition.UNKNOWN_NAME); oc.cPrint("(\010 "); if (strCnt0 <= 1) { oc.cPrint(md != null ? md.routineCName() : MethodDefinition.UNKNOWN_NAME); Main.dict.normalCalls++; oc.cPrint("(\010 "); InstanceCreation.writeNewRoutineCall(oc, cd.getMethod("<init>()"), stackObjCode); oc.cPrint("), "); } if (rcvrStr != null) { oc.cPrint("("); oc.cPrint((strCnt0 <= 1 ? Main.dict.get(Names.JAVA_LANG_STRING) : cd).castName()); oc.cPrint(")"); oc.cPrint(rcvrStr); } else if (strCnt0 > 1) { terms[0].parameterOutput(oc, asArg, type); } else { terms[0].processOutput(oc); } if (strCnt0 <= 1) { oc.cPrint(")"); } oc.cPrint(", "); terms[2].processOutput(oc); oc.cPrint(")"); Main.dict.normalCalls++; if (rcvrStr != null) { oc.cPrint(")"); } } } void processOutput(OutputContext oc) { assertCond(exprType0 != null); String rcvrStr = null; String str0 = null; if (isString) { if (strCnt0 > 1 && strCnt2 > 0) { OutputContext oc2 = new OutputContext(); terms[0].parameterOutput(oc2, false, Type.NULLREF); str0 = oc2.instanceToString(); } else { str0 = strCnt0 > 0 ? (strCnt2 == 0 && !terms[0].isAtomary() ? "(" + terms[0].stringOutput() + ")" : terms[0].stringOutput()) : LexTerm.NULL_STR; } } if (rcvr > 0) { rcvrStr = OutputContext.getRcvrName(rcvr, isString ? Type.CLASSINTERFACE : exprType0.objectSize()); oc.cPrint("("); oc.cPrint(rcvrStr); oc.cPrint("= "); if (str0 != null) { oc.cPrint("("); oc.cPrint(Type.cName[Type.CLASSINTERFACE]); oc.cPrint(")"); oc.cPrint(str0); } else { ExpressionType oldAssignmentRightType = oc.assignmentRightType; oc.assignmentRightType = null; terms[0].processOutput(oc); oc.assignmentRightType = oldAssignmentRightType; } oc.cPrint(", "); } if (str0 != null) { if (strCnt0 > 0) { ClassDefinition cd = Main.dict.get(Names.JAVA_LANG_STRING); if (strCnt2 > 0) { MethodDefinition md; if (strCnt0 > 1) { InstanceCreation.writeNewRoutineCall(oc, cd.getMethod(Names.SIGN_INIT_STRINGBUILDER), stackObjCode); cd = Main.dict.get(Names.JAVA_LANG_STRINGBUILDER); md = cd.getMethod(Names.SIGN_APPEND_STRING); } else { md = Main.dict.get(Names.JAVA_LANG_VMSYSTEM).getMethod( Names.SIGN_CONCAT0X); } oc.cPrint(md != null ? md.routineCName() : MethodDefinition.UNKNOWN_NAME); Main.dict.normalCalls++; oc.cPrint("(\010 "); } oc.cPrint(rcvrStr != null ? "(" + cd.castName() + ")" + rcvrStr : str0); if (strCnt2 > 0) { oc.cPrint(", "); } } if (strCnt2 > 0 || strCnt0 == 0) { if (strCnt0 > 0) { terms[2].processOutput(oc); } else { terms[2].atomaryOutput(oc); } if (strCnt0 > 0) { oc.cPrint(")"); if (strCnt0 > 1) { oc.cPrint(")"); } } } } else { int s0 = exprType0.objectSize(); int s2 = exprType2.objectSize(); int sm = s0 <= s2 ? s2 : s0; ConstValue value; if (sm == Type.LONG && (value = evaluateConstValue()) != null) { oc.cPrint(value.stringOutput()); } else if (sym != LexTerm.DIVIDE && sym != LexTerm.MOD ? sym == LexTerm.FILLSHIFT_RIGHT || sym == LexTerm.SHIFT_RIGHT || sym == LexTerm.SHIFT_LEFT : sm >= Type.FLOAT || (t0IsLiteral() ? !t2IsNonZeroLiteral() : sm == Type.LONG || constVal2 == null || !constVal2.isNonZero() || constVal2.isMinusOne())) { outputDivShift(oc, sym, sym == LexTerm.DIVIDE || sym == LexTerm.MOD ? sm : s0); if (sm >= Type.LONG && sm > s0 && (sym == LexTerm.DIVIDE || sym == LexTerm.MOD)) { oc.cPrint("("); oc.cPrint(Type.cName[sm]); oc.cPrint(")"); if (rcvrStr != null) { oc.cPrint(rcvrStr); } else { terms[0].atomaryOutput(oc); } } else if (rcvrStr != null) { oc.cPrint(rcvrStr); } else { terms[0].processOutput(oc); } oc.cPrint(", "); if (sym == LexTerm.DIVIDE || sym == LexTerm.MOD) { if (sm >= Type.LONG && sm > s2) { oc.cPrint("("); oc.cPrint(Type.cName[sm]); oc.cPrint(")"); terms[2].atomaryOutput(oc); } else { terms[2].processOutput(oc); } } else if (s2 == Type.LONG) { oc.cPrint("("); oc.cPrint(Type.cName[Type.INT]); oc.cPrint(")"); terms[2].atomaryOutput(oc); } else { terms[2].processOutput(oc); } oc.cPrint(")"); } else if (constVal2 != null && rcvrStr == null && sym == LexTerm.BITAND && s0 < Type.INT && s2 <= Type.INT && constVal2.getIntValue() == (s0 != Type.BYTE ? 0xffff : 0xff)) { oc.cPrint("("); oc.cPrint(Type.cName[Type.INT]); oc.cPrint(")(("); oc.cPrint(s0 != Type.BYTE ? Type.cName[Type.CHAR] : "unsigned\003 \003" + "char"); oc.cPrint(")"); terms[0].atomaryOutput(oc); oc.cPrint(")"); } else { terms[0].insideArithOp(); terms[2].insideArithOp(); if (sm < Type.INT && sm != Type.BOOLEAN) { oc.cPrint("("); oc.cPrint(Type.cName[Type.INT]); oc.cPrint(")"); } int opLevel = getPrecedenceLevel(); if (sm >= Type.LONG && sm > s0) { oc.cPrint("("); oc.cPrint(Type.cName[sm]); oc.cPrint(")"); ConstValue constVal0; if (rcvrStr != null) { oc.cPrint(rcvrStr); } else if (sm >= Type.FLOAT && !asLiteral && (constVal0 = terms[0].evaluateConstValue()) != null && !constVal0.isNonZero()) { oc.cPrint(sm == Type.FLOAT ? "JCGO_FP_ZEROF" : "JCGO_FP_ZERO"); } else { terms[0].atomaryOutput(oc); } } else if (rcvrStr != null) { oc.cPrint(rcvrStr); } else if (s0 == Type.BOOLEAN || opLevel < terms[0].getPrecedenceLevel()) { terms[0].atomaryOutput(oc); } else { terms[0].processOutput(oc); } oc.cPrint("\003 "); terms[1].processOutput(oc); oc.cPrint("\003 "); if (sm >= Type.LONG && sm > s2) { oc.cPrint("("); oc.cPrint(Type.cName[sm]); oc.cPrint(")"); if (sm >= Type.FLOAT && constVal2 != null && !asLiteral && !constVal2.isNonZero()) { oc.cPrint(sm == Type.FLOAT ? "JCGO_FP_ZEROF" : "JCGO_FP_ZERO"); } else { terms[2].atomaryOutput(oc); } } else if (s2 == Type.BOOLEAN || opLevel < terms[2].getPrecedenceLevel()) { terms[2].atomaryOutput(oc); } else { terms[2].processOutput(oc); } } } if (rcvrStr != null) { oc.cPrint(")"); } } static Term wrapInValueOf(Context c, Term t) { int s0 = t.exprType().objectSize(); return s0 >= Type.CLASSINTERFACE && t.isNotNull() ? new MethodInvocation( c, t, Names.TOSTRING) : new MethodInvocation(c, Main.dict.get(Names.JAVA_LANG_STRING), Names.VALUEOF, s0 == Type.CLASSINTERFACE + Type.CHAR || s0 == Type.NULLREF ? (new CastExpression( new Expression(new ClassOrIfaceType(Main.dict .get(Names.JAVA_LANG_OBJECT))), t)) .processPassOneInner(c, false).setLineInfoFrom( t) : t); } ExpressionType traceClassInit() { terms[0].traceClassInit(); terms[2].traceClassInit(); if (isString && strCnt0 > 0 && strCnt2 > 0) { MethodDefinition md; if (strCnt0 + strCnt2 > 2) { ClassDefinition cd = Main.dict .get(Names.JAVA_LANG_STRINGBUILDER); md = cd.getMethod("<init>()"); if (md != null) { md.methodTraceClassInit(false, null, null); } md = cd.getMethod(Names.SIGN_APPEND_STRING); if (md != null) { md.methodTraceClassInit(false, null, null); } md = Main.dict.get(Names.JAVA_LANG_STRING).getMethod( Names.SIGN_INIT_STRINGBUILDER); } else { md = Main.dict.get(Names.JAVA_LANG_VMSYSTEM).getMethod( Names.SIGN_CONCAT0X); } if (md != null) { md.methodTraceClassInit(false, null, null); } } return null; } }