From b387d909b517f15247a082f14afaf940e3d89e8d Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Thu, 1 Nov 2012 20:08:09 -0400 Subject: [PATCH] fixed quote bug --- builtin.go | 41 ++++++++++++++++-------------------- skeam.go | 61 ++++++++++++++++++++++++++++++++++-------------------- special.go | 19 +++++++---------- 3 files changed, 64 insertions(+), 57 deletions(-) diff --git a/builtin.go b/builtin.go index 193e471..8c69394 100644 --- a/builtin.go +++ b/builtin.go @@ -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 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 }, } diff --git a/skeam.go b/skeam.go index 0f30711..9a3f89d 100644 --- a/skeam.go +++ b/skeam.go @@ -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 } diff --git a/special.go b/special.go index 6936128..1acbc67 100644 --- a/special.go +++ b/special.go @@ -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])) }