shader: Let parseExpr return statements for Call

This commit is contained in:
Hajime Hoshi 2020-06-07 17:50:28 +09:00
parent e117086ca1
commit e64c806698

View File

@ -191,7 +191,8 @@ func (cs *compileState) parseDecl(b *block, d ast.Decl) {
case token.VAR: case token.VAR:
for _, s := range d.Specs { for _, s := range d.Specs {
s := s.(*ast.ValueSpec) s := s.(*ast.ValueSpec)
vs, inits := cs.parseVariable(b, s) vs, inits, stmts := cs.parseVariable(b, s)
b.ir.Stmts = append(b.ir.Stmts, stmts...)
if b == &cs.global { if b == &cs.global {
// TODO: Should rhs be ignored? // TODO: Should rhs be ignored?
for i, v := range vs { for i, v := range vs {
@ -246,7 +247,7 @@ func (cs *compileState) parseDecl(b *block, d ast.Decl) {
} }
} }
func (s *compileState) parseVariable(block *block, vs *ast.ValueSpec) ([]variable, []*shaderir.Expr) { func (s *compileState) parseVariable(block *block, vs *ast.ValueSpec) ([]variable, []*shaderir.Expr, []shaderir.Stmt) {
var t typ var t typ
if vs.Type != nil { if vs.Type != nil {
t = s.parseType(vs.Type) t = s.parseType(vs.Type)
@ -254,6 +255,7 @@ func (s *compileState) parseVariable(block *block, vs *ast.ValueSpec) ([]variabl
var vars []variable var vars []variable
var inits []*shaderir.Expr var inits []*shaderir.Expr
var stmts []shaderir.Stmt
for i, n := range vs.Names { for i, n := range vs.Names {
var init ast.Expr var init ast.Expr
if len(vs.Values) > 0 { if len(vs.Values) > 0 {
@ -270,12 +272,13 @@ func (s *compileState) parseVariable(block *block, vs *ast.ValueSpec) ([]variabl
var expr *shaderir.Expr var expr *shaderir.Expr
if init != nil { if init != nil {
e := s.parseExpr(block, init) e, ss := s.parseExpr(block, init)
expr = &e expr = &e
stmts = append(stmts, ss...)
} }
inits = append(inits, expr) inits = append(inits, expr)
} }
return vars, inits return vars, inits, stmts
} }
func (s *compileState) parseConstant(vs *ast.ValueSpec) []constant { func (s *compileState) parseConstant(vs *ast.ValueSpec) []constant {
@ -446,23 +449,30 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out
v.typ = cs.detectType(block, l.Rhs[i]) v.typ = cs.detectType(block, l.Rhs[i])
block.vars = append(block.vars, v) block.vars = append(block.vars, v)
block.ir.LocalVars = append(block.ir.LocalVars, v.typ.ir) block.ir.LocalVars = append(block.ir.LocalVars, v.typ.ir)
// Prase RHS first for the order of the statements.
rhs, stmts := cs.parseExpr(block, l.Rhs[i])
block.ir.Stmts = append(block.ir.Stmts, stmts...)
lhs, stmts := cs.parseExpr(block, l.Lhs[i])
block.ir.Stmts = append(block.ir.Stmts, stmts...)
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
Type: shaderir.Assign, Type: shaderir.Assign,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{lhs, rhs},
cs.parseExpr(block, l.Lhs[i]),
cs.parseExpr(block, l.Rhs[i]),
},
}) })
} }
case token.ASSIGN: case token.ASSIGN:
// TODO: What about the statement `a,b = b,a?` // TODO: What about the statement `a,b = b,a?`
for i := range l.Rhs { for i := range l.Rhs {
// Prase RHS first for the order of the statements.
rhs, stmts := cs.parseExpr(block, l.Rhs[i])
block.ir.Stmts = append(block.ir.Stmts, stmts...)
lhs, stmts := cs.parseExpr(block, l.Lhs[i])
block.ir.Stmts = append(block.ir.Stmts, stmts...)
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
Type: shaderir.Assign, Type: shaderir.Assign,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{lhs, rhs},
cs.parseExpr(block, l.Lhs[i]),
cs.parseExpr(block, l.Rhs[i]),
},
}) })
} }
} }
@ -478,7 +488,8 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out
cs.parseDecl(block, l.Decl) cs.parseDecl(block, l.Decl)
case *ast.ReturnStmt: case *ast.ReturnStmt:
for i, r := range l.Results { for i, r := range l.Results {
e := cs.parseExpr(block, r) e, stmts := cs.parseExpr(block, r)
block.ir.Stmts = append(block.ir.Stmts, stmts...)
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
Type: shaderir.Assign, Type: shaderir.Assign,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{
@ -565,7 +576,7 @@ func (s *compileState) detectType(b *block, expr ast.Expr) typ {
} }
} }
func (cs *compileState) parseExpr(block *block, expr ast.Expr) shaderir.Expr { func (cs *compileState) parseExpr(block *block, expr ast.Expr) (shaderir.Expr, []shaderir.Stmt) {
switch e := expr.(type) { switch e := expr.(type) {
case *ast.BasicLit: case *ast.BasicLit:
switch e.Kind { switch e.Kind {
@ -573,22 +584,22 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr) shaderir.Expr {
v, err := strconv.ParseInt(e.Value, 10, 32) v, err := strconv.ParseInt(e.Value, 10, 32)
if err != nil { if err != nil {
cs.addError(e.Pos(), fmt.Sprintf("unexpected literal: %s", e.Value)) cs.addError(e.Pos(), fmt.Sprintf("unexpected literal: %s", e.Value))
return shaderir.Expr{} return shaderir.Expr{}, nil
} }
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.IntExpr, Type: shaderir.IntExpr,
Int: int32(v), Int: int32(v),
} }, nil
case token.FLOAT: case token.FLOAT:
v, err := strconv.ParseFloat(e.Value, 32) v, err := strconv.ParseFloat(e.Value, 32)
if err != nil { if err != nil {
cs.addError(e.Pos(), fmt.Sprintf("unexpected literal: %s", e.Value)) cs.addError(e.Pos(), fmt.Sprintf("unexpected literal: %s", e.Value))
return shaderir.Expr{} return shaderir.Expr{}, nil
} }
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.FloatExpr, Type: shaderir.FloatExpr,
Float: float32(v), Float: float32(v),
} }, nil
default: default:
cs.addError(e.Pos(), fmt.Sprintf("literal not implemented: %#v", e)) cs.addError(e.Pos(), fmt.Sprintf("literal not implemented: %#v", e))
} }
@ -635,60 +646,76 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr) shaderir.Expr {
op = shaderir.OrOr op = shaderir.OrOr
default: default:
cs.addError(e.Pos(), fmt.Sprintf("unexpected operator: %s", e.Op)) cs.addError(e.Pos(), fmt.Sprintf("unexpected operator: %s", e.Op))
return shaderir.Expr{} return shaderir.Expr{}, nil
} }
var stmts []shaderir.Stmt
// Prase RHS first for the order of the statements.
rhs, ss := cs.parseExpr(block, e.Y)
stmts = append(stmts, ss...)
lhs, ss := cs.parseExpr(block, e.X)
stmts = append(stmts, ss...)
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.Binary, Type: shaderir.Binary,
Op: op, Op: op,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{lhs, rhs},
cs.parseExpr(block, e.X), }, stmts
cs.parseExpr(block, e.Y),
},
}
case *ast.CallExpr: case *ast.CallExpr:
exprs := []shaderir.Expr{ var exprs []shaderir.Expr
cs.parseExpr(block, e.Fun), var stmts []shaderir.Stmt
}
// Parse the argument first for the order of the statements.
for _, a := range e.Args { for _, a := range e.Args {
e := cs.parseExpr(block, a) e, ss := cs.parseExpr(block, a)
// TODO: Convert integer literals to float literals if necessary. // TODO: Convert integer literals to float literals if necessary.
exprs = append(exprs, e) exprs = append(exprs, e)
stmts = append(stmts, ss...)
} }
// TODO: When len(stmts) is not 0?
expr, ss := cs.parseExpr(block, e.Fun)
exprs = append([]shaderir.Expr{expr}, exprs...)
stmts = append(stmts, ss...)
// TODO: Return statements to call the function separately.
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.Call, Type: shaderir.Call,
Exprs: exprs, Exprs: exprs,
} }, stmts
case *ast.Ident: case *ast.Ident:
if i, ok := block.findLocalVariable(e.Name); ok { if i, ok := block.findLocalVariable(e.Name); ok {
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.LocalVariable, Type: shaderir.LocalVariable,
Index: i, Index: i,
} }, nil
} }
if i, ok := cs.findUniformVariable(e.Name); ok { if i, ok := cs.findUniformVariable(e.Name); ok {
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.UniformVariable, Type: shaderir.UniformVariable,
Index: i, Index: i,
} }, nil
} }
if f, ok := shaderir.ParseBuiltinFunc(e.Name); ok { if f, ok := shaderir.ParseBuiltinFunc(e.Name); ok {
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.BuiltinFuncExpr, Type: shaderir.BuiltinFuncExpr,
BuiltinFunc: f, BuiltinFunc: f,
} }, nil
} }
cs.addError(e.Pos(), fmt.Sprintf("unexpected identifier: %s", e.Name)) cs.addError(e.Pos(), fmt.Sprintf("unexpected identifier: %s", e.Name))
case *ast.SelectorExpr: case *ast.SelectorExpr:
expr, stmts := cs.parseExpr(block, e.X)
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.FieldSelector, Type: shaderir.FieldSelector,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{
cs.parseExpr(block, e.X), expr,
{ {
Type: shaderir.SwizzlingExpr, Type: shaderir.SwizzlingExpr,
Swizzling: e.Sel.Name, Swizzling: e.Sel.Name,
}, },
}, },
} }, stmts
case *ast.UnaryExpr: case *ast.UnaryExpr:
var op shaderir.Op var op shaderir.Op
switch e.Op { switch e.Op {
@ -700,17 +727,16 @@ func (cs *compileState) parseExpr(block *block, expr ast.Expr) shaderir.Expr {
op = shaderir.NotOp op = shaderir.NotOp
default: default:
cs.addError(e.Pos(), fmt.Sprintf("unexpected operator: %s", e.Op)) cs.addError(e.Pos(), fmt.Sprintf("unexpected operator: %s", e.Op))
return shaderir.Expr{} return shaderir.Expr{}, nil
} }
expr, stmts := cs.parseExpr(block, e.X)
return shaderir.Expr{ return shaderir.Expr{
Type: shaderir.Unary, Type: shaderir.Unary,
Op: op, Op: op,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{expr},
cs.parseExpr(block, e.X), }, stmts
},
}
default: default:
cs.addError(e.Pos(), fmt.Sprintf("expression not implemented: %#v", e)) cs.addError(e.Pos(), fmt.Sprintf("expression not implemented: %#v", e))
} }
return shaderir.Expr{} return shaderir.Expr{}, nil
} }