The buge (#47) is vanquished!!!!
This commit is contained in:
parent
81c4f1e46b
commit
e2d944d534
|
@ -417,6 +417,14 @@ func (this *Tree) analyzeOperation (
|
|||
err := this.typeRestricted(operation.Position, into)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
intoUntrustworthy := into == nil || mode == force || mode == coerce
|
||||
|
||||
undefined := func (ty entity.Type) (entity.Expression, error) {
|
||||
return nil, errors.Errorf (
|
||||
operation.Position, "operator %v undefined for %v",
|
||||
operation.Operator, entity.FormatType(ty))
|
||||
}
|
||||
|
||||
wrongInto := func () (entity.Expression, error) {
|
||||
return nil, errors.Errorf (
|
||||
operation.Position, "expected %v",
|
||||
|
@ -428,6 +436,28 @@ func (this *Tree) analyzeOperation (
|
|||
operation.Position, "wrong argument count for %v",
|
||||
operation.Operator)
|
||||
}
|
||||
|
||||
determineArgumentType := func () (entity.Type, int, error) {
|
||||
// find the first argument that has explicit type information.
|
||||
boss := -1
|
||||
var argumentType entity.Type
|
||||
for index, argument := range operation.Arguments {
|
||||
if argument.HasExplicitType() {
|
||||
argument, err := this.analyzeExpression(nil, strict, argument)
|
||||
if err != nil { return nil, -1, err }
|
||||
boss = index
|
||||
operation.Arguments[index] = argument
|
||||
argumentType = argument.Type()
|
||||
break
|
||||
}
|
||||
}
|
||||
if argumentType == nil {
|
||||
return nil, -1, errors.Errorf (
|
||||
operation.Position,
|
||||
"operation arguments have ambiguous type")
|
||||
}
|
||||
return argumentType, boss, err
|
||||
}
|
||||
|
||||
nSameType := func (n int, constraint func (entity.Type) bool) (entity.Expression, error) {
|
||||
if n > 0 {
|
||||
|
@ -436,17 +466,29 @@ func (this *Tree) analyzeOperation (
|
|||
if len(operation.Arguments) < 1 { return wrongArgCount() }
|
||||
}
|
||||
n = len(operation.Arguments)
|
||||
if !constraint(into) { return wrongInto() }
|
||||
|
||||
left, err := this.analyzeExpression(into, mode, operation.Arguments[0])
|
||||
if err != nil { return nil, err }
|
||||
operation.Arguments[0] = left
|
||||
operation.Ty = left.Type()
|
||||
boss := -1
|
||||
var argumentType entity.Type
|
||||
if intoUntrustworthy {
|
||||
// determine the type of all arguments (and the return
|
||||
// type) using determineArgumentType
|
||||
var err error
|
||||
argumentType, boss, err = determineArgumentType()
|
||||
if err != nil { return nil, err }
|
||||
if !constraint(argumentType) { return undefined(argumentType) }
|
||||
} else {
|
||||
// into is trustworthy, so we don't need to determine
|
||||
// anything
|
||||
argumentType = into
|
||||
}
|
||||
if !constraint(argumentType) { return undefined(argumentType) }
|
||||
operation.Ty = argumentType
|
||||
|
||||
for index := 1; index < n; index ++ {
|
||||
for index, argument := range operation.Arguments {
|
||||
if index == boss { continue }
|
||||
argument, err := this.analyzeExpression (
|
||||
left.Type(), strict,
|
||||
operation.Arguments[index])
|
||||
operation.Ty, strict,
|
||||
argument)
|
||||
if err != nil { return nil, err }
|
||||
operation.Arguments[index] = argument
|
||||
}
|
||||
|
@ -455,41 +497,21 @@ func (this *Tree) analyzeOperation (
|
|||
}
|
||||
|
||||
comparison := func (argConstraint func (entity.Type) bool) (entity.Expression, error) {
|
||||
if len(operation.Arguments) < 2 { return wrongArgCount() }
|
||||
if !isBoolean(into) { return wrongInto() }
|
||||
operation.Ty = builtinType("Bool")
|
||||
if len(operation.Arguments) < 2 { return wrongArgCount() }
|
||||
if !isBoolean(into) && !intoUntrustworthy { return wrongInto() }
|
||||
operation.Ty = builtinType("Bool")
|
||||
|
||||
// find the first argument that has explicit type information.
|
||||
// TODO: possibly make a method of expressions to check this
|
||||
// without analyzing anything
|
||||
boss := -1
|
||||
var argumentType entity.Type
|
||||
for index, argument := range operation.Arguments {
|
||||
argument, err := this.analyzeExpression(nil, strict, argument)
|
||||
if err == nil {
|
||||
boss = index
|
||||
operation.Arguments[index] = argument
|
||||
argumentType = argument.Type()
|
||||
break
|
||||
}
|
||||
}
|
||||
if argumentType == nil {
|
||||
return nil, errors.Errorf (
|
||||
operation.Position,
|
||||
"operation arguments have ambiguous type")
|
||||
}
|
||||
// determine argument type
|
||||
argumentType, boss, err := determineArgumentType()
|
||||
if err != nil { return nil, err }
|
||||
if !argConstraint(argumentType) { return undefined(argumentType) }
|
||||
|
||||
// analyze all remaining arguments
|
||||
for index, argument := range operation.Arguments {
|
||||
if index == boss { continue }
|
||||
|
||||
argument, err := this.analyzeExpression (
|
||||
argumentType, strict, argument)
|
||||
if err != nil {
|
||||
boss = index
|
||||
operation.Arguments[index] = argument
|
||||
break
|
||||
}
|
||||
if err != nil { return nil, err }
|
||||
operation.Arguments[index] = argument
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue