fixed quote bug

master
Jordan Orelli 12 years ago
parent c4fed38dd9
commit b387d909b5

@ -144,13 +144,11 @@ var length = builtin{
name: "length",
arity: 1,
fn: func(vals []interface{}) (interface{}, error) {
switch t := vals[0].(type) {
case sexp:
return len(t), nil
case list:
return len(t.sexp), nil
}
s, ok := vals[0].(*sexp)
if !ok {
return nil, fmt.Errorf("first argument must be sexp, received %v", reflect.TypeOf(vals[0]))
}
return len(s.items), nil
},
}
@ -158,7 +156,7 @@ var lst = builtin{
name: "list",
variadic: true,
fn: func(vals []interface{}) (interface{}, error) {
return list{sexp(vals), 1}, nil
return &sexp{items: vals, quotelvl: 1}, nil
},
}
@ -166,11 +164,8 @@ var islist = builtin{
name: "list?",
arity: 1,
fn: func(vals []interface{}) (interface{}, error) {
switch vals[0].(type) {
case list, sexp:
return true, nil
}
return false, nil
_, ok := vals[0].(*sexp)
return ok, nil
},
}
@ -178,11 +173,11 @@ var isnull = builtin{
name: "null?",
arity: 1,
fn: func(vals []interface{}) (interface{}, error) {
s, ok := vals[0].(sexp)
s, ok := vals[0].(*sexp)
if !ok {
return false, nil
}
return len(s) == 0, nil
return len(s.items) == 0, nil
},
}
@ -199,14 +194,14 @@ var cons = builtin{
name: "cons",
arity: 2,
fn: func(vals []interface{}) (interface{}, error) {
s := sexp{vals[0]}
s := &sexp{items: vals[0:1]}
switch t := vals[1].(type) {
case sexp:
return append(s, t...), nil
case *sexp:
s.items = append(s.items, t.items...)
default:
return append(s, t), nil
s.items = append(s.items, t)
}
panic("not reached")
return s, nil
},
}
@ -214,11 +209,11 @@ var car = builtin{
name: "car",
arity: 1,
fn: func(vals []interface{}) (interface{}, error) {
s, ok := vals[0].(sexp)
s, ok := vals[0].(*sexp)
if !ok {
return nil, errors.New("expected list")
}
return s[0], nil
return s.items[0], nil
},
}
@ -226,10 +221,10 @@ var cdr = builtin{
name: "cdr",
arity: 1,
fn: func(vals []interface{}) (interface{}, error) {
s, ok := vals[0].(sexp)
s, ok := vals[0].(*sexp)
if !ok {
return nil, errors.New("expected list")
}
return s[1:], nil
return s.items[1:], nil
},
}

