From 08270ee729d0673f69f9285135d9b75945310015 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 11 Aug 2020 23:51:22 +0900 Subject: [PATCH] shader: Enable to parse ... in an array type --- examples/shader/radialblur.go | 2 +- examples/shader/radialblur_go.go | 2 +- internal/shader/expr.go | 3 +++ internal/shader/type.go | 42 +++++++++++++++++--------------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/examples/shader/radialblur.go b/examples/shader/radialblur.go index cacd7dd6a..d794d9555 100644 --- a/examples/shader/radialblur.go +++ b/examples/shader/radialblur.go @@ -24,7 +24,7 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 { dir := normalize(position.xy - Cursor) clr := image2TextureAt(texCoord) - samples := [10]float{ + samples := [...]float{ -22, -14, -8, -4, -2, 2, 4, 8, 14, 22, } // TODO: Add len(samples) diff --git a/examples/shader/radialblur_go.go b/examples/shader/radialblur_go.go index 46796aac0..5fb658487 100644 --- a/examples/shader/radialblur_go.go +++ b/examples/shader/radialblur_go.go @@ -3,4 +3,4 @@ package main -var radialblur_go = []byte("// Copyright 2020 The Ebiten Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// +build ignore\n\npackage main\n\nvar Time float\nvar Cursor vec2\nvar ScreenSize vec2\n\nfunc Fragment(position vec4, texCoord vec2, color vec4) vec4 {\n\tdir := normalize(position.xy - Cursor)\n\tclr := image2TextureAt(texCoord)\n\n\tsamples := [10]float{\n\t\t-22, -14, -8, -4, -2, 2, 4, 8, 14, 22,\n\t}\n\t// TODO: Add len(samples)\n\tsum := clr\n\tfor i := 0; i < 10; i++ {\n\t\tpos := texCoord + dir*samples[i]/imageSrcTextureSize()\n\t\tsum += image2TextureBoundsAt(pos)\n\t}\n\tsum /= 10 + 1\n\n\tdist := distance(position.xy, Cursor)\n\tt := clamp(dist/256, 0, 1)\n\treturn mix(clr, sum, t)\n}\n") +var radialblur_go = []byte("// Copyright 2020 The Ebiten Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// +build ignore\n\npackage main\n\nvar Time float\nvar Cursor vec2\nvar ScreenSize vec2\n\nfunc Fragment(position vec4, texCoord vec2, color vec4) vec4 {\n\tdir := normalize(position.xy - Cursor)\n\tclr := image2TextureAt(texCoord)\n\n\tsamples := [...]float{\n\t\t-22, -14, -8, -4, -2, 2, 4, 8, 14, 22,\n\t}\n\t// TODO: Add len(samples)\n\tsum := clr\n\tfor i := 0; i < 10; i++ {\n\t\tpos := texCoord + dir*samples[i]/imageSrcTextureSize()\n\t\tsum += image2TextureBoundsAt(pos)\n\t}\n\tsum /= 10 + 1\n\n\tdist := distance(position.xy, Cursor)\n\tt := clamp(dist/256, 0, 1)\n\treturn mix(clr, sum, t)\n}\n") diff --git a/internal/shader/expr.go b/internal/shader/expr.go index 89143c820..818a27178 100644 --- a/internal/shader/expr.go +++ b/internal/shader/expr.go @@ -452,6 +452,9 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr) ([]shaderir.Expr, if !ok { return nil, nil, nil, false } + if t.Main == shaderir.Array && t.Length == -1 { + t.Length = len(e.Elts) + } idx := block.totalLocalVariableNum() block.vars = append(block.vars, variable{ diff --git a/internal/shader/type.go b/internal/shader/type.go index c3b8c3c06..f6ea38008 100644 --- a/internal/shader/type.go +++ b/internal/shader/type.go @@ -53,24 +53,28 @@ func (cs *compileState) parseType(block *block, expr ast.Expr) (shaderir.Type, b cs.addError(t.Pos(), fmt.Sprintf("array length must be specified")) return shaderir.Type{}, false } - // TODO: Parse ellipsis - - exprs, _, _, ok := cs.parseExpr(block, t.Len) - if !ok { - return shaderir.Type{}, false - } - if len(exprs) != 1 { - cs.addError(t.Pos(), fmt.Sprintf("invalid length of array")) - return shaderir.Type{}, false - } - if exprs[0].Type != shaderir.NumberExpr { - cs.addError(t.Pos(), fmt.Sprintf("length of array must be a constant number")) - return shaderir.Type{}, false - } - len, ok := gconstant.Int64Val(exprs[0].Const) - if !ok { - cs.addError(t.Pos(), fmt.Sprintf("length of array must be an integer")) - return shaderir.Type{}, false + var length int + if _, ok := t.Len.(*ast.Ellipsis); ok { + length = -1 // Determine the length later. + } else { + exprs, _, _, ok := cs.parseExpr(block, t.Len) + if !ok { + return shaderir.Type{}, false + } + if len(exprs) != 1 { + cs.addError(t.Pos(), fmt.Sprintf("invalid length of array")) + return shaderir.Type{}, false + } + if exprs[0].Type != shaderir.NumberExpr { + cs.addError(t.Pos(), fmt.Sprintf("length of array must be a constant number")) + return shaderir.Type{}, false + } + l, ok := gconstant.Int64Val(exprs[0].Const) + if !ok { + cs.addError(t.Pos(), fmt.Sprintf("length of array must be an integer")) + return shaderir.Type{}, false + } + length = int(l) } elm, ok := cs.parseType(block, t.Elt) @@ -84,7 +88,7 @@ func (cs *compileState) parseType(block *block, expr ast.Expr) (shaderir.Type, b return shaderir.Type{ Main: shaderir.Array, Sub: []shaderir.Type{elm}, - Length: int(len), + Length: length, }, true case *ast.StructType: cs.addError(t.Pos(), "struct is not implemented")