package value import ( "fmt" "jinx/pkg/lang/vm/code" "jinx/pkg/lang/vm/mem" "strconv" "strings" ) type Data interface { String(mem.Mem) (string, error) } type IntData int64 func (i IntData) Get() int64 { return int64(i) } func (i IntData) String(_ mem.Mem) (string, error) { return strconv.FormatInt(int64(i), 10), nil } type FloatData float64 func (f FloatData) Get() float64 { return float64(f) } func (f FloatData) String(_ mem.Mem) (string, error) { return strconv.FormatFloat(float64(f), 'f', -1, 64), nil } type StringData struct { data mem.Ptr } func (s StringData) String(m mem.Mem) (string, error) { if data, err := m.Get(s.data); err == nil { return "\"" + data.(StringCell).Get() + "\"", nil } else { return "", err } } func (s StringData) RawString(m mem.Mem) (string, error) { if data, err := m.Get(s.data); err == nil { return data.(StringCell).Get(), nil } else { return "", err } } type BoolData bool func (b BoolData) Get() bool { return bool(b) } func (b BoolData) String(_ mem.Mem) (string, error) { return strconv.FormatBool(bool(b)), nil } type ArrayData struct { data mem.Ptr } func (a ArrayData) String(m mem.Mem) (string, error) { val, err := m.Get(a.data) if err != nil { return "", err } arr := val.(ArrayCell).Get() builder := strings.Builder{} builder.WriteString("[") for i, v := range arr { if i > 0 { builder.WriteString(", ") } if s, err := v.Data().String(m); err == nil { builder.WriteString(s) } else { return "", err } } builder.WriteString("]") return builder.String(), nil } func (a ArrayData) Len(m mem.Mem) (int, error) { data, err := m.Get(a.data) if err != nil { return 0, err } arr := data.(ArrayCell).Get() return len(arr), nil } func (a ArrayData) At(m mem.Mem, i int) (Value, error) { data, err := m.Get(a.data) if err != nil { return Value{}, err } arr := data.(ArrayCell).Get() return arr[i], nil } func (a ArrayData) Push(m mem.Mem, v Value) error { data, err := m.Get(a.data) if err != nil { return err } arr := data.(ArrayCell).Get() arr = append(arr, v) m.Set(a.data, ArrayCell(arr)) return nil } type NullData struct{} func (n NullData) String(_ mem.Mem) (string, error) { return "null", nil } type FunctionData struct { pos code.Pos args uint env mem.Ptr native NativeFunc } type NativeFunc func([]Value) (Value, error) func (f FunctionData) Pos() code.Pos { return f.pos } func (f FunctionData) Args() uint { return f.args } func (f FunctionData) Env() mem.Ptr { return f.env } func (f FunctionData) Native() NativeFunc { return f.native } func (f FunctionData) WithEnv(env mem.Ptr) FunctionData { return FunctionData{pos: f.pos, args: f.args, env: env, native: f.native} } func (f FunctionData) WithArgs(args uint) FunctionData { return FunctionData{pos: f.pos, args: args, env: f.env, native: f.native} } func (f FunctionData) String(_ mem.Mem) (string, error) { if f.native != nil { return fmt.Sprintf("", f.args), nil } else { return fmt.Sprintf("", f.args, f.pos.Module, f.pos.PC), nil } } type TypeRefData struct { typeRef mem.Ptr } func (t TypeRefData) String(_ mem.Mem) (string, error) { return fmt.Sprintf("", t.typeRef), nil } func (t TypeRefData) TypeRef() mem.Ptr { return t.typeRef } func (t TypeRefData) GetMethod(m mem.Mem, name string) (bool, FunctionData, error) { cell, err := m.Get(t.typeRef) if err != nil { return false, FunctionData{}, err } typ := cell.(TypeCell).Get() method, ok := typ.Methods[name] return ok, method, nil } func (t TypeRefData) AddMethod(m mem.Mem, name string, method FunctionData) error { cell, err := m.Get(t.typeRef) if err != nil { return err } typ := cell.(TypeCell).Get() typ.Methods[name] = method if err := m.Set(t.typeRef, TypeCell(typ)); err != nil { return err } return nil } type ObjectData struct { t mem.Ptr obj mem.Ptr } func (o ObjectData) String(_ mem.Mem) (string, error) { return fmt.Sprintf("", o.obj), nil } func (o ObjectData) Ptr() mem.Ptr { return o.obj } func (o ObjectData) Type() mem.Ptr { return o.t } func (o ObjectData) WithType(t mem.Ptr) ObjectData { return ObjectData{t: t, obj: o.obj} }