@ -13,23 +13,32 @@ import (
var DEBUG = false
type sexp []interface{}
type sexp struct {
items []interface{}
quotelvl int
}
func newSexp() *sexp {
return &sexp{
items: make([]interface{}, 0, 8),
quotelvl: 0,
}
}
func (s sexp) String() string {
parts := make([]string, len(s))
for i, _ := range s {
parts[i] = fmt.Sprint(s[i])
parts := make([]string, len(s.items))
for i, _ := range s.items {
parts[i] = fmt.Sprint(s.items[i])
}
return "(" + strings.Join(parts, " ") + ")"
}
type list struct {
sexp
quotelevel int
func (s *sexp) append(item interface{}) {
s.items = append(s.items, item)
}
func (l list) String() string {
return l.sexp.String()
func (s sexp) len() int {
return len(s.items)
}
type symbol string
@ -106,17 +115,17 @@ func (s *sexp) readIn(c chan token) error {
case closeParenToken:
return nil
case openParenToken:
child := make(sexp, 0)
child := newSexp()
if err := child.readIn(c); err != nil {
return err
}
*s = append(*s, child)
s.append(child)
default:
v, err := atom(t)
if err != nil {
return err
}
*s = append(*s, v)
s.append(v)
}
}
return errors.New("unexpected EOF in sexp.readIn")
@ -129,7 +138,7 @@ func parse(c chan token) (interface{}, error) {
case closeParenToken:
return nil, errors.New("unexpected EOF in read")
case openParenToken:
s := make(sexp, 0)
s := newSexp()
if err := s.readIn(c); err != nil {
return nil, err
}
@ -143,7 +152,7 @@ func parse(c chan token) (interface{}, error) {
func eval(v interface{}, env *environment) (interface{}, error) {
if v == nil {
return sexp{}, nil
return &sexp{}, nil
}
switch t := v.(type) {
@ -156,22 +165,27 @@ func eval(v interface{}, env *environment) (interface{}, error) {
}
return eval(s, env)
case sexp:
case *sexp:
debugPrint("eval sexp")
if len(t) == 0 {
if t.len() == 0 {
return nil, errors.New("illegal evaluation of empty sexp ()")
}
if t.quotelvl > 0 {
return t, nil
}
// eval the first item
v, err := eval(t[0], env)
v, err := eval(t.items[0], env)
if err != nil {
return nil, err
}
// check to see if this is a special form
if spec, ok := v.(special); ok {
if len(t) > 1 {
return spec(env, t[1:]...)
debugPrint("special!")
if len(t.items) > 1 {
return spec(env, t.items[1:]...)
} else {
return spec(env)
}
@ -179,8 +193,8 @@ func eval(v interface{}, env *environment) (interface{}, error) {
// exec builtin func if one exists
if b, ok := v.(builtin); ok {
if len(t) > 1 {
return b.call(env, t[1:])
if len(t.items) > 1 {
return b.call(env, t.items[1:])
} else {
return b.call(env, nil)
}
@ -188,8 +202,8 @@ func eval(v interface{}, env *environment) (interface{}, error) {
// exec lambda if possible
if l, ok := v.(lambda); ok {
if len(t) > 1 {
return l.call(env, t[1:])
if len(t.items) > 1 {
return l.call(env, t.items[1:])
} else {
return l.call(env, nil)
}
@ -198,6 +212,7 @@ func eval(v interface{}, env *environment) (interface{}, error) {
return nil, fmt.Errorf(`expected special form or builtin procedure, received %v`, reflect.TypeOf(v))
default:
debugPrint("default eval")
return v, nil
}

@ -82,14 +82,11 @@ func quote(_ *environment, args ...interface{}) (interface{}, error) {
}
switch t := args[0].(type) {
case list:
fmt.Println("got a list...")
t.quotelevel++
case *sexp:
t.quotelvl++
return t, nil
case sexp:
return list{t, 1}, nil
default:
return t, nil
return &sexp{items: []interface{}{t}, quotelvl: 1}, nil
}
panic("not reached")
}
@ -162,7 +159,7 @@ func set(env *environment, args ...interface{}) (interface{}, error) {
type lambda struct {
env *environment
arglabels []symbol
body sexp
body *sexp
}
func (l lambda) call(env *environment, rawArgs []interface{}) (interface{}, error) {
@ -199,13 +196,13 @@ func mklambda(env *environment, args ...interface{}) (interface{}, error) {
return nil, err
}
params, ok := args[0].(sexp)
params, ok := args[0].(*sexp)
if !ok {
return nil, fmt.Errorf(`first argument to *lambda* must be sexp, received %v`, reflect.TypeOf(args[0]))
}
arglabels := make([]symbol, 0, len(params))
for _, v := range params {
arglabels := make([]symbol, 0, len(params.items))
for _, v := range params.items {
s, ok := v.(symbol)
if !ok {
return nil, fmt.Errorf(`lambda args must all be symbols; received invalid %v`, reflect.TypeOf(v))
@ -213,7 +210,7 @@ func mklambda(env *environment, args ...interface{}) (interface{}, error) {
arglabels = append(arglabels, s)
}
body, ok := args[1].(sexp)
body, ok := args[1].(*sexp)
if !ok {
return nil, fmt.Errorf(`second argument to *lambda* must be sexp, received %v`, reflect.TypeOf(args[1]))
}

Loading…
Cancel
Save