From 3ca6e411945c5bdb0d547f2a6cb17510dadae309 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 5 Jul 2020 00:03:21 +0900 Subject: [PATCH] shader: Refactoring: Add statements later --- internal/shader/shader.go | 4 +- internal/shader/stmt.go | 105 +++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 48 deletions(-) diff --git a/internal/shader/shader.go b/internal/shader/shader.go index a8403a347..92064e23e 100644 --- a/internal/shader/shader.go +++ b/internal/shader/shader.go @@ -621,9 +621,11 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out }() for _, l := range b.List { - if !cs.parseStmt(block, l, inParams) { + stmts, ok := cs.parseStmt(block, l, inParams) + if !ok { return nil, false } + block.ir.Stmts = append(block.ir.Stmts, stmts...) } return block, true diff --git a/internal/shader/stmt.go b/internal/shader/stmt.go index 73b9f279d..ab8eb6c42 100644 --- a/internal/shader/stmt.go +++ b/internal/shader/stmt.go @@ -22,28 +22,34 @@ import ( "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) { case *ast.AssignStmt: switch stmt.Tok { case token.DEFINE: 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")) - return false + return nil, false } - if !cs.assign(block, stmt.Pos(), stmt.Lhs, stmt.Rhs, true) { - return false + ss, ok := cs.assign(block, stmt.Pos(), stmt.Lhs, stmt.Rhs, true) + if !ok { + return nil, false } + stmts = append(stmts, ss...) case token.ASSIGN: // TODO: What about the statement `a,b = b,a?` 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")) - return false + return nil, false } - if !cs.assign(block, stmt.Pos(), stmt.Lhs, stmt.Rhs, false) { - return false + ss, ok := cs.assign(block, stmt.Pos(), stmt.Lhs, stmt.Rhs, 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: var op shaderir.Op switch stmt.Tok { @@ -58,17 +64,20 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab case token.REM_ASSIGN: op = shaderir.ModOp } - rhs, _, stmts, ok := cs.parseExpr(block, stmt.Rhs[0]) + + rhs, _, ss, ok := cs.parseExpr(block, stmt.Rhs[0]) if !ok { - return false + return nil, false } - block.ir.Stmts = append(block.ir.Stmts, stmts...) - lhs, _, stmts, ok := cs.parseExpr(block, stmt.Lhs[0]) + stmts = append(stmts, ss...) + + lhs, _, ss, ok := cs.parseExpr(block, stmt.Lhs[0]) if !ok { - return false + return nil, false } - block.ir.Stmts = append(block.ir.Stmts, stmts...) - block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ + stmts = append(stmts, ss...) + + stmts = append(stmts, shaderir.Stmt{ Type: shaderir.Assign, Exprs: []shaderir.Expr{ lhs[0], @@ -88,9 +97,9 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab case *ast.BlockStmt: b, ok := cs.parseBlock(block, stmt, nil, nil) if !ok { - return false + return nil, false } - block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ + stmts = append(stmts, shaderir.Stmt{ Type: shaderir.BlockStmt, Blocks: []shaderir.Block{ b.ir, @@ -98,15 +107,15 @@ func (cs *compileState) parseStmt(block *block, stmt ast.Stmt, inParams []variab }) case *ast.DeclStmt: if !cs.parseDecl(block, stmt.Decl) { - return false + return nil, false } case *ast.ReturnStmt: for i, r := range stmt.Results { - exprs, _, stmts, ok := cs.parseExpr(block, r) + exprs, _, ss, ok := cs.parseExpr(block, r) if !ok { - return false + return nil, false } - block.ir.Stmts = append(block.ir.Stmts, stmts...) + stmts = append(stmts, ss...) if len(exprs) == 0 { 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") continue } - block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ + stmts = append(stmts, shaderir.Stmt{ Type: shaderir.Assign, 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, }) case *ast.ExprStmt: - exprs, _, stmts, ok := cs.parseExpr(block, stmt.X) + exprs, _, ss, ok := cs.parseExpr(block, stmt.X) if !ok { - return false + return nil, false } - block.ir.Stmts = append(block.ir.Stmts, stmts...) + stmts = append(stmts, ss...) + for _, expr := range exprs { if expr.Type != shaderir.Call { continue } - block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ + stmts = append(stmts, shaderir.Stmt{ Type: shaderir.ExprStmt, Exprs: []shaderir.Expr{expr}, }) } default: 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 rhsTypes []shaderir.Type for i, e := range lhs { if len(lhs) == len(rhs) { // 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 { - return false + return nil, false } - block.ir.Stmts = append(block.ir.Stmts, stmts...) + stmts = append(stmts, ss...) if define { v := variable{ @@ -173,7 +184,7 @@ func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr, } if len(ts) > 1 { cs.addError(pos, fmt.Sprintf("single-value context and multiple-value context cannot be mixed")) - return false + return nil, false } if len(ts) == 1 { 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 { 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 { - return false + return nil, false } - block.ir.Stmts = append(block.ir.Stmts, stmts...) + stmts = append(stmts, ss...) if r[0].Type == shaderir.NumberExpr { 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, Exprs: []shaderir.Expr{l[0], r[0]}, }) } else { if i == 0 { - var stmts []shaderir.Stmt + var ss []shaderir.Stmt var ok bool - rhsExprs, rhsTypes, stmts, ok = cs.parseExpr(block, rhs[0]) + rhsExprs, rhsTypes, ss, ok = cs.parseExpr(block, rhs[0]) if !ok { - return false + return nil, false } if len(rhsExprs) != len(lhs) { 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 { @@ -227,17 +238,17 @@ func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr, block.vars = append(block.vars, v) } - l, _, stmts, ok := cs.parseExpr(block, lhs[i]) + l, _, ss, ok := cs.parseExpr(block, lhs[i]) 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, Exprs: []shaderir.Expr{l[0], rhsExprs[i]}, }) } } - return true + return stmts, true }