package gw.rating.flow.domain uses com.google.common.collect.ImmutableList uses gw.api.locale.DisplayKey uses gw.lang.parser.ICoercer uses gw.lang.reflect.IType uses gw.rating.flow.util.RateflowTypeUtils uses gw.rating.flow.util.TypeMaps uses gw.validation.PCValidationContext uses java.util.stream.Collectors class AssignmentStatement extends Statement { public final var Variable : CalcStepVariable public final var LineNumber : int public final var Operands : ImmutableList protected final var _codeSize: int property get CodeSize(): int { return _codeSize } construct(variable: CalcStepVariable, lineNum : int, operandList: List, aHighlightElement: RateRoutineHighlightElement) { Variable = variable LineNumber = lineNum Operands = ImmutableList.copyOf(operandList) _highlightElement = aHighlightElement _codeSize = 1 + Operands*.CodeSize.sum() } function getExpressionType(context : GenerationContext): IType { if (Operands.Count == 1) { // return type of single operand - unless its special cased var operand = Operands.first() if (operand typeis InScopeOperand) { if (operand.IsModifier) { // // var value = ParseUtil.getInScopeVariableKey(operand.ParamName) + "?." // + TypeMaps.typeStringToModifierGetterFunctionName(operand.ParamValueTypeName) +"(\"" + operand.ParamValue + "\")" // // Above becomes: // var value = ?.get{Typekey|Decimal|Boolean|Date}ModifierValue() var valueTypeName = TypeMaps.typeStringToModifierGetterFunctionName(operand.ParamValueTypeName) if (valueTypeName.contains("Typekey")) { return java.lang.String } else if (valueTypeName.contains("Decimal")) { return java.math.BigDecimal } else if (valueTypeName.contains("Boolean")) { return java.lang.Boolean } else if (valueTypeName.contains("Date")) { return java.util.Date } else { // Don't think this can happen. See TypeMaps.MODIFIER_TYPE_TO_FUNCTION_EXPANSION return java.lang.String // Best guess } } else if (operand.isCovTerm) { var valueType = RateflowTypeUtils.parseType(operand.ParamValueTypeName) if (CalcStepValueDelegate.isCovTermType(valueType)) { // var value = "${ParseUtil.getInScopeVariableKey(operand.ParamName)}?.${operand.ParamValue}?.PatternCode" return valueType.TypeInfo.getProperty("PatternCode").Type } // else: use default below } } return operand.getDataType(context) } else { // our only operators are +-*/ so this must be numeric return java.math.BigDecimal } } override function generate(context: GenerationContext) { generate(context, null) } function generate(context: GenerationContext, coercer: ICoercer) { if (Variable == null) { addToContextOrThrow(context.Context, DisplayKey.get("Validation.Rating.RateTableDefinition.MissingAssignmentTarget")) return // If we didn't throw, can't proceed without a variable to assign to. } var varMap = context.VarMap _start = context.beginCodeGen() var isDeclaration = false if (Variable.TypeOfVariable == CalcStepVariable.Type.Local) { if (Parent == null // don't generate var declaration if we're in a nested block -- it would be invisible and not varMap.containsKey(Variable.VariableKey)) { varMap.put(Variable.VariableKey, getExpressionType(context)) isDeclaration = true } } else if (Variable.TypeOfVariable == CalcStepVariable.Type.Loop) { if (Variable.VariableFieldName == null) { if (varMap.containsKey(Variable.VariableKey)) { // Illegal attempt to modify a loop variable addToContextOrThrow(context.Context, DisplayKey.get("Validation.Rating.RateRoutineDefinition.LoopVariable.IllegalModification", Variable.VariableName)) } else { // Loop variable declaration varMap.put(Variable.VariableKey, Variable.ReferenceType) isDeclaration = true } } else if (not varMap.containsKey(Variable.VariableKey)) { addToContextOrThrow(context.Context, DisplayKey.get("Validation.Rating.RateRoutineDefinition.LoopVariable.Unknown", Variable.VariableFieldName)) } } var variableName = Variable.VariableReference.replaceAll("\\?\\.", ".") // Since VariableReference is null-safe context.WorksheetHelper.wrapStatement(this, \ -> { if (!context.WorksheetsEnabled) { if (isDeclaration && context.AddLocalVarDecls) { context.append("var ") } context.append(variableName) context.append(" = ") } var coerce = false if (coercer != null) { var lhsType = Variable.ReferenceType if (lhsType == null) { lhsType = getExpressionType(context) } if (lhsType != null) { coerce = true context.append('(').append(coercer.Class.Name).append(".instance().coerceValue(") .append(Variable.getVariableType(context).Name).append(", ") } } var lastOperand = Operands.last() if (lastOperand typeis RoundingMethodOperand) { var roundingOperand = lastOperand roundingOperand.CalculationOperands = Operands.stream() .filter(\op -> op != roundingOperand) .collect(Collectors.toList()) roundingOperand.generate(context) } else { generateSub(Operands, context) } if (coerce) { context.append(") as ").append(Variable.getVariableType(context).Name).append(')') } }, isDeclaration, variableName) _end = context.endCodeGen() } private function generateSub(operandList : List, context: GenerationContext) { operandList.each(\ op -> { if (op.OperatorType != TC_STORE) { context.append(' ').append(op.OperatorType.ExpressionOperator).append(' ') } op.generate(context) }) } override function getOffendingOperand(issue: gw.lang.parser.IParseIssue) : CalcStepOperand { return Operands.firstWhere(\c -> c.Start.First <= issue.Line and c.End.First >= issue.Line and c.Start.Second <= issue.Column and c.End.Second >= issue.Column) } private function addToContextOrThrow(context: PCValidationContext, message: String) { if (HighlightElement == null) { throw new IllegalStateException(message) } else { HighlightElement.addToContextOrThrow(context, message) } } }