internal/shader: refactoring

This commit is contained in:
Hajime Hoshi 2023-07-24 02:06:54 +09:00
parent 0657e67cef
commit 5a1109e56a
2 changed files with 17 additions and 51 deletions

View File

@ -34,22 +34,6 @@ func canTruncateToFloat(v gconstant.Value) bool {
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 {
isInt := func(s *shaderir.Expr, t shaderir.Type) bool {
if t.Main == shaderir.Int {
@ -78,22 +62,6 @@ func isValidForModOp(lhs, rhs *shaderir.Expr, lhst, rhst shaderir.Type) bool {
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`)
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 !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 t shaderir.Type
switch op {
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 {
case token.LAND, token.LOR:
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}
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]) {
return nil, nil, nil, false
}
@ -196,11 +156,6 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar
}
fallthrough
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)
switch {

View File

@ -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 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() {
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 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 {
return constant.ToFloat(lhs.Const).Kind() != constant.Unknown
}
@ -75,6 +83,9 @@ func AreValidTypesForBinaryOp(op Op, lhs, rhs *Expr, lhst, rhst Type) bool {
// Ditto.
if rhst.Main == None {
if op == ModOp {
return constant.ToInt(rhs.Const).Kind() != constant.Unknown && lhst.Main == Int
}
if lhst.Main == Float {
return constant.ToFloat(rhs.Const).Kind() != constant.Unknown
}