@@ -24,7 +24,23 @@ type Atom string
24
24
type String string
25
25
type InternalFunc func (... Item ) (Item , error )
26
26
27
- var Nil = Atom ("NIL" )
27
+ type Tokenizer interface {
28
+ NextItem () * TokenItem
29
+ }
30
+
31
+ var T , Nil * Symbol
32
+
33
+ func (a Atom ) ToUpper () Atom {
34
+ return Atom (strings .ToUpper (string (a )))
35
+ }
36
+
37
+ func init () {
38
+ Nil = internSymbol (Atom ("NIL" ))
39
+ Nil .Bind ("NIL" )
40
+
41
+ T = internSymbol (Atom ("t" ))
42
+ T .Bind ("T" )
43
+ }
28
44
29
45
var ErrorEOF = errors .New ("End of File" )
30
46
@@ -41,51 +57,53 @@ func (items ItemList) String() string {
41
57
}
42
58
43
59
func (s String ) String () string {
44
- return fmt .Sprintf (" \" %s \" " , string (s ))
60
+ return fmt .Sprintf (`"%s"` , string (s ))
45
61
}
46
62
47
- func read (s * Scanner ) (Item , error ) {
48
- tok , lit := s . Scan ()
49
- if tok == WS {
50
- tok , lit = s . Scan ()
63
+ func read (l Tokenizer ) (Item , error ) {
64
+ t := l . NextItem ()
65
+ if t . token == WS {
66
+ t = l . NextItem ()
51
67
}
52
- //log.Println ("scan:", tok, lit )
53
- switch tok {
68
+ //log.Printf ("scan: %v\n ", t )
69
+ switch t . token {
54
70
case LEFT_PAREN :
55
- return readList (s )
71
+ return readList (l )
72
+ case RIGHT_PAREN :
73
+ return nil , nil
56
74
case ATOM :
57
- return Atom (lit ), nil
75
+ return Atom (t . lit ), nil
58
76
case QUOTE :
59
- return readQuote (s )
77
+ return readQuote (l )
60
78
case NUMBER :
61
- v , err := strconv .ParseFloat (lit , 64 )
79
+ v , err := strconv .ParseFloat (t . lit , 64 )
62
80
if err != nil {
63
- log .Println ("Number fail:" , err )
81
+ log .Fatal ("Number fail:" , err )
64
82
}
65
83
return Number (v ), nil
66
- case RIGHT_PAREN :
67
- return nil , nil
68
84
case EOF :
69
85
return nil , ErrorEOF
70
86
case STRING :
71
- return String (lit ), nil
87
+ return String (t .lit ), nil
88
+ case ILLEGAL :
89
+ return nil , errors .New (t .lit )
72
90
}
73
91
return nil , errors .New ("Malformed input" )
74
92
}
75
93
76
- func readQuote (s * Scanner ) (Item , error ) {
94
+ func readQuote (lex Tokenizer ) (Item , error ) {
77
95
l := ItemList {Atom ("quote" )}
78
- c , err := read (s )
96
+ c , err := read (lex )
79
97
if err != nil {
80
98
return nil , fmt .Errorf ("Failed to complete list: %v\n " , err )
81
99
}
82
100
return append (l , c ), nil
83
101
}
84
102
85
- func readList (s * Scanner ) (Item , error ) {
103
+ func readList (lex Tokenizer ) (Item , error ) {
86
104
var l ItemList
87
105
for {
88
- c , err := read (s )
106
+ c , err := read (lex )
89
107
if err != nil {
90
108
return nil , fmt .Errorf ("Failed to complete list: %v\n " , err )
91
109
}
@@ -124,7 +142,7 @@ func (env *Env) Find(a Atom) *Env {
124
142
}
125
143
126
144
func eval (expr Item , env * Env ) (interface {}, error ) {
127
- // fmt .Println(expr)
145
+ // log .Println(expr)
128
146
switch e := expr .(type ) {
129
147
case Atom :
130
148
v , ok := env .Find (e ).vars [e ]
@@ -136,6 +154,9 @@ func eval(expr Item, env *Env) (interface{}, error) {
136
154
case Number , String :
137
155
return e , nil
138
156
case ItemList :
157
+ if len (e ) == 0 {
158
+ return Nil , nil
159
+ }
139
160
switch car , _ := e [0 ].(Atom ); car {
140
161
case "quote" :
141
162
return e [1 ], nil
@@ -238,18 +259,21 @@ func apply(proc Item, args ItemList, env *Env) (Item, error) {
238
259
}
239
260
240
261
func replReader (in io.Reader , env * Env ) (interface {}, error ) {
241
- s := NewScanner (in )
262
+ // l := NewScanner(in)
263
+ buf := make ([]byte , 1024 )
264
+ n , _ := in .Read (buf )
265
+ l := NewLexer ("lispy" , string (buf [:n ]))
242
266
var result interface {}
243
267
for {
244
268
var err error
245
- expr , err := read (s )
269
+ expr , err := read (l )
270
+ //log.Println(expr, err)
246
271
if err != nil {
247
272
if err == ErrorEOF {
248
273
return result , nil
249
274
}
250
275
return result , err
251
276
}
252
- // fmt.Println(expr)
253
277
254
278
result , err = eval (expr , env )
255
279
if err != nil {
@@ -265,7 +289,7 @@ func repl(in string, env *Env) (interface{}, error) {
265
289
func replCLI (env * Env ) {
266
290
reader := bufio .NewReader (os .Stdin )
267
291
for {
268
- fmt .Print ("* " )
292
+ fmt .Print ("-> " )
269
293
text , _ := reader .ReadString ('\n' )
270
294
result , err := repl (text , env )
271
295
if err != nil && err != ErrorEOF {
@@ -320,7 +344,7 @@ func isTrue(i Item) bool {
320
344
return b
321
345
}
322
346
if a , ok := i .(Atom ); ok {
323
- if a == Nil {
347
+ if internSymbol ( a ) == Nil {
324
348
return false
325
349
}
326
350
return true
@@ -425,5 +449,6 @@ func DefaultEnv() *Env {
425
449
}
426
450
427
451
func main () {
452
+ log .SetFlags (log .LstdFlags | log .Lshortfile )
428
453
replCLI (DefaultEnv ())
429
454
}
0 commit comments