mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
internal/shader: refactoring
This commit is contained in:
parent
0657e67cef
commit
5a1109e56a
@ -34,22 +34,6 @@ func canTruncateToFloat(v gconstant.Value) bool {
|
|||||||
return gconstant.ToFloat(v).Kind() != gconstant.Unknown
|
return gconstant.ToFloat(v).Kind() != gconstant.Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
func isModAvailableForConsts(lhs, rhs *shaderir.Expr) bool {
|
|
||||||
// % is available only when
|
|
||||||
// 1) both are untyped (constant) integers
|
|
||||||
// 2) either is an typed integer and the other is truncatable to an integer
|
|
||||||
if lhs.Const.Kind() == gconstant.Int && rhs.Const.Kind() == gconstant.Int {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if lhs.Const.Kind() == gconstant.Int && canTruncateToInteger(rhs.Const) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if rhs.Const.Kind() == gconstant.Int && canTruncateToInteger(lhs.Const) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isValidForModOp(lhs, rhs *shaderir.Expr, lhst, rhst shaderir.Type) bool {
|
func isValidForModOp(lhs, rhs *shaderir.Expr, lhst, rhst shaderir.Type) bool {
|
||||||
isInt := func(s *shaderir.Expr, t shaderir.Type) bool {
|
isInt := func(s *shaderir.Expr, t shaderir.Type) bool {
|
||||||
if t.Main == shaderir.Int {
|
if t.Main == shaderir.Int {
|
||||||
@ -78,22 +62,6 @@ func isValidForModOp(lhs, rhs *shaderir.Expr, lhst, rhst shaderir.Type) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func goConstantKindString(k gconstant.Kind) string {
|
|
||||||
switch k {
|
|
||||||
case gconstant.Bool:
|
|
||||||
return "bool"
|
|
||||||
case gconstant.String:
|
|
||||||
return "string"
|
|
||||||
case gconstant.Int:
|
|
||||||
return "int"
|
|
||||||
case gconstant.Float:
|
|
||||||
return "float"
|
|
||||||
case gconstant.Complex:
|
|
||||||
return "complex"
|
|
||||||
}
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
var textureVariableRe = regexp.MustCompile(`\A__t(\d+)\z`)
|
var textureVariableRe = regexp.MustCompile(`\A__t(\d+)\z`)
|
||||||
|
|
||||||
func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, markLocalVariableUsed bool) ([]shaderir.Expr, []shaderir.Type, []shaderir.Stmt, bool) {
|
func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, markLocalVariableUsed bool) ([]shaderir.Expr, []shaderir.Type, []shaderir.Stmt, bool) {
|
||||||
@ -161,14 +129,16 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
|
|||||||
}
|
}
|
||||||
|
|
||||||
if lhs[0].Const != nil && rhs[0].Const != nil {
|
if lhs[0].Const != nil && rhs[0].Const != nil {
|
||||||
|
if !shaderir.AreValidTypesForBinaryOp(op2, &lhs[0], &rhs[0], lhst, rhst) {
|
||||||
|
// TODO: Show a better type name for untyped constants.
|
||||||
|
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), op, rhst.String()))
|
||||||
|
return nil, nil, nil, false
|
||||||
|
}
|
||||||
|
|
||||||
var v gconstant.Value
|
var v gconstant.Value
|
||||||
var t shaderir.Type
|
var t shaderir.Type
|
||||||
switch op {
|
switch op {
|
||||||
case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ, token.LAND, token.LOR:
|
case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ, token.LAND, token.LOR:
|
||||||
if !shaderir.AreValidTypesForBinaryOp(op2, &lhs[0], &rhs[0], lhst, rhst) {
|
|
||||||
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), op, rhst.String()))
|
|
||||||
return nil, nil, nil, false
|
|
||||||
}
|
|
||||||
switch op {
|
switch op {
|
||||||
case token.LAND, token.LOR:
|
case token.LAND, token.LOR:
|
||||||
b := gconstant.BoolVal(gconstant.BinaryOp(lhs[0].Const, op, rhs[0].Const))
|
b := gconstant.BoolVal(gconstant.BinaryOp(lhs[0].Const, op, rhs[0].Const))
|
||||||
@ -178,16 +148,6 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
|
|||||||
}
|
}
|
||||||
t = shaderir.Type{Main: shaderir.Bool}
|
t = shaderir.Type{Main: shaderir.Bool}
|
||||||
case token.REM:
|
case token.REM:
|
||||||
if !isModAvailableForConsts(&lhs[0], &rhs[0]) {
|
|
||||||
var wrongTypeName string
|
|
||||||
if lhs[0].Const.Kind() != gconstant.Int {
|
|
||||||
wrongTypeName = goConstantKindString(lhs[0].Const.Kind())
|
|
||||||
} else {
|
|
||||||
wrongTypeName = goConstantKindString(rhs[0].Const.Kind())
|
|
||||||
}
|
|
||||||
cs.addError(e.Pos(), fmt.Sprintf("invalid operation: operator %% not defined on untyped %s", wrongTypeName))
|
|
||||||
return nil, nil, nil, false
|
|
||||||
}
|
|
||||||
if !cs.forceToInt(e, &lhs[0]) {
|
if !cs.forceToInt(e, &lhs[0]) {
|
||||||
return nil, nil, nil, false
|
return nil, nil, nil, false
|
||||||
}
|
}
|
||||||
@ -196,11 +156,6 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
|
|||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
if !shaderir.AreValidTypesForBinaryOp(op2, &lhs[0], &rhs[0], lhst, rhst) {
|
|
||||||
cs.addError(e.Pos(), fmt.Sprintf("types don't match: %s %s %s", lhst.String(), op, rhst.String()))
|
|
||||||
return nil, nil, nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
v = gconstant.BinaryOp(lhs[0].Const, op, rhs[0].Const)
|
v = gconstant.BinaryOp(lhs[0].Const, op, rhs[0].Const)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -36,6 +36,10 @@ func AreValidTypesForBinaryOp(op Op, lhs, rhs *Expr, lhst, rhst Type) bool {
|
|||||||
|
|
||||||
// If both are untyped consts, compare the constants and try to truncate them if necessary.
|
// If both are untyped consts, compare the constants and try to truncate them if necessary.
|
||||||
if lhst.Main == None && rhst.Main == None {
|
if lhst.Main == None && rhst.Main == None {
|
||||||
|
// For %, both operands must be integers if both are constants. Truncatable to an integer is not enough.
|
||||||
|
if op == ModOp {
|
||||||
|
return lhs.Const.Kind() == constant.Int && rhs.Const.Kind() == constant.Int
|
||||||
|
}
|
||||||
if lhs.Const.Kind() == rhs.Const.Kind() {
|
if lhs.Const.Kind() == rhs.Const.Kind() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -61,6 +65,10 @@ func AreValidTypesForBinaryOp(op Op, lhs, rhs *Expr, lhst, rhst Type) bool {
|
|||||||
|
|
||||||
// If lhs is untyped and rhs is not, compare the constant and the type and try to truncate the constant if necessary.
|
// If lhs is untyped and rhs is not, compare the constant and the type and try to truncate the constant if necessary.
|
||||||
if lhst.Main == None {
|
if lhst.Main == None {
|
||||||
|
// For %, if only one of the operands is a constant, try to truncate it.
|
||||||
|
if op == ModOp {
|
||||||
|
return constant.ToInt(lhs.Const).Kind() != constant.Unknown && rhst.Main == Int
|
||||||
|
}
|
||||||
if rhst.Main == Float {
|
if rhst.Main == Float {
|
||||||
return constant.ToFloat(lhs.Const).Kind() != constant.Unknown
|
return constant.ToFloat(lhs.Const).Kind() != constant.Unknown
|
||||||
}
|
}
|
||||||
@ -75,6 +83,9 @@ func AreValidTypesForBinaryOp(op Op, lhs, rhs *Expr, lhst, rhst Type) bool {
|
|||||||
|
|
||||||
// Ditto.
|
// Ditto.
|
||||||
if rhst.Main == None {
|
if rhst.Main == None {
|
||||||
|
if op == ModOp {
|
||||||
|
return constant.ToInt(rhs.Const).Kind() != constant.Unknown && lhst.Main == Int
|
||||||
|
}
|
||||||
if lhst.Main == Float {
|
if lhst.Main == Float {
|
||||||
return constant.ToFloat(rhs.Const).Kind() != constant.Unknown
|
return constant.ToFloat(rhs.Const).Kind() != constant.Unknown
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user