Skip to content

Commit 04a3183

Browse files
authored
Merge pull request #6 from NJdevPro/extend
Merge Extend
2 parents 6fc80ac + a58a7ee commit 04a3183

File tree

6 files changed

+38
-67
lines changed

6 files changed

+38
-67
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
CC=gcc
2-
CFLAGS=-std=gnu99 -g -Wall
2+
CFLAGS=-std=gnu99 -O2 -Wall -Wshadow -Wextra -Wno-unused-parameter
33
LDFLAGS=
44

55
.PHONY: clean test

README.md

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,15 @@ CTRL-Z SUSPEND PROCESS
8585
The REPL also saves the history of commands in the file history.txt
8686
This file is loaded at startup, so one can recall previous commands.
8787

88-
Future improvements:
89-
- floating point numbers
90-
- data files
91-
- system calls
92-
9388
Known bugs:
94-
* the paste function does not work very well.
89+
* Operators "and" and "or" do not work like their typical Lisp counterpart
90+
because they evaluate all their operands at the same time instead of one
91+
by one. You may use the versions in the library.lisp file to correct this behavior.
9592
* recall of multiline commands does not work as expected.
96-
* this doesn't have tail call optimization, so expect crashes with sometimes surprisingly short lists.
97-
93+
* this doesn't have tail call optimization, so expect crashes with sometimes with surprisingly short lists.
9894

9995
Original README (completed)
100-
---------------
96+
===============
10197

10298
One day I wanted to see what I can do with 1k lines of C and
10399
decided to write a Lisp interpreter. That turned to be a
@@ -269,7 +265,8 @@ exhaustion error.
269265

270266
( progn (print "I own ")
271267
(defun add(x y)(+ x y))
272-
(println (add 3 7) " cents") ) ; -> prints "I own 10 cents"
268+
(print (add 3 7)
269+
(println " cents") ) ; -> prints "I own 10 cents"
273270

274271
### Equivalence test operators
275272

@@ -414,15 +411,3 @@ than itself. Useful for writing a macro that introduces new identifiers.
414411

