From ac16564e9512e8ca0b2b6875f7737e1a24fe05af Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Wed, 29 Jul 2020 23:49:39 +0900 Subject: [PATCH] shaderir: Add indexing Fixes #1235 --- internal/shader/expr.go | 60 ++++++++++++++++++++++ internal/shader/testdata/array.expected.vs | 1 + internal/shader/testdata/array.go | 1 + 3 files changed, 62 insertions(+) diff --git a/internal/shader/expr.go b/internal/shader/expr.go index 484769b06..3f322b164 100644 --- a/internal/shader/expr.go +++ b/internal/shader/expr.go @@ -499,6 +499,66 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr) ([]shaderir.Expr, }, }, []shaderir.Type{t}, stmts, true + case *ast.IndexExpr: + var stmts []shaderir.Stmt + + // Parse the index first + exprs, _, ss, ok := cs.parseExpr(block, e.Index) + if !ok { + return nil, nil, nil, false + } + stmts = append(stmts, ss...) + + if len(exprs) != 1 { + cs.addError(e.Pos(), fmt.Sprintf("multiple-value context is not available at an index expression")) + return nil, nil, nil, false + } + idx := exprs[0] + if idx.Type != shaderir.NumberExpr { + cs.addError(e.Pos(), fmt.Sprintf("an index must be a constant number")) + return nil, nil, nil, false + } + idx.ConstType = shaderir.ConstTypeInt + + exprs, ts, ss, ok := cs.parseExpr(block, e.X) + if !ok { + return nil, nil, nil, false + } + stmts = append(stmts, ss...) + if len(exprs) != 1 { + cs.addError(e.Pos(), fmt.Sprintf("multiple-value context is not available at an index expression")) + return nil, nil, nil, false + } + x := exprs[0] + t := ts[0] + + var typ shaderir.Type + switch t.Main { + case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4: + typ = shaderir.Type{Main: shaderir.Float} + case shaderir.Mat2: + typ = shaderir.Type{Main: shaderir.Vec2} + case shaderir.Mat3: + typ = shaderir.Type{Main: shaderir.Vec3} + case shaderir.Mat4: + typ = shaderir.Type{Main: shaderir.Vec4} + case shaderir.Array: + typ = t.Sub[0] + default: + cs.addError(e.Pos(), fmt.Sprintf("index operator cannot be applied to the type %s", t.String())) + return nil, nil, nil, false + } + + return []shaderir.Expr{ + { + Type: shaderir.Index, + Exprs: []shaderir.Expr{ + x, + idx, + }, + }, + }, []shaderir.Type{typ}, stmts, true + default: cs.addError(e.Pos(), fmt.Sprintf("expression not implemented: %#v", e)) } diff --git a/internal/shader/testdata/array.expected.vs b/internal/shader/testdata/array.expected.vs index 1cc55a604..b2aded8ed 100644 --- a/internal/shader/testdata/array.expected.vs +++ b/internal/shader/testdata/array.expected.vs @@ -14,6 +14,7 @@ void F1(out vec2[2] l0) { vec2[2] l2 = vec2[2](vec2(0), vec2(0)); (l1)[0] = vec2(1.0); l2 = l1; + ((l2)[1]).y = vec2(2.0); l0 = l2; return; } diff --git a/internal/shader/testdata/array.go b/internal/shader/testdata/array.go index 76ef502ed..8aa9c0ce1 100644 --- a/internal/shader/testdata/array.go +++ b/internal/shader/testdata/array.go @@ -9,5 +9,6 @@ func Foo() [2]vec2 { func Bar() [2]vec2 { x := [2]vec2{vec2(1)} + x[1].y = vec2(2) return x }