Skip to content

Commit

Permalink
Read files passed as input.
Browse files Browse the repository at this point in the history
Increase GC memory to 256 kb
  • Loading branch information
NJdevPro committed Oct 29, 2024
1 parent 812617f commit 5860eab
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 47 deletions.
43 changes: 43 additions & 0 deletions examples/hanoi.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
;(defun list (x . y) (cons x y))

;(defun list2 (a b) (cons a (cons b ())))
;(defun list3 (a b c) (cons a (cons b (cons c ()))))

(defmacro cond (rest)
(if (= () rest)
()
(if (= (car (car rest)) t)
(car (cdr (car rest)))
(list 'if
(car (car rest))
(car (cdr (car rest)))
(cond (cdr rest))))))

(defun mapc1 (fn xs)
(if (= () xs)
()
(progn
(fn (car xs))
(mapc1 fn (cdr xs)))))

(defun hanoi-print (disk from to)
(println (cons 'Move
(cons 'disk
(cons disk
(cons 'from
(cons from
(cons 'to
(cons to ())))))))))

(defun hanoi-move (n from to via)
(if (= n 1)
(hanoi-print n from to)
(progn
(hanoi-move (- n 1) from via to)
(hanoi-print n from to)
(hanoi-move (- n 1) via to from))))

(defun hanoi (n)
(hanoi-move n 'L 'M 'R))

(hanoi 5)
11 changes: 6 additions & 5 deletions examples/life.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
(defun list (x . y)
(cons x y))

(defun not (x)
(if x () t))

;(defun not (x)
; (if x () t))

;; (let var val body ...)
;; => ((lambda (var) body ...) val)
Expand Down Expand Up @@ -57,9 +58,9 @@
;;; Numeric operators
;;;

(defun <= (e1 e2)
(or (< e1 e2)
(= e1 e2)))
;(defun <= (e1 e2)
; (or (< e1 e2)
; (= e1 e2)))

;;;
;;; List operators
Expand Down
2 changes: 1 addition & 1 deletion gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//======================================================================

// The size of the heap in byte
#define MEMORY_SIZE 65536
#define MEMORY_SIZE 262144

extern void *root; // root of memory

Expand Down
14 changes: 9 additions & 5 deletions minilisp.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const char symbol_chars[] = "~!@#$%^&*-_=+:/?<>";
static Obj *read_expr(void *root);

static int peek(void) {
int c = getchar();
char c = getchar();
ungetc(c, stdin);
return c;
}
Expand All @@ -123,7 +123,7 @@ static Obj *reverse(Obj *p) {
// Skips the input until newline is found. Newline is one of \r, \r\n or \n.
static void skip_line(void) {
for (;;) {
int c = getchar();
char c = getchar();
if (c == EOF || c == '\n')
return;
if (c == '\r') {
Expand Down Expand Up @@ -199,7 +199,7 @@ static Obj *read_symbol(void *root, char c) {

static Obj *read_expr(void *root) {
for (;;) {
int c = getchar();
char c = getchar();
if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
continue;
if (c == EOF)
Expand Down Expand Up @@ -246,8 +246,7 @@ static void print(Obj *obj) {
fputs(")", stdout);
break;

case TINT : //lltoa(obj->value, result, 10);
printf("%lld", obj->value);
case TINT : printf("%lld", obj->value);
break;
case TSYMBOL: fputs(obj->name, stdout);
break;
Expand Down Expand Up @@ -722,6 +721,10 @@ static Obj *prim_println(void *root, Obj **env, Obj **list) {
return Nil;
}

static Obj *prim_progn(void *root, Obj **env, Obj **list) {
return progn(root, env, list);
}

// (if expr expr expr ...)
static Obj *prim_if(void *root, Obj **env, Obj **list) {
if (length(*list) < 2)
Expand Down Expand Up @@ -798,6 +801,7 @@ static void define_primitives(void *root, Obj **env) {
add_primitive(root, env, "macroexpand", prim_macroexpand);
add_primitive(root, env, "lambda", prim_lambda);
add_primitive(root, env, "if", prim_if);
add_primitive(root, env, "progn", prim_progn);
add_primitive(root, env, "=", prim_num_eq);
add_primitive(root, env, "eq", prim_eq);
add_primitive(root, env, "println", prim_println);
Expand Down
126 changes: 90 additions & 36 deletions repl.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,6 @@
#include "gc.h"
#include "minilisp.h"

#if 0
// should be ~50kb statically linked
// will save history to ~/.foo_history
// cc -fno-jump-tables -Os -o foo foo.c bestline.c
int main() {
char *line;
while ((line = bestlineWithHistory("IN> ", "foo"))) {
fputs("OUT> ", stdout);
fputs(line, stdout);
fputs("\n", stdout);
free(line);
}
}
#endif


int ends_with(const char *str, const char *suffix)
{
Expand Down Expand Up @@ -65,19 +50,33 @@ char *hints(const char *buf, const char **ansi1, const char **ansi2) {
return NULL;
}

void minilisp() {
void minilisp(char *text, size_t length) {

DEFINE1(env);
DEFINE2(env, expr);
init_minilisp(env);

/* Now this is the main loop of the typical bestline-based application.
if(text != NULL){
// Save old stdin
FILE * old_stdin = stdin;
// Open a memory stream
FILE * stream = fmemopen(text, strlen(text), "r");
// Redirect stdin to the in memory stream in order to use getchar()
stdin = stream;
eval_input(text, env, expr);
free(text);
// restore stdin
stdin = old_stdin;
fclose(stream);
}

/* Now this is the main loop of the typical bestline-based application.
* The call to bestline() will block as long as the user types something
* and presses enter.
*
* The typed string is returned as a malloc() allocated string by
* bestline, so the user needs to free() it. */
int promptnum = 1;
for(;;promptnum++) {

for(int promptnum = 1;;promptnum++) {
char prompt[15] = "";
sprintf(prompt, "%d:", promptnum);
char *line = bestline(prompt);
Expand All @@ -89,11 +88,8 @@ void minilisp() {
FILE * stream = fmemopen(line, strlen(line), "r");
// Redirect stdin to the in memory stream in order to use getchar()
stdin = stream;

usleep(50000);

if (line[0] != '\0' && line[0] != '/') {
DEFINE1(expr);
int ok = eval_input(line, env, expr);
if (ok == 0) {
bestlineHistoryAdd(line); /* Add to the history. */
Expand All @@ -106,30 +102,88 @@ void minilisp() {
} else if (line[0] == '/') {
fputs("Unreconized command: ", stdout);
fputs(line, stdout);
fputs("\n", stdout);
putchar('\n');
}

free(line);
// restore stdin
stdin = old_stdin;
fclose(stream);
}

}

__attribute((noreturn)) void error(char *fmt, ...);

static size_t read_file(char *fname, char **text) {
size_t length = 0;
FILE *f = fopen(fname, "r");
if (!f) {
error("Failed to load file %s", fname);
return 0;
}

fseek(f, 0, SEEK_END);
length = ftell(f);
fseek(f, 0, SEEK_SET);

*text = malloc(length + 1);
if (!*text) {
error("Out of memory.");
fclose(f);
return 0;
}

size_t read = fread(*text, 1, length, f);
if (read != length) {
error("Failed to read entire file");
free(*text);
*text = NULL;
fclose(f);
return 0;
}

(*text)[length] = '\0';
fclose(f);
return length;
}

void process_file(char *fname, Obj **env, Obj **expr) {
char *text;
size_t len = read_file(fname, &text);
if (len == 0) return;

// Save old stdin
FILE *old_stdin = stdin;
// Create a single stream for the entire file
FILE *stream = fmemopen(text, len, "r");
if (!stream) {
free(text);
error("Failed to create memory stream");
return;
}

// Redirect stdin to the memory stream
stdin = stream;

// Process expressions until we reach end of file
while (1) {
eval_input(text, env, expr);
}

// Cleanup
stdin = old_stdin;
fclose(stream);
free(text);
}

int main(int argc, char **argv) {

if (argc > 1){
FILE *file;
file = fopen(argv[1], "r");
if (file) {
char c;
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
else error("Failed to open file ", argv[1]);
DEFINE2(env, expr);
init_minilisp(env);

if (argc > 1) {
process_file(argv[1], env, expr);
}

/* Set the completion callback. This will be called every time the
Expand All @@ -141,7 +195,7 @@ int main(int argc, char **argv) {
* where entries are separated by newlines. */
bestlineHistoryLoad("history.txt"); /* Load the history at startup */

minilisp();
minilisp(NULL, 0);

return 0;
}

0 comments on commit 5860eab

Please sign in to comment.