forked from petermichaux/royal-scheme
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7ac9545
commit 6c6a718
Showing
11 changed files
with
359 additions
and
622 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
0.1.0 - July 22, 2011 - Peter Michaux | ||
- initial REPL | ||
- decimal integers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
.PHONY: clean cleaner | ||
|
||
scm: scm.h util.o model.o read.o eval.o print.o repl.c | ||
cc -Wall -ansi -o scm util.o model.o read.o eval.o \ | ||
print.o repl.c | ||
|
||
util.o: scm.h util.c | ||
cc -Wall -ansi -c util.c | ||
|
||
model.o: scm.h model.c | ||
cc -Wall -ansi -c model.c | ||
|
||
read.o: scm.h read.c | ||
cc -Wall -ansi -c read.c | ||
|
||
eval.o: scm.h eval.c | ||
cc -Wall -ansi -c eval.c | ||
|
||
print.o: scm.h print.c | ||
cc -Wall -ansi -c print.c | ||
|
||
clean: | ||
rm -f *.o | ||
|
||
cleaner: clean | ||
rm -f scm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#include "scm.h" | ||
|
||
/* Until we have lists and symbols, just echo. | ||
* The result of this echoing is that the repl | ||
* application is a simple pretty printer. | ||
*/ | ||
scm_object scm_eval(scm_object expression) { | ||
return expression; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#include "scm.h" | ||
|
||
/* nothing here yet */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <stdio.h> | ||
#include "scm.h" | ||
|
||
/* if an error occurs returns negative */ | ||
int scm_write(FILE *out, scm_object object) { | ||
int result; | ||
|
||
/* Cast the fixnum's value to long because we need to | ||
* specify the format string yet we don't know the size | ||
* of a fixnum's value here. Casting to long cannot | ||
* loose information so the cast is safe (i.e. won't | ||
* print an incorrect value.) | ||
*/ | ||
result = fprintf(out, "%ld", | ||
(long)scm_fixnum_value(object)); | ||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#include <stdio.h> | ||
#include <ctype.h> | ||
#include "scm.h" | ||
|
||
int scm_is_delimiter(int c) { | ||
return c == '\t' || c == '\n' || | ||
c == '\r' || c == ' ' || | ||
c == ')' || c == ';' || | ||
c == EOF; | ||
} | ||
|
||
int scm_digit_value(int c) { | ||
return c - '0'; | ||
} | ||
|
||
scm_object scm_read_number(FILE *in) { | ||
char is_negative = 0; | ||
int c; | ||
scm_int num = 0, tmp; | ||
|
||
c = getc(in); | ||
if (c == '-') { | ||
is_negative = 1; | ||
c = getc(in); | ||
} | ||
if (!isdigit(c)) { | ||
scm_fatal("scm_read_number: " | ||
"number must start with a digit"); | ||
} | ||
while (isdigit(c)) { | ||
tmp = num * 10 + scm_digit_value(c); | ||
/* The next line assumes that if adding c in the | ||
* line causes tmp to overflow, the overflow will | ||
* mean tmp is less than num. This will be true | ||
* if the base of the number being read is small | ||
* in comparison to the size of tmp. | ||
*/ | ||
if ((tmp < num) || (tmp > scm_fixnum_max)) { | ||
scm_fatal("scm_read_number: number too large"); | ||
} | ||
num = tmp; | ||
c = getc(in); | ||
} | ||
if (!scm_is_delimiter(c)) { | ||
scm_fatal("scm_read_number: " | ||
"number not followed by a delimiter"); | ||
} | ||
if (c != EOF) { | ||
c = ungetc(c, in); | ||
if (c == EOF) { | ||
scm_fatal("scm_read_number: could not ungetc"); | ||
} | ||
} | ||
/* The next line assumes that any value of num, which | ||
* is not greater than scm_fixnum_max, can be negated | ||
* and still fit into a fixnum. This is true because | ||
* of assumption of two's complement hardware. | ||
*/ | ||
return scm_fixnum_make(is_negative ? -num : num); | ||
} | ||
|
||
scm_object scm_read(FILE *in) { | ||
int c0, c1; | ||
scm_object result; | ||
|
||
loop: | ||
switch (c0 = getc(in)) { | ||
case ' ': | ||
case '\t': | ||
case '\r': | ||
case '\n': | ||
goto loop; | ||
case ';': | ||
/* comments continue to the end of the line */ | ||
while ((c0 = getc(in)) != EOF) { | ||
if (c0 == '\n') { | ||
break; | ||
} | ||
} | ||
goto loop; | ||
case '+': | ||
case '-': | ||
c1 = getc(in); | ||
if (isdigit(c1)) { | ||
c1 = ungetc(c1, in); | ||
if (c1 == EOF) { | ||
scm_fatal("scm_read: could not ungetc"); | ||
} | ||
result = scm_read_number(in); | ||
if (c0 == '-') { | ||
/* We know scm_read_number returns a | ||
* positive result in this case and | ||
* so we can negate with our assumption | ||
* of two's complement architecture. | ||
*/ | ||
result = scm_fixnum_make( | ||
- scm_fixnum_value(result)); | ||
} | ||
} | ||
else { | ||
/* TODO Add symbol support for the symbols | ||
* '+', '-' and those starting with '+' '-'. | ||
*/ | ||
scm_fatal("scm_read: symbols not supported"); | ||
} | ||
break; | ||
case '0': case '1': case '2': case '3': case '4': | ||
case '5': case '6': case '7': case '8': case '9': | ||
c0 = ungetc(c0, in); | ||
if (c0 == EOF) { | ||
scm_fatal("scm_read: could not ungetc"); | ||
} | ||
result = scm_read_number(in); | ||
break; | ||
default: | ||
scm_fatal("scm_read: unexpected char '\\%o'", c0); | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#include <stdio.h> | ||
#include "scm.h" | ||
|
||
void repl(void) { | ||
int p; | ||
scm_object object; | ||
|
||
while (1) { | ||
p = printf("> "); | ||
if (p < 0) { | ||
scm_fatal("repl: print failed"); | ||
} | ||
/* TODO Currently scm_read and scm_eval exit in the | ||
* case of failure. Eventually scm_read and | ||
* scm_eval will return Scheme error objects in the | ||
* case of failure. For example, scm_read may | ||
* return a syntax error for bad user input. Check | ||
* the return value for errors and report them to | ||
* the user. | ||
*/ | ||
object = scm_read(stdin); | ||
object = scm_eval(object); | ||
p = scm_write(stdout, object); | ||
if (p < 0) { | ||
scm_fatal("repl: print failed"); | ||
} | ||
p = printf("\n"); | ||
if (p < 0) { | ||
scm_fatal("repl: print failed"); | ||
} | ||
} | ||
} | ||
|
||
int main(void) { | ||
printf("Welcome to Royal Scheme. Ctrl-c to exit.\n"); | ||
repl(); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#ifndef SCM_H | ||
#define SCM_H | ||
|
||
#include <stdio.h> | ||
#include <limits.h> | ||
|
||
/************************* util.c *************************/ | ||
|
||
void scm_fatal(char *fmt, ...); | ||
|
||
/************************ model.c *************************/ | ||
|
||
/* Assume scm_int is large enough to hold any | ||
* scm_object fixnum. | ||
*/ | ||
typedef long scm_int; | ||
|
||
/* A scm_object can be any of Scheme's many types: | ||
* the empty list, boolean, number, symbol, | ||
* pair, vector, string, port, etc. For now we only have | ||
* fixnums which will fit in a scm_int. | ||
*/ | ||
typedef scm_int scm_object; | ||
|
||
/* Trival conversions to and from fixnum since they are | ||
* currently the only type. | ||
*/ | ||
#define scm_fixnum_make(val) ((scm_object)(val)) | ||
#define scm_fixnum_value(object) ((scm_int)(object)) | ||
/* assume a two's complement hardware representation */ | ||
#define scm_fixnum_min \ | ||
(((scm_int)1)<<(8*sizeof(scm_object)-1)) | ||
#define scm_fixnum_max (-(scm_fixnum_min+1)) | ||
|
||
/************************* read.c *************************/ | ||
|
||
scm_object scm_read(FILE *in); | ||
|
||
/************************* eval.c *************************/ | ||
|
||
scm_object scm_eval(scm_object expression); | ||
|
||
/************************ print.c *************************/ | ||
|
||
int scm_write(FILE *out, scm_object object); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <stdarg.h> | ||
#include "scm.h" | ||
|
||
/* scm_fatal is borrowed from K&R2e page 174 where it is | ||
* called "error". | ||
* | ||
* Purposely ignoring return values of fprintf and | ||
* vfprintf because we want to continue to the exit | ||
* even if there is an error printing. | ||
*/ | ||
void scm_fatal(char *fmt, ...) { | ||
va_list args; | ||
|
||
va_start(args, fmt); | ||
fprintf(stderr, "error: "); | ||
vfprintf(stderr, fmt, args); | ||
fprintf(stderr, "\n"); | ||
va_end(args); | ||
exit(1); | ||
} |