415412
As in the traditional Lisp syntax, `;` (semicolon) starts a single line comment.
416413
The comment continues to the end of line.
417-
418-
No GC Branch
419-
------------
420-
421-
There is a MiniLisp branch from which the code for garbage collection has been
422-
stripped. The accepted language is the same, but the code is simpler than the
423-
master branch's one. The reader might want to read the nogc branch first, then
424-
proceed to the master branch, to understand the code step by step.
425-
426-
The nogc branch is available at
427-
[nogc](https://github.com/rui314/minilisp/tree/nogc). The original is available
428-
at [master](https://github.com/rui314/minilisp).

src/gc.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,6 @@ void *alloc_semispace() {
116116
return mmap(NULL, MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
117117
}
118118

119-
void free_semispace(void *ptr){
120-
if (ptr) munmap(ptr, MEMORY_SIZE);
121-
mem_nused = 0;
122-
}
123-
124119
// Copies the root objects.
125120
static void forward_root_objects(void *root) {
126121
Symbols = forward(Symbols);
@@ -141,7 +136,7 @@ static bool getEnvFlag(char *name) {
141136
// http://en.wikipedia.org/wiki/Cheney%27s_algorithm
142137
void gc(void *root) {
143138
assert(!gc_running);
144-
gc_running = true; // 開始垃圾蒐集
139+
gc_running = true;
145140

146141
// Debug flags
147142
debug_gc = getEnvFlag("MINILISP_DEBUG_GC");

src/minilisp.c

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ void error(char *fmt, int line_num, ...) {
2828
}
2929

3030
// Constants
31-
static Obj *True = &(Obj){ TTRUE };
32-
static Obj *Nil = &(Obj){ TNIL };
33-
static Obj *Dot = &(Obj){ TDOT };
34-
static Obj *Cparen = &(Obj){ TCPAREN };
31+
static Obj *True = &(Obj){ .type = TTRUE, .size = sizeof(Obj) };
32+
static Obj *Nil = &(Obj){ .type = TNIL, .size = sizeof(Obj) };
33+
static Obj *Dot = &(Obj){ .type = TDOT, .size = sizeof(Obj) };
34+
static Obj *Cparen = &(Obj){ .type = TCPAREN, .size = sizeof(Obj) };
3535

3636
//======================================================================
3737
// Constructors
@@ -263,15 +263,8 @@ static Obj *read_string(void *root) {
263263
static Obj *read_expr(void *root) {
264264
for (;;) {
265265
char c = read_char();
266-
if (c == '\n') {
267-
if (peek() == '\r');
266+
if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
268267
continue;
269-
}
270-
271-
if (c == ' ' || c == '\r' || c == '\t')
272-
continue;
273-
if (c == EOF)
274-
return NULL;
275268
if (c == ';') {
276269
skip_line();
277270
continue;
@@ -292,6 +285,9 @@ static Obj *read_expr(void *root) {
292285
return make_int(root, -read_number(0));
293286
if (isalpha(c) || strchr(symbol_chars, c))
294287
return read_symbol(root, c);
288+
if (c == EOF)
289+
return NULL;
290+
295291
error("Don't know how to handle %c", filepos.line_num, c);
296292
}
297293
}
@@ -808,9 +804,9 @@ static Obj *prim_macroexpand(void *root, Obj **env, Obj **list) {
808804

809805
// (print ...)
810806
static Obj *prim_print(void *root, Obj **env, Obj **list) {
811-
for (Obj *args = *list; args != Nil; args = args->cdr) {
812-
print(eval(root, env, &(args->car)));
813-
}
807+
DEFINE1(root, tmp);
808+
*tmp = (*list)->car;
809+
print(eval(root, env, tmp));
814810
return Nil;
815811
}
816812

@@ -1023,6 +1019,8 @@ static void define_primitives(void *root, Obj **env) {
10231019
add_primitive(root, env, "while", prim_while);
10241020
add_primitive(root, env, "gensym", prim_gensym);
10251021
add_primitive(root, env, "not", prim_not);
1022+
add_primitive(root, env, "and", prim_and);
1023+
add_primitive(root, env, "or", prim_or);
10261024
add_primitive(root, env, "+", prim_plus);
10271025
add_primitive(root, env, "-", prim_minus);
10281026
add_primitive(root, env, "*", prim_mult);
@@ -1060,20 +1058,16 @@ static void define_primitives(void *root, Obj **env) {
10601058

10611059
extern void *memory;
10621060

1063-
void reset_minilisp(Obj **env) {
1061+
void init_minilisp(Obj **env) {
10641062
// Memory allocation
1065-
extern void *memory;
10661063
extern void *alloc_semispace();
1067-
extern void free_semispace(void *);
1068-
gc_root = NULL;
1069-
free_semispace(memory);
10701064
memory = alloc_semispace();
10711065

10721066
// Constants and primitives
10731067
Symbols = Nil;
1074-
*env = make_env(gc_root, &Nil, &Nil);
1075-
define_constants(gc_root, env);
1076-
define_primitives(gc_root, env);
1068+
*env = make_env(NULL, &Nil, &Nil);
1069+
define_constants(NULL, env);
1070+
define_primitives(NULL, env);
10771071
}
10781072

10791073
int eval_input(void *root, Obj **env, Obj **expr) {

src/repl.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ void minilisp(char *text, size_t length, bool with_repl, Obj **env, Obj **expr)
7575
if (with_repl)
7676
for(int promptnum = 1;; promptnum++) {
7777
char prompt[15] = "";
78+
filepos = (filepos_t){ .filename = "", .file_len = 0, .line_num = 1 };
7879
sprintf(prompt, "%d:", promptnum);
7980
char *line = bestline(prompt);
8081
if(line == NULL) continue;
@@ -96,14 +97,9 @@ void minilisp(char *text, size_t length, bool with_repl, Obj **env, Obj **expr)
9697
extern size_t mem_nused;
9798
printf("Memory used: %ld / Total: %d\n", mem_nused, MEMORY_SIZE);
9899
}
99-
else if (!strncmp(line, "/reset", 6)){
100-
DEFINE1(gc_root, env);
101-
reset_minilisp(env);
102-
}
103100
else if (!strncmp(line, "/help", 5)){
104101
puts("Type Ctrl-C to quit.");
105102
puts("/memory to display the amount of memory used.");
106-
puts("/reset to flush the interpreter objects.");
107103
}
108104
else {
109105
printf("Unreconized command: %s", line);
@@ -220,7 +216,7 @@ int main(int argc, char **argv) {
220216
parse_args(argc, argv);
221217

222218
DEFINE2(gc_root, env, expr);
223-
reset_minilisp(env);
219+
init_minilisp(env);
224220

225221
for (int i = 0; i < num_files; i++) {
226222
printf("Loading %s\n", filenames[i]);

test.sh

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/bin/bash -x
22

33
function fail() {
44
echo -n -e '\e[1;31m[ERROR]\e[0m '
@@ -7,13 +7,13 @@ function fail() {
77
}
88

99
function do_run() {
10-
error=$(echo "$3" | ./minilisp 2>&1 > /dev/null)
10+
error=$(echo "$3" | ./minilisp -r -x "${3}" 2>&1 > /dev/null)
1111
if [ -n "$error" ]; then
1212
echo FAILED
1313
fail "$error"
1414
fi
1515

16-
result=$(echo "$3" | ./minilisp 2> /dev/null | tail -1)
16+
result=$(echo "$3" | ./minilisp -r -x "${3}" 2> /dev/null | tail -1)
1717
if [ "$result" != "$2" ]; then
1818
echo FAILED
1919
fail "$2 expected, but got $result"
@@ -136,9 +136,9 @@ run restargs '(3)' '(defun f (x . y) (cons x y)) (f 3)'
136136

137137
# strings
138138
run 'string-concat' 'one & two and 3' '(string-concat "one" " & " "two" " and " 3)'
139-
#run 'symbol->string' 'twelve' "
140-
# (define twelve 12)
141-
# (symbol->string 'twelve)"
139+
run 'symbol->string' 'twelve' "
140+
(define twelve 12)
141+
(symbol->string 'twelve)"
142142
run 'string->symbol' 'twelve' '(string->symbol "twelve")'
143143

144144
# Lexical closures
@@ -154,9 +154,10 @@ run counter 3 '
154154
(counter)
155155
(counter)'
156156

157-
#run progn 'I own 10 cents' '(progn (print "I own ")
158-
# (defun add(x y)(+ x y))
159-
# (println (add 3 7) " cents"))'
157+
run progn 'I own 10 cents()' '(progn (print "I own ")
158+
(defun add(x y)(+ x y))
159+
(print (add 3 7))
160+
(print " cents"))'
160161

161162
# While loop
162163
run while 45 "

0 commit comments

Comments
 (0)