Add shift operations for numeric values#995
Conversation
/** For shifting operations make sure both values are integer */
private def convertToInteger(loc: Location, t: Type): Result.Result[Type] =
if (t.isInt) Right(t)
else if (t.isConvertibleTo(Type.Integer)) Right(Type.Integer)
else {
val error = SemanticError.InvalidType(loc, s"cannot convert $t to an integer type")
Left(error)
} The current implementation of int value check is too much permissive, since float is convertible to int. I will completely remove the conditional check. This causes the failure: https://github.com/abh80/fpp/blob/564f25468d2be477626cae34c49a0d5d354327f5/compiler/tools/fpp-check/test/numeric_shift/shift_float_value_error.ref.txt#L1 Edit: Looks like there is another bug t <- a.commonType(e.e1.id, e.e2.id, loc)
_ <- e.op match {
case Ast.Binop.Shift(_) => convertToInteger(loc, t)
...
}The common type inference automatically promotes to Float even if one value is int which causes misleading error information. However this dosent affect the intended behavior since it's only applicable if both values are integer |
|
@bocchino I have completed the implementation and testing. Can you give the initial review before I start writing the documentation? |
|
This generally looks good. I need to see a spec before I can approve it. Can you make a separate PR to the feature branch with just the spec changes? I'll review and approve, and then we can finalize this branch. Some notes on the spec changes:
|
This is a direct solution to the issue I found
Will add another case for this |
|
I will open another spec pull request 👍 |
Fixed this and opened a new pull request for spec revision #1000 |
|
@bocchino I have updated the implementation to include enum according to the spec. Can you give the review. Thanks |
Added:
Bit shift operations to numeric values
Closes #922
Tasks
Implementation
Token.scala: addedLSHIFTandRSHIFTtokens.Lexer.scala: added token parsing for new tokens.Ast.scala:ShiftTypeto encapsulate shift typesLShift extends ShiftType .....case class Shift(op: ShiftType) extends Binopto Binop.Parser.scala:expr binopnode creation for new shift tokens.analysis/CheckSemantics/CheckExprTypes.scala:convertToIntegerfor shift operations (ignoring float values).Ast.Binop.Shift(_).Value.scala:intShiftOp = (BigInt, Int) => BigIntfor shifting.private[analysis] def intShiftOp(op: Value.Binop.intShiftOp)(v: Value)(since generic binop does not support(BigInt, Int) => Bigint))Value:isNegativeandisValidShiftAmountto help inAnalysis.scala.intShiftOpmethod inPrimitiveInt,IntegerandEnumConstant.<<and>>methods toValueto perform shift operations.Analysis.scala: addedlshiftandrshiftmethod, using the new methods added toValue.CheckSemantics/EvalConstantExprs.scala: add the new caseAst.Binop.Shift(op)using the new methods added toAnalysis.util/Error.scala: Added a newInvalidShiftAmounterror toSemanticError.Tests
compiler/tools/fpp-check/test/numeric_shift: added robust test cases including edge cases and error checks.compiler/lib/src/test/input/syntax/lexer/ok/symbols.fpp: added the new<</>>symbols.fpp-syntaxtests.fpp-to-cpptests.ValueSpectests.Spec: