shader: Refactoring: Add statements later

This commit is contained in:
Hajime Hoshi 2020-07-05 00:03:21 +09:00
parent b00666df22
commit 3ca6e41194
2 changed files with 61 additions and 48 deletions

View File

@ -621,9 +621,11 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out
}() }()
for _, l := range b.List { for _, l := range b.List {
if !cs.parseStmt(block, l, inParams) { stmts, ok := cs.parseStmt(block, l, inParams)
if !ok {
return nil, false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...)
} }
return block, true return block, true

View File

@ -22,28 +22,34 @@ import (
"github.com/hajimehoshi/ebiten/internal/shaderir" "github.com/hajimehoshi/ebiten/internal/shaderir"
) )
func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variable) bool { func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variable) ([]shaderir.Stmt, bool) {
var stmts []shaderir.Stmt
switch stmt := stmt.(type) { switch stmt := stmt.(type) {
case *ast.AssignStmt: case *ast.AssignStmt:
switch stmt.Tok { switch stmt.Tok {
case token.DEFINE: case token.DEFINE:
if len(stmt.Lhs) != len(stmt.Rhs) && len(stmt.Rhs) != 1 { if len(stmt.Lhs) != len(stmt.Rhs) && len(stmt.Rhs) != 1 {
cs.addError(stmt.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed")) cs.addError(stmt.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
return false return nil, false
} }
if !cs.assign(block, stmt.Pos(), stmt.Lhs, stmt.Rhs, true) { ss, ok := cs.assign(block, stmt.Pos(), stmt.Lhs, stmt.Rhs, true)
return false if !ok {
return nil, false
} }
stmts = append(stmts, ss...)
case token.ASSIGN: case token.ASSIGN:
// TODO: What about the statement `a,b = b,a?` // TODO: What about the statement `a,b = b,a?`
if len(stmt.Lhs) != len(stmt.Rhs) && len(stmt.Rhs) != 1 { if len(stmt.Lhs) != len(stmt.Rhs) && len(stmt.Rhs) != 1 {
cs.addError(stmt.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed")) cs.addError(stmt.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
return false return nil, false
} }
if !cs.assign(block, stmt.Pos(), stmt.Lhs, stmt.Rhs, false) { ss, ok := cs.assign(block, stmt.Pos(), stmt.Lhs, stmt.Rhs, false)
return false if !ok {
return nil, false
} }
stmts = append(stmts, ss...)
case token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN: case token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN:
var op shaderir.Op var op shaderir.Op
switch stmt.Tok { switch stmt.Tok {
@ -58,17 +64,20 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
case token.REM_ASSIGN: case token.REM_ASSIGN:
op = shaderir.ModOp op = shaderir.ModOp
} }
rhs, _, stmts, ok := cs.parseExpr(block, stmt.Rhs[0])
rhs, _, ss, ok := cs.parseExpr(block, stmt.Rhs[0])
if !ok { if !ok {
return false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...) stmts = append(stmts, ss...)
lhs, _, stmts, ok := cs.parseExpr(block, stmt.Lhs[0])
lhs, _, ss, ok := cs.parseExpr(block, stmt.Lhs[0])
if !ok { if !ok {
return false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...) stmts = append(stmts, ss...)
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
stmts = append(stmts, shaderir.Stmt{
Type: shaderir.Assign, Type: shaderir.Assign,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{
lhs[0], lhs[0],
@ -88,9 +97,9 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
case *ast.BlockStmt: case *ast.BlockStmt:
b, ok := cs.parseBlock(block, stmt, nil, nil) b, ok := cs.parseBlock(block, stmt, nil, nil)
if !ok { if !ok {
return false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ stmts = append(stmts, shaderir.Stmt{
Type: shaderir.BlockStmt, Type: shaderir.BlockStmt,
Blocks: []shaderir.Block{ Blocks: []shaderir.Block{
b.ir, b.ir,
@ -98,15 +107,15 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
}) })
case *ast.DeclStmt: case *ast.DeclStmt:
if !cs.parseDecl(block, stmt.Decl) { if !cs.parseDecl(block, stmt.Decl) {
return false return nil, false
} }
case *ast.ReturnStmt: case *ast.ReturnStmt:
for i, r := range stmt.Results { for i, r := range stmt.Results {
exprs, _, stmts, ok := cs.parseExpr(block, r) exprs, _, ss, ok := cs.parseExpr(block, r)
if !ok { if !ok {
return false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...) stmts = append(stmts, ss...)
if len(exprs) == 0 { if len(exprs) == 0 {
continue continue
} }
@ -114,7 +123,7 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
cs.addError(r.Pos(), "multiple-context with return is not implemented yet") cs.addError(r.Pos(), "multiple-context with return is not implemented yet")
continue continue
} }
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ stmts = append(stmts, shaderir.Stmt{
Type: shaderir.Assign, Type: shaderir.Assign,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{
{ {
@ -125,43 +134,45 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab
}, },
}) })
} }
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ stmts = append(stmts, shaderir.Stmt{
Type: shaderir.Return, Type: shaderir.Return,
}) })
case *ast.ExprStmt: case *ast.ExprStmt:
exprs, _, stmts, ok := cs.parseExpr(block, stmt.X) exprs, _, ss, ok := cs.parseExpr(block, stmt.X)
if !ok { if !ok {
return false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...) stmts = append(stmts, ss...)
for _, expr := range exprs { for _, expr := range exprs {
if expr.Type != shaderir.Call { if expr.Type != shaderir.Call {
continue continue
} }
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ stmts = append(stmts, shaderir.Stmt{
Type: shaderir.ExprStmt, Type: shaderir.ExprStmt,
Exprs: []shaderir.Expr{expr}, Exprs: []shaderir.Expr{expr},
}) })
} }
default: default:
cs.addError(stmt.Pos(), fmt.Sprintf("unexpected statement: %#v", stmt)) cs.addError(stmt.Pos(), fmt.Sprintf("unexpected statement: %#v", stmt))
return false return nil, false
} }
return true return stmts, true
} }
func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr, define bool) bool { func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr, define bool) ([]shaderir.Stmt, bool) {
var stmts []shaderir.Stmt
var rhsExprs []shaderir.Expr var rhsExprs []shaderir.Expr
var rhsTypes []shaderir.Type var rhsTypes []shaderir.Type
for i, e := range lhs { for i, e := range lhs {
if len(lhs) == len(rhs) { if len(lhs) == len(rhs) {
// Prase RHS first for the order of the statements. // Prase RHS first for the order of the statements.
r, origts, stmts, ok := cs.parseExpr(block, rhs[i]) r, origts, ss, ok := cs.parseExpr(block, rhs[i])
if !ok { if !ok {
return false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...) stmts = append(stmts, ss...)
if define { if define {
v := variable{ v := variable{
@ -173,7 +184,7 @@ func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr,
} }
if len(ts) > 1 { if len(ts) > 1 {
cs.addError(pos, fmt.Sprintf("single-value context and multiple-value context cannot be mixed")) cs.addError(pos, fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
return false return nil, false
} }
if len(ts) == 1 { if len(ts) == 1 {
v.typ = ts[0] v.typ = ts[0]
@ -183,14 +194,14 @@ func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr,
if len(r) > 1 { if len(r) > 1 {
cs.addError(pos, fmt.Sprintf("single-value context and multiple-value context cannot be mixed")) cs.addError(pos, fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
return false return nil, false
} }
l, _, stmts, ok := cs.parseExpr(block, lhs[i]) l, _, ss, ok := cs.parseExpr(block, lhs[i])
if !ok { if !ok {
return false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...) stmts = append(stmts, ss...)
if r[0].Type == shaderir.NumberExpr { if r[0].Type == shaderir.NumberExpr {
switch block.vars[l[0].Index].typ.Main { switch block.vars[l[0].Index].typ.Main {
@ -201,22 +212,22 @@ func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr,
} }
} }
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ stmts = append(stmts, shaderir.Stmt{
Type: shaderir.Assign, Type: shaderir.Assign,
Exprs: []shaderir.Expr{l[0], r[0]}, Exprs: []shaderir.Expr{l[0], r[0]},
}) })
} else { } else {
if i == 0 { if i == 0 {
var stmts []shaderir.Stmt var ss []shaderir.Stmt
var ok bool var ok bool
rhsExprs, rhsTypes, stmts, ok = cs.parseExpr(block, rhs[0]) rhsExprs, rhsTypes, ss, ok = cs.parseExpr(block, rhs[0])
if !ok { if !ok {
return false return nil, false
} }
if len(rhsExprs) != len(lhs) { if len(rhsExprs) != len(lhs) {
cs.addError(pos, fmt.Sprintf("single-value context and multiple-value context cannot be mixed")) cs.addError(pos, fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...) stmts = append(stmts, ss...)
} }
if define { if define {
@ -227,17 +238,17 @@ func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr,
block.vars = append(block.vars, v) block.vars = append(block.vars, v)
} }
l, _, stmts, ok := cs.parseExpr(block, lhs[i]) l, _, ss, ok := cs.parseExpr(block, lhs[i])
if !ok { if !ok {
return false return nil, false
} }
block.ir.Stmts = append(block.ir.Stmts, stmts...) stmts = append(stmts, ss...)
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ stmts = append(stmts, shaderir.Stmt{
Type: shaderir.Assign, Type: shaderir.Assign,
Exprs: []shaderir.Expr{l[0], rhsExprs[i]}, Exprs: []shaderir.Expr{l[0], rhsExprs[i]},
}) })
} }
} }
return true return stmts, true
} }