Pass all analyzer tests
This commit is contained in:
parent
47beb9e41f
commit
605fd24228
|
@ -103,8 +103,7 @@ func (this *Tree) canAssign (
|
|||
*entity.TypeStruct,
|
||||
*entity.TypeInt,
|
||||
*entity.TypeFloat,
|
||||
*entity.TypeWord,
|
||||
*entity.TypeBool:
|
||||
*entity.TypeWord:
|
||||
|
||||
if !destination.Equals(source) {
|
||||
return fail()
|
||||
|
@ -138,14 +137,14 @@ func (this *Tree) canAssignCoerce (
|
|||
// base type
|
||||
case *entity.TypeInt,
|
||||
*entity.TypeFloat,
|
||||
*entity.TypeWord,
|
||||
*entity.TypeBool:
|
||||
*entity.TypeWord:
|
||||
switch source.(type) {
|
||||
case *entity.TypeInt,
|
||||
*entity.TypeFloat,
|
||||
*entity.TypeWord,
|
||||
*entity.TypeBool: return nil
|
||||
default: return fail()
|
||||
*entity.TypeWord:
|
||||
return nil
|
||||
default:
|
||||
return fail()
|
||||
}
|
||||
|
||||
case *entity.TypePointer,
|
||||
|
@ -271,8 +270,7 @@ func (this *Tree) areStructurallyEquivalent (left, right entity.Type) bool {
|
|||
// terminals
|
||||
case *entity.TypeInt,
|
||||
*entity.TypeFloat,
|
||||
*entity.TypeWord,
|
||||
*entity.TypeBool:
|
||||
*entity.TypeWord:
|
||||
return left.Equals(right)
|
||||
|
||||
default: panic(fmt.Sprint("BUG: analyzer doesnt know about type ", left))
|
||||
|
@ -390,9 +388,10 @@ func (this *Tree) isOrdered (ty entity.Type) bool {
|
|||
|
||||
// isBoolean returns whether or not the specified type is a boolean.
|
||||
func (this *Tree) isBoolean (ty entity.Type) bool {
|
||||
switch this.reduceToBase(ty).(type) {
|
||||
case *entity.TypeBool: return true
|
||||
default: return false
|
||||
for {
|
||||
named, ok := ty.(*entity.TypeNamed)
|
||||
if !ok { return false }
|
||||
if named.Name == "Bool" { return true }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -354,7 +354,10 @@ func (this *Tree) analyzeOperation (
|
|||
comparison := func (argConstraint func (entity.Type) bool) (entity.Expression, error) {
|
||||
if len(operation.Arguments) < 2 { return wrongArgCount() }
|
||||
if !this.isBoolean(into) { return wrongInto() }
|
||||
operation.Ty = &entity.TypeBool { }
|
||||
operation.Ty = &entity.TypeNamed {
|
||||
Name: "Bool",
|
||||
Type: this.Types["Bool"].Type,
|
||||
}
|
||||
|
||||
// find the first argument that has explicit type information.
|
||||
// TODO: possibly make a method of expressions to check this
|
||||
|
@ -413,14 +416,14 @@ func (this *Tree) analyzeOperation (
|
|||
case entity.OperatorLogicalOr,
|
||||
entity.OperatorLogicalAnd,
|
||||
entity.OperatorLogicalXor:
|
||||
return nSameType(2, this.isBoolean)
|
||||
return nSameType(-1, this.isBoolean)
|
||||
|
||||
// bit manipulation
|
||||
case entity.OperatorNot:
|
||||
return nSameType(1, this.isInteger)
|
||||
|
||||
case entity.OperatorOr, entity.OperatorAnd, entity.OperatorXor:
|
||||
return nSameType(2, this.isInteger)
|
||||
return nSameType(-1, this.isInteger)
|
||||
|
||||
case entity.OperatorLeftShift, entity.OperatorRightShift:
|
||||
if len(operation.Arguments) != 2 { return wrongArgCount() }
|
||||
|
@ -535,7 +538,10 @@ func (this *Tree) analyzeIfElse (
|
|||
error,
|
||||
) {
|
||||
condition, err := this.analyzeExpression (
|
||||
&entity.TypeBool { },
|
||||
&entity.TypeNamed {
|
||||
Name: "Bool",
|
||||
Type: this.Types["Bool"].Type,
|
||||
},
|
||||
weak, ifelse.Condition)
|
||||
if err != nil { return nil, err }
|
||||
ifelse.Condition = condition
|
||||
|
|
|
@ -54,28 +54,30 @@ func TestOperationArgCount (test *testing.T) {
|
|||
testString (test,
|
||||
`
|
||||
[main] = {
|
||||
[+ 1 2 3 4]
|
||||
[++ 1]
|
||||
[- 1 2 3 4]
|
||||
[-- 1]
|
||||
[* 5 6]
|
||||
[/ 32 16]
|
||||
[% 5 6]
|
||||
[!! true]
|
||||
[|| false]
|
||||
[&& true true false true]
|
||||
[^^ true true false true]
|
||||
[! 1]
|
||||
[| 1 2]
|
||||
[& 3 1]
|
||||
[^ 1 2 3 4]
|
||||
[<< 1 8]
|
||||
[>> 8 1]
|
||||
[< 1 2 3 4]
|
||||
[> 1 2 3 4]
|
||||
[<= 10 5 3]
|
||||
[>= 1 2 3 3 4]
|
||||
[= 2 2 2 3 9]
|
||||
x:Int
|
||||
b:Bool
|
||||
x = [+ 1 2 3 4]
|
||||
x = [++ 1]
|
||||
x = [- 1 2 3 4]
|
||||
x = [-- 1]
|
||||
x = [* 5 6]
|
||||
x = [/ 32 16]
|
||||
x = [% 5 6]
|
||||
x = [!! 1]
|
||||
x = [|| 1 2]
|
||||
x = [&& 3 1 5]
|
||||
x = [^^ 1 2 3 4]
|
||||
b = [! true]
|
||||
b = [| true false]
|
||||
b = [& true true]
|
||||
b = [^ true true false true]
|
||||
x = [<< 1 8]
|
||||
x = [>> 8 1]
|
||||
b = [< x 2 3 4]
|
||||
b = [> x 2 3 4]
|
||||
b = [<= x 5 3]
|
||||
b = [>= x 2 3 3 4]
|
||||
b = [= x 2 2 3 9]
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
|
|
@ -149,8 +149,8 @@ func (this *Tree) analyzeTypeInternal (
|
|||
}
|
||||
return ty, nil
|
||||
|
||||
// floating point, word, and boolean types
|
||||
case *entity.TypeFloat, *entity.TypeWord, *entity.TypeBool:
|
||||
// floating point and word types
|
||||
case *entity.TypeFloat, *entity.TypeWord:
|
||||
return ty, nil
|
||||
|
||||
default: panic(fmt.Sprint("BUG: analyzer doesnt know about type ", ty))
|
||||
|
|
|
@ -190,17 +190,6 @@ func (this *TypeWord) Equals (ty Type) bool {
|
|||
return ok && real.Signed == this.Signed
|
||||
}
|
||||
|
||||
// TypeBool represents a boolean type.
|
||||
type TypeBool struct {
|
||||
Pos lexer.Position
|
||||
}
|
||||
func (*TypeBool) ty(){}
|
||||
func (this *TypeBool) String () string { return "Bool" }
|
||||
func (this *TypeBool) Equals (ty Type) bool {
|
||||
_, ok := ty.(*TypeBool)
|
||||
return ok
|
||||
}
|
||||
|
||||
// TypesEqual checks if two types are equal to eachother, even if one or both
|
||||
// are nil.
|
||||
func TypesEqual (left, right Type) bool {
|
||||
|
|
Loading…
Reference in New Issue