205 lines
7.2 KiB
Go
205 lines
7.2 KiB
Go
package entity
|
|
|
|
import "fmt"
|
|
import "git.tebibyte.media/fspl/fspl/errors"
|
|
|
|
var _ Expression = &LiteralInt { }
|
|
// LiteralInt specifies an integer value. It can be assigned to any type that is
|
|
// derived from an integer or a float, as long as the value fo the literal can
|
|
// fit within the range of the type. It cannot be directly assigned to an
|
|
// interface because it contains no inherent type information. A value cast may
|
|
// be used for this purpose.
|
|
type LiteralInt struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
Value int
|
|
|
|
// Semantics
|
|
Ty Type
|
|
}
|
|
func (*LiteralInt) expression(){}
|
|
func (this *LiteralInt) Position () errors.Position { return this.Pos }
|
|
func (this *LiteralInt) Type () Type { return this.Ty }
|
|
func (this *LiteralInt) HasExplicitType () bool { return false }
|
|
func (this *LiteralInt) IsConstant () bool { return true }
|
|
func (this *LiteralInt) Description () string { return "integer literal" }
|
|
func (this *LiteralInt) String () string {
|
|
return fmt.Sprint(this.Value)
|
|
}
|
|
|
|
var _ Expression = &LiteralFloat { }
|
|
// LiteralFloat specifies a floating point value. It can be assigned to any type
|
|
// that is derived from a float. It cannot be directly assigned to an interface
|
|
// because it contains no inherent type information. A value cast may be used
|
|
// for this purpose.
|
|
type LiteralFloat struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
Value float64
|
|
|
|
// Semantics
|
|
Ty Type
|
|
}
|
|
func (*LiteralFloat) expression(){}
|
|
func (this *LiteralFloat) Position () errors.Position { return this.Pos }
|
|
func (this *LiteralFloat) Type () Type { return this.Ty }
|
|
func (this *LiteralFloat) HasExplicitType () bool { return false }
|
|
func (this *LiteralFloat) Description () string { return "floating point literal" }
|
|
func (this *LiteralFloat) IsConstant () bool { return true }
|
|
func (this *LiteralFloat) String () string {
|
|
return fmt.Sprint(this.Value)
|
|
}
|
|
|
|
var _ Expression = &LiteralString { }
|
|
// LiteralString specifies a string value. It takes on different data
|
|
// representations depending on what the base type of what it is assigned to is
|
|
// structurally equivalent to:
|
|
// - Integer: Single unicode code point. When assigning to an integer, the
|
|
// string literal may not be longer than one code point, and that code point
|
|
// must fit in the integer.
|
|
// - Slice of 8 bit integers: UTF-8 string.
|
|
// - Slice of 16 bit integers: UTF-16 string.
|
|
// - Slice of 32 bit (or larger) integers: UTF-32 string.
|
|
// - Array of integers: The same as slices of integers, but the string literal
|
|
// must fit inside of the array.
|
|
// - Pointer to 8 bit integer: Null-terminated UTF-8 string (AKA C-string).
|
|
// A string literal cannot be directly assigned to an interface because it
|
|
// contains no inherent type information. A value cast may be used for this
|
|
// purpose.
|
|
type LiteralString struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
ValueUTF8 string
|
|
ValueUTF16 []uint16
|
|
ValueUTF32 []rune
|
|
|
|
// Semantics
|
|
Ty Type
|
|
}
|
|
func (*LiteralString) expression(){}
|
|
func (this *LiteralString) Position () errors.Position { return this.Pos }
|
|
func (this *LiteralString) Type () Type { return this.Ty }
|
|
func (this *LiteralString) HasExplicitType () bool { return false }
|
|
func (this *LiteralString) Description () string { return "string literal" }
|
|
func (this *LiteralString) IsConstant () bool { return true }
|
|
func (this *LiteralString) String () string {
|
|
return Quote(this.ValueUTF8)
|
|
}
|
|
|
|
var _ Expression = &LiteralArray { }
|
|
// LiteralArray is a composite array literal. It can contain any number of
|
|
// values. It can be assigned to any array type that:
|
|
// 1. has an identical length, and
|
|
// 2. who's element type can be assigned to by all the element values in the
|
|
// literal.
|
|
// It cannot be directly assigned to an interface because it contains no
|
|
// inherent type information. A value cast may be used for this purpose.
|
|
type LiteralArray struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
Elements []Expression
|
|
|
|
// Semantics
|
|
Ty Type
|
|
}
|
|
func (*LiteralArray) expression(){}
|
|
func (this *LiteralArray) Position () errors.Position { return this.Pos }
|
|
func (this *LiteralArray) Type () Type { return this.Ty }
|
|
func (this *LiteralArray) HasExplicitType () bool { return false }
|
|
func (this *LiteralArray) Description () string { return "array literal" }
|
|
func (this *LiteralArray) IsConstant () bool {
|
|
for _, element := range this.Elements {
|
|
if !element.IsConstant() { return false }
|
|
}
|
|
return true
|
|
}
|
|
func (this *LiteralArray) String () string {
|
|
out := "("
|
|
for index, element := range this.Elements {
|
|
if index > 0 { out += " " }
|
|
out += fmt.Sprint(element)
|
|
}
|
|
return out + ")"
|
|
}
|
|
|
|
var _ Expression = &LiteralStruct { }
|
|
// LiteralStruct is a composite structure literal. It can contain any number of
|
|
// name:value pairs. It can be assigned to any struct type that:
|
|
// 1. has at least the members specified in the literal
|
|
// 2. who's member types can be assigned to by the corresponding member
|
|
// values in the literal.
|
|
// It cannot be directly assigned to an interface because it contains no
|
|
// inherent type information. A value cast may be used for this purpose.
|
|
type LiteralStruct struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
Members []*Member
|
|
|
|
// Semantics
|
|
Ty Type
|
|
MemberOrder []string
|
|
MemberMap map[string] *Member
|
|
}
|
|
func (*LiteralStruct) expression(){}
|
|
func (this *LiteralStruct) Position () errors.Position { return this.Pos }
|
|
func (this *LiteralStruct) Type () Type { return this.Ty }
|
|
func (this *LiteralStruct) HasExplicitType () bool { return false }
|
|
func (this *LiteralStruct) Description () string { return "struct literal" }
|
|
func (this *LiteralStruct) IsConstant () bool {
|
|
for _, member := range this.Members {
|
|
if !member.Value.IsConstant() { return false }
|
|
}
|
|
return true
|
|
}
|
|
func (this *LiteralStruct) String () string {
|
|
out := "(."
|
|
for _, member := range this.Members {
|
|
out += fmt.Sprint(" ", member)
|
|
}
|
|
return out + ")"
|
|
}
|
|
|
|
var _ Expression = &LiteralBoolean { }
|
|
// LiteralBoolean is a boolean literal. It may be either true or false. It can
|
|
// be assigned to any type derived from a boolean. It cannot be directly
|
|
// assigned to an interface because it contains no inherent type information. A
|
|
// value cast may be used for this purpose.
|
|
type LiteralBoolean struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
Value bool
|
|
|
|
// Semantics
|
|
Ty Type
|
|
}
|
|
func (*LiteralBoolean) expression(){}
|
|
func (this *LiteralBoolean) Position () errors.Position { return this.Pos }
|
|
func (this *LiteralBoolean) Type () Type { return this.Ty }
|
|
func (this *LiteralBoolean) HasExplicitType () bool { return false }
|
|
func (this *LiteralBoolean) Description () string { return "boolean literal" }
|
|
func (this *LiteralBoolean) IsConstant () bool { return true }
|
|
func (this *LiteralBoolean) String () string {
|
|
if this.Value {
|
|
return "true"
|
|
} else {
|
|
return "false"
|
|
}
|
|
}
|
|
|
|
var _ Expression = &LiteralNil { }
|
|
// TODO: document, put in spec, fully implement nil for slices interfaces etc
|
|
type LiteralNil struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
|
|
// Semantics
|
|
Ty Type
|
|
}
|
|
func (*LiteralNil) expression(){}
|
|
func (this *LiteralNil) Position () errors.Position { return this.Pos }
|
|
func (this *LiteralNil) Type () Type { return this.Ty }
|
|
func (this *LiteralNil) HasExplicitType () bool { return false }
|
|
func (this *LiteralNil) Description () string { return "nil" }
|
|
func (this *LiteralNil) IsConstant () bool { return true }
|
|
func (this *LiteralNil) String () string { return "nil" }
|