func (self *Pair) Eval(env *scope.Scope) value.Value { var first value.Value var second value.Value if self.Second == NilPair { second = value.NilPairValue } else { switch self.Second.(type) { case *Name: second = value.NewSymbol(self.Second.(*Name).Identifier) default: second = self.Second.Eval(env) } } if name, ok := self.First.(*Name); ok { // treat Name as Symbol first = value.NewSymbol(name.Identifier) } else if _, ok := self.First.(*UnquoteBase); ok { // our parser garantees unquote-splicing only appears in quasiquote // and unquote-splicing will be evaluated to a list first = self.First.Eval(env) // () empty list must be handled if first == value.NilPairValue { return second } // seek for the last element var last value.Value = first for { switch last.(type) { case *value.PairValue: pair := last.(*value.PairValue) if pair.Second == value.NilPairValue { pair.Second = second return first } last = pair.Second default: if second == value.NilPairValue { return first } else { // `(,@(cdr '(1 . 2) 3)) panic(fmt.Sprintf("unquote-splicing: expected list?, given: %s", first)) } } } } else { first = self.First.Eval(env) } return value.NewPairValue(first, second) }
func (self *TypeOf) Apply(args []value.Value) value.Value { if len(args) != 1 { panic(fmt.Sprint("argument mismatch for `type-of', expected 1, given: ", len(args))) } symbol := "unknown" switch args[0].(type) { case *value.IntValue: symbol = "integer" case *value.FloatValue: symbol = "float" case *value.BoolValue: symbol = "bool" case *value.StringValue: symbol = "string" case *value.Channel: symbol = "channel" case *value.EmptyPairValue: symbol = "nilpair" case *value.PairValue: symbol = "pair" case *value.Closure: symbol = "procedure" case value.PrimFunc: symbol = "procedure" case *value.Symbol: symbol = args[0].(*value.Symbol).Value } return value.NewSymbol(symbol) }
func (self *QuoteBase) Eval(env *scope.Scope) value.Value { if name, ok := self.Body.(*Name); ok { return value.NewSymbol(name.Identifier) } else { return self.Body.Eval(env) } }