private void EmitRangeExprNode(ImperativeNode node, ref ProtoCore.Type inferedType) { // (Ayush) Using Decimal type instead of Double for the sake of precision. For eg. doing 0.3d - 0.1d gives a result a little less than 0.2. These inaccuracies propogate // through a range expression and quickly cause wrong values to be returned. // TODO: Revert to using double, and use extension methods to compare with tolerance RangeExprNode range = node as RangeExprNode; if ((range.FromNode is NullNode || range.FromNode is BooleanNode) || (range.ToNode is NullNode || range.ToNode is BooleanNode) || (range.StepNode is NullNode || range.StepNode is BooleanNode)) { throw new ProtoCore.Exceptions.CompileErrorsOccured("Invalid range expression"); } else if ((range.FromNode is IntNode || range.FromNode is DoubleNode) && (range.ToNode is IntNode || range.ToNode is DoubleNode) && (range.StepNode is IntNode || range.StepNode is DoubleNode)) { ProtoCore.Type type = new ProtoCore.Type(); type.UID = (int)PrimitiveType.kTypeVoid; type.IsIndexable = true; type.Name = "double"; type.UID = (int)PrimitiveType.kTypeDouble; type.rank = 1; int totalSteps = 0; bool terminate = false; decimal current = (range.FromNode is IntNode) ? Int64.Parse((range.FromNode as IntNode).value) : Decimal.Parse((range.FromNode as DoubleNode).value); decimal end = (range.ToNode is IntNode) ? Int64.Parse((range.ToNode as IntNode).value) : Decimal.Parse((range.ToNode as DoubleNode).value); ProtoCore.DSASM.RangeStepOperator stepoperator = range.stepoperator; decimal step = (range.StepNode is IntNode) ? Int64.Parse((range.StepNode as IntNode).value) : Decimal.Parse((range.StepNode as DoubleNode).value); decimal stepsize = 1.0M; if (stepoperator == ProtoCore.DSASM.RangeStepOperator.stepsize) { if (step == 0) { EmitNullNode(new NullNode(), ref inferedType); return; } if ((end > current && step < 0) || (end < current && step > 0)) { EmitNullNode(new NullNode(), ref inferedType); return; } stepsize = step; } else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.num) { if (!(range.StepNode is IntNode)) { EmitNullNode(new NullNode(), ref inferedType); return; } if (step <= 0) { EmitNullNode(new NullNode(), ref inferedType); return; } if ((step - 1) == 0) stepsize = 0; else stepsize = (end - current) / (step - 1); } else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.approxsize) { if (step == 0) { EmitNullNode(new NullNode(), ref inferedType); return; } RangeExprNode rnode = range; IntNode newStep = new IntNode(); rnode.StepNode = newStep; rnode.stepoperator = ProtoCore.DSASM.RangeStepOperator.num; decimal dist = end - current; if (dist == 0) { newStep.value = "1"; } else { decimal ceilStepSize = Math.Ceiling((dist) / step); decimal floorStepSize = Math.Floor((dist) / step); decimal numOfSteps; if ((ceilStepSize == 0) || (floorStepSize == 0)) numOfSteps = 2; else numOfSteps = (Math.Abs(dist / ceilStepSize - step) < Math.Abs(dist / floorStepSize - step)) ? ceilStepSize + 1 : floorStepSize + 1; newStep.value = numOfSteps.ToString(); } EmitRangeExprNode(rnode, ref inferedType); return; } bool isIntArray = (range.FromNode is IntNode) && (range.ToNode is IntNode) && (range.StepNode is IntNode) && (Math.Equals(stepsize, Math.Truncate(stepsize))); if (isIntArray) { type.Name = "int"; type.UID = (int)ProtoCore.PrimitiveType.kTypeInt; } if (stepsize == 0) { for (int i = 0; i < step; ++i) { if (isIntArray) EmitIntNode(new IntNode { value = current.ToString() }, ref type); else EmitDoubleNode(new DoubleNode { value = current.ToString() }, ref type); ++totalSteps; } } else { while (true) { if (stepoperator == ProtoCore.DSASM.RangeStepOperator.stepsize) terminate = (step < 0) ? ((current < end) ? true : false) : ((current > end) ? true : false); else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.num) terminate = (totalSteps >= step) ? true : false; if (terminate) break; if (isIntArray) EmitIntNode(new IntNode { value = current.ToString() }, ref type); else EmitDoubleNode(new DoubleNode { value = current.ToString() }, ref type); current += stepsize; ++totalSteps; } } inferedType = type; } else { //traverse the from node DfsTraverse(range.FromNode, ref inferedType); //traverse the To node DfsTraverse(range.ToNode, ref inferedType); //traverse the step node DfsTraverse(range.StepNode, ref inferedType); inferedType.IsIndexable = true; inferedType.rank++; } }
private void EmitRangeExprNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { RangeExprNode range = node as RangeExprNode; // Do some static checking...probably it is not necessary. // Need to move these checkings to built-in function. if ((range.FromNode is IntNode || range.FromNode is DoubleNode) && (range.ToNode is IntNode || range.ToNode is DoubleNode) && (range.StepNode == null || (range.StepNode != null && (range.StepNode is IntNode || range.StepNode is DoubleNode)))) { decimal current = (range.FromNode is IntNode) ? Int64.Parse((range.FromNode as IntNode).value) : Decimal.Parse((range.FromNode as DoubleNode).value); decimal end = (range.ToNode is IntNode) ? Int64.Parse((range.ToNode as IntNode).value) : Decimal.Parse((range.ToNode as DoubleNode).value); ProtoCore.DSASM.RangeStepOperator stepoperator = range.stepoperator; decimal step = 1; if (range.StepNode != null) { step = (range.StepNode is IntNode) ? Int64.Parse((range.StepNode as IntNode).value) : Decimal.Parse((range.StepNode as DoubleNode).value); } if (stepoperator == ProtoCore.DSASM.RangeStepOperator.stepsize) { if (range.StepNode == null && end < current) { step = -1; } if (step == 0) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithStepSizeZero, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } if ((end > current && step < 0) || (end < current && step > 0)) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithInvalidStepSize, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } } else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.num) { if (range.StepNode != null && !(range.StepNode is IntNode)) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithNonIntegerStepNumber, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } if (step <= 0) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithNegativeStepNumber, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } } else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.approxsize) { if (step == 0) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithStepSizeZero, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } } } // Replace with build-in RangeExpression() function. - Yu Ke var tmpFrom = nodeBuilder.BuildTempVariable(); var assignFrom = nodeBuilder.BuildBinaryExpression(tmpFrom, range.FromNode); EmitBinaryExpressionNode(assignFrom, ref inferedType); var tmpTo = nodeBuilder.BuildTempVariable(); var assignTo = nodeBuilder.BuildBinaryExpression(tmpTo, range.ToNode); EmitBinaryExpressionNode(assignTo, ref inferedType); var tmpStep = nodeBuilder.BuildTempVariable(); var assignStep = nodeBuilder.BuildBinaryExpression(tmpStep, range.StepNode == null ? new NullNode() : range.StepNode); EmitBinaryExpressionNode(assignStep, ref inferedType); BooleanNode hasStep = new BooleanNode { value = range.StepNode == null ? "false" : "true" }; var tmpStepSkip = nodeBuilder.BuildTempVariable(); var assignStepSkip = nodeBuilder.BuildBinaryExpression(tmpStepSkip, hasStep); EmitBinaryExpressionNode(assignStepSkip, ref inferedType); IntNode op = new IntNode(); switch (range.stepoperator) { case ProtoCore.DSASM.RangeStepOperator.stepsize: op.value = "0"; break; case ProtoCore.DSASM.RangeStepOperator.num: op.value = "1"; break; case ProtoCore.DSASM.RangeStepOperator.approxsize: op.value = "2"; break; default: op.value = "-1"; break; } var rangeExprFunc = nodeBuilder.BuildFunctionCall(Constants.kFunctionRangeExpression, new List<ImperativeNode> { tmpFrom, tmpTo, tmpStep, op, tmpStepSkip }); NodeUtils.CopyNodeLocation(rangeExprFunc, range); EmitFunctionCallNode(rangeExprFunc, ref inferedType, false, graphNode); if (range.ArrayDimensions != null) { int dimensions = DfsEmitArrayIndexHeap(range.ArrayDimensions); EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, dimensions.ToString() + "[dim]"); EmitPushArrayIndex(dimensions); } }
private void EmitRangeExprNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { RangeExprNode range = node as RangeExprNode; // Do some static checking...probably it is not necessary. // Need to move these checkings to built-in function. if ((range.FromNode is IntNode || range.FromNode is DoubleNode) && (range.ToNode is IntNode || range.ToNode is DoubleNode) && (range.StepNode == null || (range.StepNode != null && (range.StepNode is IntNode || range.StepNode is DoubleNode)))) { double current = (range.FromNode is IntNode) ? (range.FromNode as IntNode).Value : (range.FromNode as DoubleNode).Value; double end = (range.ToNode is IntNode) ? (range.ToNode as IntNode).Value : (range.ToNode as DoubleNode).Value; ProtoCore.DSASM.RangeStepOperator stepoperator = range.stepoperator; double step = 1; if (range.StepNode != null) { step = (range.StepNode is IntNode) ? (range.StepNode as IntNode).Value : (range.StepNode as DoubleNode).Value; } bool hasAmountOp = range.HasRangeAmountOperator; string warningMsg = String.Empty; if (stepoperator == ProtoCore.DSASM.RangeStepOperator.stepsize) { if (!hasAmountOp) { if (range.StepNode == null && end < current) { step = -1; } if (step == 0) { warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithStepSizeZero; } else if ((end > current && step < 0) || (end < current && step > 0)) { warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithInvalidStepSize; } } } else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.num) { if (hasAmountOp) { warningMsg = ProtoCore.Properties.Resources.kRangeExpressionConflictOperator; } else if (range.StepNode != null && !(range.StepNode is IntNode)) { warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithNonIntegerStepNumber; } else if (step <= 0) { warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithNegativeStepNumber; } } else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.approxsize) { if (hasAmountOp) { warningMsg = ProtoCore.Properties.Resources.kRangeExpressionConflictOperator; } else if (step == 0) { warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithStepSizeZero; } } if (!string.IsNullOrEmpty(warningMsg)) { buildStatus.LogWarning(WarningID.kInvalidRangeExpression, warningMsg, core.CurrentDSFileName, range.StepNode.line, range.StepNode.col, graphNode); EmitNullNode(new NullNode(), ref inferedType); return; } } IntNode op = null; switch (range.stepoperator) { case ProtoCore.DSASM.RangeStepOperator.stepsize: op = new IntNode(0); break; case ProtoCore.DSASM.RangeStepOperator.num: op = new IntNode(1); break; case ProtoCore.DSASM.RangeStepOperator.approxsize: op = new IntNode(2); break; default: op = new IntNode(-1); break; } var rangeExprFunc = nodeBuilder.BuildFunctionCall( Constants.kFunctionRangeExpression, new List<ImperativeNode> { range.FromNode, range.ToNode, range.StepNode ?? new NullNode(), op, new BooleanNode(range.StepNode != null), new BooleanNode(range.HasRangeAmountOperator) }); NodeUtils.CopyNodeLocation(rangeExprFunc, range); EmitFunctionCallNode(rangeExprFunc, ref inferedType, false, graphNode); if (range.ArrayDimensions != null) { int dimensions = DfsEmitArrayIndexHeap(range.ArrayDimensions); EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, dimensions.ToString() + "[dim]"); EmitPushArrayIndex(dimensions); } }
public IntNode(IntNode rhs) : base(rhs) { Value = rhs.Value; }
public IntNode(IntNode rhs) : base(rhs) { value = rhs.value; }