Start analyzing literals
This commit is contained in:
parent
c88ba16bdc
commit
a6fec780c7
|
@ -1,9 +1,11 @@
|
|||
package analyzer
|
||||
|
||||
import "fmt"
|
||||
import "math"
|
||||
import "github.com/alecthomas/participle/v2"
|
||||
import "github.com/alecthomas/participle/v2/lexer"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/integer"
|
||||
|
||||
type strictness int; const (
|
||||
// name equivalence
|
||||
|
@ -304,3 +306,45 @@ func (this *Tree) isBoolean (ty entity.Type) bool {
|
|||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
// isFloat returns whether or not the specified type is a float.
|
||||
func (this *Tree) isFloat (ty entity.Type) bool {
|
||||
switch this.reduceToBase(ty).(type) {
|
||||
case *entity.TypeFloat: return true
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
// isUnsigned returns whether or not the specified type is an unsigned integer.
|
||||
func (this *Tree) isUnsigned (ty entity.Type) bool {
|
||||
switch this.reduceToBase(ty).(type) {
|
||||
case *entity.TypeInt: return ty.(*entity.TypeInt).Signed
|
||||
case *entity.TypeWord: return ty.(*entity.TypeInt).Signed
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
// inRange returns whether the specified value can fit within the given integer
|
||||
// type.
|
||||
func (this *Tree) inRange (ty entity.Type, value int64) bool {
|
||||
base := this.reduceToBase(ty)
|
||||
switch base.(type) {
|
||||
case *entity.TypeInt:
|
||||
base := base.(*entity.TypeInt)
|
||||
if base.Signed {
|
||||
return value > integer.SignedMin(base.Width) &&
|
||||
value < integer.SignedMax(base.Width)
|
||||
} else {
|
||||
return value > 0 &&
|
||||
uint64(value) < integer.UnsignedMax(base.Width)
|
||||
}
|
||||
case *entity.TypeWord:
|
||||
base := base.(*entity.TypeWord)
|
||||
if base.Signed {
|
||||
return value > math.MinInt && value < math.MaxInt
|
||||
} else {
|
||||
return value > 0 && uint64(value) < math.MaxUint
|
||||
}
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,17 @@ func (this *Tree) analyzeExpression (
|
|||
// return this.analyzeBreak(into, mode, expression.(*entity.Break))
|
||||
// case *entity.Return:
|
||||
// return this.analyzeReturn(into, mode, expression.(*entity.Return))
|
||||
// TODO literals
|
||||
|
||||
case *entity.LiteralInt:
|
||||
return this.analyzeLiteralInt(into, mode, expression.(*entity.LiteralInt))
|
||||
case *entity.LiteralFloat:
|
||||
return this.analyzeLiteralFloat(into, mode, expression.(*entity.LiteralFloat))
|
||||
case *entity.LiteralArray:
|
||||
return this.analyzeLiteralArray(into, mode, expression.(*entity.LiteralArray))
|
||||
case *entity.LiteralStruct:
|
||||
return this.analyzeLiteralStruct(into, mode, expression.(*entity.LiteralStruct))
|
||||
case *entity.LiteralBoolean:
|
||||
return this.analyzeLiteralBoolean(into, mode, expression.(*entity.LiteralBoolean))
|
||||
default:
|
||||
panic(fmt.Sprint (
|
||||
"BUG: analyzer doesnt know about expression ",
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package analyzer
|
||||
|
||||
// import "fmt"
|
||||
import "github.com/alecthomas/participle/v2"
|
||||
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||
|
||||
func (this *Tree) analyzeLiteralInt (
|
||||
into entity.Type,
|
||||
mode strictness,
|
||||
literal *entity.LiteralInt,
|
||||
) (
|
||||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
if !this.isNumeric(into) {
|
||||
return nil, participle.Errorf (
|
||||
literal.Pos, "cannot use integer literal as %v",
|
||||
into)
|
||||
}
|
||||
|
||||
if this.isInteger(into) && !this.inRange(into, int64(literal.Value)) {
|
||||
return nil, participle.Errorf (
|
||||
literal.Pos, "integer literal out of range for type %v",
|
||||
into)
|
||||
}
|
||||
|
||||
literal.Ty = into
|
||||
return literal, nil
|
||||
}
|
||||
|
||||
func (this *Tree) analyzeLiteralFloat (
|
||||
into entity.Type,
|
||||
mode strictness,
|
||||
literal *entity.LiteralFloat,
|
||||
) (
|
||||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
if !this.isFloat(into) {
|
||||
return nil, participle.Errorf (
|
||||
literal.Pos, "cannot use float literal as %v",
|
||||
into)
|
||||
}
|
||||
|
||||
literal.Ty = into
|
||||
return literal, nil
|
||||
}
|
||||
|
||||
func (this *Tree) analyzeLiteralArray (
|
||||
into entity.Type,
|
||||
mode strictness,
|
||||
literal *entity.LiteralArray,
|
||||
) (
|
||||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
base, ok := this.reduceToBase(into).(*entity.TypeArray)
|
||||
if !ok {
|
||||
return nil, participle.Errorf (
|
||||
literal.Pos, "cannot use array literal as %v",
|
||||
into)
|
||||
}
|
||||
|
||||
if base.Length != len(literal.Elements) {
|
||||
return nil, participle.Errorf (
|
||||
literal.Pos, "expected %v elements",
|
||||
base.Length)
|
||||
}
|
||||
|
||||
for index, element := range literal.Elements {
|
||||
element, err := this.analyzeExpression(base.Element, strict, element)
|
||||
if err != nil { return nil, err }
|
||||
literal.Elements[index] = element
|
||||
}
|
||||
|
||||
literal.Ty = into
|
||||
return literal, nil
|
||||
}
|
Loading…
Reference in New Issue