fspl/analyzer/literal.go

153 lines
3.3 KiB
Go

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
}
func (this *Tree) analyzeLiteralStruct (
into entity.Type,
mode strictness,
literal *entity.LiteralStruct,
) (
entity.Expression,
error,
) {
base, ok := this.reduceToBase(into).(*entity.TypeStruct)
if !ok {
return nil, participle.Errorf (
literal.Pos, "cannot use struct literal as %v",
into)
}
literal, err := this.assembleStructLiteralMap(literal)
if err != nil { return nil, err }
for name, member := range literal.MemberMap {
correct, ok := base.MemberMap[name]
if !ok {
return nil, participle.Errorf (
literal.Pos, "no member %v.%s",
into, name)
}
value, err := this.analyzeExpression(correct.Type(), strict, member.Value)
if err != nil { return nil, err }
member.Value = value
}
literal.Ty = into
return literal, nil
}
func (this *Tree) analyzeLiteralBoolean (
into entity.Type,
mode strictness,
literal *entity.LiteralBoolean,
) (
entity.Expression,
error,
) {
if !this.isBoolean(into) {
return nil, participle.Errorf (
literal.Pos, "cannot use boolean literal as %v",
into)
}
literal.Ty = into
return literal, nil
}
func (this *Tree) assembleStructLiteralMap (
literal *entity.LiteralStruct,
) (
*entity.LiteralStruct,
error,
) {
literal.MemberMap = make(map[string] *entity.Member)
literal.MemberOrder = make([]string, len(literal.Members))
for index, member := range literal.Members {
if previous, exists := literal.MemberMap[member.Name]; exists {
return literal, participle.Errorf (
member.Pos, "%s already listed in struct literal at %v",
member.Name, previous.Pos)
}
literal.MemberMap [member.Name] = member
literal.MemberOrder[index] = member.Name
literal.Members [index] = member
}
return literal, nil
}