mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
parent
f63b87f675
commit
d6047f3988
@ -29,11 +29,15 @@ func canTruncateToInteger(v gconstant.Value) bool {
|
|||||||
return gconstant.ToInt(v).Kind() != gconstant.Unknown
|
return gconstant.ToInt(v).Kind() != gconstant.Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canTruncateToFloat(v gconstant.Value) bool {
|
||||||
|
return gconstant.ToFloat(v).Kind() != gconstant.Unknown
|
||||||
|
}
|
||||||
|
|
||||||
func isUntypedInteger(expr *shaderir.Expr) bool {
|
func isUntypedInteger(expr *shaderir.Expr) bool {
|
||||||
return expr.Const.Kind() == gconstant.Int && expr.ConstType == shaderir.ConstTypeNone
|
return expr.Const.Kind() == gconstant.Int && expr.ConstType == shaderir.ConstTypeNone
|
||||||
}
|
}
|
||||||
|
|
||||||
func isModAvailable(lhs, rhs *shaderir.Expr) bool {
|
func isModAvailableForConsts(lhs, rhs *shaderir.Expr) bool {
|
||||||
// % is available only when
|
// % is available only when
|
||||||
// 1) both are untyped integers
|
// 1) both are untyped integers
|
||||||
// 2) either is an typed integer and the other is truncatable to an integer
|
// 2) either is an typed integer and the other is truncatable to an integer
|
||||||
@ -49,6 +53,78 @@ func isModAvailable(lhs, rhs *shaderir.Expr) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canCompare(lhs, rhs *shaderir.Expr, lhst, rhst shaderir.Type) bool {
|
||||||
|
switch {
|
||||||
|
case lhs.Const != nil && rhs.Const != nil:
|
||||||
|
switch {
|
||||||
|
case lhs.ConstType == shaderir.ConstTypeNone && rhs.ConstType == shaderir.ConstTypeNone:
|
||||||
|
if canTruncateToFloat(lhs.Const) && canTruncateToFloat(rhs.Const) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if canTruncateToInteger(lhs.Const) && canTruncateToInteger(rhs.Const) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return lhs.Const.Kind() == rhs.Const.Kind()
|
||||||
|
case lhs.ConstType == shaderir.ConstTypeNone:
|
||||||
|
switch rhs.ConstType {
|
||||||
|
case shaderir.ConstTypeFloat:
|
||||||
|
return canTruncateToFloat(lhs.Const)
|
||||||
|
case shaderir.ConstTypeInt:
|
||||||
|
return canTruncateToInteger(lhs.Const)
|
||||||
|
}
|
||||||
|
case rhs.ConstType == shaderir.ConstTypeNone:
|
||||||
|
switch lhs.ConstType {
|
||||||
|
case shaderir.ConstTypeInt:
|
||||||
|
return canTruncateToInteger(rhs.Const)
|
||||||
|
case shaderir.ConstTypeFloat:
|
||||||
|
return canTruncateToFloat(rhs.Const)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lhs.ConstType == rhs.ConstType
|
||||||
|
|
||||||
|
case lhs.Const != nil:
|
||||||
|
switch lhs.ConstType {
|
||||||
|
case shaderir.ConstTypeNone:
|
||||||
|
if rhst.Main == shaderir.Float {
|
||||||
|
return canTruncateToFloat(lhs.Const)
|
||||||
|
}
|
||||||
|
if rhst.Main == shaderir.Int {
|
||||||
|
return canTruncateToInteger(lhs.Const)
|
||||||
|
}
|
||||||
|
case shaderir.ConstTypeFloat:
|
||||||
|
return rhst.Main == shaderir.Float
|
||||||
|
case shaderir.ConstTypeInt:
|
||||||
|
return rhst.Main == shaderir.Int
|
||||||
|
case shaderir.ConstTypeBool:
|
||||||
|
return rhst.Main == shaderir.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
case rhs.Const != nil:
|
||||||
|
switch rhs.ConstType {
|
||||||
|
case shaderir.ConstTypeNone:
|
||||||
|
if lhst.Main == shaderir.Float {
|
||||||
|
return canTruncateToFloat(rhs.Const)
|
||||||
|
}
|
||||||
|
if lhst.Main == shaderir.Int {
|
||||||
|
return canTruncateToInteger(rhs.Const)
|
||||||
|
}
|
||||||
|
case shaderir.ConstTypeFloat:
|
||||||
|
return lhst.Main == shaderir.Float
|
||||||
|
case shaderir.ConstTypeInt:
|
||||||
|
return lhst.Main == shaderir.Int
|
||||||
|
case shaderir.ConstTypeBool:
|
||||||
|
return lhst.Main == shaderir.Bool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comparing matrices are forbidden (#2187).
|
||||||
|
if lhst.IsMatrix() || rhst.IsMatrix() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhst.Equal(&rhst)
|
||||||
|
}
|
||||||
|
|
||||||
func goConstantKindString(k gconstant.Kind) string {
|
func goConstantKindString(k gconstant.Kind) string {
|
||||||
switch k {
|
switch k {
|
||||||
case gconstant.Bool:
|
case gconstant.Bool:
|
||||||
@ -127,11 +203,15 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
|
|||||||
var t shaderir.Type
|
var t shaderir.Type
|
||||||
switch op {
|
switch op {
|
||||||
case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
|
case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
|
||||||
|
if !canCompare(&lhs[0], &rhs[0], lhst, rhst) {
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), op, rhst.String()))
|
||||||
|
return nil, nil, nil, false
|
||||||
|
}
|
||||||
v = gconstant.MakeBool(gconstant.Compare(lhs[0].Const, op, rhs[0].Const))
|
v = gconstant.MakeBool(gconstant.Compare(lhs[0].Const, op, rhs[0].Const))
|
||||||
t = shaderir.Type{Main: shaderir.Bool}
|
t = shaderir.Type{Main: shaderir.Bool}
|
||||||
default:
|
default:
|
||||||
if op == token.REM {
|
if op == token.REM {
|
||||||
if !isModAvailable(&lhs[0], &rhs[0]) {
|
if !isModAvailableForConsts(&lhs[0], &rhs[0]) {
|
||||||
var wrongTypeName string
|
var wrongTypeName string
|
||||||
if lhs[0].Const.Kind() != gconstant.Int {
|
if lhs[0].Const.Kind() != gconstant.Int {
|
||||||
wrongTypeName = goConstantKindString(lhs[0].Const.Kind())
|
wrongTypeName = goConstantKindString(lhs[0].Const.Kind())
|
||||||
@ -173,7 +253,10 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
|
|||||||
var t shaderir.Type
|
var t shaderir.Type
|
||||||
switch {
|
switch {
|
||||||
case op == shaderir.LessThanOp || op == shaderir.LessThanEqualOp || op == shaderir.GreaterThanOp || op == shaderir.GreaterThanEqualOp || op == shaderir.EqualOp || op == shaderir.NotEqualOp || op == shaderir.VectorEqualOp || op == shaderir.VectorNotEqualOp || op == shaderir.AndAnd || op == shaderir.OrOr:
|
case op == shaderir.LessThanOp || op == shaderir.LessThanEqualOp || op == shaderir.GreaterThanOp || op == shaderir.GreaterThanEqualOp || op == shaderir.EqualOp || op == shaderir.NotEqualOp || op == shaderir.VectorEqualOp || op == shaderir.VectorNotEqualOp || op == shaderir.AndAnd || op == shaderir.OrOr:
|
||||||
// TODO: Check types of the operands.
|
if !canCompare(&lhs[0], &rhs[0], lhst, rhst) {
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), e.Op, rhst.String()))
|
||||||
|
return nil, nil, nil, false
|
||||||
|
}
|
||||||
t = shaderir.Type{Main: shaderir.Bool}
|
t = shaderir.Type{Main: shaderir.Bool}
|
||||||
case lhs[0].Const != nil && rhs[0].Const == nil:
|
case lhs[0].Const != nil && rhs[0].Const == nil:
|
||||||
switch rhst.Main {
|
switch rhst.Main {
|
||||||
|
@ -2189,3 +2189,153 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #2187
|
||||||
|
func TestSyntaxEqual(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
stmt string
|
||||||
|
err bool
|
||||||
|
}{
|
||||||
|
{stmt: "_ = false == true", err: false},
|
||||||
|
{stmt: "_ = false != true", err: false},
|
||||||
|
{stmt: "_ = false == 1", err: true},
|
||||||
|
{stmt: "_ = false != 1", err: true},
|
||||||
|
{stmt: "_ = false == 1.0", err: true},
|
||||||
|
{stmt: "_ = false != 1.0", err: true},
|
||||||
|
{stmt: "_ = false == 1.1", err: true},
|
||||||
|
{stmt: "_ = false != 1.1", err: true},
|
||||||
|
{stmt: "a, b := false, true; _ = a == b", err: false},
|
||||||
|
{stmt: "a, b := false, true; _ = a != b", err: false},
|
||||||
|
{stmt: "a, b := false, 1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := false, 1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := false, 1.0; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := false, 1.0; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := false, 1.1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := false, 1.1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := false, vec2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := false, vec2(1); _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := false, mat2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := false, mat2(1); _ = a != b", err: true},
|
||||||
|
|
||||||
|
{stmt: "_ = 1 == true", err: true},
|
||||||
|
{stmt: "_ = 1 != true", err: true},
|
||||||
|
{stmt: "_ = 1 == 1", err: false},
|
||||||
|
{stmt: "_ = 1 != 1", err: false},
|
||||||
|
{stmt: "_ = 1 == 1.0", err: false},
|
||||||
|
{stmt: "_ = 1 != 1.0", err: false},
|
||||||
|
{stmt: "_ = 1 == 1.1", err: false},
|
||||||
|
{stmt: "_ = 1 != 1.1", err: false},
|
||||||
|
{stmt: "a, b := 1, true; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1, true; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1, 1; _ = a == b", err: false},
|
||||||
|
{stmt: "a, b := 1, 1; _ = a != b", err: false},
|
||||||
|
{stmt: "a, b := 1, 1.0; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1, 1.0; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1, 1.1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1, 1.1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1, vec2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1, vec2(1); _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1, mat2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1, mat2(1); _ = a != b", err: true},
|
||||||
|
|
||||||
|
{stmt: "_ = 1.0 == true", err: true},
|
||||||
|
{stmt: "_ = 1.0 != true", err: true},
|
||||||
|
{stmt: "_ = 1.0 == 1", err: false},
|
||||||
|
{stmt: "_ = 1.0 != 1", err: false},
|
||||||
|
{stmt: "_ = 1.0 == 1.0", err: false},
|
||||||
|
{stmt: "_ = 1.0 != 1.0", err: false},
|
||||||
|
{stmt: "_ = 1.0 == 1.1", err: false},
|
||||||
|
{stmt: "_ = 1.0 != 1.1", err: false},
|
||||||
|
{stmt: "a, b := 1.0, true; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1.0, true; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1.0, 1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1.0, 1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1.0, 1.0; _ = a == b", err: false},
|
||||||
|
{stmt: "a, b := 1.0, 1.0; _ = a != b", err: false},
|
||||||
|
{stmt: "a, b := 1.0, 1.1; _ = a == b", err: false},
|
||||||
|
{stmt: "a, b := 1.0, 1.1; _ = a != b", err: false},
|
||||||
|
{stmt: "a, b := 1.0, vec2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1.0, vec2(1); _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1.0, mat2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1.0, mat2(1); _ = a != b", err: true},
|
||||||
|
|
||||||
|
{stmt: "_ = 1.1 == true", err: true},
|
||||||
|
{stmt: "_ = 1.1 != true", err: true},
|
||||||
|
{stmt: "_ = 1.1 == 1", err: false},
|
||||||
|
{stmt: "_ = 1.1 != 1", err: false},
|
||||||
|
{stmt: "_ = 1.1 == 1.0", err: false},
|
||||||
|
{stmt: "_ = 1.1 != 1.0", err: false},
|
||||||
|
{stmt: "_ = 1.1 == 1.1", err: false},
|
||||||
|
{stmt: "_ = 1.1 != 1.1", err: false},
|
||||||
|
{stmt: "a, b := 1.1, true; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1.1, true; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1.1, 1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1.1, 1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1.1, 1.0; _ = a == b", err: false},
|
||||||
|
{stmt: "a, b := 1.1, 1.0; _ = a != b", err: false},
|
||||||
|
{stmt: "a, b := 1.1, 1.1; _ = a == b", err: false},
|
||||||
|
{stmt: "a, b := 1.1, 1.1; _ = a != b", err: false},
|
||||||
|
{stmt: "a, b := 1.1, vec2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1.1, vec2(1); _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := 1.1, mat2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := 1.1, mat2(1); _ = a != b", err: true},
|
||||||
|
|
||||||
|
{stmt: "_ = vec2(1) == true", err: true},
|
||||||
|
{stmt: "_ = vec2(1) != true", err: true},
|
||||||
|
{stmt: "_ = vec2(1) == 1", err: true},
|
||||||
|
{stmt: "_ = vec2(1) != 1", err: true},
|
||||||
|
{stmt: "_ = vec2(1) == 1.0", err: true},
|
||||||
|
{stmt: "_ = vec2(1) != 1.0", err: true},
|
||||||
|
{stmt: "_ = vec2(1) == 1.1", err: true},
|
||||||
|
{stmt: "_ = vec2(1) != 1.1", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), true; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), true; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), 1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), 1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), 1.0; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), 1.0; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), 1.1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), 1.1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), vec2(1); _ = a == b", err: false},
|
||||||
|
{stmt: "a, b := vec2(1), vec2(1); _ = a != b", err: false},
|
||||||
|
{stmt: "a, b := vec2(1), mat2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := vec2(1), mat2(1); _ = a != b", err: true},
|
||||||
|
|
||||||
|
{stmt: "_ = mat2(1) == true", err: true},
|
||||||
|
{stmt: "_ = mat2(1) != true", err: true},
|
||||||
|
{stmt: "_ = mat2(1) == 1", err: true},
|
||||||
|
{stmt: "_ = mat2(1) != 1", err: true},
|
||||||
|
{stmt: "_ = mat2(1) == 1.0", err: true},
|
||||||
|
{stmt: "_ = mat2(1) != 1.0", err: true},
|
||||||
|
{stmt: "_ = mat2(1) == 1.1", err: true},
|
||||||
|
{stmt: "_ = mat2(1) != 1.1", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), true; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), true; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), 1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), 1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), 1.0; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), 1.0; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), 1.1; _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), 1.1; _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), vec2(1); _ = a == b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), vec2(1); _ = a != b", err: true},
|
||||||
|
{stmt: "a, b := mat2(1), mat2(1); _ = a == b", err: true}, // Comparing matrices are not allowed.
|
||||||
|
{stmt: "a, b := mat2(1), mat2(1); _ = a != b", err: true}, // Comparing matrices are not allowed.
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
stmt := c.stmt
|
||||||
|
src := fmt.Sprintf(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
%s
|
||||||
|
return position
|
||||||
|
}`, stmt)
|
||||||
|
_, err := compileToIR([]byte(src))
|
||||||
|
if err == nil && c.err {
|
||||||
|
t.Errorf("%s must return an error but does not", stmt)
|
||||||
|
} else if err != nil && !c.err {
|
||||||
|
t.Errorf("%s must not return nil but returned %v", stmt, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user