/******************************************************************************* * Copyright © 2012, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.gen.javascript.templates.eglx.lang; import org.eclipse.edt.gen.javascript.CommonUtilities; import org.eclipse.edt.gen.javascript.Constants; import org.eclipse.edt.gen.javascript.Context; import org.eclipse.edt.gen.javascript.templates.JavaScriptTemplate; import org.eclipse.edt.mof.codegen.api.TabbedWriter; import org.eclipse.edt.mof.egl.*; import org.eclipse.edt.mof.egl.utils.TypeUtils; public class NumberTypeTemplate extends JavaScriptTemplate { /* WARNING: Template methods in this class should use an if/else convention to ensure * that they only process the Number type, otherwise, they should defer to ctx.invokeSuper. */ // this method gets invoked when there is a specific fixed precision needed public void genDefaultValue(FixedPrecisionType type, Context ctx, TabbedWriter out) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { processDefaultValue(type, ctx, out); } else { ctx.invokeSuper(this, genDefaultValue, type, ctx, out); } } // this method gets invoked when there is a generic (unknown) fixed precision needed public void genDefaultValue(Type type, Context ctx, TabbedWriter out) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { processDefaultValue(type, ctx, out); } else { ctx.invokeSuper(this, genDefaultValue, type, ctx, out); } } public void processDefaultValue(Type type, Context ctx, TabbedWriter out) { out.print(Constants.JSRT_EGL_NAMESPACE + ctx.getNativeMapping("eglx.lang.ENumber") + ".ZERO"); } public Boolean isMathLibDecimalBoxingWanted(Type type, Context ctx) { return !type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber"); } // this method gets invoked when there is a specific fixed precision needed public void genSignature(FixedPrecisionType type, Context ctx, TabbedWriter out) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { String signature = "N" + type.getLength() + ":" + type.getDecimals() + ";"; out.print(signature); } else { ctx.invokeSuper(this, genSignature, type, ctx, out); } } // this method gets invoked when there is a generic (unknown) fixed precision needed public void genSignature(ParameterizableType type, Context ctx, TabbedWriter out) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { String signature = "N;"; out.print(signature); } else { ctx.invokeSuper(this, genSignature, type, ctx, out); } } protected boolean needsConversion(Type fromType, Type toType) { boolean result = true; if (TypeUtils.isNumericType(fromType) && !CommonUtilities.needsConversion(fromType, toType)) result = CommonUtilities.isJavaScriptBigDecimal(toType); return result; } public void genConversionOperation(Type type, Context ctx, TabbedWriter out, AsExpression arg) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber") && (arg.getConversionOperation() != null)) { Type toType = arg.getEType(); out.print(ctx.getNativeImplementationMapping(toType) + '.'); out.print(CommonUtilities.getOpName(ctx, arg.getConversionOperation())); out.print("("); Expression objectExpr = arg.getObjectExpr(); if (objectExpr instanceof BoxingExpression){ objectExpr = ((BoxingExpression)objectExpr).getExpr(); } ctx.invoke(genExpression, objectExpr, ctx, out); ctx.invoke(genTypeDependentOptions, arg.getEType(), ctx, out, arg); out.print(")"); } else { // we need to invoke the logic in type template to call back to the other conversion situations ctx.invokeSuper(this, genConversionOperation, type, ctx, out, arg); } } public void genTypeDependentOptions(ParameterizableType type, Context ctx, TabbedWriter out, AsExpression arg) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { out.print(", "); // if we get here, then we have been given an integer literal, to be represented as a FixedPrecisionType. So, we must // set the dependend options to be a list of nines if (arg.getObjectExpr() instanceof IntegerLiteral) { String value = ((IntegerLiteral) arg.getObjectExpr()).getValue(); if (value.startsWith("-")) value = value.substring(1); if (value.length() > 4) out.print("egl.javascript.BigDecimal.prototype.NINES[8]"); else out.print("egl.javascript.BigDecimal.prototype.NINES[3]"); } else out.print("egl.javascript.BigDecimal.prototype.NINES[8]"); } else ctx.invokeSuper(this, genTypeDependentOptions, type, ctx, out, arg); } public void genTypeDependentOptions(ParameterizableType type, Context ctx, TabbedWriter out) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { out.print(", "); out.print("egl.javascript.BigDecimal.prototype.NINES[8]"); } else ctx.invokeSuper(this, genTypeDependentOptions, type, ctx, out); } public void genBinaryExpression(Type type, Context ctx, TabbedWriter out, BinaryExpression arg) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { out.print(getNativeStringPrefixOperation(arg)); ctx.invoke(genExpression, arg.getLHS(), ctx, out, arg.getOperation().getParameters().get(0)); out.print(getNativeStringOperation(arg)); ctx.invoke(genExpression, arg.getRHS(), ctx, out, arg.getOperation().getParameters().get(1)); out.print(getNativeStringPostfixOperation(arg)); } else ctx.invokeSuper(this, genBinaryExpression, type, ctx, out, arg); } public void genIsaExpression(Type type, Context ctx, TabbedWriter out, IsAExpression arg) { if (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { if (TypeUtils.Type_Number.equals(type.getTypeSignature())) { out.print("egl.is("); ctx.invoke(genExpression, arg.getObjectExpr(), ctx, out); if (arg.getObjectExpr().getType().getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) { out.print(".eze$$value"); } out.print(", \"NUMERIC\",egl.isnumeric)"); } else { ctx.invokeSuper(this, genIsaExpression, type, ctx, out, arg); } } else ctx.invokeSuper(this, genIsaExpression, type, ctx, out, arg); } public void genContainerBasedInvocation(EGLClass type, Context ctx, TabbedWriter out, InvocationExpression expr) { ctx.invoke(genRuntimeTypeName, type, ctx, out, TypeNameKind.EGLImplementation); out.print("."); ctx.invoke(genName, expr.getTarget(), ctx, out); out.print("("); if (!(expr.getTarget() instanceof Member) || !((Member)expr.getTarget()).isStatic()) ctx.invoke(genExpression, expr.getQualifier(), ctx, out); if (expr.getArguments() != null && expr.getArguments().size() > 0) out.print(", "); ctx.invoke(genInvocationArguments, expr, ctx, out); out.print(")"); } @SuppressWarnings("static-access") protected String getNativeStringPrefixOperation(BinaryExpression expr) { String op = expr.getOperator(); if (op.equals(expr.Op_PLUS)) return "egl.addEGLNumber("; if (op.equals(expr.Op_MINUS)) return "egl.subtractEGLNumber("; if (op.equals(expr.Op_MULTIPLY)) return "egl.multiplyEGLNumber("; if (op.equals(expr.Op_DIVIDE)) return "egl.divideEGLNumber("; if (op.equals(expr.Op_MODULO)) return "egl.remainderEGLNumber("; if (op.equals(expr.Op_EQ)) return "egl.compareEGLNumbers("; if (op.equals(expr.Op_NE)) return "egl.compareEGLNumbers("; if (op.equals(expr.Op_LT)) return "egl.compareEGLNumbers("; if (op.equals(expr.Op_GT)) return "egl.compareEGLNumbers("; if (op.equals(expr.Op_LE)) return "egl.compareEGLNumbers("; if (op.equals(expr.Op_GE)) return "egl.compareEGLNumbers("; if (op.equals(expr.Op_POWER)) return "egl.powEGLNumber("; return "("; } @SuppressWarnings("static-access") protected String getNativeStringOperation(BinaryExpression expr) { String op = expr.getOperator(); // these are the defaults for what can be handled by the java string class if (op.equals(expr.Op_PLUS)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_MINUS)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_MULTIPLY)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_DIVIDE)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_EQ)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_NE)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_LT)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_GT)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_LE)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_GE)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_AND)) return " && "; if (op.equals(expr.Op_OR)) return " || "; if (op.equals(expr.Op_CONCAT)) return " + "; if (op.equals(expr.Op_MODULO)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; if (op.equals(expr.Op_POWER)) return ", " + eglNumberTypeArg(expr.getLHS()) + ", "; return ""; } @SuppressWarnings("static-access") protected String getNativeStringPostfixOperation(BinaryExpression expr) { String op = expr.getOperator(); if (op.equals(expr.Op_PLUS)) return ", " + eglNumberTypeArg(expr.getRHS()) + ")"; if (op.equals(expr.Op_MINUS)) return ", " + eglNumberTypeArg(expr.getRHS()) + ")"; if (op.equals(expr.Op_MULTIPLY)) return ", " + eglNumberTypeArg(expr.getRHS()) + ")"; if (op.equals(expr.Op_DIVIDE)) return ", " + eglNumberTypeArg(expr.getRHS()) + ")"; if (op.equals(expr.Op_EQ)) return ", " + eglNumberTypeArg(expr.getRHS()) + ") == 0"; if (op.equals(expr.Op_NE)) return ", " + eglNumberTypeArg(expr.getRHS()) + ") !=0"; if (op.equals(expr.Op_LT)) return ", " + eglNumberTypeArg(expr.getRHS()) + ") < 0"; if (op.equals(expr.Op_GT)) return ", " + eglNumberTypeArg(expr.getRHS()) + ") > 0"; if (op.equals(expr.Op_LE)) return ", " + eglNumberTypeArg(expr.getRHS()) + ") <= 0"; if (op.equals(expr.Op_GE)) return ", " + eglNumberTypeArg(expr.getRHS()) + ") >= 0"; if (op.equals(expr.Op_MODULO)) return ", " + eglNumberTypeArg(expr.getRHS()) + ")"; if (op.equals(expr.Op_POWER)) return ", " + eglNumberTypeArg(expr.getRHS()) + ")"; return ")"; } /** * Returns the value that'll identify the kind of argument passed to the egl.*EGLNumber functions. * <UL> * <LI>-1 means we must inspect the value to learn its type * <LI>0 means it's a JavaScript Number and not an EGL float or smallfloat * <LI>1 means it's an EGL BigDecimal * <LI>2 means it's an EGL float or smallfloat * </UL> */ private static String eglNumberTypeArg( Expression expr ) { Type type = expr.getType(); int kind = TypeUtils.getTypeKind(type); if ( (type.getTypeSignature().equalsIgnoreCase("eglx.lang.ENumber")) || isCharacterType( type ) ) { return "-1"; } else if ( isBigDecimalType( type ) ) { return "1"; } else if ( kind == TypeUtils.TypeKind_FLOAT || kind == TypeUtils.TypeKind_SMALLFLOAT ) { return "2"; } else { // int, smallint, null, date return "0"; } } private static boolean isCharacterType( Type type ) { switch ( TypeUtils.getTypeKind(type) ) { case TypeUtils.TypeKind_CHAR: case TypeUtils.TypeKind_DBCHAR: case TypeUtils.TypeKind_MBCHAR: case TypeUtils.TypeKind_UNICODE: case TypeUtils.TypeKind_LIMITEDSTRING: case TypeUtils.TypeKind_STRING: return true; default: return false; } } /** * @param type * @return True if so */ private static boolean isFixedLengthNumericType( Type type ) { switch ( TypeUtils.getTypeKind(type) ) { case TypeUtils.TypeKind_MONEY: case TypeUtils.TypeKind_NUM: case TypeUtils.TypeKind_NUMC: case TypeUtils.TypeKind_BIN: case TypeUtils.TypeKind_DECIMAL: case TypeUtils.TypeKind_PACF: return true; default: return false; } } /** * checks if the type is to use the egl.javascript.BigDecimal class * in the generated JavaScript code * * @param type * @return True if so */ private static boolean isBigDecimalType( Type type ) { return ( TypeUtils.getTypeKind(type) == TypeUtils.TypeKind_BIGINT || isFixedLengthNumericType( type ) ); } }