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)) }