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.(*UnquoteSplicing); 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 *Cons) Apply(args []value.Value) value.Value { if len(args) != 2 { panic(fmt.Sprintf("cons: arguments mismatch, expected: 2, given: ", args)) } return value.NewPairValue(args[0], args[1]) }