package selsl import "fmt" type Slots map[string]Object func (s Slots) Set(name string, inst Object) Slots { s[name] = inst return s } func (s Slots) Get(name string) Object { res, ok := s[name] if !ok { return Nil } return res } func (s Slots) Clone() Slots { clone := Slots{} for k, v := range s { clone[k] = v.Clone() } return clone } // Constants for special object slot names const ( ParentSlot = "*parent" SelfSlot = "*self" MeSlot = "*me" ArgsSlot = "*args" ) // Effect is the effect an object has on return from a Run type Effect int // Constants for effects const ( EffectNone Effect = 0 EffectBreak Effect = 1 EffectReturn Effect = 2 EffectThrow Effect = 4 ) // Object is the interface for all objects in SELSL. type Object interface { Name() string Slots() Slots Run(env Object) Object Effect() Effect Clone() Object } var Nil Object = NewInstance("nil") func ParentOf(val Object) Object { return val.Slots().Get(ParentSlot) } type Environment struct { Instance } func NewEnvironment(parent, me, to Object, args ...Object) *Environment { name := "_env" if parent != nil { name = parent.Name() + "_env" } res := &Environment{Instance{name: name, slots: Slots{}}} res.Set(ParentSlot, parent) res.Set(SelfSlot, to) res.Set(ArgsSlot, List(args)) res.Set(MeSlot, me) return res } func Send(to Object, message string, me, here Object, args ...Object) Object { env := NewEnvironment(here, me, to, args...) lookup := to value := lookup.Slots().Get(message) for value == Nil { lookup = ParentOf(lookup) if lookup == Nil || lookup == nil { panic("Object does not support message " + message) } value = lookup.Slots().Get(message) } return value.Run(env) } type Instance struct { name string slots Slots } func (i Instance) Name() string { return i.name } func (i Instance) Slots() Slots { return i.slots } func (i Instance) Effect() Effect { return EffectNone } func (i Instance) Run(env Object) Object { return i } func (i *Instance) Set(name string, inst Object) *Instance { i.slots.Set(name, inst) return i } func (i Instance) DeepCopy() Instance { return Instance{name: i.name + "", slots: i.slots.Clone()} } func (i Instance) Clone() Object { return i.DeepCopy() } func NewInstance(name string) *Instance { return &Instance{name: name, slots: Slots{}} } type Primitive func(env Object) Object func (p Primitive) Name() string { return "primitive" } func (p Primitive) Slots() Slots { emptySlots := Slots{} return emptySlots } func (p Primitive) Effect() Effect { return EffectNone } func (p Primitive) Run(env Object) Object { return p(env) } func (p Primitive) Clone() Object { return p } func Self(o Object) Object { return o.Slots().Get(SelfSlot) } func Me(o Object) Object { return o.Slots().Get(MeSlot) } func Args(o Object) List { list := o.Slots().Get(ArgsSlot) if list == Nil { return List{} } return list.(List) } func Unary(unary func(target Object) Object) Primitive { return func(env Object) Object { return unary(Self(env)) } } func Nullary(nullary func() Object) Primitive { return func(env Object) Object { return nullary() } } type String string func (s String) Name() string { return string(s) } var StringType Object = NewInstance("String"). Set(ParentSlot, RootType) var StringSlots Slots = Slots{}.Set(ParentSlot, StringType) func (s String) Slots() Slots { return StringSlots } func (s String) Effect() Effect { return EffectNone } func (s String) Run(env Object) Object { return s } func (s String) Clone() Object { return String(s + "") } func NameOf(o Object) Object { return String(o.Name()) } func NameString(o Object) func() Object { return func() Object { return NameOf(o) } } var RootType Object = NewInstance("Type").Set("name", Unary(NameOf)) type List []Object func (l List) Name() string { res := fmt.Sprintf("list: ") sep := "" for _, o := range l { res = fmt.Sprintf("%s %s %s", res, sep, o.Name()) sep = "and" } res += ";" return res } var ListType Object = NewInstance("List"). Set(ParentSlot, RootType) var ListSlots Slots = Slots{}.Set(ParentSlot, ListType) func (l List) Slots() Slots { return ListSlots } func (l List) Effect() Effect { return EffectNone } func (l List) Run(env Object) Object { return l } func (l List) DeepCopy() List { res := List{} for _, o := range l { res = append(res, o.Clone()) } return res } func (l List) Clone() Object { return l.DeepCopy() } /* var RootType Object = NewInstance("Type").Slot("string") var InstanceType Type = NewType("Instance", &RootType, nil) var ErrorType Type = NewType("Error", &InstanceType, nil) var StringType Type = NewType("String", &InstanceType, nil) var IntType Type = NewType("Int", &InstanceType, nil) var ListType Type = NewType("List", &InstanceType, nil) var MethodType Type = NewType("Method", &InstanceType, nil) type Error struct { Instance Object error } func (s Error) String() string { return fmt.Sprintf("%s", s.Object) } func NewError(name string, Slots Slots, Object error) Error { return Error{Instance: NewInstance(name, ErrorType, Slots), Object: Object} } type Int struct { Instance Object int64 } func NewInt(name string, Slots Slots, Object int64) Int { return Int{Instance: NewInstance(name, IntType, Slots), Object: Object} } func (i Int) String() string { return fmt.Sprintf("%d", i.Object) } type List struct { Instance Object []Object } func NewList(name string, Slots Slots, Object ...Object) List { return List{Instance: NewInstance(name, ListType, Slots), Object: Object} } func (l List) String() string { return fmt.Sprintf("[%v]", l.Object) } type Method struct { Instance Signature List Object func(env Object, self Object, args ...Object) List } func NewMethod(name string, Slots Slots, signature List, Object func(env Object, self Object, args ...Object) List) Method { return Method{Instance: NewInstance(name, MethodType, Slots), Signature: signature, Object: Object} } func (m Method) String() string { return fmt.Sprintf("Method: %s", m.Name()) } var _ Object = RootType var _ Object = InstanceType var _ Object = Error{} var _ Object = String{} var _ Object = Int{} var _ Object = List{} var _ Object = Method{} */