Last active
August 29, 2015 14:07
-
-
Save UplinkCoder/8dc304ffc75ad2a3de40 to your computer and use it in GitHub Desktop.
ValueRange Visitor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module d.semantic.valuerange; | |
import d.semantic.semantic; | |
import d.ir.type; | |
import d.ast.expression; | |
import d.ir.expression; | |
struct ValueRange { | |
double _min; | |
double _max; | |
bool isInRangeOf(ValueRange that) { | |
return (that._max>=_max && that._min<=_min); | |
} | |
bool isInRangeOf (TypeKind k) { | |
return isInRangeOf(rangeOf(k)); | |
} | |
ValueRange opBinary (string op)(ValueRange rhs) { | |
static if (op=="-") { | |
return ValueRange(_min-rhs._max, _max-rhs._min); | |
} else static if (op=="+") { | |
return ValueRange(_min+rhs._min, _max+rhs._max); | |
} else | |
assert(0, "Not Implemented"); | |
} | |
unittest { | |
assert(ValueRange(0,255)-ValueRange(128,128) == ValueRange(-128,127)); | |
assert(ValueRange(3,3)+ValueRange(-5,2)==ValueRange(-2,5)); | |
} | |
ValueRange merge (ValueRange rhs) { | |
import std.algorithm:max,min; | |
return ValueRange(min(_min, rhs._min), max(_max, rhs._max)); | |
} | |
static ValueRange rangeOf(TypeKind t) { | |
if (t == TypeKind.Bool) { | |
return ValueRange(bool.min,bool.max); | |
} else if (t == TypeKind.Ubyte) { | |
return ValueRange (ubyte.min,ubyte.max); | |
} else if (t == TypeKind.Ushort) { | |
return ValueRange (ushort.min,ushort.max); | |
} else if (t == TypeKind.Uint) { | |
return ValueRange (uint.min,uint.max); | |
} else if (t == TypeKind.Ulong) { | |
return ValueRange (ulong.min,ulong.max); | |
} else if (t == TypeKind.Byte) { | |
return ValueRange (byte.min,byte.max); | |
} else if (t == TypeKind.Short) { | |
return ValueRange (short.min,short.max); | |
} else if (t == TypeKind.Int) { | |
return ValueRange (int.min,int.max); | |
} else if (t == TypeKind.Long) { | |
return ValueRange (long.min,cast(double)long.max); | |
} | |
assert(0,"Rangeof does not accept " ~ typeid(t).toString() ); | |
} | |
} | |
struct ValueRangeVisitor { | |
SemanticPass pass; | |
this(SemanticPass pass) | |
{ | |
this.pass = pass; | |
} | |
ValueRange visit(VariableExpression e) { | |
auto BType = peelAlias(e.type); | |
assert(typeid(BType.type) == typeid(BuiltinType)); | |
return ValueRange.rangeOf((cast(BuiltinType) BType.type).kind); | |
} | |
ValueRange visit(AstBinaryExpression e) { | |
ValueRange lhs = visit(e.lhs); | |
ValueRange rhs = visit(e.rhs); | |
switch (e.op) with (BinaryOp) { | |
case Add : return lhs+rhs; | |
case Sub : return lhs-rhs; | |
default : assert(0, "BinaryOp " ~ e.toString(pass.context)~" not supported by ValueRangeVisitor" ); | |
} | |
} | |
ValueRange visit(AstExpression e) { | |
return this.dispatch!(function ValueRange(AstExpression e) { | |
assert(0, "ValueRange " ~ typeid(e).toString() ~ " is unknown."); | |
})(e); | |
} | |
ValueRange visit(IntegerLiteral!false e) { | |
return ValueRange(e.value,e.value); | |
} | |
ValueRange visit(IntegerLiteral!true e) { | |
return ValueRange(e.value,e.value); | |
} | |
unittest { | |
import d.location; | |
import std.stdio; | |
auto il = new IntegerLiteral!false(Location.init,1,TypeKind.Int); | |
assert(ValueRangeVisitor().visit(il).isInRangeOf(TypeKind.Byte)); | |
assert(ValueRangeVisitor().visit(il).isInRangeOf(TypeKind.Bool)); | |
assert(ValueRangeVisitor().visit(new AstBinaryExpression(Location.init, BinaryOp.Sub, new IntegerLiteral!false(Location.init, 255, TypeKind.Uint),new IntegerLiteral!false(Location.init, 128, TypeKind.Int))).isInRangeOf(TypeKind.Byte)); | |
assert(ValueRange.rangeOf(TypeKind.Ubyte).isInRangeOf(TypeKind.Short)); | |
assert(!(ValueRange.rangeOf(TypeKind.Short).isInRangeOf(TypeKind.Byte))); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Also, VRP struct should work for integers as well. Using float here will have cause issues. Right now, SDC do not support floating point at all.