shader: Implment defining variables in multiple-value context

This commit is contained in:
Hajime Hoshi 2020-06-08 11:57:54 +09:00
parent 75706504bf
commit 91fb8e92d8
4 changed files with 93 additions and 13 deletions

View File

@ -542,28 +542,69 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out
case *ast.AssignStmt:
switch l.Tok {
case token.DEFINE:
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
}
var rhsTypes []shaderir.Type
for i, e := range l.Lhs {
v := variable{
name: e.(*ast.Ident).Name,
}
ts := cs.detectType(block, l.Rhs[i])
if len(ts) > 1 {
cs.addError(l.Pos(), fmt.Sprintf("the numbers of lhs and rhs don't match"))
if len(l.Lhs) == len(l.Rhs) {
ts := cs.detectType(block, l.Rhs[i])
if len(ts) > 1 {
cs.addError(l.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
}
v.typ = ts[0]
} else {
if i == 0 {
rhsTypes = cs.detectType(block, l.Rhs[0])
if len(rhsTypes) != len(l.Lhs) {
cs.addError(l.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed"))
}
}
v.typ = rhsTypes[i]
}
v.typ = ts[0]
block.vars = append(block.vars, v)
}
var rhsExprs []shaderir.Expr
for i := range l.Lhs {
// 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...)
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...)
// TODO: Treat multiple expressions
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
Type: shaderir.Assign,
Exprs: []shaderir.Expr{lhs[0], rhs[0]},
})
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]},
})
}
}
case token.ASSIGN:
// TODO: What about the statement `a,b = b,a?`

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,10 @@
package main
func Foo(foo vec2) vec4 {
r1, r2 := Bar()
return vec4(foo, r1, r1)
}
func Bar() (float, float) {
return 0, 0
}

View File

@ -89,7 +89,19 @@ func (cs *compileState) detectType(b *block, expr ast.Expr) []shaderir.Type {
return []shaderir.Type{{Main: shaderir.Mat3}}
case shaderir.Mat4F:
return []shaderir.Type{{Main: shaderir.Mat4}}
default:
// TODO: Add more functions
cs.addError(expr.Pos(), fmt.Sprintf("detecting types is not implemented for: %s", n))
}
}
for _, f := range cs.funcs {
if f.name == n {
// TODO: Is it correct to combine out-params and return param?
ts := f.ir.OutParams
if f.ir.Return.Main != shaderir.None {
ts = append(ts, f.ir.Return)
}
return ts
}
}
cs.addError(expr.Pos(), fmt.Sprintf("unexpected call: %s", n))