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 }