Pass all analyzer tests

This commit is contained in:
Sasha Koshka 2023-11-04 17:59:04 -04:00
parent 47beb9e41f
commit 605fd24228
5 changed files with 47 additions and 51 deletions

View File

@ -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 }
}
}

View File

@ -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

View File

@ -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]
}
`)
}

View File

@ -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))

View File

@ -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 {