shader: Make parseType return a boolean value indicating ok

This commit is contained in:
Hajime Hoshi 2020-07-29 12:02:07 +09:00
parent d9c54bc0d0
commit 2dc6cbe51a
2 changed files with 46 additions and 26 deletions

View File

@ -260,7 +260,10 @@ func (cs *compileState) parseDecl(b *block, d ast.Decl) ([]shaderir.Stmt, bool)
// TODO: Parse other types // TODO: Parse other types
for _, s := range d.Specs { for _, s := range d.Specs {
s := s.(*ast.TypeSpec) s := s.(*ast.TypeSpec)
t := cs.parseType(b, s.Type) t, ok := cs.parseType(b, s.Type)
if !ok {
return nil, false
}
b.types = append(b.types, typ{ b.types = append(b.types, typ{
name: s.Name.Name, name: s.Name.Name,
ir: t, ir: t,
@ -385,7 +388,11 @@ func (s *compileState) parseVariable(block *block, vs *ast.ValueSpec) ([]variabl
var declt shaderir.Type var declt shaderir.Type
if vs.Type != nil { if vs.Type != nil {
declt = s.parseType(block, vs.Type) var ok bool
declt, ok = s.parseType(block, vs.Type)
if !ok {
return nil, nil, nil, false
}
} }
var ( var (
@ -483,7 +490,11 @@ func (s *compileState) parseVariable(block *block, vs *ast.ValueSpec) ([]variabl
func (s *compileState) parseConstant(block *block, vs *ast.ValueSpec) []constant { func (s *compileState) parseConstant(block *block, vs *ast.ValueSpec) []constant {
var t shaderir.Type var t shaderir.Type
if vs.Type != nil { if vs.Type != nil {
t = s.parseType(block, vs.Type) var ok bool
t, ok = s.parseType(block, vs.Type)
if !ok {
return nil
}
} }
var cs []constant var cs []constant
@ -499,7 +510,10 @@ func (s *compileState) parseConstant(block *block, vs *ast.ValueSpec) []constant
func (cs *compileState) parseFuncParams(block *block, d *ast.FuncDecl) (in, out []variable) { func (cs *compileState) parseFuncParams(block *block, d *ast.FuncDecl) (in, out []variable) {
for _, f := range d.Type.Params.List { for _, f := range d.Type.Params.List {
t := cs.parseType(block, f.Type) t, ok := cs.parseType(block, f.Type)
if !ok {
return
}
for _, n := range f.Names { for _, n := range f.Names {
in = append(in, variable{ in = append(in, variable{
name: n.Name, name: n.Name,
@ -513,7 +527,10 @@ func (cs *compileState) parseFuncParams(block *block, d *ast.FuncDecl) (in, out
} }
for _, f := range d.Type.Results.List { for _, f := range d.Type.Results.List {
t := cs.parseType(block, f.Type) t, ok := cs.parseType(block, f.Type)
if !ok {
return
}
if len(f.Names) == 0 { if len(f.Names) == 0 {
out = append(out, variable{ out = append(out, variable{
name: "", name: "",

View File

@ -22,72 +22,75 @@ import (
"github.com/hajimehoshi/ebiten/internal/shaderir" "github.com/hajimehoshi/ebiten/internal/shaderir"
) )
func (cs *compileState) parseType(block *block, expr ast.Expr) shaderir.Type { func (cs *compileState) parseType(block *block, expr ast.Expr) (shaderir.Type, bool) {
switch t := expr.(type) { switch t := expr.(type) {
case *ast.Ident: case *ast.Ident:
switch t.Name { switch t.Name {
case "bool": case "bool":
return shaderir.Type{Main: shaderir.Bool} return shaderir.Type{Main: shaderir.Bool}, true
case "int": case "int":
return shaderir.Type{Main: shaderir.Int} return shaderir.Type{Main: shaderir.Int}, true
case "float": case "float":
return shaderir.Type{Main: shaderir.Float} return shaderir.Type{Main: shaderir.Float}, true
case "vec2": case "vec2":
return shaderir.Type{Main: shaderir.Vec2} return shaderir.Type{Main: shaderir.Vec2}, true
case "vec3": case "vec3":
return shaderir.Type{Main: shaderir.Vec3} return shaderir.Type{Main: shaderir.Vec3}, true
case "vec4": case "vec4":
return shaderir.Type{Main: shaderir.Vec4} return shaderir.Type{Main: shaderir.Vec4}, true
case "mat2": case "mat2":
return shaderir.Type{Main: shaderir.Mat2} return shaderir.Type{Main: shaderir.Mat2}, true
case "mat3": case "mat3":
return shaderir.Type{Main: shaderir.Mat3} return shaderir.Type{Main: shaderir.Mat3}, true
case "mat4": case "mat4":
return shaderir.Type{Main: shaderir.Mat4} return shaderir.Type{Main: shaderir.Mat4}, true
default: default:
cs.addError(t.Pos(), fmt.Sprintf("unexpected type: %s", t.Name)) cs.addError(t.Pos(), fmt.Sprintf("unexpected type: %s", t.Name))
return shaderir.Type{} return shaderir.Type{}, false
} }
case *ast.ArrayType: case *ast.ArrayType:
if t.Len == nil { if t.Len == nil {
cs.addError(t.Pos(), fmt.Sprintf("array length must be specified")) cs.addError(t.Pos(), fmt.Sprintf("array length must be specified"))
return shaderir.Type{} return shaderir.Type{}, false
} }
// TODO: Parse ellipsis // TODO: Parse ellipsis
exprs, _, _, ok := cs.parseExpr(block, t.Len) exprs, _, _, ok := cs.parseExpr(block, t.Len)
if !ok { if !ok {
return shaderir.Type{} return shaderir.Type{}, false
} }
if len(exprs) != 1 { if len(exprs) != 1 {
cs.addError(t.Pos(), fmt.Sprintf("invalid length of array")) cs.addError(t.Pos(), fmt.Sprintf("invalid length of array"))
return shaderir.Type{} return shaderir.Type{}, false
} }
if exprs[0].Type != shaderir.NumberExpr { if exprs[0].Type != shaderir.NumberExpr {
cs.addError(t.Pos(), fmt.Sprintf("length of array must be a constant number")) cs.addError(t.Pos(), fmt.Sprintf("length of array must be a constant number"))
return shaderir.Type{} return shaderir.Type{}, false
} }
len, ok := gconstant.Int64Val(exprs[0].Const) len, ok := gconstant.Int64Val(exprs[0].Const)
if !ok { if !ok {
cs.addError(t.Pos(), fmt.Sprintf("length of array must be an integer")) cs.addError(t.Pos(), fmt.Sprintf("length of array must be an integer"))
return shaderir.Type{} return shaderir.Type{}, false
} }
elm := cs.parseType(block, t.Elt) elm, ok := cs.parseType(block, t.Elt)
if !ok {
return shaderir.Type{}, false
}
if elm.Main == shaderir.Array { if elm.Main == shaderir.Array {
cs.addError(t.Pos(), fmt.Sprintf("array of array is forbidden")) cs.addError(t.Pos(), fmt.Sprintf("array of array is forbidden"))
return shaderir.Type{} return shaderir.Type{}, false
} }
return shaderir.Type{ return shaderir.Type{
Main: shaderir.Array, Main: shaderir.Array,
Sub: []shaderir.Type{elm}, Sub: []shaderir.Type{elm},
Length: int(len), Length: int(len),
} }, true
case *ast.StructType: case *ast.StructType:
cs.addError(t.Pos(), "struct is not implemented") cs.addError(t.Pos(), "struct is not implemented")
return shaderir.Type{} return shaderir.Type{}, false
default: default:
cs.addError(t.Pos(), fmt.Sprintf("unepxected type: %v", t)) cs.addError(t.Pos(), fmt.Sprintf("unepxected type: %v", t))
return shaderir.Type{} return shaderir.Type{}, false
} }
} }