123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- 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{}
- */
|