mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 19:58:54 +01:00
shader: Parse function bodies
This commit is contained in:
parent
91e5dde320
commit
afd114e606
@ -19,6 +19,7 @@ import (
|
|||||||
"go/ast"
|
"go/ast"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/shaderir"
|
"github.com/hajimehoshi/ebiten/internal/shaderir"
|
||||||
@ -38,8 +39,6 @@ type constant struct {
|
|||||||
|
|
||||||
type function struct {
|
type function struct {
|
||||||
name string
|
name string
|
||||||
in []string
|
|
||||||
out []string
|
|
||||||
block *block
|
block *block
|
||||||
|
|
||||||
ir shaderir.Func
|
ir shaderir.Func
|
||||||
@ -218,39 +217,46 @@ func (cs *compileState) parseFunc(d *ast.FuncDecl, block *block) function {
|
|||||||
return function{}
|
return function{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var in []string
|
var vars []variable
|
||||||
|
|
||||||
var inT []shaderir.Type
|
var inT []shaderir.Type
|
||||||
for _, f := range d.Type.Params.List {
|
for _, f := range d.Type.Params.List {
|
||||||
t := cs.parseType(f.Type)
|
t := cs.parseType(f.Type)
|
||||||
for _, n := range f.Names {
|
for _, n := range f.Names {
|
||||||
in = append(in, n.Name)
|
vars = append(vars, variable{
|
||||||
|
name: n.Name,
|
||||||
|
typ: t,
|
||||||
|
})
|
||||||
inT = append(inT, t.ir)
|
inT = append(inT, t.ir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var out []string
|
|
||||||
var outT []shaderir.Type
|
var outT []shaderir.Type
|
||||||
if d.Type.Results != nil {
|
if d.Type.Results != nil {
|
||||||
for _, f := range d.Type.Results.List {
|
for _, f := range d.Type.Results.List {
|
||||||
t := cs.parseType(f.Type)
|
t := cs.parseType(f.Type)
|
||||||
if len(f.Names) == 0 {
|
if len(f.Names) == 0 {
|
||||||
out = append(out, "")
|
vars = append(vars, variable{
|
||||||
|
name: "",
|
||||||
|
typ: t,
|
||||||
|
})
|
||||||
outT = append(outT, t.ir)
|
outT = append(outT, t.ir)
|
||||||
} else {
|
} else {
|
||||||
for _, n := range f.Names {
|
for _, n := range f.Names {
|
||||||
out = append(out, n.Name)
|
vars = append(vars, variable{
|
||||||
|
name: n.Name,
|
||||||
|
typ: t,
|
||||||
|
})
|
||||||
outT = append(outT, t.ir)
|
outT = append(outT, t.ir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b := cs.parseBlock(block, d.Body)
|
b := cs.parseBlock(block, d.Body, vars)
|
||||||
|
|
||||||
return function{
|
return function{
|
||||||
name: d.Name.Name,
|
name: d.Name.Name,
|
||||||
in: in,
|
|
||||||
out: out,
|
|
||||||
block: b,
|
block: b,
|
||||||
ir: shaderir.Func{
|
ir: shaderir.Func{
|
||||||
Index: len(cs.ir.Funcs),
|
Index: len(cs.ir.Funcs),
|
||||||
@ -261,8 +267,9 @@ func (cs *compileState) parseFunc(d *ast.FuncDecl, block *block) function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt) *block {
|
func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, locals []variable) *block {
|
||||||
block := &block{
|
block := &block{
|
||||||
|
vars: locals,
|
||||||
outer: outer,
|
outer: outer,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +311,7 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt) *block {
|
|||||||
cs.parseDecl(block, l.Decl, false)
|
cs.parseDecl(block, l.Decl, false)
|
||||||
case *ast.ReturnStmt:
|
case *ast.ReturnStmt:
|
||||||
for _, r := range l.Results {
|
for _, r := range l.Results {
|
||||||
e := cs.parseExpr(r)
|
e := cs.parseExpr(block, r)
|
||||||
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{
|
||||||
@ -369,22 +376,74 @@ func (s *compileState) detectType(b *block, expr ast.Expr) typ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *compileState) parseExpr(expr ast.Expr) shaderir.Expr {
|
func (b *block) findLocalVariable(name string) (int, bool) {
|
||||||
switch e := expr.(type) {
|
for i, v := range b.vars {
|
||||||
case *ast.CallExpr:
|
if v.name == name {
|
||||||
return shaderir.Expr{
|
return i, true
|
||||||
Type: shaderir.Call,
|
}
|
||||||
Exprs: []shaderir.Expr{
|
}
|
||||||
cs.parseExpr(e.Fun),
|
if b.outer != nil {
|
||||||
},
|
return b.outer.findLocalVariable(name)
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *compileState) parseExpr(block *block, expr ast.Expr) shaderir.Expr {
|
||||||
|
switch e := expr.(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
switch e.Kind {
|
||||||
|
case token.INT:
|
||||||
|
v, err := strconv.ParseInt(e.Value, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("unexpected literal: %s", e.Value))
|
||||||
|
return shaderir.Expr{}
|
||||||
}
|
}
|
||||||
case *ast.Ident:
|
|
||||||
return shaderir.Expr{
|
return shaderir.Expr{
|
||||||
Type: shaderir.BuiltinFuncExpr,
|
Type: shaderir.IntExpr,
|
||||||
BuiltinFunc: shaderir.BuiltinFunc(e.Name),
|
Int: int32(v),
|
||||||
|
}
|
||||||
|
case token.FLOAT:
|
||||||
|
v, err := strconv.ParseFloat(e.Value, 32)
|
||||||
|
if err != nil {
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("unexpected literal: %s", e.Value))
|
||||||
|
return shaderir.Expr{}
|
||||||
|
}
|
||||||
|
return shaderir.Expr{
|
||||||
|
Type: shaderir.FloatExpr,
|
||||||
|
Float: float32(v),
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
cs.addError(expr.Pos(), fmt.Sprintf("detecting expression not implemented: %#v", e))
|
cs.addError(e.Pos(), fmt.Sprintf("literal not implemented: %#v", e))
|
||||||
|
}
|
||||||
|
case *ast.CallExpr:
|
||||||
|
exprs := []shaderir.Expr{
|
||||||
|
cs.parseExpr(block, e.Fun),
|
||||||
|
}
|
||||||
|
for _, a := range e.Args {
|
||||||
|
exprs = append(exprs, cs.parseExpr(block, a))
|
||||||
|
}
|
||||||
|
return shaderir.Expr{
|
||||||
|
Type: shaderir.Call,
|
||||||
|
Exprs: exprs,
|
||||||
|
}
|
||||||
|
case *ast.Ident:
|
||||||
|
i, ok := block.findLocalVariable(e.Name)
|
||||||
|
if ok {
|
||||||
|
return shaderir.Expr{
|
||||||
|
Type: shaderir.LocalVariable,
|
||||||
|
Index: i,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f, ok := shaderir.ParseBuiltinFunc(e.Name)
|
||||||
|
if ok {
|
||||||
|
return shaderir.Expr{
|
||||||
|
Type: shaderir.BuiltinFuncExpr,
|
||||||
|
BuiltinFunc: f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("unexpected identifier: %s", e.Name))
|
||||||
|
default:
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("expression not implemented: %#v", e))
|
||||||
}
|
}
|
||||||
return shaderir.Expr{}
|
return shaderir.Expr{}
|
||||||
}
|
}
|
||||||
|
@ -192,3 +192,63 @@ const (
|
|||||||
Not BuiltinFunc = "not"
|
Not BuiltinFunc = "not"
|
||||||
Texture2DF BuiltinFunc = "texture2D"
|
Texture2DF BuiltinFunc = "texture2D"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ParseBuiltinFunc(str string) (BuiltinFunc, bool) {
|
||||||
|
switch BuiltinFunc(str) {
|
||||||
|
case Vec2F,
|
||||||
|
Vec3F,
|
||||||
|
Vec4F,
|
||||||
|
Mat2F,
|
||||||
|
Mat3F,
|
||||||
|
Mat4F,
|
||||||
|
Radians,
|
||||||
|
Degrees,
|
||||||
|
Sin,
|
||||||
|
Cos,
|
||||||
|
Tan,
|
||||||
|
Asin,
|
||||||
|
Acos,
|
||||||
|
Atan,
|
||||||
|
Pow,
|
||||||
|
Exp,
|
||||||
|
Log,
|
||||||
|
Exp2,
|
||||||
|
Log2,
|
||||||
|
Sqrt,
|
||||||
|
Inversesqrt,
|
||||||
|
Abs,
|
||||||
|
Sign,
|
||||||
|
Floor,
|
||||||
|
Ceil,
|
||||||
|
Fract,
|
||||||
|
Mod,
|
||||||
|
Min,
|
||||||
|
Max,
|
||||||
|
Clamp,
|
||||||
|
Mix,
|
||||||
|
Step,
|
||||||
|
Smoothstep,
|
||||||
|
Length,
|
||||||
|
Distance,
|
||||||
|
Dot,
|
||||||
|
Cross,
|
||||||
|
Normalize,
|
||||||
|
Faceforward,
|
||||||
|
Reflect,
|
||||||
|
MatrixCompMult,
|
||||||
|
OuterProduct,
|
||||||
|
Transpose,
|
||||||
|
LessThan,
|
||||||
|
LessThanEqual,
|
||||||
|
GreaterThan,
|
||||||
|
GreaterThanEqual,
|
||||||
|
Equal,
|
||||||
|
NotEqual,
|
||||||
|
Any,
|
||||||
|
All,
|
||||||
|
Not,
|
||||||
|
Texture2DF:
|
||||||
|
return BuiltinFunc(str), true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user