mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 11:48:55 +01:00
internal/shader: bug fix: % should be valid only for integers
Closes #1947
This commit is contained in:
parent
ca3f84fdd6
commit
83bd0772d4
@ -29,6 +29,22 @@ func canTruncateToInteger(v gconstant.Value) bool {
|
|||||||
return gconstant.ToInt(v).Kind() != gconstant.Unknown
|
return gconstant.ToInt(v).Kind() != gconstant.Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func goConstantKindString(k gconstant.Kind) string {
|
||||||
|
switch k {
|
||||||
|
case gconstant.Bool:
|
||||||
|
return "bool"
|
||||||
|
case gconstant.String:
|
||||||
|
return "string"
|
||||||
|
case gconstant.Int:
|
||||||
|
return "int"
|
||||||
|
case gconstant.Float:
|
||||||
|
return "float"
|
||||||
|
case gconstant.Complex:
|
||||||
|
return "complex"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
var textureVariableRe = regexp.MustCompile(`\A__t(\d+)\z`)
|
var textureVariableRe = regexp.MustCompile(`\A__t(\d+)\z`)
|
||||||
|
|
||||||
func (cs *compileState) parseExpr(block *block, expr ast.Expr, markLocalVariableUsed bool) ([]shaderir.Expr, []shaderir.Type, []shaderir.Stmt, bool) {
|
func (cs *compileState) parseExpr(block *block, expr ast.Expr, markLocalVariableUsed bool) ([]shaderir.Expr, []shaderir.Type, []shaderir.Stmt, bool) {
|
||||||
@ -94,6 +110,18 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr, markLocalVariable
|
|||||||
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 lhs[0].Const.Kind() != gconstant.Int || rhs[0].Const.Kind() != gconstant.Int {
|
||||||
|
var wrongTypeName string
|
||||||
|
if lhs[0].Const.Kind() != gconstant.Int {
|
||||||
|
wrongTypeName = goConstantKindString(lhs[0].Const.Kind())
|
||||||
|
} else {
|
||||||
|
wrongTypeName = goConstantKindString(rhs[0].Const.Kind())
|
||||||
|
}
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("invalid operation: operator %% not defined on untyped %s", wrongTypeName))
|
||||||
|
return nil, nil, nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
v = gconstant.BinaryOp(lhs[0].Const, op, rhs[0].Const)
|
v = gconstant.BinaryOp(lhs[0].Const, op, rhs[0].Const)
|
||||||
if v.Kind() == gconstant.Float {
|
if v.Kind() == gconstant.Float {
|
||||||
t = shaderir.Type{Main: shaderir.Float}
|
t = shaderir.Type{Main: shaderir.Float}
|
||||||
@ -174,6 +202,20 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr, markLocalVariable
|
|||||||
return nil, nil, nil, false
|
return nil, nil, nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if op == shaderir.ModOp {
|
||||||
|
// TODO: What about ivec?
|
||||||
|
if lhst.Main != shaderir.Int || rhst.Main != shaderir.Int {
|
||||||
|
var wrongType shaderir.Type
|
||||||
|
if lhst.Main != shaderir.Int {
|
||||||
|
wrongType = lhst
|
||||||
|
} else {
|
||||||
|
wrongType = rhst
|
||||||
|
}
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("invalid operation: operator %% not defined on %s", wrongType.String()))
|
||||||
|
return nil, nil, nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return []shaderir.Expr{
|
return []shaderir.Expr{
|
||||||
{
|
{
|
||||||
Type: shaderir.Binary,
|
Type: shaderir.Binary,
|
||||||
|
@ -75,19 +75,32 @@ func (cs *compileState) parseStmt(block *block, fname string, stmt ast.Stmt, inP
|
|||||||
op = shaderir.ModOp
|
op = shaderir.ModOp
|
||||||
}
|
}
|
||||||
|
|
||||||
rhs, _, ss, ok := cs.parseExpr(block, stmt.Rhs[0], true)
|
rhs, rts, ss, ok := cs.parseExpr(block, stmt.Rhs[0], true)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
stmts = append(stmts, ss...)
|
stmts = append(stmts, ss...)
|
||||||
|
|
||||||
lhs, ts, ss, ok := cs.parseExpr(block, stmt.Lhs[0], true)
|
lhs, lts, ss, ok := cs.parseExpr(block, stmt.Lhs[0], true)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
stmts = append(stmts, ss...)
|
stmts = append(stmts, ss...)
|
||||||
|
|
||||||
if rhs[0].Type == shaderir.NumberExpr && ts[0].Main == shaderir.Int {
|
if op == shaderir.ModOp {
|
||||||
|
if lts[0].Main != shaderir.Int || rts[0].Main != shaderir.Int {
|
||||||
|
var wrongType shaderir.Type
|
||||||
|
if lts[0].Main != shaderir.Int {
|
||||||
|
wrongType = lts[0]
|
||||||
|
} else {
|
||||||
|
wrongType = rts[0]
|
||||||
|
}
|
||||||
|
cs.addError(stmt.Pos(), fmt.Sprintf("invalid operation: operator %% not defined on %s", wrongType.String()))
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rhs[0].Type == shaderir.NumberExpr && rts[0].Main == shaderir.Int {
|
||||||
if !cs.forceToInt(stmt, &rhs[0]) {
|
if !cs.forceToInt(stmt, &rhs[0]) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
100
shader_test.go
100
shader_test.go
@ -1269,3 +1269,103 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
t.Errorf("error must be non-nil but was nil")
|
t.Errorf("error must be non-nil but was nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #1947
|
||||||
|
func TestShaderOperatorMod(t *testing.T) {
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2.0 % 0.5
|
||||||
|
return vec4(a)
|
||||||
|
}`)); err == nil {
|
||||||
|
t.Errorf("error must be non-nil but was nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2.0
|
||||||
|
b := 0.5
|
||||||
|
return vec4(a % b)
|
||||||
|
}`)); err == nil {
|
||||||
|
t.Errorf("error must be non-nil but was nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2
|
||||||
|
b := 0.5
|
||||||
|
return vec4(a % b)
|
||||||
|
}`)); err == nil {
|
||||||
|
t.Errorf("error must be non-nil but was nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2.5
|
||||||
|
b := 1
|
||||||
|
return vec4(a % b)
|
||||||
|
}`)); err == nil {
|
||||||
|
t.Errorf("error must be non-nil but was nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2
|
||||||
|
b := 1
|
||||||
|
return vec4(a % b)
|
||||||
|
}`)); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2
|
||||||
|
return vec4(a % 1)
|
||||||
|
}`)); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 1
|
||||||
|
return vec4(2 % a)
|
||||||
|
}`)); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2
|
||||||
|
a %= 1
|
||||||
|
return vec4(a)
|
||||||
|
}`)); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2
|
||||||
|
a %= 0.5
|
||||||
|
return vec4(a)
|
||||||
|
}`)); err == nil {
|
||||||
|
t.Errorf("error must be non-nil but was nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ebiten.NewShader([]byte(`package main
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
a := 2.0
|
||||||
|
a %= 1
|
||||||
|
return vec4(a)
|
||||||
|
}`)); err == nil {
|
||||||
|
t.Errorf("error must be non-nil but was nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user