internal/shader: bug fix: check types correctly for assign operators

Closes #1950
This commit is contained in:
Hajime Hoshi 2022-01-12 00:23:55 +09:00
parent 83bd0772d4
commit d110716dc0
6 changed files with 104 additions and 19 deletions

View File

@ -87,25 +87,38 @@ func (cs *compileState) parseStmt(block *block, fname string, stmt ast.Stmt, inP
}
stmts = append(stmts, ss...)
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
}
}
// Treat an integer literal as an integer constant value.
if rhs[0].Type == shaderir.NumberExpr && rts[0].Main == shaderir.Int {
if !cs.forceToInt(stmt, &rhs[0]) {
return nil, false
}
}
if lts[0].Main != rts[0].Main {
switch lts[0].Main {
case shaderir.Int:
if !cs.forceToInt(stmt, &rhs[0]) {
return nil, false
}
case shaderir.Float:
if rhs[0].Const != nil && rhs[0].Const.Kind() == gconstant.Int {
rhs[0].Const = gconstant.ToFloat(rhs[0].Const)
rhs[0].ConstType = shaderir.ConstTypeFloat
} else {
cs.addError(stmt.Pos(), fmt.Sprintf("invalid operation: mismatched types %s and %s", lts[0].String(), rts[0].String()))
return nil, false
}
default:
cs.addError(stmt.Pos(), fmt.Sprintf("invalid operation: mismatched types %s and %s", lts[0].String(), rts[0].String()))
return nil, false
}
}
if op == shaderir.ModOp && lts[0].Main != shaderir.Int {
cs.addError(stmt.Pos(), fmt.Sprintf("invalid operation: operator %% not defined on %s", lts[0].String()))
return nil, false
}
stmts = append(stmts, shaderir.Stmt{
Type: shaderir.Assign,
Exprs: []shaderir.Expr{

View File

@ -5,11 +5,11 @@ void F0(out vec2 l0) {
vec2 l3 = vec2(0);
l1 = vec2(0.0);
for (int l2 = 0; l2 < 100; l2++) {
(l1).x = ((l1).x) + (l2);
(l1).x = ((l1).x) + (float(l2));
}
l3 = vec2(0.0);
for (float l4 = 10.0; l4 >= 0.0; l4 -= 2.0) {
(l3).x = ((l3).x) + (l4);
(l3).x = ((l3).x) + (float(l4));
}
l0 = l1;
return;

View File

@ -3,11 +3,11 @@ package main
func Foo() vec2 {
v := vec2(0)
for i := 0; i < 100; i++ {
v.x += i
v.x += float(i)
}
v2 := vec2(0)
for i := 10.0; i >= 0; i -= 2 {
v2.x += i
v2.x += float(i)
}
_ = v2
return v

View File

@ -5,7 +5,7 @@ void F0(out vec2 l0) {
vec2 l3 = vec2(0);
l1 = vec2(0.0);
for (int l2 = 0; l2 < 100; l2++) {
(l1).x = ((l1).x) + (l2);
(l1).x = ((l1).x) + (float(l2));
if (((l1).x) >= (100.0)) {
break;
}

View File

@ -3,7 +3,7 @@ package main
func Foo() vec2 {
v := vec2(0)
for i := 0; i < 100; i++ {
v.x += i
v.x += float(i)
if v.x >= 100 {
break
}

View File

@ -1351,6 +1351,16 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
if _, err := ebiten.NewShader([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := 2
a %= 1.0
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
@ -1369,3 +1379,65 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
t.Errorf("error must be non-nil but was nil")
}
}
func TestShaderOperatorAssign(t *testing.T) {
if _, err := ebiten.NewShader([]byte(`package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
a := 1.0
a += 2
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 := 1.0
a += 2.0
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 := 1.0
a += 2.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 := 1
a += 2
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 := 1
a += 2.0
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 := 1
a += 2.1
return vec4(a)
}`)); err == nil {
t.Errorf("error must be non-nil but was nil")
}
}