123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- 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"
- )
- // IsReturner is a marker interface for types that cause
- // a return.
- type IsReturner interface{ IsReturn() }
- // Breaker is a marker interface for a type that cases
- // a break in flow.
- type IsBreaker interface{ IsBreak() }
- // A Thrower is a marker interface for a type that causes
- // a throw.
- type IsThrower interface{ IsThrow() }
- // Type is the type of an object. It is simply a string.
- type Type string
- // A message can be send to an object. It is also an object.
- type Message struct {
- Name string
- Args []Object
- Env Object
- Actor
- }
- func (m Message) String() string {
- return "message: " + m.Name
- }
- func (Message) Type() Type {
- return Type("message")
- }
- func (m Message) Value(env Object) Object {
- return m
- }
- func (m Message) Send(Message) Object {
- return m
- }
- // Object is the interface for all objects in SELSL.
- type Object interface {
- // String stringifies the value of the object.
- String() string
- // Type returns the name of the type in lower case.
- Type() Type
- // Value evaluates the object in a context.
- Value(env Object) Object
- // Send sends a message to the object.
- Send(msg Message) Object
- }
- type NilObject struct{}
- func (NilObject) String() string {
- return "nil"
- }
- func (NilObject) Value(env Object) Object {
- return nil
- }
- func (NilObject) Type() Type {
- return Type("nil")
- }
- func (NilObject) Send(Message) Object {
- return Nil
- }
- var Nil Object = NilObject{}
- func ParentOf(val Object) Object {
- return val.Send(Message{Name: 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 SendInEnv(to Object, message string, env Object) Object {
- 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.Value(env)
- }
- func Send(to Object, message string, me, here Object, args ...Object) Object {
- env := NewEnvironment(here, me, to, args...)
- return SendInEnv(to, message, env)
- }
- */
- // Instance is a concrete implementation of Object
- // which can be embedded into Go structs to help them
- // become Objects themselves.
- type Instance struct {
- // the type of the instance, used in Type()
- kind Type
- // Slots, used to store members
- slots Slots
- }
- // String stringifies the value of the instance.
- func (i Instance) String() string {
- res := string(i.kind) + " { "
- for k, v := range i.slots {
- res += "\n" + k + ":" + v.String()
- }
- res += " } "
- return res
- }
- func (i Instance) Type() Type {
- return Type(i.kind)
- }
- func (i Instance) Value(env Object) Object {
- return i
- }
- func (i Instance) Send(message Message) Object {
- value := i.slots.Get(message.Name)
- if value == nil || value == Nil {
- // XXX should return an error in stead.
- return Nil
- }
- return value.Value(message.Env)
- }
- func (i *Instance) Set(name string, inst Object) *Instance {
- i.slots.Set(name, inst)
- return i
- }
- func NewInstance(kind string) *Instance {
- return &Instance{kind: Type(kind), slots: Slots{}}
- }
- // A primitive is a function implemented in Go that
- // on evaluation as an Object calls that function
- // with the given environment
- type Primitive func(env Object) Object
- func (p Primitive) Type() Type {
- return Type("primitive")
- }
- func (p Primitive) Send(m Message) Object {
- return p.Value(m)
- }
- func (p Primitive) Value(env Object) Object {
- return p(env)
- }
- func Self(o Object) Object {
- return o.Send(Message{Name: SelfSlot})
- }
- func Me(o Object) Object {
- return o.Send(Message{Name: MeSlot})
- }
- func Args(o Object) List {
- list := o.Send(Message{Name: 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) String() string {
- return string(s)
- }
- func (s String) Type() Type {
- return Type("string")
- }
- func (p String) Send(m Message) Object {
- // XXX implement string methods here
- return Nil
- }
- func (s String) Value(env Object) Object {
- return s
- }
- type List []Object
- func (l List) Type() Type {
- return Type("list")
- }
- func (l List) String() string {
- res := fmt.Sprintf("list: ")
- sep := ""
- for _, o := range l {
- res = fmt.Sprintf("%s %s %s", res, sep, o.String())
- sep = "and"
- }
- res += ";"
- return res
- }
- func (l List) Send(m Message) Object {
- // XXX implement list methods here
- return Nil
- }
- func (l List) Value(env Object) Object {
- return l
- }
- type Error struct {
- *Instance
- Error error
- }
- func (e Error) String() string {
- return fmt.Sprintf("error `%s`", e.Error)
- }
- func (e Error) Value(env Object) Object {
- return e
- }
- func NewErrorBasic(err error) Error {
- return Error{Instance: NewInstance("error"), Error: err}
- }
- func NewError(err string) Error {
- return NewErrorBasic(fmt.Errorf("%s", err))
- }
- type Int struct {
- *Instance
- Int int64
- }
- func NewInt(i int64) Int {
- return Int{Instance: NewInstance("int"), Int: i}
- }
- func (i Int) String() string {
- return fmt.Sprintf("%d", i.Int)
- }
- func (i Int) Value(env Object) Object {
- return i
- }
- type Statement struct {
- *Instance
- Command Object
- Param List
- }
- func (s Statement) String() string {
- return fmt.Sprintf("%s %s.", s.Command.String(), s.Param.String())
- }
- /*
- func (s Statement) Value(env Object) Object {
- cenv := env
- cenv.Slots().Set(ArgsSlot, s.Param)
- return SendInEnv(env, s.Command.Name(), cenv)
- }*/
- var _ Object = Error{}
- var _ Object = String("")
- var _ Object = Int{}
- var _ Object = List{}
|