1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612 |
- package tengo
- import (
- "bytes"
- "fmt"
- "math"
- "strconv"
- "strings"
- "time"
- "github.com/d5/tengo/v2/parser"
- "github.com/d5/tengo/v2/token"
- )
- var (
- // TrueValue represents a true value.
- TrueValue Object = &Bool{value: true}
- // FalseValue represents a false value.
- FalseValue Object = &Bool{value: false}
- // UndefinedValue represents an undefined value.
- UndefinedValue Object = &Undefined{}
- )
- // Object represents an object in the VM.
- type Object interface {
- // TypeName should return the name of the type.
- TypeName() string
- // String should return a string representation of the type's value.
- String() string
- // BinaryOp should return another object that is the result of a given
- // binary operator and a right-hand side object. If BinaryOp returns an
- // error, the VM will treat it as a run-time error.
- BinaryOp(op token.Token, rhs Object) (Object, error)
- // IsFalsy should return true if the value of the type should be considered
- // as falsy.
- IsFalsy() bool
- // Equals should return true if the value of the type should be considered
- // as equal to the value of another object.
- Equals(another Object) bool
- // Copy should return a copy of the type (and its value). Copy function
- // will be used for copy() builtin function which is expected to deep-copy
- // the values generally.
- Copy() Object
- // IndexGet should take an index Object and return a result Object or an
- // error for indexable objects. Indexable is an object that can take an
- // index and return an object. If error is returned, the runtime will treat
- // it as a run-time error and ignore returned value. If Object is not
- // indexable, ErrNotIndexable should be returned as error. If nil is
- // returned as value, it will be converted to UndefinedToken value by the
- // runtime.
- IndexGet(index Object) (value Object, err error)
- // IndexSet should take an index Object and a value Object for index
- // assignable objects. Index assignable is an object that can take an index
- // and a value on the left-hand side of the assignment statement. If Object
- // is not index assignable, ErrNotIndexAssignable should be returned as
- // error. If an error is returned, it will be treated as a run-time error.
- IndexSet(index, value Object) error
- // Iterate should return an Iterator for the type.
- Iterate() Iterator
- // CanIterate should return whether the Object can be Iterated.
- CanIterate() bool
- // Call should take an arbitrary number of arguments and returns a return
- // value and/or an error, which the VM will consider as a run-time error.
- Call(args ...Object) (ret Object, err error)
- // CanCall should return whether the Object can be Called.
- CanCall() bool
- }
- // ObjectImpl represents a default Object Implementation. To defined a new
- // value type, one can embed ObjectImpl in their type declarations to avoid
- // implementing all non-significant methods. TypeName() and String() methods
- // still need to be implemented.
- type ObjectImpl struct {
- }
- // TypeName returns the name of the type.
- func (o *ObjectImpl) TypeName() string {
- panic(ErrNotImplemented)
- }
- func (o *ObjectImpl) String() string {
- panic(ErrNotImplemented)
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *ObjectImpl) BinaryOp(_ token.Token, _ Object) (Object, error) {
- return nil, ErrInvalidOperator
- }
- // Copy returns a copy of the type.
- func (o *ObjectImpl) Copy() Object {
- return nil
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *ObjectImpl) IsFalsy() bool {
- return false
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *ObjectImpl) Equals(x Object) bool {
- return o == x
- }
- // IndexGet returns an element at a given index.
- func (o *ObjectImpl) IndexGet(_ Object) (res Object, err error) {
- return nil, ErrNotIndexable
- }
- // IndexSet sets an element at a given index.
- func (o *ObjectImpl) IndexSet(_, _ Object) (err error) {
- return ErrNotIndexAssignable
- }
- // Iterate returns an iterator.
- func (o *ObjectImpl) Iterate() Iterator {
- return nil
- }
- // CanIterate returns whether the Object can be Iterated.
- func (o *ObjectImpl) CanIterate() bool {
- return false
- }
- // Call takes an arbitrary number of arguments and returns a return value
- // and/or an error.
- func (o *ObjectImpl) Call(_ ...Object) (ret Object, err error) {
- return nil, nil
- }
- // CanCall returns whether the Object can be Called.
- func (o *ObjectImpl) CanCall() bool {
- return false
- }
- // Array represents an array of objects.
- type Array struct {
- ObjectImpl
- Value []Object
- }
- // TypeName returns the name of the type.
- func (o *Array) TypeName() string {
- return "array"
- }
- func (o *Array) String() string {
- var elements []string
- for _, e := range o.Value {
- elements = append(elements, e.String())
- }
- return fmt.Sprintf("[%s]", strings.Join(elements, ", "))
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *Array) BinaryOp(op token.Token, rhs Object) (Object, error) {
- if rhs, ok := rhs.(*Array); ok {
- switch op {
- case token.Add:
- if len(rhs.Value) == 0 {
- return o, nil
- }
- return &Array{Value: append(o.Value, rhs.Value...)}, nil
- }
- }
- return nil, ErrInvalidOperator
- }
- // Copy returns a copy of the type.
- func (o *Array) Copy() Object {
- var c []Object
- for _, elem := range o.Value {
- c = append(c, elem.Copy())
- }
- return &Array{Value: c}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Array) IsFalsy() bool {
- return len(o.Value) == 0
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Array) Equals(x Object) bool {
- var xVal []Object
- switch x := x.(type) {
- case *Array:
- xVal = x.Value
- case *ImmutableArray:
- xVal = x.Value
- default:
- return false
- }
- if len(o.Value) != len(xVal) {
- return false
- }
- for i, e := range o.Value {
- if !e.Equals(xVal[i]) {
- return false
- }
- }
- return true
- }
- // IndexGet returns an element at a given index.
- func (o *Array) IndexGet(index Object) (res Object, err error) {
- intIdx, ok := index.(*Int)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
- idxVal := int(intIdx.Value)
- if idxVal < 0 || idxVal >= len(o.Value) {
- res = UndefinedValue
- return
- }
- res = o.Value[idxVal]
- return
- }
- // IndexSet sets an element at a given index.
- func (o *Array) IndexSet(index, value Object) (err error) {
- intIdx, ok := ToInt(index)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
- if intIdx < 0 || intIdx >= len(o.Value) {
- err = ErrIndexOutOfBounds
- return
- }
- o.Value[intIdx] = value
- return nil
- }
- // Iterate creates an array iterator.
- func (o *Array) Iterate() Iterator {
- return &ArrayIterator{
- v: o.Value,
- l: len(o.Value),
- }
- }
- // CanIterate returns whether the Object can be Iterated.
- func (o *Array) CanIterate() bool {
- return true
- }
- // Bool represents a boolean value.
- type Bool struct {
- ObjectImpl
- // this is intentionally non-public to force using objects.TrueValue and
- // FalseValue always
- value bool
- }
- func (o *Bool) String() string {
- if o.value {
- return "true"
- }
- return "false"
- }
- // TypeName returns the name of the type.
- func (o *Bool) TypeName() string {
- return "bool"
- }
- // Copy returns a copy of the type.
- func (o *Bool) Copy() Object {
- return o
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Bool) IsFalsy() bool {
- return !o.value
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Bool) Equals(x Object) bool {
- return o == x
- }
- // GobDecode decodes bool value from input bytes.
- func (o *Bool) GobDecode(b []byte) (err error) {
- o.value = b[0] == 1
- return
- }
- // GobEncode encodes bool values into bytes.
- func (o *Bool) GobEncode() (b []byte, err error) {
- if o.value {
- b = []byte{1}
- } else {
- b = []byte{0}
- }
- return
- }
- // BuiltinFunction represents a builtin function.
- type BuiltinFunction struct {
- ObjectImpl
- Name string
- Value CallableFunc
- }
- // TypeName returns the name of the type.
- func (o *BuiltinFunction) TypeName() string {
- return "builtin-function:" + o.Name
- }
- func (o *BuiltinFunction) String() string {
- return "<builtin-function>"
- }
- // Copy returns a copy of the type.
- func (o *BuiltinFunction) Copy() Object {
- return &BuiltinFunction{Value: o.Value}
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *BuiltinFunction) Equals(_ Object) bool {
- return false
- }
- // Call executes a builtin function.
- func (o *BuiltinFunction) Call(args ...Object) (Object, error) {
- return o.Value(args...)
- }
- // CanCall returns whether the Object can be Called.
- func (o *BuiltinFunction) CanCall() bool {
- return true
- }
- // BuiltinModule is an importable module that's written in Go.
- type BuiltinModule struct {
- Attrs map[string]Object
- }
- // Import returns an immutable map for the module.
- func (m *BuiltinModule) Import(moduleName string) (interface{}, error) {
- return m.AsImmutableMap(moduleName), nil
- }
- // AsImmutableMap converts builtin module into an immutable map.
- func (m *BuiltinModule) AsImmutableMap(moduleName string) *ImmutableMap {
- attrs := make(map[string]Object, len(m.Attrs))
- for k, v := range m.Attrs {
- attrs[k] = v.Copy()
- }
- attrs["__module_name__"] = &String{Value: moduleName}
- return &ImmutableMap{Value: attrs}
- }
- // Bytes represents a byte array.
- type Bytes struct {
- ObjectImpl
- Value []byte
- }
- func (o *Bytes) String() string {
- return string(o.Value)
- }
- // TypeName returns the name of the type.
- func (o *Bytes) TypeName() string {
- return "bytes"
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *Bytes) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch op {
- case token.Add:
- switch rhs := rhs.(type) {
- case *Bytes:
- if len(o.Value)+len(rhs.Value) > MaxBytesLen {
- return nil, ErrBytesLimit
- }
- return &Bytes{Value: append(o.Value, rhs.Value...)}, nil
- }
- }
- return nil, ErrInvalidOperator
- }
- // Copy returns a copy of the type.
- func (o *Bytes) Copy() Object {
- return &Bytes{Value: append([]byte{}, o.Value...)}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Bytes) IsFalsy() bool {
- return len(o.Value) == 0
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Bytes) Equals(x Object) bool {
- t, ok := x.(*Bytes)
- if !ok {
- return false
- }
- return bytes.Equal(o.Value, t.Value)
- }
- // IndexGet returns an element (as Int) at a given index.
- func (o *Bytes) IndexGet(index Object) (res Object, err error) {
- intIdx, ok := index.(*Int)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
- idxVal := int(intIdx.Value)
- if idxVal < 0 || idxVal >= len(o.Value) {
- res = UndefinedValue
- return
- }
- res = &Int{Value: int64(o.Value[idxVal])}
- return
- }
- // Iterate creates a bytes iterator.
- func (o *Bytes) Iterate() Iterator {
- return &BytesIterator{
- v: o.Value,
- l: len(o.Value),
- }
- }
- // CanIterate returns whether the Object can be Iterated.
- func (o *Bytes) CanIterate() bool {
- return true
- }
- // Char represents a character value.
- type Char struct {
- ObjectImpl
- Value rune
- }
- func (o *Char) String() string {
- return string(o.Value)
- }
- // TypeName returns the name of the type.
- func (o *Char) TypeName() string {
- return "char"
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *Char) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch rhs := rhs.(type) {
- case *Char:
- switch op {
- case token.Add:
- r := o.Value + rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Char{Value: r}, nil
- case token.Sub:
- r := o.Value - rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Char{Value: r}, nil
- case token.Less:
- if o.Value < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case *Int:
- switch op {
- case token.Add:
- r := o.Value + rune(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Char{Value: r}, nil
- case token.Sub:
- r := o.Value - rune(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Char{Value: r}, nil
- case token.Less:
- if int64(o.Value) < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if int64(o.Value) > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if int64(o.Value) <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if int64(o.Value) >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
- return nil, ErrInvalidOperator
- }
- // Copy returns a copy of the type.
- func (o *Char) Copy() Object {
- return &Char{Value: o.Value}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Char) IsFalsy() bool {
- return o.Value == 0
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Char) Equals(x Object) bool {
- t, ok := x.(*Char)
- if !ok {
- return false
- }
- return o.Value == t.Value
- }
- // CompiledFunction represents a compiled function.
- type CompiledFunction struct {
- ObjectImpl
- Instructions []byte
- NumLocals int // number of local variables (including function parameters)
- NumParameters int
- VarArgs bool
- SourceMap map[int]parser.Pos
- Free []*ObjectPtr
- }
- // TypeName returns the name of the type.
- func (o *CompiledFunction) TypeName() string {
- return "compiled-function"
- }
- func (o *CompiledFunction) String() string {
- return "<compiled-function>"
- }
- // Copy returns a copy of the type.
- func (o *CompiledFunction) Copy() Object {
- return &CompiledFunction{
- Instructions: append([]byte{}, o.Instructions...),
- NumLocals: o.NumLocals,
- NumParameters: o.NumParameters,
- VarArgs: o.VarArgs,
- Free: append([]*ObjectPtr{}, o.Free...), // DO NOT Copy() of elements; these are variable pointers
- }
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *CompiledFunction) Equals(_ Object) bool {
- return false
- }
- // SourcePos returns the source position of the instruction at ip.
- func (o *CompiledFunction) SourcePos(ip int) parser.Pos {
- for ip >= 0 {
- if p, ok := o.SourceMap[ip]; ok {
- return p
- }
- ip--
- }
- return parser.NoPos
- }
- // CanCall returns whether the Object can be Called.
- func (o *CompiledFunction) CanCall() bool {
- return true
- }
- // Error represents an error value.
- type Error struct {
- ObjectImpl
- Value Object
- }
- // TypeName returns the name of the type.
- func (o *Error) TypeName() string {
- return "error"
- }
- func (o *Error) String() string {
- if o.Value != nil {
- return fmt.Sprintf("error: %s", o.Value.String())
- }
- return "error"
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Error) IsFalsy() bool {
- return true // error is always false.
- }
- // Copy returns a copy of the type.
- func (o *Error) Copy() Object {
- return &Error{Value: o.Value.Copy()}
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Error) Equals(x Object) bool {
- return o == x // pointer equality
- }
- // IndexGet returns an element at a given index.
- func (o *Error) IndexGet(index Object) (res Object, err error) {
- if strIdx, _ := ToString(index); strIdx != "value" {
- err = ErrInvalidIndexOnError
- return
- }
- res = o.Value
- return
- }
- // Float represents a floating point number value.
- type Float struct {
- ObjectImpl
- Value float64
- }
- func (o *Float) String() string {
- return strconv.FormatFloat(o.Value, 'f', -1, 64)
- }
- // TypeName returns the name of the type.
- func (o *Float) TypeName() string {
- return "float"
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *Float) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch rhs := rhs.(type) {
- case *Float:
- switch op {
- case token.Add:
- r := o.Value + rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Sub:
- r := o.Value - rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Mul:
- r := o.Value * rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Quo:
- r := o.Value / rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Less:
- if o.Value < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case *Int:
- switch op {
- case token.Add:
- r := o.Value + float64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Sub:
- r := o.Value - float64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Mul:
- r := o.Value * float64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Quo:
- r := o.Value / float64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Less:
- if o.Value < float64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > float64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= float64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= float64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
- return nil, ErrInvalidOperator
- }
- // Copy returns a copy of the type.
- func (o *Float) Copy() Object {
- return &Float{Value: o.Value}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Float) IsFalsy() bool {
- return math.IsNaN(o.Value)
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Float) Equals(x Object) bool {
- t, ok := x.(*Float)
- if !ok {
- return false
- }
- return o.Value == t.Value
- }
- // ImmutableArray represents an immutable array of objects.
- type ImmutableArray struct {
- ObjectImpl
- Value []Object
- }
- // TypeName returns the name of the type.
- func (o *ImmutableArray) TypeName() string {
- return "immutable-array"
- }
- func (o *ImmutableArray) String() string {
- var elements []string
- for _, e := range o.Value {
- elements = append(elements, e.String())
- }
- return fmt.Sprintf("[%s]", strings.Join(elements, ", "))
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *ImmutableArray) BinaryOp(op token.Token, rhs Object) (Object, error) {
- if rhs, ok := rhs.(*ImmutableArray); ok {
- switch op {
- case token.Add:
- return &Array{Value: append(o.Value, rhs.Value...)}, nil
- }
- }
- return nil, ErrInvalidOperator
- }
- // Copy returns a copy of the type.
- func (o *ImmutableArray) Copy() Object {
- var c []Object
- for _, elem := range o.Value {
- c = append(c, elem.Copy())
- }
- return &Array{Value: c}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *ImmutableArray) IsFalsy() bool {
- return len(o.Value) == 0
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *ImmutableArray) Equals(x Object) bool {
- var xVal []Object
- switch x := x.(type) {
- case *Array:
- xVal = x.Value
- case *ImmutableArray:
- xVal = x.Value
- default:
- return false
- }
- if len(o.Value) != len(xVal) {
- return false
- }
- for i, e := range o.Value {
- if !e.Equals(xVal[i]) {
- return false
- }
- }
- return true
- }
- // IndexGet returns an element at a given index.
- func (o *ImmutableArray) IndexGet(index Object) (res Object, err error) {
- intIdx, ok := index.(*Int)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
- idxVal := int(intIdx.Value)
- if idxVal < 0 || idxVal >= len(o.Value) {
- res = UndefinedValue
- return
- }
- res = o.Value[idxVal]
- return
- }
- // Iterate creates an array iterator.
- func (o *ImmutableArray) Iterate() Iterator {
- return &ArrayIterator{
- v: o.Value,
- l: len(o.Value),
- }
- }
- // CanIterate returns whether the Object can be Iterated.
- func (o *ImmutableArray) CanIterate() bool {
- return true
- }
- // ImmutableMap represents an immutable map object.
- type ImmutableMap struct {
- ObjectImpl
- Value map[string]Object
- }
- // TypeName returns the name of the type.
- func (o *ImmutableMap) TypeName() string {
- return "immutable-map"
- }
- func (o *ImmutableMap) String() string {
- var pairs []string
- for k, v := range o.Value {
- pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
- }
- return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
- }
- // Copy returns a copy of the type.
- func (o *ImmutableMap) Copy() Object {
- c := make(map[string]Object)
- for k, v := range o.Value {
- c[k] = v.Copy()
- }
- return &Map{Value: c}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *ImmutableMap) IsFalsy() bool {
- return len(o.Value) == 0
- }
- // IndexGet returns the value for the given key.
- func (o *ImmutableMap) IndexGet(index Object) (res Object, err error) {
- strIdx, ok := ToString(index)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
- res, ok = o.Value[strIdx]
- if !ok {
- res = UndefinedValue
- }
- return
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *ImmutableMap) Equals(x Object) bool {
- var xVal map[string]Object
- switch x := x.(type) {
- case *Map:
- xVal = x.Value
- case *ImmutableMap:
- xVal = x.Value
- default:
- return false
- }
- if len(o.Value) != len(xVal) {
- return false
- }
- for k, v := range o.Value {
- tv := xVal[k]
- if !v.Equals(tv) {
- return false
- }
- }
- return true
- }
- // Iterate creates an immutable map iterator.
- func (o *ImmutableMap) Iterate() Iterator {
- var keys []string
- for k := range o.Value {
- keys = append(keys, k)
- }
- return &MapIterator{
- v: o.Value,
- k: keys,
- l: len(keys),
- }
- }
- // CanIterate returns whether the Object can be Iterated.
- func (o *ImmutableMap) CanIterate() bool {
- return true
- }
- // Int represents an integer value.
- type Int struct {
- ObjectImpl
- Value int64
- }
- func (o *Int) String() string {
- return strconv.FormatInt(o.Value, 10)
- }
- // TypeName returns the name of the type.
- func (o *Int) TypeName() string {
- return "int"
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch rhs := rhs.(type) {
- case *Int:
- switch op {
- case token.Add:
- r := o.Value + rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Sub:
- r := o.Value - rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Mul:
- r := o.Value * rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Quo:
- r := o.Value / rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Rem:
- r := o.Value % rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.And:
- r := o.Value & rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Or:
- r := o.Value | rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Xor:
- r := o.Value ^ rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.AndNot:
- r := o.Value &^ rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Shl:
- r := o.Value << uint64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Shr:
- r := o.Value >> uint64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Less:
- if o.Value < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case *Float:
- switch op {
- case token.Add:
- return &Float{Value: float64(o.Value) + rhs.Value}, nil
- case token.Sub:
- return &Float{Value: float64(o.Value) - rhs.Value}, nil
- case token.Mul:
- return &Float{Value: float64(o.Value) * rhs.Value}, nil
- case token.Quo:
- return &Float{Value: float64(o.Value) / rhs.Value}, nil
- case token.Less:
- if float64(o.Value) < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if float64(o.Value) > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if float64(o.Value) <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if float64(o.Value) >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case *Char:
- switch op {
- case token.Add:
- return &Char{Value: rune(o.Value) + rhs.Value}, nil
- case token.Sub:
- return &Char{Value: rune(o.Value) - rhs.Value}, nil
- case token.Less:
- if o.Value < int64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > int64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= int64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= int64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
- return nil, ErrInvalidOperator
- }
- // Copy returns a copy of the type.
- func (o *Int) Copy() Object {
- return &Int{Value: o.Value}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Int) IsFalsy() bool {
- return o.Value == 0
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Int) Equals(x Object) bool {
- t, ok := x.(*Int)
- if !ok {
- return false
- }
- return o.Value == t.Value
- }
- // Map represents a map of objects.
- type Map struct {
- ObjectImpl
- Value map[string]Object
- }
- // TypeName returns the name of the type.
- func (o *Map) TypeName() string {
- return "map"
- }
- func (o *Map) String() string {
- var pairs []string
- for k, v := range o.Value {
- pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
- }
- return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
- }
- // Copy returns a copy of the type.
- func (o *Map) Copy() Object {
- c := make(map[string]Object)
- for k, v := range o.Value {
- c[k] = v.Copy()
- }
- return &Map{Value: c}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Map) IsFalsy() bool {
- return len(o.Value) == 0
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Map) Equals(x Object) bool {
- var xVal map[string]Object
- switch x := x.(type) {
- case *Map:
- xVal = x.Value
- case *ImmutableMap:
- xVal = x.Value
- default:
- return false
- }
- if len(o.Value) != len(xVal) {
- return false
- }
- for k, v := range o.Value {
- tv := xVal[k]
- if !v.Equals(tv) {
- return false
- }
- }
- return true
- }
- // IndexGet returns the value for the given key.
- func (o *Map) IndexGet(index Object) (res Object, err error) {
- strIdx, ok := ToString(index)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
- res, ok = o.Value[strIdx]
- if !ok {
- res = UndefinedValue
- }
- return
- }
- // IndexSet sets the value for the given key.
- func (o *Map) IndexSet(index, value Object) (err error) {
- strIdx, ok := ToString(index)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
- o.Value[strIdx] = value
- return nil
- }
- // Iterate creates a map iterator.
- func (o *Map) Iterate() Iterator {
- var keys []string
- for k := range o.Value {
- keys = append(keys, k)
- }
- return &MapIterator{
- v: o.Value,
- k: keys,
- l: len(keys),
- }
- }
- // CanIterate returns whether the Object can be Iterated.
- func (o *Map) CanIterate() bool {
- return true
- }
- // ObjectPtr represents a free variable.
- type ObjectPtr struct {
- ObjectImpl
- Value *Object
- }
- func (o *ObjectPtr) String() string {
- return "free-var"
- }
- // TypeName returns the name of the type.
- func (o *ObjectPtr) TypeName() string {
- return "<free-var>"
- }
- // Copy returns a copy of the type.
- func (o *ObjectPtr) Copy() Object {
- return o
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *ObjectPtr) IsFalsy() bool {
- return o.Value == nil
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *ObjectPtr) Equals(x Object) bool {
- return o == x
- }
- // String represents a string value.
- type String struct {
- ObjectImpl
- Value string
- runeStr []rune
- }
- // TypeName returns the name of the type.
- func (o *String) TypeName() string {
- return "string"
- }
- func (o *String) String() string {
- return strconv.Quote(o.Value)
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *String) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch op {
- case token.Add:
- switch rhs := rhs.(type) {
- case *String:
- if len(o.Value)+len(rhs.Value) > MaxStringLen {
- return nil, ErrStringLimit
- }
- return &String{Value: o.Value + rhs.Value}, nil
- default:
- rhsStr := rhs.String()
- if len(o.Value)+len(rhsStr) > MaxStringLen {
- return nil, ErrStringLimit
- }
- return &String{Value: o.Value + rhsStr}, nil
- }
- case token.Less:
- switch rhs := rhs.(type) {
- case *String:
- if o.Value < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case token.LessEq:
- switch rhs := rhs.(type) {
- case *String:
- if o.Value <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case token.Greater:
- switch rhs := rhs.(type) {
- case *String:
- if o.Value > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case token.GreaterEq:
- switch rhs := rhs.(type) {
- case *String:
- if o.Value >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
- return nil, ErrInvalidOperator
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *String) IsFalsy() bool {
- return len(o.Value) == 0
- }
- // Copy returns a copy of the type.
- func (o *String) Copy() Object {
- return &String{Value: o.Value}
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *String) Equals(x Object) bool {
- t, ok := x.(*String)
- if !ok {
- return false
- }
- return o.Value == t.Value
- }
- // IndexGet returns a character at a given index.
- func (o *String) IndexGet(index Object) (res Object, err error) {
- intIdx, ok := index.(*Int)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
- idxVal := int(intIdx.Value)
- if o.runeStr == nil {
- o.runeStr = []rune(o.Value)
- }
- if idxVal < 0 || idxVal >= len(o.runeStr) {
- res = UndefinedValue
- return
- }
- res = &Char{Value: o.runeStr[idxVal]}
- return
- }
- // Iterate creates a string iterator.
- func (o *String) Iterate() Iterator {
- if o.runeStr == nil {
- o.runeStr = []rune(o.Value)
- }
- return &StringIterator{
- v: o.runeStr,
- l: len(o.runeStr),
- }
- }
- // CanIterate returns whether the Object can be Iterated.
- func (o *String) CanIterate() bool {
- return true
- }
- // Time represents a time value.
- type Time struct {
- ObjectImpl
- Value time.Time
- }
- func (o *Time) String() string {
- return o.Value.String()
- }
- // TypeName returns the name of the type.
- func (o *Time) TypeName() string {
- return "time"
- }
- // BinaryOp returns another object that is the result of a given binary
- // operator and a right-hand side object.
- func (o *Time) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch rhs := rhs.(type) {
- case *Int:
- switch op {
- case token.Add: // time + int => time
- if rhs.Value == 0 {
- return o, nil
- }
- return &Time{Value: o.Value.Add(time.Duration(rhs.Value))}, nil
- case token.Sub: // time - int => time
- if rhs.Value == 0 {
- return o, nil
- }
- return &Time{Value: o.Value.Add(time.Duration(-rhs.Value))}, nil
- }
- case *Time:
- switch op {
- case token.Sub: // time - time => int (duration)
- return &Int{Value: int64(o.Value.Sub(rhs.Value))}, nil
- case token.Less: // time < time => bool
- if o.Value.Before(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value.After(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value.Equal(rhs.Value) || o.Value.Before(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value.Equal(rhs.Value) || o.Value.After(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
- return nil, ErrInvalidOperator
- }
- // Copy returns a copy of the type.
- func (o *Time) Copy() Object {
- return &Time{Value: o.Value}
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Time) IsFalsy() bool {
- return o.Value.IsZero()
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Time) Equals(x Object) bool {
- t, ok := x.(*Time)
- if !ok {
- return false
- }
- return o.Value.Equal(t.Value)
- }
- // Undefined represents an undefined value.
- type Undefined struct {
- ObjectImpl
- }
- // TypeName returns the name of the type.
- func (o *Undefined) TypeName() string {
- return "undefined"
- }
- func (o *Undefined) String() string {
- return "<undefined>"
- }
- // Copy returns a copy of the type.
- func (o *Undefined) Copy() Object {
- return o
- }
- // IsFalsy returns true if the value of the type is falsy.
- func (o *Undefined) IsFalsy() bool {
- return true
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *Undefined) Equals(x Object) bool {
- return o == x
- }
- // IndexGet returns an element at a given index.
- func (o *Undefined) IndexGet(_ Object) (Object, error) {
- return UndefinedValue, nil
- }
- // Iterate creates a map iterator.
- func (o *Undefined) Iterate() Iterator {
- return o
- }
- // CanIterate returns whether the Object can be Iterated.
- func (o *Undefined) CanIterate() bool {
- return true
- }
- // Next returns true if there are more elements to iterate.
- func (o *Undefined) Next() bool {
- return false
- }
- // Key returns the key or index value of the current element.
- func (o *Undefined) Key() Object {
- return o
- }
- // Value returns the value of the current element.
- func (o *Undefined) Value() Object {
- return o
- }
- // UserFunction represents a user function.
- type UserFunction struct {
- ObjectImpl
- Name string
- Value CallableFunc
- }
- // TypeName returns the name of the type.
- func (o *UserFunction) TypeName() string {
- return "user-function:" + o.Name
- }
- func (o *UserFunction) String() string {
- return "<user-function>"
- }
- // Copy returns a copy of the type.
- func (o *UserFunction) Copy() Object {
- return &UserFunction{Value: o.Value, Name: o.Name}
- }
- // Equals returns true if the value of the type is equal to the value of
- // another object.
- func (o *UserFunction) Equals(_ Object) bool {
- return false
- }
- // Call invokes a user function.
- func (o *UserFunction) Call(args ...Object) (Object, error) {
- return o.Value(args...)
- }
- // CanCall returns whether the Object can be Called.
- func (o *UserFunction) CanCall() bool {
- return true
- }
|