@@ -12,10 +12,12 @@ import (
12
12
)
13
13
14
14
const (
15
- VERSION = "golisp v1.0.2.1"
16
- VERBOSE = true
15
+ VERSION = "golisp v1.0.3.0"
17
16
)
18
17
18
+ // removeEmpty takes a list of strings
19
+ // and removes any elements that are empty strings
20
+ // returning a new array of string with no empty elements
19
21
func removeEmpty (tokens []string ) []string {
20
22
var result []string
21
23
for _ , c := range tokens {
@@ -26,7 +28,10 @@ func removeEmpty(tokens []string) []string {
26
28
return result
27
29
}
28
30
29
- func recover_error () {
31
+ // recoverError is used to recover from panics
32
+ // that are generated by parse / eval. It will
33
+ // print the error and the stack trace
34
+ func recoverError () {
30
35
if r := recover (); r != nil {
31
36
fmt .Println ("Parse Error:" , r )
32
37
buf := make ([]byte , 1 << 16 )
@@ -36,7 +41,7 @@ func recover_error() {
36
41
}
37
42
38
43
func parse (program string ) Object {
39
- defer recover_error ()
44
+ defer recoverError ()
40
45
41
46
tokens := tokenize (program )
42
47
return build_ast (& tokens )
@@ -51,13 +56,18 @@ type Object interface{}
51
56
52
57
type List []Object
53
58
59
+ // String method for Number types
60
+ // tries to print as an int, if not
61
+ // then float
54
62
func (n Number ) String () string {
55
63
if float64 (n ) == float64 (int64 (n )) {
56
64
return fmt .Sprintf ("%d" , int64 (n ))
57
65
}
58
66
return fmt .Sprintf ("%f" , n )
59
67
}
60
68
69
+ // String method for List type, converts
70
+ // into a LISP compatible list format
61
71
func (l List ) String () string {
62
72
var s []string
63
73
for _ , v := range l {
@@ -76,6 +86,8 @@ type Lambda struct {
76
86
body Object
77
87
}
78
88
89
+ // Build the abstract syntax tree from
90
+ // a (pointer to a) list of tokens.
79
91
func build_ast (tokens * []string ) Object {
80
92
token := pop (tokens )
81
93
@@ -94,6 +106,8 @@ func build_ast(tokens *[]string) Object {
94
106
}
95
107
}
96
108
109
+ // pop removes and return the head of a list of tokens
110
+ // make changes in-place via pointer
97
111
func pop (tokens * []string ) string {
98
112
if len (* tokens ) == 0 {
99
113
panic ("unexpected EOF while reading" )
@@ -104,6 +118,8 @@ func pop(tokens *[]string) string {
104
118
return token
105
119
}
106
120
121
+ // atom converts a string to a primitive
122
+ // either a Number or a Symbol
107
123
func atom (token string ) Object {
108
124
n , err := strconv .ParseFloat (token , 64 )
109
125
if err == nil {
@@ -112,6 +128,7 @@ func atom(token string) Object {
112
128
return Symbol (token )
113
129
}
114
130
131
+ // tokenize turns a string into a list of tokens
115
132
func tokenize (chars string ) []string {
116
133
chars = strings .Replace (chars , "(" , " ( " , - 1 )
117
134
chars = strings .Replace (chars , ")" , " ) " , - 1 )
@@ -187,6 +204,8 @@ func print(args []Object) Object {
187
204
return args [0 ]
188
205
}
189
206
207
+ // getStandardEnv instantiates and populates
208
+ // the standard environment used for evaluation
190
209
func getStandardEnv () Env {
191
210
e := Env {
192
211
mapping : make (map [Symbol ]Object ),
@@ -207,8 +226,11 @@ func getStandardEnv() Env {
207
226
return e
208
227
}
209
228
229
+ // eval takes an object (from parse) and evaluates
230
+ // it inside the environment
231
+ // for example eval(parse("(* 2 2)"))
210
232
func (e * Env ) eval (x Object ) Object {
211
- defer recover_error ()
233
+ defer recoverError ()
212
234
213
235
if val , is_symbol := x .(Symbol ); is_symbol {
214
236
return e .mapping [val ]
@@ -267,6 +289,8 @@ func (e *Env) eval(x Object) Object {
267
289
}
268
290
}
269
291
292
+ // repl provides a REPL for the LISP machine
293
+ // that the user can interact with
270
294
func repl (e Env , profile_code bool ) {
271
295
for {
272
296
reader := bufio .NewReader (os .Stdin )
@@ -287,6 +311,7 @@ func repl(e Env, profile_code bool) {
287
311
}
288
312
}
289
313
314
+ // main checks arguments and launches the REPL
290
315
func main () {
291
316
profile_code := flag .Bool ("profile" , false , "profile code execution time" )
292
317
show_version := flag .Bool ("version" , false , "show program version and exit" )
0 commit comments