221 lines
5.9 KiB
Go
221 lines
5.9 KiB
Go
package analyzer
|
|
|
|
import "fmt"
|
|
|
|
// IntLiteral represents a constant signed integer value.
|
|
type IntLiteral struct {
|
|
locatable
|
|
value int64
|
|
}
|
|
|
|
// UIntLiteral represents a constant unsigned itneger value.
|
|
type UIntLiteral struct {
|
|
locatable
|
|
value uint64
|
|
}
|
|
|
|
// FloatLiteral represents a constant floating point value.
|
|
type FloatLiteral struct {
|
|
locatable
|
|
value float64
|
|
}
|
|
|
|
// StringLiteral represents a constant text value.
|
|
type StringLiteral struct {
|
|
locatable
|
|
value string
|
|
}
|
|
|
|
// ToString outputs the data in the argument as a string.
|
|
func (literal IntLiteral) ToString (indent int) (output string) {
|
|
output += doIndent(indent, fmt.Sprint("intLiteral ", literal.value, "\n"))
|
|
return
|
|
}
|
|
|
|
// What returns the type of the argument
|
|
func (literal IntLiteral) What () (what Type) {
|
|
what.actual = &PrimitiveI64
|
|
what.length = 1
|
|
return
|
|
}
|
|
|
|
// Equals returns whether the literal is equal to the specified value.
|
|
func (literal IntLiteral) Equals (value any) (equal bool) {
|
|
equal = literal.value == value
|
|
return
|
|
}
|
|
|
|
// Value returns the literal's value
|
|
func (literal IntLiteral) Value () (value any) {
|
|
value = literal.value
|
|
return
|
|
}
|
|
|
|
// Resolve resolves the argument to a constant literal, which in this case is
|
|
// trivial because the literal is already constant.
|
|
func (literal IntLiteral) Resolve () (constant Argument, err error) {
|
|
constant = literal
|
|
return
|
|
}
|
|
|
|
// canBePassedAs returns true if this literal can be implicitly cast to the
|
|
// specified type, and false if it can't.
|
|
func (literal IntLiteral) canBePassedAs (what Type) (allowed bool) {
|
|
// can be passed to singular types that are signed numbers at a
|
|
// primitive level.
|
|
allowed =
|
|
what.isSingular() &&
|
|
what.isSignedNumeric()
|
|
return
|
|
}
|
|
|
|
// ToString outputs the data in the argument as a string.
|
|
func (literal UIntLiteral) ToString (indent int) (output string) {
|
|
output += doIndent(indent, fmt.Sprint("uintLiteral ", literal.value, "\n"))
|
|
return
|
|
}
|
|
|
|
// What returns the type of the argument
|
|
func (literal UIntLiteral) What () (what Type) {
|
|
what.actual = &PrimitiveU64
|
|
what.length = 1
|
|
return
|
|
}
|
|
|
|
// Equals returns whether the literal is equal to the specified value.
|
|
func (literal UIntLiteral) Equals (value any) (equal bool) {
|
|
equal = literal.value == value
|
|
return
|
|
}
|
|
|
|
// Value returns the literal's value
|
|
func (literal UIntLiteral) Value () (value any) {
|
|
value = literal.value
|
|
return
|
|
}
|
|
|
|
// canBePassedAs returns true if this literal can be implicitly cast to the
|
|
// specified type, and false if it can't.
|
|
func (literal UIntLiteral) canBePassedAs (what Type) (allowed bool) {
|
|
// can be passed to singular types that are numbers at a primitive level.
|
|
allowed =
|
|
what.isSingular() &&
|
|
what.isNumeric()
|
|
return
|
|
}
|
|
|
|
// Resolve resolves the argument to a constant literal, which in this case is
|
|
// trivial because the literal is already constant.
|
|
func (literal UIntLiteral) Resolve () (constant Argument, err error) {
|
|
constant = literal
|
|
return
|
|
}
|
|
|
|
// What returns the type of the argument
|
|
func (literal FloatLiteral) What () (what Type) {
|
|
what.actual = &PrimitiveF64
|
|
what.length = 1
|
|
return
|
|
}
|
|
|
|
// ToString outputs the data in the argument as a string.
|
|
func (literal FloatLiteral) ToString (indent int) (output string) {
|
|
output += doIndent(indent, fmt.Sprint("floatLiteral ", literal.value, "\n"))
|
|
return
|
|
}
|
|
|
|
// Equals returns whether the literal is equal to the specified value.
|
|
func (literal FloatLiteral) Equals (value any) (equal bool) {
|
|
equal = literal.value == value
|
|
return
|
|
}
|
|
|
|
// Value returns the literal's value
|
|
func (literal FloatLiteral) Value () (value any) {
|
|
value = literal.value
|
|
return
|
|
}
|
|
|
|
// Resolve resolves the argument to a constant literal, which in this case is
|
|
// trivial because the literal is already constant.
|
|
func (literal FloatLiteral) Resolve () (constant Argument, err error) {
|
|
constant = literal
|
|
return
|
|
}
|
|
|
|
// canBePassedAs returns true if this literal can be implicitly cast to the
|
|
// specified type, and false if it can't.
|
|
func (literal FloatLiteral) canBePassedAs (what Type) (allowed bool) {
|
|
// must be a singlular value
|
|
if !what.isSingular() { return }
|
|
|
|
// can be passed to types that are floats at a primitive level.
|
|
primitive := what.underlyingPrimitive()
|
|
switch primitive {
|
|
case
|
|
&PrimitiveF64,
|
|
&PrimitiveF32:
|
|
|
|
allowed = true
|
|
}
|
|
return
|
|
}
|
|
|
|
// What returns the type of the argument
|
|
func (literal StringLiteral) What () (what Type) {
|
|
what.actual = &BuiltInString
|
|
what.length = 1
|
|
return
|
|
}
|
|
|
|
// ToString outputs the data in the argument as a string.
|
|
func (literal StringLiteral) ToString (indent int) (output string) {
|
|
output += doIndent(indent, fmt.Sprint("stringLiteral '", literal.value, "'\n"))
|
|
return
|
|
}
|
|
|
|
// Equals returns whether the literal is equal to the specified value.
|
|
func (literal StringLiteral) Equals (value any) (equal bool) {
|
|
equal = literal.value == value
|
|
return
|
|
}
|
|
|
|
// Value returns the literal's value
|
|
func (literal StringLiteral) Value () (value any) {
|
|
value = literal.value
|
|
return
|
|
}
|
|
|
|
// Resolve resolves the argument to a constant literal, which in this case is
|
|
// trivial because the literal is already constant.
|
|
func (literal StringLiteral) Resolve () (constant Argument, err error) {
|
|
constant = literal
|
|
return
|
|
}
|
|
|
|
// canBePassedAs returns true if this literal can be implicitly cast to the
|
|
// specified type, and false if it can't.
|
|
func (literal StringLiteral) canBePassedAs (what Type) (allowed bool) {
|
|
// can be passed to types that are numbers at a primitive level, or
|
|
// types that can be reduced to a variable array pointing to numbers at
|
|
// a primitive level.
|
|
|
|
// we don't check the length of what, becasue when setting a static
|
|
// array to a string literal, excess data will be cut off (and if it is
|
|
// shorter, the excess space will be filled with zeros).
|
|
|
|
reduced, worked := what.reduce()
|
|
if worked {
|
|
// if the type was reduced to a non-basic type, only pass to
|
|
// singular dynamic arrays.
|
|
if !what.isSingular() { return }
|
|
if reduced.kind != TypeKindVariableArray { return }
|
|
what = reduced
|
|
allowed = what.points.isNumeric()
|
|
} else {
|
|
allowed = what.isNumeric()
|
|
}
|
|
|
|
return
|
|
}
|