From c36d2165e69e58ae19b6f2e587c670f9bb6940af Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 21 Jun 2020 21:47:23 +0900 Subject: [PATCH] shader: Parse number literals in unary expressions correctly Fixes #1190 --- internal/shader/shader.go | 36 ++++++++++++---- .../shader/testdata/number_unary.expected.vs | 41 +++++++++++++++++++ internal/shader/testdata/number_unary.go | 25 +++++++++++ 3 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 internal/shader/testdata/number_unary.expected.vs create mode 100644 internal/shader/testdata/number_unary.go diff --git a/internal/shader/shader.go b/internal/shader/shader.go index 580ff8483..a37e0c252 100644 --- a/internal/shader/shader.go +++ b/internal/shader/shader.go @@ -1136,6 +1136,10 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr) ([]shaderir.Expr, }, nil, nil, true } cs.addError(e.Pos(), fmt.Sprintf("unexpected identifier: %s", e.Name)) + + case *ast.ParenExpr: + return cs.parseExpr(block, e.X) + case *ast.SelectorExpr: exprs, _, stmts, ok := cs.parseExpr(block, e.X) if !ok { @@ -1171,7 +1175,31 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr) ([]shaderir.Expr, }, }, }, []shaderir.Type{t}, stmts, true + case *ast.UnaryExpr: + exprs, t, stmts, ok := cs.parseExpr(block, e.X) + if !ok { + return nil, nil, nil, false + } + if len(exprs) != 1 { + cs.addError(e.Pos(), fmt.Sprintf("multiple-value context is not available at a unary operator: %s", e.X)) + return nil, nil, nil, false + } + + if exprs[0].Type == shaderir.NumberExpr { + v := gconstant.UnaryOp(e.Op, exprs[0].Const, 0) + t := shaderir.Type{Main: shaderir.Int} + if v.Kind() == gconstant.Float { + t = shaderir.Type{Main: shaderir.Float} + } + return []shaderir.Expr{ + { + Type: shaderir.NumberExpr, + Const: v, + }, + }, []shaderir.Type{t}, stmts, true + } + var op shaderir.Op switch e.Op { case token.ADD: @@ -1184,14 +1212,6 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr) ([]shaderir.Expr, cs.addError(e.Pos(), fmt.Sprintf("unexpected operator: %s", e.Op)) return nil, nil, nil, false } - exprs, t, stmts, ok := cs.parseExpr(block, e.X) - if !ok { - return nil, nil, nil, false - } - if len(exprs) != 1 { - cs.addError(e.Pos(), fmt.Sprintf("multiple-value context is not available at a unary operator: %s", e.X)) - return nil, nil, nil, false - } return []shaderir.Expr{ { Type: shaderir.Unary, diff --git a/internal/shader/testdata/number_unary.expected.vs b/internal/shader/testdata/number_unary.expected.vs new file mode 100644 index 000000000..23731211e --- /dev/null +++ b/internal/shader/testdata/number_unary.expected.vs @@ -0,0 +1,41 @@ +void F0(out vec4 l0) { + int l1 = 0; + int l2 = 0; + int l3 = 0; + int l4 = 0; + float l5 = float(0); + float l6 = float(0); + float l7 = float(0); + float l8 = float(0); + l1 = 5; + l2 = -5; + l3 = -5; + l4 = 5; + l5 = 5.0; + l6 = -5.0; + l7 = -5.0; + l8 = 5.0; + l0 = (vec4(l1, l2, l3, l4)) + (vec4(l5, l6, l7, l8)); + return; +} + +void F1(out vec4 l0) { + int l1 = 0; + int l2 = 0; + int l3 = 0; + int l4 = 0; + float l5 = float(0); + float l6 = float(0); + float l7 = float(0); + float l8 = float(0); + l1 = 5; + l2 = -5; + l3 = -5; + l4 = 5; + l5 = 5.0; + l6 = -5.0; + l7 = -5.0; + l8 = 5.0; + l0 = (vec4(l1, l2, l3, l4)) + (vec4(l5, l6, l7, l8)); + return; +} diff --git a/internal/shader/testdata/number_unary.go b/internal/shader/testdata/number_unary.go new file mode 100644 index 000000000..e6b2905cd --- /dev/null +++ b/internal/shader/testdata/number_unary.go @@ -0,0 +1,25 @@ +package main + +func Foo1() vec4 { + x0 := +(+5) + x1 := +(-5) + x2 := -(+5) + x3 := -(-5) + x4 := +(+5.0) + x5 := +(-5.0) + x6 := -(+5.0) + x7 := -(-5.0) + return vec4(x0, x1, x2, x3) + vec4(x4, x5, x6, x7) +} + +func Foo2() vec4 { + var x0 = +(+5) + var x1 = +(-5) + var x2 = -(+5) + var x3 = -(-5) + var x4 = +(+5.0) + var x5 = +(-5.0) + var x6 = -(+5.0) + var x7 = -(-5.0) + return vec4(x0, x1, x2, x3) + vec4(x4, x5, x6, x7) +}