minischeme: add char

This commit is contained in:
Peter McGoron 2024-08-22 21:51:25 -04:00
parent 45cfd8ff11
commit 93cfe0d94a
4 changed files with 79 additions and 12 deletions

View File

@ -2,7 +2,7 @@
miniscm-run-tests: miniscm/scm tests.scm miniscm-run-tests: miniscm/scm tests.scm
./miniscm/scm < tests.scm ./miniscm/scm < tests.scm
miniscm/scm: miniscm/scm: miniscm/miniscm.c
c89 -DSYSV -DInitFile=\"miniscm/init.scm\" miniscm/miniscm.c -o miniscm/scm c89 -g -DSYSV -DInitFile=\"miniscm/init.scm\" miniscm/miniscm.c -o miniscm/scm
clean: clean:
rm -f miniscm rm -f miniscm

View File

@ -17,6 +17,8 @@ designed to be used by a severely limited Scheme interpreter, which
* lacks ``call/cc``, ``call-with-values``, etc * lacks ``call/cc``, ``call-with-values``, etc
* lacks user definable macros * lacks user definable macros
* only uses required features from R3RS * only uses required features from R3RS
(except ``open-input-port``, ``close-input-port``, ``read-char``,
``open-output-port``, ``close-output-port``, ``write-char``)
* has fixnums only * has fixnums only
* minimizes the use of strings * minimizes the use of strings
* does not use "load" recursively * does not use "load" recursively

View File

@ -73,6 +73,3 @@
(equal? (cdr x) (cdr y))) (equal? (cdr x) (cdr y)))
(and (not (pair? y)) (and (not (pair? y))
(eqv? x y)))) (eqv? x y))))
(display "This is a limited version of MiniScheme used to run UNSLISP.")

View File

