mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
tweak chained comparisons
This commit is contained in:
parent
dfce292294
commit
b428343c2a
@ -96,10 +96,11 @@ internal fun Program.addTypecasts(errors: IErrorReporter, options: CompilationOp
|
||||
caster.applyModifications()
|
||||
}
|
||||
|
||||
fun Program.desugaring(errors: IErrorReporter): Int {
|
||||
fun Program.desugaring(errors: IErrorReporter) {
|
||||
val desugar = CodeDesugarer(this, errors)
|
||||
desugar.visit(this)
|
||||
return desugar.applyModifications()
|
||||
while(errors.noErrors() && desugar.applyModifications()>0)
|
||||
desugar.visit(this)
|
||||
}
|
||||
|
||||
internal fun Program.verifyFunctionArgTypes(errors: IErrorReporter) {
|
||||
@ -110,9 +111,8 @@ internal fun Program.verifyFunctionArgTypes(errors: IErrorReporter) {
|
||||
internal fun Program.preprocessAst(errors: IErrorReporter, options: CompilationOptions) {
|
||||
val transforms = AstPreprocessor(this, errors, options)
|
||||
transforms.visit(this)
|
||||
var mods = transforms.applyModifications()
|
||||
while(mods>0)
|
||||
mods = transforms.applyModifications()
|
||||
while(errors.noErrors() && transforms.applyModifications()>0)
|
||||
transforms.visit(this)
|
||||
}
|
||||
|
||||
internal fun Program.checkIdentifiers(errors: IErrorReporter, options: CompilationOptions) {
|
||||
|
@ -26,6 +26,7 @@ internal class CodeDesugarer(val program: Program, private val errors: IErrorRep
|
||||
// - pointer[word] replaced by @(pointer+word)
|
||||
// - @(&var) and @(&var+1) replaced by lsb(var) and msb(var) if var is a word
|
||||
// - flatten chained assignments
|
||||
// - rewrite chained comparisons like i<x<j into i<x and x<j
|
||||
|
||||
override fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> {
|
||||
fun jumpAfter(stmt: Statement): Iterable<IAstModification> {
|
||||
@ -259,6 +260,29 @@ _after:
|
||||
return listOf(IAstModification.ReplaceNode(expr, squareCall, parent))
|
||||
}
|
||||
|
||||
// desugar chained comparisons: i < x < j ---> i<x and x<j
|
||||
// only if i<x or x<j was not written in parentheses! (i<x) < y, i < (x<y) -> leave untouched
|
||||
if(expr.operator in ComparisonOperators) {
|
||||
val leftBinExpr = expr.left as? BinaryExpression
|
||||
val rightBinExpr = expr.right as? BinaryExpression
|
||||
if(leftBinExpr!=null && !leftBinExpr.insideParentheses && leftBinExpr.operator in ComparisonOperators) {
|
||||
if(!leftBinExpr.right.isSimple) {
|
||||
errors.warn("possible multiple evaluation of subexpression in chained comparison, consider using a temporary variable", leftBinExpr.right.position)
|
||||
}
|
||||
val right = BinaryExpression(leftBinExpr.right.copy(), expr.operator, expr.right, leftBinExpr.right.position)
|
||||
val desugar = BinaryExpression(leftBinExpr, "and", right, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, desugar, parent))
|
||||
}
|
||||
else if(rightBinExpr!=null && !rightBinExpr.insideParentheses && rightBinExpr.operator in ComparisonOperators) {
|
||||
if(!rightBinExpr.left.isSimple) {
|
||||
errors.warn("possible multiple evaluation of subexpression in chained comparison, consider using a temporary variable", rightBinExpr.left.position)
|
||||
}
|
||||
val left = BinaryExpression(expr.left, expr.operator, rightBinExpr.left.copy(), rightBinExpr.left.position)
|
||||
val desugar = BinaryExpression(left, "and", rightBinExpr, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, desugar, parent))
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
@ -171,30 +171,6 @@ internal class StatementReorderer(
|
||||
}
|
||||
|
||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||
// desugar chained comparisons: i < x < j ---> i<x and x<j
|
||||
// only if i<x or x<j was not written in parentheses! (i<x) < y, i < (x<y) -> leave untouched
|
||||
if(expr.operator in ComparisonOperators) {
|
||||
val leftBinExpr = expr.left as? BinaryExpression
|
||||
val rightBinExpr = expr.right as? BinaryExpression
|
||||
if(leftBinExpr!=null && !leftBinExpr.insideParentheses && leftBinExpr.operator in ComparisonOperators) {
|
||||
if(!leftBinExpr.right.isSimple) {
|
||||
errors.warn("possible multiple evaluation of subexpression in chained comparison, consider using a temporary variable", leftBinExpr.right.position)
|
||||
}
|
||||
val right = BinaryExpression(leftBinExpr.right.copy(), expr.operator, expr.right, leftBinExpr.right.position)
|
||||
val desugar = BinaryExpression(leftBinExpr, "and", right, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, desugar, parent))
|
||||
}
|
||||
else if(rightBinExpr!=null && !rightBinExpr.insideParentheses && rightBinExpr.operator in ComparisonOperators) {
|
||||
if(!rightBinExpr.left.isSimple) {
|
||||
errors.warn("possible multiple evaluation of subexpression in chained comparison, consider using a temporary variable", rightBinExpr.left.position)
|
||||
}
|
||||
val left = BinaryExpression(expr.left, expr.operator, rightBinExpr.left.copy(), rightBinExpr.left.position)
|
||||
val desugar = BinaryExpression(left, "and", rightBinExpr, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, desugar, parent))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ConstValue <associativeoperator> X --> X <associativeoperator> ConstValue
|
||||
// (this should be done by the ExpressionSimplifier when optimizing is enabled,
|
||||
// but the current assembly code generator for IF statements now also depends on it, so we do it here regardless of optimization.)
|
||||
|
@ -173,7 +173,7 @@ class BinaryExpression(
|
||||
replacement.parent = this
|
||||
}
|
||||
|
||||
override fun copy() = BinaryExpression(left.copy(), operator, right.copy(), position)
|
||||
override fun copy() = BinaryExpression(left.copy(), operator, right.copy(), position, insideParentheses)
|
||||
override fun toString() = "[$left $operator $right]"
|
||||
|
||||
override val isSimple = false
|
||||
|
Loading…
x
Reference in New Issue
Block a user