예제 #1
0
파일: apply.go 프로젝트: luoxing91/goLisp
// (1 2 '(3)) => (1 2 3)
func ExpandApplyArgs(args []value.Value) value.Value {
	prev := value.NewPairValue(nil, nil)
	curr := value.NewPairValue(nil, nil)
	front := prev
	expectlist := false

	for i, arg := range args {
		switch arg.(type) {
		case *value.PairValue:
			prev.Second = arg.(*value.PairValue)
			for {
				if _, ok := arg.(*value.PairValue); ok {
					arg = arg.(*value.PairValue).Second
				} else if _, ok := arg.(*value.EmptyPairValue); ok {
					break
				} else {
					panic(fmt.Sprint("apply: expected list, given: ", arg))
				}
			}
			expectlist = false
			if i != len(args)-1 {
				panic(fmt.Sprint("apply: expected list, given: ", arg))
			}
		case *value.EmptyPairValue:
			expectlist = false
			if i != len(args)-1 {
				panic(fmt.Sprint("apply: expected list, given: ", arg))
			}
		default:
			expectlist = true
			curr.First = arg
			prev.Second = curr
			prev = curr
			curr = value.NewPairValue(nil, nil)
		}
	}
	if expectlist {
		panic(fmt.Sprint("apply: expected list, given: ", args[len(args)-1]))
	}
	return front.Second
}
예제 #2
0
파일: ast.go 프로젝트: luoxing91/goLisp
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)
}
예제 #3
0
파일: cdr.go 프로젝트: luoxing91/goLisp
func (self *Cons) Apply(args []value.Value) value.Value {
	checkargsnumber(args, 2)
	return value.NewPairValue(args[0], args[1])
}