This repository has been archived on 2024-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
arf/analyzer/literals.go

219 lines
5.9 KiB
Go
Raw Normal View History

2022-09-22 15:51:45 -06:00
package analyzer
import "fmt"
2022-10-11 22:48:55 -06:00
// IntLiteral represents a constant signed integer value.
2022-10-11 16:31:37 -06:00
type IntLiteral struct {
locatable
value int64
}
2022-10-11 22:48:55 -06:00
// UIntLiteral represents a constant unsigned itneger value.
2022-10-11 16:31:37 -06:00
type UIntLiteral struct {
locatable
value uint64
}
2022-10-11 22:48:55 -06:00
// FloatLiteral represents a constant floating point value.
2022-10-11 16:31:37 -06:00
type FloatLiteral struct {
locatable
value float64
}
2022-10-11 22:48:55 -06:00
// StringLiteral represents a constant text value.
2022-10-11 16:31:37 -06:00
type StringLiteral struct {
locatable
value string
}
2022-09-22 15:51:45 -06:00
// ToString outputs the data in the argument as a string.
func (literal IntLiteral) ToString (indent int) (output string) {
2022-10-11 16:31:37 -06:00
output += doIndent(indent, fmt.Sprint("arg int ", literal.value, "\n"))
2022-09-22 15:51:45 -06:00
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
}
2022-10-14 18:06:11 -06:00
// 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
}
2022-09-22 15:51:45 -06:00
// ToString outputs the data in the argument as a string.
func (literal UIntLiteral) ToString (indent int) (output string) {
2022-10-11 16:31:37 -06:00
output += doIndent(indent, fmt.Sprint("arg uint ", literal.value, "\n"))
2022-09-22 15:51:45 -06:00
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
}
2022-10-14 18:06:11 -06:00
// 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
}
2022-09-22 15:51:45 -06:00
// ToString outputs the data in the argument as a string.
func (literal FloatLiteral) ToString (indent int) (output string) {
2022-10-11 16:31:37 -06:00
output += doIndent(indent, fmt.Sprint("arg float ", literal.value, "\n"))
2022-09-22 15:51:45 -06:00
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
}
2022-10-14 18:06:11 -06:00
// 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
}
2022-09-22 15:51:45 -06:00
// ToString outputs the data in the argument as a string.
func (literal StringLiteral) ToString (indent int) (output string) {
2022-10-11 16:31:37 -06:00
output += doIndent(indent, fmt.Sprint("arg string '", literal.value, "'\n"))
2022-09-22 15:51:45 -06:00
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
}
2022-10-14 18:06:11 -06:00
// 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.isNumeric()
return
}