101 lines
1.6 KiB
Go
101 lines
1.6 KiB
Go
package runtime
|
|
|
|
import "fmt"
|
|
|
|
//go:generate stringer -type LoxType -trimprefix LoxType
|
|
type LoxType int
|
|
|
|
const (
|
|
LoxTypeString LoxType = iota
|
|
LoxTypeNumber
|
|
LoxTypeBoolean
|
|
LoxTypeNil
|
|
LoxTypeUndefined
|
|
)
|
|
|
|
type LoxValue struct {
|
|
raw any
|
|
}
|
|
|
|
func (v *LoxValue) Type() LoxType {
|
|
switch v.raw.(type) {
|
|
case string:
|
|
return LoxTypeString
|
|
case float64:
|
|
return LoxTypeNumber
|
|
case bool:
|
|
return LoxTypeBoolean
|
|
case nil:
|
|
return LoxTypeNil
|
|
default:
|
|
return LoxTypeUndefined
|
|
}
|
|
}
|
|
|
|
func (v *LoxValue) Debug() string {
|
|
return fmt.Sprintf("%+v", v.raw)
|
|
}
|
|
|
|
func (v *LoxValue) String() string {
|
|
if string, ok := v.raw.(string); ok {
|
|
return string
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (v *LoxValue) Number() float64 {
|
|
if number, ok := v.raw.(float64); ok {
|
|
return number
|
|
}
|
|
return 0.0
|
|
}
|
|
|
|
func (v *LoxValue) IsString() bool {
|
|
return v.Type() == LoxTypeString
|
|
}
|
|
|
|
func (v *LoxValue) IsNumber() bool {
|
|
return v.Type() == LoxTypeNumber
|
|
}
|
|
func (v *LoxValue) IsTruthy() bool {
|
|
switch v.Type() {
|
|
case LoxTypeBoolean:
|
|
b, ok := v.raw.(bool)
|
|
return ok && b
|
|
case LoxTypeNumber, LoxTypeString:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func (v *LoxValue) IsNil() bool {
|
|
return v.Type() == LoxTypeNil
|
|
}
|
|
|
|
func (v *LoxValue) IsUndefined() bool {
|
|
return v.Type() == LoxTypeUndefined
|
|
}
|
|
|
|
func (v *LoxValue) Equals(other *LoxValue) bool {
|
|
return AreEqual(v, other)
|
|
}
|
|
|
|
func Value(v any) *LoxValue {
|
|
return &LoxValue{v}
|
|
}
|
|
|
|
func AreEqual(a, b *LoxValue) bool {
|
|
typeA := a.Type()
|
|
typeB := b.Type()
|
|
|
|
if typeA != typeB {
|
|
return false
|
|
}
|
|
|
|
return a.raw == b.raw
|
|
}
|
|
|
|
func AreEqualValue(a, b *LoxValue) *LoxValue {
|
|
return Value(AreEqual(a, b))
|
|
}
|