shader: Implement assigning

This commit is contained in:
Hajime Hoshi 2020-06-10 22:25:40 +09:00
parent 04502aaaa8
commit 4a60c01f03
3 changed files with 72 additions and 48 deletions

View File

@ -570,57 +570,14 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out
block.vars = append(block.vars, v)
}
var rhsExprs []shaderir.Expr
for i := range l.Lhs {
// Prase RHS first for the order of the statements.
if len(l.Lhs) == len(l.Rhs) {
rhs, stmts := cs.parseExpr(block, l.Rhs[i])
if len(rhs) > 1 {
cs.addError(l.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
}
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{
Type: shaderir.Assign,
Exprs: []shaderir.Expr{lhs[0], rhs[0]},
})
} else {
if i == 0 {
var stmts []shaderir.Stmt
rhsExprs, stmts = cs.parseExpr(block, l.Rhs[0])
if len(rhsExprs) != len(l.Lhs) {
cs.addError(l.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
}
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{
Type: shaderir.Assign,
Exprs: []shaderir.Expr{lhs[0], rhsExprs[i]},
})
}
}
cs.assign(block, l.Pos(), l.Lhs, l.Rhs)
case token.ASSIGN:
// TODO: What about the statement `a,b = b,a?`
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...)
// TODO: Treat multiple expressions
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
Type: shaderir.Assign,
Exprs: []shaderir.Expr{lhs[0], rhs[0]},
})
if len(l.Lhs) != len(l.Rhs) && len(l.Rhs) != 1 {
cs.addError(l.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
return nil
}
cs.assign(block, l.Pos(), l.Lhs, l.Rhs)
}
case *ast.BlockStmt:
b := cs.parseBlock(block, l, nil, nil)
@ -677,6 +634,45 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out
return block
}
func (cs *compileState) assign(block *block, pos token.Pos, lhs, rhs []ast.Expr) {
var rhsExprs []shaderir.Expr
for i := range lhs {
// Prase RHS first for the order of the statements.
if len(lhs) == len(rhs) {
rhs, stmts := cs.parseExpr(block, rhs[i])
if len(rhs) > 1 {
cs.addError(pos, fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
}
block.ir.Stmts = append(block.ir.Stmts, stmts...)
lhs, stmts := cs.parseExpr(block, lhs[i])
block.ir.Stmts = append(block.ir.Stmts, stmts...)
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
Type: shaderir.Assign,
Exprs: []shaderir.Expr{lhs[0], rhs[0]},
})
} else {
if i == 0 {
var stmts []shaderir.Stmt
rhsExprs, stmts = cs.parseExpr(block, rhs[0])
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...)
}
lhs, stmts := cs.parseExpr(block, lhs[i])
block.ir.Stmts = append(block.ir.Stmts, stmts...)
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
Type: shaderir.Assign,
Exprs: []shaderir.Expr{lhs[0], rhsExprs[i]},
})
}
}
}
func (cs *compileState) parseExpr(block *block, expr ast.Expr) ([]shaderir.Expr, []shaderir.Stmt) {
switch e := expr.(type) {
case *ast.BasicLit:

View File

@ -0,0 +1,17 @@
void F0(in vec2 l0, out vec4 l1) {
float l2 = 0.0;
float l3 = 0.0;
float l4 = 0.0;
float l5 = 0.0;
F1(l4, l5);
l2 = l4;
l3 = l5;
l1 = vec4(l0, l2, l2);
return;
}
void F1(out float l0, out float l1) {
l0 = 0.0;
l1 = 0.0;
return;
}

View File

@ -0,0 +1,11 @@
package main
func Foo(foo vec2) vec4 {
var r1, r2 float
r1, r2 = Bar()
return vec4(foo, r1, r1)
}
func Bar() (float, float) {
return 0, 0
}