|
@@ -0,0 +1,323 @@
|
|
|
+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) Clone() Slots {
|
|
|
+ clone := Slots{}
|
|
|
+ for k, v := range s {
|
|
|
+ clone[k] = v.Clone()
|
|
|
+ }
|
|
|
+ return clone
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const (
|
|
|
+ ParentSlot = "*parent"
|
|
|
+ SelfSlot = "*self"
|
|
|
+ MeSlot = "*me"
|
|
|
+ ArgsSlot = "*args"
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+type Effect int
|
|
|
+
|
|
|
+
|
|
|
+const (
|
|
|
+ EffectNone Effect = 0
|
|
|
+ EffectBreak Effect = 1
|
|
|
+ EffectReturn Effect = 2
|
|
|
+ EffectThrow Effect = 4
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+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 {
|
|
|
+ res, ok := val.Slots()[ParentSlot]
|
|
|
+ if ok {
|
|
|
+ return res
|
|
|
+ }
|
|
|
+ return Nil
|
|
|
+}
|
|
|
+
|
|
|
+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, ok := lookup.Slots()[message]
|
|
|
+ for !ok || value == nil {
|
|
|
+ lookup = ParentOf(lookup)
|
|
|
+ if lookup == Nil || lookup == nil {
|
|
|
+ panic("Object does not support message " + message)
|
|
|
+ }
|
|
|
+ value, ok = lookup.Slots()[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()[SelfSlot]
|
|
|
+}
|
|
|
+
|
|
|
+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{}
|
|
|
+*/
|