mirror of
https://github.com/irmen/prog8.git
synced 2024-10-09 13:55:19 +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()
|
caster.applyModifications()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Program.desugaring(errors: IErrorReporter): Int {
|
fun Program.desugaring(errors: IErrorReporter) {
|
||||||
val desugar = CodeDesugarer(this, errors)
|
val desugar = CodeDesugarer(this, errors)
|
||||||
desugar.visit(this)
|
desugar.visit(this)
|
||||||
return desugar.applyModifications()
|
while(errors.noErrors() && desugar.applyModifications()>0)
|
||||||
|
desugar.visit(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.verifyFunctionArgTypes(errors: IErrorReporter) {
|
internal fun Program.verifyFunctionArgTypes(errors: IErrorReporter) {
|
||||||
@ -110,9 +111,8 @@ internal fun Program.verifyFunctionArgTypes(errors: IErrorReporter) {
|
|||||||
internal fun Program.preprocessAst(errors: IErrorReporter, options: CompilationOptions) {
|
internal fun Program.preprocessAst(errors: IErrorReporter, options: CompilationOptions) {
|
||||||
val transforms = AstPreprocessor(this, errors, options)
|
val transforms = AstPreprocessor(this, errors, options)
|
||||||
transforms.visit(this)
|
transforms.visit(this)
|
||||||
var mods = transforms.applyModifications()
|
while(errors.noErrors() && transforms.applyModifications()>0)
|
||||||
while(mods>0)
|
transforms.visit(this)
|
||||||
mods = transforms.applyModifications()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Program.checkIdentifiers(errors: IErrorReporter, options: CompilationOptions) {
|
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)
|
// - pointer[word] replaced by @(pointer+word)
|
||||||
// - @(&var) and @(&var+1) replaced by lsb(var) and msb(var) if var is a word
|
// - @(&var) and @(&var+1) replaced by lsb(var) and msb(var) if var is a word
|
||||||
// - flatten chained assignments
|
// - 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> {
|
override fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> {
|
||||||
fun jumpAfter(stmt: Statement): Iterable<IAstModification> {
|
fun jumpAfter(stmt: Statement): Iterable<IAstModification> {
|
||||||
@ -259,6 +260,29 @@ _after:
|
|||||||
return listOf(IAstModification.ReplaceNode(expr, squareCall, parent))
|
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
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,30 +171,6 @@ internal class StatementReorderer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
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
|
// ConstValue <associativeoperator> X --> X <associativeoperator> ConstValue
|
||||||
// (this should be done by the ExpressionSimplifier when optimizing is enabled,
|
// (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.)
|
// 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
|
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 fun toString() = "[$left $operator $right]"
|
||||||
|
|
||||||
override val isSimple = false
|
override val isSimple = false
|
||||||
|
Loading…
Reference in New Issue
Block a user