@ -25,6 +25,13 @@
*-- *--
*/ */
/* TODO: Add basic port operations.
*
* UNSLISP only needs one input port and one output port (besides stdin
* and stdout). The easiest thing to do is to make ports integers that
* reference a global list of FILE*.
*/
/* /*
* Here is System declaration. * Here is System declaration.
* Please define exactly one symbol in the following section. * Please define exactly one symbol in the following section.
@ -66,14 +73,17 @@
* Define or undefine following symbols as you need. * Define or undefine following symbols as you need.
*/ */
/* #define VERBOSE */ /* define this if you want verbose GC */ /* #define VERBOSE */ /* define this if you want verbose GC */
#define VERBOSE
#define AVOID_HACK_LOOP /* define this if your compiler is poor #define AVOID_HACK_LOOP /* define this if your compiler is poor
* enougth to complain "do { } while (0)" * enougth to complain "do { } while (0)"
* construction. * construction.
*/ */
#if 0
#define USE_SETJMP /* undef this if you do not want to use setjmp() */ #define USE_SETJMP /* undef this if you do not want to use setjmp() */
#define USE_QQUOTE /* undef this if you do not need quasiquote */ #define USE_QQUOTE /* undef this if you do not need quasiquote */
#define USE_MACRO /* undef this if you do not need macro */ #define USE_MACRO /* undef this if you do not need macro */
#endif
#ifdef USE_QQUOTE #ifdef USE_QQUOTE
/*-- /*--
@ -102,7 +112,7 @@
#define banner "Hello, This is Mini-Scheme Interpreter Version 0.85k4-a.\n" #define banner "Hello, This is Mini-Scheme Interpreter Version 0.85k4-a for UNSLISP.\n"
#include <stdio.h> #include <stdio.h>
@ -224,6 +234,7 @@ typedef struct cell *pointer;
# define T_MACRO 256 /* 0000000100000000 */ # define T_MACRO 256 /* 0000000100000000 */
#endif #endif
#define T_PROMISE 512 /* 0000001000000000 */ #define T_PROMISE 512 /* 0000001000000000 */
#define T_CHAR 1024 /* 0000010000000000 */
#define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */ #define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */
#define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */ #define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */
#define MARK 32768 /* 1000000000000000 */ #define MARK 32768 /* 1000000000000000 */
@ -238,6 +249,7 @@ typedef struct cell *pointer;
#define isnumber(p) (type(p)&T_NUMBER) #define isnumber(p) (type(p)&T_NUMBER)
#define ivalue(p) ((p)->_object._number._ivalue) #define ivalue(p) ((p)->_object._number._ivalue)
#define ischar(p) (type(p)&T_CHAR)
#define ispair(p) (type(p)&T_PAIR) #define ispair(p) (type(p)&T_PAIR)
#define car(p) ((p)->_object._cons._car) #define car(p) ((p)->_object._cons._car)
@ -329,6 +341,18 @@ jmp_buf error_jmp;
#endif #endif
char gc_verbose; /* if gc_verbose is not zero, print gc status */ char gc_verbose; /* if gc_verbose is not zero, print gc status */
stricmp(x, y)
char *x;
char *y;
{
for (; tolower((unsigned char)(*x++))
== tolower((unsigned char)(*y++));
x++, y++)
if (!*x)
break;
return *x - *y;
}
/* allocate new cell segment */ /* allocate new cell segment */
alloc_cellseg(n) alloc_cellseg(n)
int n; int n;
@ -526,6 +550,24 @@ char *q;
return (mk_number(atol(q))); return (mk_number(atol(q)));
} }
/* make char */
pointer mk_char(name)
char *name;
{
register pointer x = get_cell(NIL, NIL);
type(x) = (T_CHAR | T_ATOM);
if (stricmp(name, "space") == 0) {
ivalue(x) = ' ';
} else if (stricmp(name, "newline") == 0) {
ivalue(x) = '\n';
} else {
ivalue(x) = *name;
}
return x;
}
/* make constant */ /* make constant */
pointer mk_const(name) pointer mk_const(name)
char *name; char *name;
@ -548,8 +590,11 @@ char *name;
sprintf(tmp, "0x%s", &name[1]); sprintf(tmp, "0x%s", &name[1]);
sscanf(tmp, "%lx", &x); sscanf(tmp, "%lx", &x);
return (mk_number(x)); return (mk_number(x));
} else } else if (*name == '\\') { /* Character constant */
return (mk_char(&name[1]));
} else {
return (NIL); return (NIL);
}
} }
@ -858,6 +903,16 @@ int f;
p = "#<CLOSURE>"; p = "#<CLOSURE>";
else if (iscontinuation(l)) else if (iscontinuation(l))
p = "#<CONTINUATION>"; p = "#<CONTINUATION>";
else if (ischar(l)) {
if (ivalue(l) == '\n')
p = "#\\newline";
else if (ivalue(l) == ' ')
p = "#\\space";
else {
p = strbuff;
sprintf(p, "#\\%c", ivalue(l));
}
}
if (f < 0) if (f < 0)
return strlen(p); return strlen(p);
fputs(p, outfp); fputs(p, outfp);
@ -948,6 +1003,11 @@ register pointer a, b;
return (ivalue(a) == ivalue(b)); return (ivalue(a) == ivalue(b));
else else
return (0); return (0);
} else if (ischar(a)) {
if (ischar(b))
return (ivalue(a) == ivalue(b));
else
return (0);
} else } else
return (a == b); return (a == b);
} }
@ -1115,7 +1175,7 @@ register pointer a, b;
#define OP_GET_CLOSURE 101 #define OP_GET_CLOSURE 101
#define OP_CLOSUREP 102 #define OP_CLOSUREP 102
#define OP_MACROP 103 #define OP_MACROP 103
#define OP_CHAR 104
static FILE *tmpfp; static FILE *tmpfp;
static int tok; static int tok;
@ -1716,6 +1776,8 @@ register short op;
s_retbool(issymbol(car(args))); s_retbool(issymbol(car(args)));
case OP_NUMBER: /* number? */ case OP_NUMBER: /* number? */
s_retbool(isnumber(car(args))); s_retbool(isnumber(car(args)));
case OP_CHAR: /* char? */
s_retbool(ischar(car(args)));
case OP_STRING: /* string? */ case OP_STRING: /* string? */
s_retbool(isstring(car(args))); s_retbool(isstring(car(args)));
case OP_PROC: /* procedure? */ case OP_PROC: /* procedure? */
@ -1958,6 +2020,7 @@ register short op;
fprintf(outfp, "'"); fprintf(outfp, "'");
args = cadr(args); args = cadr(args);
s_goto(OP_P0LIST); s_goto(OP_P0LIST);
#ifdef USE_QQUOTE
} else if (car(args) == QQUOTE && ok_abbrev(cdr(args))) { } else if (car(args) == QQUOTE && ok_abbrev(cdr(args))) {
fprintf(outfp, "`"); fprintf(outfp, "`");
args = cadr(args); args = cadr(args);
@ -1970,6 +2033,7 @@ register short op;
fprintf(outfp, ",@"); fprintf(outfp, ",@");
args = cadr(args); args = cadr(args);
s_goto(OP_P0LIST); s_goto(OP_P0LIST);
#endif
} else { } else {
fprintf(outfp, "("); fprintf(outfp, "(");
s_save(OP_P1LIST, cdr(args), NIL); s_save(OP_P1LIST, cdr(args), NIL);
@ -2045,6 +2109,7 @@ register short op;
++w; ++w;
args = cadr(args); args = cadr(args);
s_goto(OP_P0_WIDTH); s_goto(OP_P0_WIDTH);
#ifdef USE_QQUOTE
} else if (car(args) == QQUOTE } else if (car(args) == QQUOTE
&& ok_abbrev(cdr(args))) { && ok_abbrev(cdr(args))) {
++w; ++w;
@ -2060,6 +2125,7 @@ register short op;
w += 2; w += 2;
args = cadr(args); args = cadr(args);
s_goto(OP_P0_WIDTH); s_goto(OP_P0_WIDTH);
#endif
} else { } else {
++w; ++w;
s_save(OP_P1_WIDTH, cdr(args), NIL); s_save(OP_P1_WIDTH, cdr(args), NIL);
@ -2231,10 +2297,11 @@ pointer (*dispatch_table[])() = {
opexe_6, /* OP_P1_WIDTH, */ opexe_6, /* OP_P1_WIDTH, */
opexe_6, /* OP_GET_CLOSURE, */ opexe_6, /* OP_GET_CLOSURE, */
opexe_6, /* OP_CLOSUREP, */ opexe_6, /* OP_CLOSUREP, */
#ifdef USE_MACRO /* OP_MACROP is kept in to fill in a slot. Will return illegal
* operator when macros are disabled. */
opexe_6, /* OP_MACROP, */ opexe_6, /* OP_MACROP, */
#endif
opexe_3 /* OP_CHAR */
}; };
@ -2382,6 +2449,7 @@ init_procs()
mk_proc(OP_MACROP, "macro?"); /* a.k */ mk_proc(OP_MACROP, "macro?"); /* a.k */
#endif #endif
mk_proc(OP_QUIT, "quit"); mk_proc(OP_QUIT, "quit");
mk_proc(OP_CHAR, "char?");
} }