Merge branch 'master' into bench
This commit is contained in:
commit
895666b4be
12
.travis.yml
12
.travis.yml
|
@ -1,16 +1,20 @@
|
||||||
|
sudo: false
|
||||||
language: c
|
language: c
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- gcc-multilib
|
||||||
|
# - valgrind
|
||||||
env:
|
env:
|
||||||
- CFLAGS="-m32"
|
- CFLAGS="-m32"
|
||||||
- CFLAGS="-m64"
|
- CFLAGS="-m64"
|
||||||
before_script:
|
|
||||||
- sudo apt-get update -qq
|
|
||||||
- sudo apt-get install -y libc6:i386 libgcc1:i386 gcc-4.6-base:i386 gcc-multilib
|
|
||||||
script:
|
script:
|
||||||
- perl --version
|
- perl --version
|
||||||
- make test
|
- make test
|
||||||
|
# - make test-contrib TEST_RUNNER="valgrind -q --leak-check=full --dsymutil=yes --error-exitcode=1 bin/picrin"
|
||||||
- make clean
|
- make clean
|
||||||
- make debug
|
- make debug
|
||||||
- make test 2> /dev/null >/dev/null
|
- make test
|
||||||
|
|
23
Makefile
23
Makefile
|
@ -7,15 +7,6 @@ PICRIN_SRCS = \
|
||||||
src/init_contrib.c
|
src/init_contrib.c
|
||||||
PICRIN_OBJS = \
|
PICRIN_OBJS = \
|
||||||
$(PICRIN_SRCS:.c=.o)
|
$(PICRIN_SRCS:.c=.o)
|
||||||
PICRIN_LIBS = \
|
|
||||||
piclib/picrin/base.scm\
|
|
||||||
piclib/picrin/macro.scm\
|
|
||||||
piclib/picrin/record.scm\
|
|
||||||
piclib/picrin/array.scm\
|
|
||||||
piclib/picrin/control.scm\
|
|
||||||
piclib/picrin/experimental/lambda.scm\
|
|
||||||
piclib/picrin/syntax-rules.scm\
|
|
||||||
piclib/picrin/test.scm
|
|
||||||
|
|
||||||
CONTRIB_SRCS =
|
CONTRIB_SRCS =
|
||||||
CONTRIB_OBJS = $(CONTRIB_SRCS:.c=.o)
|
CONTRIB_OBJS = $(CONTRIB_SRCS:.c=.o)
|
||||||
|
@ -24,24 +15,26 @@ CONTRIB_INITS =
|
||||||
CONTRIB_TESTS =
|
CONTRIB_TESTS =
|
||||||
CONTRIB_DOCS = $(wildcard contrib/*/docs/*.rst)
|
CONTRIB_DOCS = $(wildcard contrib/*/docs/*.rst)
|
||||||
|
|
||||||
|
TEST_RUNNER = bin/picrin
|
||||||
|
|
||||||
CFLAGS += -I./extlib/benz/include -Wall -Wextra
|
CFLAGS += -I./extlib/benz/include -Wall -Wextra
|
||||||
LDFLAGS += -lm
|
LDFLAGS += -lm
|
||||||
|
|
||||||
prefix = /usr/local
|
prefix = /usr/local
|
||||||
|
|
||||||
all: CFLAGS += -O2
|
all: CFLAGS += -O2 -DNDEBUG=1
|
||||||
all: bin/picrin
|
all: bin/picrin
|
||||||
|
|
||||||
include $(sort $(wildcard contrib/*/nitro.mk))
|
|
||||||
|
|
||||||
debug: CFLAGS += -O0 -g
|
debug: CFLAGS += -O0 -g
|
||||||
debug: bin/picrin
|
debug: bin/picrin
|
||||||
|
|
||||||
|
include $(sort $(wildcard contrib/*/nitro.mk))
|
||||||
|
|
||||||
bin/picrin: $(PICRIN_OBJS) $(CONTRIB_OBJS) lib/libbenz.a
|
bin/picrin: $(PICRIN_OBJS) $(CONTRIB_OBJS) lib/libbenz.a
|
||||||
$(CC) $(CFLAGS) -o $@ $(PICRIN_OBJS) $(CONTRIB_OBJS) lib/libbenz.a $(LDFLAGS)
|
$(CC) $(CFLAGS) -o $@ $(PICRIN_OBJS) $(CONTRIB_OBJS) lib/libbenz.a $(LDFLAGS)
|
||||||
|
|
||||||
src/load_piclib.c: $(PICRIN_LIBS) $(CONTRIB_LIBS)
|
src/load_piclib.c: $(CONTRIB_LIBS)
|
||||||
perl etc/mkloader.pl $(PICRIN_LIBS) $(CONTRIB_LIBS) > $@
|
perl etc/mkloader.pl $(CONTRIB_LIBS) > $@
|
||||||
|
|
||||||
src/init_contrib.c:
|
src/init_contrib.c:
|
||||||
perl etc/mkinit.pl $(CONTRIB_INITS) > $@
|
perl etc/mkinit.pl $(CONTRIB_INITS) > $@
|
||||||
|
@ -74,7 +67,7 @@ test: test-contribs test-nostdlib
|
||||||
test-contribs: bin/picrin $(CONTRIB_TESTS)
|
test-contribs: bin/picrin $(CONTRIB_TESTS)
|
||||||
|
|
||||||
test-nostdlib:
|
test-nostdlib:
|
||||||
$(CC) -I extlib/benz/include -D'PIC_ENABLE_LIBC=0' -D'PIC_ENABLE_FLOAT=0' -D'PIC_ENABLE_STDIO=0' -nostdlib -fPIC -shared -std=c89 -ansi -pedantic -Wall -Wextra -o lib/libbenz.so $(BENZ_SRCS) etc/libc_polyfill.c -fno-stack-protector
|
$(CC) -I extlib/benz/include -D'PIC_ENABLE_LIBC=0' -D'PIC_ENABLE_FLOAT=0' -D'PIC_ENABLE_STDIO=0' -ffreestanding -nostdlib -fPIC -shared -std=c89 -pedantic -Wall -Wextra -Werror -o lib/libbenz.so $(BENZ_SRCS) etc/libc_polyfill.c -fno-stack-protector
|
||||||
rm -f lib/libbenz.so
|
rm -f lib/libbenz.so
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
|
|
|
@ -258,10 +258,13 @@ pic_callcc_full(pic_state *pic, struct pic_proc *proc)
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
pic_callcc_full_trampoline(pic_state *pic, struct pic_proc *proc)
|
pic_callcc_callcc(pic_state *pic)
|
||||||
{
|
{
|
||||||
|
struct pic_proc *proc;
|
||||||
struct pic_fullcont *cont;
|
struct pic_fullcont *cont;
|
||||||
|
|
||||||
|
pic_get_args(pic, "l", &proc);
|
||||||
|
|
||||||
save_cont(pic, &cont);
|
save_cont(pic, &cont);
|
||||||
if (setjmp(cont->jmp)) {
|
if (setjmp(cont->jmp)) {
|
||||||
return pic_values_by_list(pic, cont->results);
|
return pic_values_by_list(pic, cont->results);
|
||||||
|
@ -277,20 +280,10 @@ pic_callcc_full_trampoline(pic_state *pic, struct pic_proc *proc)
|
||||||
/* save the continuation object in proc */
|
/* save the continuation object in proc */
|
||||||
pic_proc_env_set(pic, c, "cont", pic_obj_value(dat));
|
pic_proc_env_set(pic, c, "cont", pic_obj_value(dat));
|
||||||
|
|
||||||
return pic_apply_trampoline(pic, proc, pic_list1(pic, pic_obj_value(c)));
|
return pic_apply_trampoline_list(pic, proc, pic_list1(pic, pic_obj_value(c)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_callcc_callcc(pic_state *pic)
|
|
||||||
{
|
|
||||||
struct pic_proc *cb;
|
|
||||||
|
|
||||||
pic_get_args(pic, "l", &cb);
|
|
||||||
|
|
||||||
return pic_callcc_full_trampoline(pic, cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define pic_redefun(pic, lib, name, func) \
|
#define pic_redefun(pic, lib, name, func) \
|
||||||
pic_set(pic, lib, name, pic_obj_value(pic_make_proc(pic, func)))
|
pic_set(pic, lib, name, pic_obj_value(pic_make_proc(pic, func)))
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,11 @@
|
||||||
((wrap (let ((register (make-register)))
|
((wrap (let ((register (make-register)))
|
||||||
(lambda (var)
|
(lambda (var)
|
||||||
(let ((id (register var)))
|
(let ((id (register var)))
|
||||||
(if (undefined? id)
|
(if id
|
||||||
|
(cdr id)
|
||||||
(let ((id (make-identifier var env)))
|
(let ((id (make-identifier var env)))
|
||||||
(register var id)
|
(register var id)
|
||||||
id)
|
id))))))
|
||||||
id)))))
|
|
||||||
(walk (lambda (f form)
|
(walk (lambda (f form)
|
||||||
(cond
|
(cond
|
||||||
((variable? form)
|
((variable? form)
|
||||||
|
@ -106,11 +106,11 @@
|
||||||
((rename (let ((register (make-register)))
|
((rename (let ((register (make-register)))
|
||||||
(lambda (var)
|
(lambda (var)
|
||||||
(let ((id (register var)))
|
(let ((id (register var)))
|
||||||
(if (undefined? id)
|
(if id
|
||||||
|
(cdr id)
|
||||||
(let ((id (make-identifier var mac-env)))
|
(let ((id (make-identifier var mac-env)))
|
||||||
(register var id)
|
(register var id)
|
||||||
id)
|
id))))))
|
||||||
id)))))
|
|
||||||
(compare (lambda (x y)
|
(compare (lambda (x y)
|
||||||
(variable=?
|
(variable=?
|
||||||
(make-identifier x use-env)
|
(make-identifier x use-env)
|
||||||
|
@ -124,25 +124,25 @@
|
||||||
(letrec
|
(letrec
|
||||||
((inject (lambda (var1)
|
((inject (lambda (var1)
|
||||||
(let ((var2 (register1 var1)))
|
(let ((var2 (register1 var1)))
|
||||||
(if (undefined? var2)
|
(if var2
|
||||||
|
(cdr var2)
|
||||||
(let ((var2 (make-identifier var1 use-env)))
|
(let ((var2 (make-identifier var1 use-env)))
|
||||||
(register1 var1 var2)
|
(register1 var1 var2)
|
||||||
(register2 var2 var1)
|
(register2 var2 var1)
|
||||||
var2)
|
var2)))))
|
||||||
var2))))
|
|
||||||
(rename (let ((register (make-register)))
|
(rename (let ((register (make-register)))
|
||||||
(lambda (var)
|
(lambda (var)
|
||||||
(let ((id (register var)))
|
(let ((id (register var)))
|
||||||
(if (undefined? id)
|
(if id
|
||||||
|
(cdr id)
|
||||||
(let ((id (make-identifier var mac-env)))
|
(let ((id (make-identifier var mac-env)))
|
||||||
(register var id)
|
(register var id)
|
||||||
id)
|
id))))))
|
||||||
id)))))
|
|
||||||
(flip (lambda (var2) ; unwrap if injected, wrap if not injected
|
(flip (lambda (var2) ; unwrap if injected, wrap if not injected
|
||||||
(let ((var1 (register2 var2)))
|
(let ((var1 (register2 var2)))
|
||||||
(if (undefined? var1)
|
(if var1
|
||||||
(rename var2)
|
(cdr var1)
|
||||||
var1))))
|
(rename var2)))))
|
||||||
(walk (lambda (f form)
|
(walk (lambda (f form)
|
||||||
(cond
|
(cond
|
||||||
((variable? form)
|
((variable? form)
|
|
@ -0,0 +1,6 @@
|
||||||
|
CONTRIB_LIBS += $(wildcard contrib/10.macro/*.scm)
|
||||||
|
|
||||||
|
CONTRIB_TESTS += test-macro
|
||||||
|
|
||||||
|
test-macro: bin/picrin
|
||||||
|
$(TEST_RUNNER) contrib/10.macro/t/ir-macro.scm
|
|
@ -0,0 +1,310 @@
|
||||||
|
#include "picrin.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_floor2(pic_state *pic)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
bool e1, e2;
|
||||||
|
|
||||||
|
pic_get_args(pic, "II", &i, &e1, &j, &e2);
|
||||||
|
|
||||||
|
if (e1 && e2) {
|
||||||
|
int k;
|
||||||
|
|
||||||
|
k = (i < 0 && j < 0) || (0 <= i && 0 <= j)
|
||||||
|
? i / j
|
||||||
|
: (i / j) - 1;
|
||||||
|
|
||||||
|
return pic_values2(pic, pic_int_value(k), pic_int_value(i - k * j));
|
||||||
|
} else {
|
||||||
|
double q, r;
|
||||||
|
|
||||||
|
q = floor((double)i/j);
|
||||||
|
r = i - j * q;
|
||||||
|
return pic_values2(pic, pic_float_value(q), pic_float_value(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_trunc2(pic_state *pic)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
bool e1, e2;
|
||||||
|
|
||||||
|
pic_get_args(pic, "II", &i, &e1, &j, &e2);
|
||||||
|
|
||||||
|
if (e1 && e2) {
|
||||||
|
return pic_values2(pic, pic_int_value(i/j), pic_int_value(i - (i/j) * j));
|
||||||
|
} else {
|
||||||
|
double q, r;
|
||||||
|
|
||||||
|
q = trunc((double)i/j);
|
||||||
|
r = i - j * q;
|
||||||
|
|
||||||
|
return pic_values2(pic, pic_float_value(q), pic_float_value(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_floor(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
bool e;
|
||||||
|
|
||||||
|
pic_get_args(pic, "F", &f, &e);
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
return pic_int_value((int)f);
|
||||||
|
} else {
|
||||||
|
return pic_float_value(floor(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_ceil(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
bool e;
|
||||||
|
|
||||||
|
pic_get_args(pic, "F", &f, &e);
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
return pic_int_value((int)f);
|
||||||
|
} else {
|
||||||
|
return pic_float_value(ceil(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_trunc(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
bool e;
|
||||||
|
|
||||||
|
pic_get_args(pic, "F", &f, &e);
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
return pic_int_value((int)f);
|
||||||
|
} else {
|
||||||
|
return pic_float_value(trunc(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_round(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
bool e;
|
||||||
|
|
||||||
|
pic_get_args(pic, "F", &f, &e);
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
return pic_int_value((int)f);
|
||||||
|
} else {
|
||||||
|
return pic_float_value(round(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_finite_p(pic_state *pic)
|
||||||
|
{
|
||||||
|
pic_value v;
|
||||||
|
|
||||||
|
pic_get_args(pic, "o", &v);
|
||||||
|
|
||||||
|
if (pic_int_p(v))
|
||||||
|
return pic_true_value();
|
||||||
|
if (pic_float_p(v) && ! (isinf(pic_float(v)) || isnan(pic_float(v))))
|
||||||
|
return pic_true_value();
|
||||||
|
else
|
||||||
|
return pic_false_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_infinite_p(pic_state *pic)
|
||||||
|
{
|
||||||
|
pic_value v;
|
||||||
|
|
||||||
|
pic_get_args(pic, "o", &v);
|
||||||
|
|
||||||
|
if (pic_float_p(v) && isinf(pic_float(v)))
|
||||||
|
return pic_true_value();
|
||||||
|
else
|
||||||
|
return pic_false_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_nan_p(pic_state *pic)
|
||||||
|
{
|
||||||
|
pic_value v;
|
||||||
|
|
||||||
|
pic_get_args(pic, "o", &v);
|
||||||
|
|
||||||
|
if (pic_float_p(v) && isnan(pic_float(v)))
|
||||||
|
return pic_true_value();
|
||||||
|
else
|
||||||
|
return pic_false_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_exp(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
return pic_float_value(exp(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_log(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f,g;
|
||||||
|
int argc;
|
||||||
|
|
||||||
|
argc = pic_get_args(pic, "f|f", &f, &g);
|
||||||
|
if (argc == 1) {
|
||||||
|
return pic_float_value(log(f));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return pic_float_value(log(f) / log(g));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_sin(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
f = sin(f);
|
||||||
|
return pic_float_value(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_cos(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
f = cos(f);
|
||||||
|
return pic_float_value(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_tan(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
f = tan(f);
|
||||||
|
return pic_float_value(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_acos(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
f = acos(f);
|
||||||
|
return pic_float_value(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_asin(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
f = asin(f);
|
||||||
|
return pic_float_value(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_atan(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f,g;
|
||||||
|
int argc;
|
||||||
|
|
||||||
|
argc = pic_get_args(pic, "f|f", &f, &g);
|
||||||
|
if (argc == 1) {
|
||||||
|
f = atan(f);
|
||||||
|
return pic_float_value(f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return pic_float_value(atan2(f,g));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_sqrt(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
|
||||||
|
return pic_float_value(sqrt(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_abs(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
bool e;
|
||||||
|
|
||||||
|
pic_get_args(pic, "F", &f, &e);
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
return pic_int_value(f < 0 ? -f : f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return pic_float_value(fabs(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_expt(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f, g, h;
|
||||||
|
bool e1, e2;
|
||||||
|
|
||||||
|
pic_get_args(pic, "FF", &f, &e1, &g, &e2);
|
||||||
|
|
||||||
|
h = pow(f, g);
|
||||||
|
if (e1 && e2) {
|
||||||
|
if (h <= INT_MAX) {
|
||||||
|
return pic_int_value((int)h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pic_float_value(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pic_init_math(pic_state *pic)
|
||||||
|
{
|
||||||
|
pic_deflibrary (pic, "(picrin math)") {
|
||||||
|
pic_defun(pic, "floor/", pic_number_floor2);
|
||||||
|
pic_defun(pic, "truncate/", pic_number_trunc2);
|
||||||
|
pic_defun(pic, "floor", pic_number_floor);
|
||||||
|
pic_defun(pic, "ceiling", pic_number_ceil);
|
||||||
|
pic_defun(pic, "truncate", pic_number_trunc);
|
||||||
|
pic_defun(pic, "round", pic_number_round);
|
||||||
|
|
||||||
|
pic_defun(pic, "finite?", pic_number_finite_p);
|
||||||
|
pic_defun(pic, "infinite?", pic_number_infinite_p);
|
||||||
|
pic_defun(pic, "nan?", pic_number_nan_p);
|
||||||
|
pic_defun(pic, "sqrt", pic_number_sqrt);
|
||||||
|
pic_defun(pic, "exp", pic_number_exp);
|
||||||
|
pic_defun(pic, "log", pic_number_log);
|
||||||
|
pic_defun(pic, "sin", pic_number_sin);
|
||||||
|
pic_defun(pic, "cos", pic_number_cos);
|
||||||
|
pic_defun(pic, "tan", pic_number_tan);
|
||||||
|
pic_defun(pic, "acos", pic_number_acos);
|
||||||
|
pic_defun(pic, "asin", pic_number_asin);
|
||||||
|
pic_defun(pic, "atan", pic_number_atan);
|
||||||
|
pic_defun(pic, "abs", pic_number_abs);
|
||||||
|
pic_defun(pic, "expt", pic_number_expt);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
CONTRIB_INITS += math
|
||||||
|
|
||||||
|
CONTRIB_SRCS += contrib/10.math/math.c
|
|
@ -27,5 +27,5 @@ CONTRIB_TESTS += test-r7rs
|
||||||
|
|
||||||
test-r7rs: bin/picrin
|
test-r7rs: bin/picrin
|
||||||
for test in `ls contrib/20.r7rs/t/*.scm`; do \
|
for test in `ls contrib/20.r7rs/t/*.scm`; do \
|
||||||
bin/picrin "$$test"; \
|
$(TEST_RUNNER) "$$test"; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
(define-library (scheme base)
|
(define-library (scheme base)
|
||||||
(import (picrin base)
|
(import (picrin base)
|
||||||
|
(only (picrin math)
|
||||||
|
abs
|
||||||
|
expt
|
||||||
|
floor/
|
||||||
|
truncate/
|
||||||
|
floor
|
||||||
|
ceiling
|
||||||
|
truncate
|
||||||
|
round
|
||||||
|
sqrt
|
||||||
|
nan?
|
||||||
|
infinite?)
|
||||||
(picrin macro)
|
(picrin macro)
|
||||||
(picrin record)
|
|
||||||
(picrin syntax-rules)
|
|
||||||
(picrin string)
|
(picrin string)
|
||||||
(scheme file))
|
(scheme file))
|
||||||
|
|
||||||
|
@ -76,63 +86,57 @@
|
||||||
|
|
||||||
;; 4.2.7. Exception handling
|
;; 4.2.7. Exception handling
|
||||||
|
|
||||||
(define-syntax guard-aux
|
(define-syntax (guard-aux reraise . clauses)
|
||||||
(syntax-rules (else =>)
|
(letrec
|
||||||
((guard-aux reraise (else result1 result2 ...))
|
((else?
|
||||||
(begin result1 result2 ...))
|
(lambda (clause)
|
||||||
((guard-aux reraise (test => result))
|
(and (list? clause) (equal? #'else (car clause)))))
|
||||||
(let ((temp test))
|
(=>?
|
||||||
(if temp
|
(lambda (clause)
|
||||||
(result temp)
|
(and (list? clause) (= (length clause) 3) (equal? #'=> (list-ref clause 1))))))
|
||||||
reraise)))
|
(if (null? clauses)
|
||||||
((guard-aux reraise (test => result)
|
reraise
|
||||||
clause1 clause2 ...)
|
(let ((clause (car clauses))
|
||||||
(let ((temp test))
|
(rest (cdr clauses)))
|
||||||
(if temp
|
(cond
|
||||||
(result temp)
|
((else? clause)
|
||||||
(guard-aux reraise clause1 clause2 ...))))
|
#`(begin #,@(cdr clause)))
|
||||||
((guard-aux reraise (test))
|
((=>? clause)
|
||||||
(or test reraise))
|
#`(let ((tmp #,(list-ref clause 0)))
|
||||||
((guard-aux reraise (test) clause1 clause2 ...)
|
(if tmp
|
||||||
(let ((temp test))
|
(#,(list-ref clause 2) tmp)
|
||||||
(if temp
|
(guard-aux #,reraise #,@rest))))
|
||||||
temp
|
((= (length clause) 1)
|
||||||
(guard-aux reraise clause1 clause2 ...))))
|
#`(or #,(car clause) (guard-aux #,reraise #,@rest)))
|
||||||
((guard-aux reraise (test result1 result2 ...))
|
(else
|
||||||
(if test
|
#`(if #,(car clause)
|
||||||
(begin result1 result2 ...)
|
(begin #,@(cdr clause))
|
||||||
reraise))
|
(guard-aux #,reraise #,@rest))))))))
|
||||||
((guard-aux reraise
|
|
||||||
(test result1 result2 ...)
|
|
||||||
clause1 clause2 ...)
|
|
||||||
(if test
|
|
||||||
(begin result1 result2 ...)
|
|
||||||
(guard-aux reraise clause1 clause2 ...)))))
|
|
||||||
|
|
||||||
(define-syntax guard
|
(define-syntax (guard formal . body)
|
||||||
(syntax-rules ()
|
(let ((var (car formal))
|
||||||
((guard (var clause ...) e1 e2 ...)
|
(clauses (cdr formal)))
|
||||||
((call/cc
|
#`((call/cc
|
||||||
(lambda (guard-k)
|
(lambda (guard-k)
|
||||||
(with-exception-handler
|
(with-exception-handler
|
||||||
(lambda (condition)
|
(lambda (condition)
|
||||||
((call/cc
|
((call/cc
|
||||||
(lambda (handler-k)
|
(lambda (handler-k)
|
||||||
(guard-k
|
(guard-k
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(let ((var condition))
|
(let ((#,var condition))
|
||||||
(guard-aux
|
(guard-aux
|
||||||
(handler-k
|
(handler-k
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(raise-continuable condition)))
|
(raise-continuable condition)))
|
||||||
clause ...))))))))
|
#,@clauses))))))))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(call-with-values
|
(call-with-values
|
||||||
(lambda () e1 e2 ...)
|
(lambda () #,@body)
|
||||||
(lambda args
|
(lambda args
|
||||||
(guard-k
|
(guard-k
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(apply values args)))))))))))))
|
(apply values args))))))))))))
|
||||||
|
|
||||||
(export guard)
|
(export guard)
|
||||||
|
|
||||||
|
@ -149,6 +153,243 @@
|
||||||
|
|
||||||
;; 4.3.2 Pattern language
|
;; 4.3.2 Pattern language
|
||||||
|
|
||||||
|
(define (succ n)
|
||||||
|
(+ n 1))
|
||||||
|
|
||||||
|
(define (pred n)
|
||||||
|
(if (= n 0)
|
||||||
|
0
|
||||||
|
(- n 1)))
|
||||||
|
|
||||||
|
(define (every? args)
|
||||||
|
(if (null? args)
|
||||||
|
#t
|
||||||
|
(if (car args)
|
||||||
|
(every? (cdr args))
|
||||||
|
#f)))
|
||||||
|
|
||||||
|
(define (filter f list)
|
||||||
|
(if (null? list)
|
||||||
|
'()
|
||||||
|
(if (f (car list))
|
||||||
|
(cons (car list)
|
||||||
|
(filter f (cdr list)))
|
||||||
|
(filter f (cdr list)))))
|
||||||
|
|
||||||
|
(define (take-tail n list)
|
||||||
|
(let drop ((n (- (length list) n)) (list list))
|
||||||
|
(if (= n 0)
|
||||||
|
list
|
||||||
|
(drop (- n 1) (cdr list)))))
|
||||||
|
|
||||||
|
(define (drop-tail n list)
|
||||||
|
(let take ((n (- (length list) n)) (list list))
|
||||||
|
(if (= n 0)
|
||||||
|
'()
|
||||||
|
(cons (car list) (take (- n 1) (cdr list))))))
|
||||||
|
|
||||||
|
(define (map-keys f assoc)
|
||||||
|
(map (lambda (s) `(,(f (car s)) . ,(cdr s))) assoc))
|
||||||
|
|
||||||
|
(define (map-values f assoc)
|
||||||
|
(map (lambda (s) `(,(car s) . ,(f (cdr s)))) assoc))
|
||||||
|
|
||||||
|
;; TODO
|
||||||
|
;; - placeholder
|
||||||
|
;; - vector
|
||||||
|
;; - (... template) pattern
|
||||||
|
|
||||||
|
;; p ::= constant
|
||||||
|
;; | var
|
||||||
|
;; | (p ... . p) (in input pattern, tail p should be a proper list)
|
||||||
|
;; | (p . p)
|
||||||
|
|
||||||
|
(define (compile ellipsis literals rules)
|
||||||
|
|
||||||
|
(define (constant? obj)
|
||||||
|
(and (not (pair? obj))
|
||||||
|
(not (variable? obj))))
|
||||||
|
|
||||||
|
(define (literal? obj)
|
||||||
|
(and (variable? obj)
|
||||||
|
(memq obj literals)))
|
||||||
|
|
||||||
|
(define (many? pat)
|
||||||
|
(and (pair? pat)
|
||||||
|
(pair? (cdr pat))
|
||||||
|
(variable? (cadr pat))
|
||||||
|
(variable=? (cadr pat) ellipsis)))
|
||||||
|
|
||||||
|
(define (pattern-validator pat) ; pattern -> validator
|
||||||
|
(letrec
|
||||||
|
((pattern-validator
|
||||||
|
(lambda (pat form)
|
||||||
|
(cond
|
||||||
|
((constant? pat)
|
||||||
|
#`(equal? '#,pat #,form))
|
||||||
|
((literal? pat)
|
||||||
|
#`(and (variable? #,form) (variable=? #'#,pat #,form)))
|
||||||
|
((variable? pat)
|
||||||
|
#t)
|
||||||
|
((many? pat)
|
||||||
|
(let ((head #`(drop-tail #,(length (cddr pat)) #,form))
|
||||||
|
(tail #`(take-tail #,(length (cddr pat)) #,form)))
|
||||||
|
#`(and (list? #,form)
|
||||||
|
(>= (length #,form) #,(length (cddr pat)))
|
||||||
|
(every? (map (lambda (#,'it) #,(pattern-validator (car pat) 'it)) #,head))
|
||||||
|
#,(pattern-validator (cddr pat) tail))))
|
||||||
|
((pair? pat)
|
||||||
|
#`(and (pair? #,form)
|
||||||
|
#,(pattern-validator (car pat) #`(car #,form))
|
||||||
|
#,(pattern-validator (cdr pat) #`(cdr #,form))))
|
||||||
|
(else
|
||||||
|
#f)))))
|
||||||
|
(pattern-validator pat 'it)))
|
||||||
|
|
||||||
|
(define (pattern-variables pat) ; pattern -> (freevar)
|
||||||
|
(cond
|
||||||
|
((constant? pat)
|
||||||
|
'())
|
||||||
|
((literal? pat)
|
||||||
|
'())
|
||||||
|
((variable? pat)
|
||||||
|
`(,pat))
|
||||||
|
((many? pat)
|
||||||
|
(append (pattern-variables (car pat))
|
||||||
|
(pattern-variables (cddr pat))))
|
||||||
|
((pair? pat)
|
||||||
|
(append (pattern-variables (car pat))
|
||||||
|
(pattern-variables (cdr pat))))))
|
||||||
|
|
||||||
|
(define (pattern-levels pat) ; pattern -> ((var * int))
|
||||||
|
(cond
|
||||||
|
((constant? pat)
|
||||||
|
'())
|
||||||
|
((literal? pat)
|
||||||
|
'())
|
||||||
|
((variable? pat)
|
||||||
|
`((,pat . 0)))
|
||||||
|
((many? pat)
|
||||||
|
(append (map-values succ (pattern-levels (car pat)))
|
||||||
|
(pattern-levels (cddr pat))))
|
||||||
|
((pair? pat)
|
||||||
|
(append (pattern-levels (car pat))
|
||||||
|
(pattern-levels (cdr pat))))))
|
||||||
|
|
||||||
|
(define (pattern-selectors pat) ; pattern -> ((var * selector))
|
||||||
|
(letrec
|
||||||
|
((pattern-selectors
|
||||||
|
(lambda (pat form)
|
||||||
|
(cond
|
||||||
|
((constant? pat)
|
||||||
|
'())
|
||||||
|
((literal? pat)
|
||||||
|
'())
|
||||||
|
((variable? pat)
|
||||||
|
`((,pat . ,form)))
|
||||||
|
((many? pat)
|
||||||
|
(let ((head #`(drop-tail #,(length (cddr pat)) #,form))
|
||||||
|
(tail #`(take-tail #,(length (cddr pat)) #,form)))
|
||||||
|
(let ((envs (pattern-selectors (car pat) 'it)))
|
||||||
|
(append
|
||||||
|
(map-values (lambda (s) #`(map (lambda (#,'it) #,s) #,head)) envs)
|
||||||
|
(pattern-selectors (cddr pat) tail)))))
|
||||||
|
((pair? pat)
|
||||||
|
(append (pattern-selectors (car pat) #`(car #,form))
|
||||||
|
(pattern-selectors (cdr pat) #`(cdr #,form))))))))
|
||||||
|
(pattern-selectors pat 'it)))
|
||||||
|
|
||||||
|
(define (template-representation pat levels selectors)
|
||||||
|
(cond
|
||||||
|
((constant? pat)
|
||||||
|
pat)
|
||||||
|
((variable? pat)
|
||||||
|
(let ((it (assq pat levels)))
|
||||||
|
(if it
|
||||||
|
(if (= 0 (cdr it))
|
||||||
|
(cdr (assq pat selectors))
|
||||||
|
(error "unmatched pattern variable level" pat))
|
||||||
|
#`(#,'rename '#,pat))))
|
||||||
|
((many? pat)
|
||||||
|
(letrec*
|
||||||
|
((inner-pat
|
||||||
|
(car pat))
|
||||||
|
(inner-levels
|
||||||
|
(map (lambda (s) `(,(car s) . ,(pred (cdr s)))) levels))
|
||||||
|
(inner-freevars
|
||||||
|
(filter (lambda (v) (assq v levels)) (pattern-variables inner-pat)))
|
||||||
|
(inner-vars
|
||||||
|
;; select only vars declared with ellipsis
|
||||||
|
(filter (lambda (v) (> (cdr (assq v levels)) 0)) inner-freevars))
|
||||||
|
(inner-tmps
|
||||||
|
(map (lambda (v) #'it) inner-vars))
|
||||||
|
(inner-selectors
|
||||||
|
;; first env '(map cons ...)' shadows second env 'selectors'
|
||||||
|
(append (map cons inner-vars inner-tmps) selectors))
|
||||||
|
(inner-rep
|
||||||
|
(template-representation inner-pat inner-levels inner-selectors))
|
||||||
|
(sorted-selectors
|
||||||
|
(map (lambda (v) (assq v selectors)) inner-vars))
|
||||||
|
(list-of-selectors
|
||||||
|
;; ((a . xs) (b . ys) (c . zs)) -> (xs ys zs)
|
||||||
|
(map cdr sorted-selectors)))
|
||||||
|
(let ((rep1 #`(map (lambda #,inner-tmps #,inner-rep) #,@list-of-selectors))
|
||||||
|
(rep2 (template-representation (cddr pat) levels selectors)))
|
||||||
|
#`(append #,rep1 #,rep2))))
|
||||||
|
((pair? pat)
|
||||||
|
#`(cons #,(template-representation (car pat) levels selectors)
|
||||||
|
#,(template-representation (cdr pat) levels selectors)))))
|
||||||
|
|
||||||
|
(define (compile-rule pattern template)
|
||||||
|
(let ((levels
|
||||||
|
(pattern-levels pattern))
|
||||||
|
(selectors
|
||||||
|
(pattern-selectors pattern)))
|
||||||
|
(template-representation template levels selectors)))
|
||||||
|
|
||||||
|
(define (compile-rules rules)
|
||||||
|
(if (null? rules)
|
||||||
|
#`(error "unmatch")
|
||||||
|
(let ((pattern (car (car rules)))
|
||||||
|
(template (cadr (car rules))))
|
||||||
|
#`(if #,(pattern-validator pattern)
|
||||||
|
#,(compile-rule pattern template)
|
||||||
|
#,(compile-rules (cdr rules))))))
|
||||||
|
|
||||||
|
(define (compile rules)
|
||||||
|
#`(call-with-current-environment
|
||||||
|
(lambda (env)
|
||||||
|
(letrec
|
||||||
|
((#,'rename (let ((reg (make-register)))
|
||||||
|
(lambda (x)
|
||||||
|
(let ((y (reg x)))
|
||||||
|
(if y
|
||||||
|
(cdr y)
|
||||||
|
(let ((id (make-identifier x env)))
|
||||||
|
(reg x id)
|
||||||
|
id)))))))
|
||||||
|
(lambda #,'it
|
||||||
|
#,(compile-rules rules))))))
|
||||||
|
|
||||||
|
(let ((rules (map-keys cdr rules))) ; TODO: check pattern head is a variable
|
||||||
|
(compile rules)))
|
||||||
|
|
||||||
|
(define-syntax (syntax-rules . args)
|
||||||
|
(if (list? (car args))
|
||||||
|
#`(syntax-rules ... #,@args)
|
||||||
|
(let ((ellipsis (car args))
|
||||||
|
(literals (car (cdr args)))
|
||||||
|
(rules (cdr (cdr args))))
|
||||||
|
(compile ellipsis literals rules))))
|
||||||
|
|
||||||
|
(define-syntax (define-auxiliary-syntax var)
|
||||||
|
#`(define-macro #,var
|
||||||
|
(lambda _
|
||||||
|
(error "invalid use of auxiliary syntax" '#,var))))
|
||||||
|
|
||||||
|
(define-auxiliary-syntax _)
|
||||||
|
(define-auxiliary-syntax ...)
|
||||||
|
|
||||||
(export syntax-rules
|
(export syntax-rules
|
||||||
_
|
_
|
||||||
...)
|
...)
|
||||||
|
@ -171,6 +412,56 @@
|
||||||
|
|
||||||
;; 5.5 Recored-type definitions
|
;; 5.5 Recored-type definitions
|
||||||
|
|
||||||
|
(define ((boot-make-record-type <meta-type>) name)
|
||||||
|
(let ((rectype (make-record <meta-type>)))
|
||||||
|
(record-set! rectype 'name name)
|
||||||
|
rectype))
|
||||||
|
|
||||||
|
(define <record-type>
|
||||||
|
(let ((<record-type> ((boot-make-record-type #t) 'record-type)))
|
||||||
|
(record-set! <record-type> '@@type <record-type>)
|
||||||
|
<record-type>))
|
||||||
|
|
||||||
|
(define make-record-type (boot-make-record-type <record-type>))
|
||||||
|
|
||||||
|
(define-syntax (define-record-constructor type name . fields)
|
||||||
|
(let ((record #'record))
|
||||||
|
#`(define (#,name . #,fields)
|
||||||
|
(let ((#,record (make-record #,type)))
|
||||||
|
#,@(map (lambda (field) #`(record-set! #,record '#,field #,field)) fields)
|
||||||
|
#,record))))
|
||||||
|
|
||||||
|
(define-syntax (define-record-predicate type name)
|
||||||
|
#`(define (#,name obj)
|
||||||
|
(and (record? obj)
|
||||||
|
(eq? (record-type obj) #,type))))
|
||||||
|
|
||||||
|
(define-syntax (define-record-accessor pred field accessor)
|
||||||
|
#`(define (#,accessor record)
|
||||||
|
(if (#,pred record)
|
||||||
|
(record-ref record '#,field)
|
||||||
|
(error (string-append (symbol->string '#,accessor) ": wrong record type") record))))
|
||||||
|
|
||||||
|
(define-syntax (define-record-modifier pred field modifier)
|
||||||
|
#`(define (#,modifier record val)
|
||||||
|
(if (#,pred record)
|
||||||
|
(record-set! record '#,field val)
|
||||||
|
(error (string-append (symbol->string '#,modifier) ": wrong record type") record))))
|
||||||
|
|
||||||
|
(define-syntax (define-record-field pred field accessor . modifier-opt)
|
||||||
|
(if (null? modifier-opt)
|
||||||
|
#`(define-record-accessor #,pred #,field #,accessor)
|
||||||
|
#`(begin
|
||||||
|
(define-record-accessor #,pred #,field #,accessor)
|
||||||
|
(define-record-modifier #,pred #,field #,(car modifier-opt)))))
|
||||||
|
|
||||||
|
(define-syntax (define-record-type name ctor pred . fields)
|
||||||
|
#`(begin
|
||||||
|
(define #,name (make-record-type '#,name))
|
||||||
|
(define-record-constructor #,name #,@ctor)
|
||||||
|
(define-record-predicate #,name #,pred)
|
||||||
|
#,@(map (lambda (field) #`(define-record-field #,pred #,@field)) fields)))
|
||||||
|
|
||||||
(export define-record-type)
|
(export define-record-type)
|
||||||
|
|
||||||
;; 6.1. Equivalence predicates
|
;; 6.1. Equivalence predicates
|
||||||
|
@ -181,6 +472,16 @@
|
||||||
|
|
||||||
;; 6.2. Numbers
|
;; 6.2. Numbers
|
||||||
|
|
||||||
|
(define complex? number?)
|
||||||
|
(define real? number?)
|
||||||
|
(define rational? number?)
|
||||||
|
(define (integer? o)
|
||||||
|
(or (exact? o)
|
||||||
|
(and (inexact? o)
|
||||||
|
(not (nan? o))
|
||||||
|
(not (infinite? o))
|
||||||
|
(= o (floor o)))))
|
||||||
|
|
||||||
(define (exact-integer? x)
|
(define (exact-integer? x)
|
||||||
(and (exact? x)
|
(and (exact? x)
|
||||||
(integer? x)))
|
(integer? x)))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(define-library (scheme inexact)
|
(define-library (scheme inexact)
|
||||||
(import (picrin base))
|
(import (picrin base)
|
||||||
|
(picrin math))
|
||||||
|
|
||||||
(export acos
|
(export acos
|
||||||
asin
|
asin
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
(scheme lazy)
|
(scheme lazy)
|
||||||
(scheme eval)
|
(scheme eval)
|
||||||
(scheme load)
|
(scheme load)
|
||||||
(picrin base))
|
(only (picrin base)
|
||||||
|
library-environment
|
||||||
|
find-library))
|
||||||
|
|
||||||
(define-library (scheme null)
|
(define-library (scheme null)
|
||||||
(import (scheme base))
|
(import (scheme base))
|
||||||
|
|
|
@ -11,7 +11,7 @@ file_error(pic_state *pic, const char *msg)
|
||||||
{
|
{
|
||||||
struct pic_error *e;
|
struct pic_error *e;
|
||||||
|
|
||||||
e = pic_make_error(pic, pic->sFILE, msg, pic_nil_value());
|
e = pic_make_error(pic, pic_intern(pic, "file"), msg, pic_nil_value());
|
||||||
|
|
||||||
pic_raise(pic, pic_obj_value(e));
|
pic_raise(pic, pic_obj_value(e));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,27 +4,20 @@
|
||||||
|
|
||||||
#include "picrin.h"
|
#include "picrin.h"
|
||||||
|
|
||||||
void
|
|
||||||
pic_load(pic_state *pic, const char *filename)
|
|
||||||
{
|
|
||||||
struct pic_port *port;
|
|
||||||
|
|
||||||
port = pic_open_file(pic, filename, PIC_PORT_IN | PIC_PORT_TEXT);
|
|
||||||
|
|
||||||
pic_load_port(pic, port);
|
|
||||||
|
|
||||||
pic_close_port(pic, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
pic_load_load(pic_state *pic)
|
pic_load_load(pic_state *pic)
|
||||||
{
|
{
|
||||||
pic_value envid;
|
pic_value envid;
|
||||||
char *fn;
|
char *fn;
|
||||||
|
struct pic_port *port;
|
||||||
|
|
||||||
pic_get_args(pic, "z|o", &fn, &envid);
|
pic_get_args(pic, "z|o", &fn, &envid);
|
||||||
|
|
||||||
pic_load(pic, fn);
|
port = pic_open_file(pic, fn, PIC_PORT_IN | PIC_PORT_TEXT);
|
||||||
|
|
||||||
|
pic_load(pic, port);
|
||||||
|
|
||||||
|
pic_close_port(pic, port);
|
||||||
|
|
||||||
return pic_undef_value();
|
return pic_undef_value();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,16 @@ void
|
||||||
pic_str_set(pic_state *pic, pic_str *str, size_t i, char c)
|
pic_str_set(pic_state *pic, pic_str *str, size_t i, char c)
|
||||||
{
|
{
|
||||||
pic_str *x, *y, *z, *tmp;
|
pic_str *x, *y, *z, *tmp;
|
||||||
|
char buf[1];
|
||||||
|
|
||||||
if (pic_str_len(str) <= i) {
|
if (pic_str_len(str) <= i) {
|
||||||
pic_errorf(pic, "index out of range %d", i);
|
pic_errorf(pic, "index out of range %d", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf[0] = c;
|
||||||
|
|
||||||
x = pic_str_sub(pic, str, 0, i);
|
x = pic_str_sub(pic, str, 0, i);
|
||||||
y = pic_make_str_fill(pic, 1, c);
|
y = pic_make_str(pic, buf, 1);
|
||||||
z = pic_str_sub(pic, str, i + 1, pic_str_len(str));
|
z = pic_str_sub(pic, str, i + 1, pic_str_len(str));
|
||||||
|
|
||||||
tmp = pic_str_cat(pic, x, pic_str_cat(pic, y, z));
|
tmp = pic_str_cat(pic, x, pic_str_cat(pic, y, z));
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
(import (picrin base)
|
(import (scheme base)
|
||||||
(picrin syntax-rules)
|
|
||||||
(picrin test))
|
(picrin test))
|
||||||
|
|
||||||
(test-begin)
|
(test-begin "syntax-rules")
|
||||||
|
|
||||||
(define-syntax extract?
|
(define-syntax extract?
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
|
@ -3,5 +3,5 @@ CONTRIB_TESTS += test-optional
|
||||||
|
|
||||||
test-optional: bin/picrin
|
test-optional: bin/picrin
|
||||||
for test in `ls contrib/30.optional/t/*.scm`; do \
|
for test in `ls contrib/30.optional/t/*.scm`; do \
|
||||||
bin/picrin $$test; \
|
$(TEST_RUNNER) $$test; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -27,6 +27,16 @@
|
||||||
(reset (lambda ()
|
(reset (lambda ()
|
||||||
(k v))))))))))
|
(k v))))))))))
|
||||||
|
|
||||||
(export shift
|
(define-syntax reset*
|
||||||
reset))
|
(syntax-rules ()
|
||||||
|
((_ expr ...)
|
||||||
|
(reset (lambda () expr ...)))))
|
||||||
|
|
||||||
|
(define-syntax shift*
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ k expr ...)
|
||||||
|
(shift (lambda (k) expr ...)))))
|
||||||
|
|
||||||
|
(export (rename shift* shift)
|
||||||
|
(rename reset* reset)))
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,5 @@ CONTRIB_TESTS += test-random
|
||||||
|
|
||||||
test-random: bin/picrin
|
test-random: bin/picrin
|
||||||
for test in `ls contrib/30.random/t/*.scm`; do \
|
for test in `ls contrib/30.random/t/*.scm`; do \
|
||||||
bin/picrin $$test; \
|
$(TEST_RUNNER) $$test; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -12,5 +12,5 @@ contrib/src/readline.o: contrib/src/readline.c
|
||||||
|
|
||||||
test-readline: bin/picrin
|
test-readline: bin/picrin
|
||||||
for test in `ls contrib/30.readline/t/*.scm`; do \
|
for test in `ls contrib/30.readline/t/*.scm`; do \
|
||||||
bin/picrin $$test; \
|
$(TEST_RUNNER) $$test; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
(picrin readline history)
|
(picrin readline history)
|
||||||
(picrin test))
|
(picrin test))
|
||||||
|
|
||||||
(define testfile "picrin_readline_test_file")
|
(define testfile "/tmp/picrin_readline_test_file")
|
||||||
(test-begin)
|
(test-begin)
|
||||||
|
|
||||||
(test 0 (history-length))
|
(test 0 (history-length))
|
||||||
|
|
|
@ -4,5 +4,5 @@ CONTRIB_TESTS += test-regexp
|
||||||
|
|
||||||
test-regexp: bin/picrin
|
test-regexp: bin/picrin
|
||||||
for test in `ls contrib/30.regexp/t/*.scm`; do \
|
for test in `ls contrib/30.regexp/t/*.scm`; do \
|
||||||
bin/picrin $$test; \
|
$(TEST_RUNNER) $$test; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
CONTRIB_LIBS += $(wildcard contrib/30.test/*.scm)
|
|
@ -1,6 +1,6 @@
|
||||||
(define-library (picrin test)
|
(define-library (picrin test)
|
||||||
(import (picrin base)
|
(import (scheme base)
|
||||||
(picrin syntax-rules))
|
(scheme write))
|
||||||
|
|
||||||
(define test-counter 0)
|
(define test-counter 0)
|
||||||
(define counter 0)
|
(define counter 0)
|
|
@ -0,0 +1 @@
|
||||||
|
CONTRIB_LIBS += $(wildcard contrib/40.procedure/*.scm)
|
|
@ -0,0 +1,25 @@
|
||||||
|
(define-library (picrin procedure)
|
||||||
|
(import (scheme base))
|
||||||
|
(export >>
|
||||||
|
<<
|
||||||
|
constant
|
||||||
|
identity)
|
||||||
|
|
||||||
|
(define identity values)
|
||||||
|
|
||||||
|
(define (constant . args)
|
||||||
|
(lambda _
|
||||||
|
(apply values args)))
|
||||||
|
|
||||||
|
(define (>> . fs)
|
||||||
|
(if (null? fs)
|
||||||
|
identity
|
||||||
|
(let ((f (car fs))
|
||||||
|
(g (apply >> (cdr fs))))
|
||||||
|
(lambda args
|
||||||
|
(call-with-values (lambda () (apply f args))
|
||||||
|
(lambda args
|
||||||
|
(apply g args)))))))
|
||||||
|
|
||||||
|
(define (<< . fs)
|
||||||
|
(apply >> (reverse fs))))
|
|
@ -1,5 +1,8 @@
|
||||||
CONTRIB_INITS += socket
|
CONTRIB_INITS += \
|
||||||
|
srfi_0 \
|
||||||
|
srfi_106
|
||||||
CONTRIB_LIBS += \
|
CONTRIB_LIBS += \
|
||||||
|
contrib/40.srfi/srfi/0.scm\
|
||||||
contrib/40.srfi/srfi/1.scm\
|
contrib/40.srfi/srfi/1.scm\
|
||||||
contrib/40.srfi/srfi/8.scm\
|
contrib/40.srfi/srfi/8.scm\
|
||||||
contrib/40.srfi/srfi/17.scm\
|
contrib/40.srfi/srfi/17.scm\
|
||||||
|
@ -9,10 +12,12 @@ CONTRIB_LIBS += \
|
||||||
contrib/40.srfi/srfi/95.scm\
|
contrib/40.srfi/srfi/95.scm\
|
||||||
contrib/40.srfi/srfi/106.scm\
|
contrib/40.srfi/srfi/106.scm\
|
||||||
contrib/40.srfi/srfi/111.scm
|
contrib/40.srfi/srfi/111.scm
|
||||||
CONTRIB_SRCS += contrib/40.srfi/src/106.c
|
CONTRIB_SRCS += \
|
||||||
|
contrib/40.srfi/src/0.c\
|
||||||
|
contrib/40.srfi/src/106.c
|
||||||
CONTRIB_TESTS += test-srfi
|
CONTRIB_TESTS += test-srfi
|
||||||
|
|
||||||
test-srfi: bin/picrin
|
test-srfi: bin/picrin
|
||||||
for test in `ls contrib/40.srfi/t/*.scm`; do \
|
for test in `ls contrib/40.srfi/t/*.scm`; do \
|
||||||
bin/picrin "$$test"; \
|
$(TEST_RUNNER) "$$test"; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include "picrin.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
pic_init_srfi_0(pic_state *pic)
|
||||||
|
{
|
||||||
|
pic_add_feature(pic, "srfi-0");
|
||||||
|
pic_add_feature(pic, "srfi-1");
|
||||||
|
pic_add_feature(pic, "srfi-8");
|
||||||
|
pic_add_feature(pic, "srfi-17");
|
||||||
|
pic_add_feature(pic, "srfi-26");
|
||||||
|
pic_add_feature(pic, "srfi-43");
|
||||||
|
pic_add_feature(pic, "srfi-60");
|
||||||
|
pic_add_feature(pic, "srfi-95");
|
||||||
|
pic_add_feature(pic, "srfi-106");
|
||||||
|
pic_add_feature(pic, "srfi-111");
|
||||||
|
}
|
|
@ -397,7 +397,7 @@ pic_socket_call_with_socket(pic_state *pic)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_init_socket(pic_state *pic)
|
pic_init_srfi_106(pic_state *pic)
|
||||||
{
|
{
|
||||||
pic_deflibrary (pic, "(srfi 106)") {
|
pic_deflibrary (pic, "(srfi 106)") {
|
||||||
pic_defun_(pic, "socket?", pic_socket_socket_p);
|
pic_defun_(pic, "socket?", pic_socket_socket_p);
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
(define-library (srfi 0)
|
||||||
|
(import (scheme base))
|
||||||
|
(export cond-expand))
|
|
@ -315,8 +315,7 @@
|
||||||
(let rec ((clist clist) (cont values))
|
(let rec ((clist clist) (cont values))
|
||||||
(if (null? clist)
|
(if (null? clist)
|
||||||
(cont knil)
|
(cont knil)
|
||||||
(let ((tail (map cdr clists)))
|
(rec (cdr clist) (lambda (x) (cont (kons clist x))))))
|
||||||
(rec tail (lambda (x) (cont (kons clist x)))))))
|
|
||||||
(let rec ((clists (cons clist clists)) (cont values))
|
(let rec ((clists (cons clist clists)) (cont values))
|
||||||
(if (every pair? clists)
|
(if (every pair? clists)
|
||||||
(let ((tail (map cdr clists)))
|
(let ((tail (map cdr clists)))
|
||||||
|
@ -497,11 +496,11 @@
|
||||||
(define (any pred clist . clists)
|
(define (any pred clist . clists)
|
||||||
(if (null? clists)
|
(if (null? clists)
|
||||||
(let rec ((clist clist))
|
(let rec ((clist clist))
|
||||||
(if (pair? clist)
|
(and (pair? clist)
|
||||||
(or (pred (car clist))
|
(or (pred (car clist))
|
||||||
(rec (cdr clist)))))
|
(rec (cdr clist)))))
|
||||||
(let rec ((clists (cons clist clists)))
|
(let rec ((clists (cons clist clists)))
|
||||||
(if (every pair? clists)
|
(and (every pair? clists)
|
||||||
(or (apply pred (map car clists))
|
(or (apply pred (map car clists))
|
||||||
(rec (map cdr clists)))))))
|
(rec (map cdr clists)))))))
|
||||||
|
|
||||||
|
@ -510,11 +509,11 @@
|
||||||
(if (null? clists)
|
(if (null? clists)
|
||||||
(let rec ((clist clist))
|
(let rec ((clist clist))
|
||||||
(or (null? clist)
|
(or (null? clist)
|
||||||
(if (pred (car clist))
|
(and (pred (car clist))
|
||||||
(rec (cdr clist)))))
|
(rec (cdr clist)))))
|
||||||
(let rec ((clists (cons clist clists)))
|
(let rec ((clists (cons clist clists)))
|
||||||
(or (any null? clists)
|
(or (any null? clists)
|
||||||
(if (apply pred (map car clists))
|
(and (apply pred (map car clists))
|
||||||
(rec (map cdr clists))))))))
|
(rec (map cdr clists))))))))
|
||||||
|
|
||||||
(define (list-index pred clist . clists)
|
(define (list-index pred clist . clists)
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
(letrec ((setter
|
(letrec ((setter
|
||||||
(lambda (proc)
|
(lambda (proc)
|
||||||
(let ((setter (dictionary-ref (attribute proc) '@@setter)))
|
(let ((setter (dictionary-ref (attribute proc) '@@setter)))
|
||||||
(if (undefined? setter)
|
(if setter
|
||||||
(error "no setter found")
|
(cdr setter)
|
||||||
setter))))
|
(error "no setter found")))))
|
||||||
(set-setter!
|
(set-setter!
|
||||||
(lambda (proc setter)
|
(lambda (proc setter)
|
||||||
(dictionary-set! (attribute proc) '@@setter setter))))
|
(dictionary-set! (attribute proc) '@@setter setter))))
|
||||||
|
|
|
@ -0,0 +1,292 @@
|
||||||
|
;; Certain portions of this document -- the specific, marked segments of text
|
||||||
|
;; describing the R5RS procedures -- were adapted with permission from the R5RS
|
||||||
|
;; report.
|
||||||
|
;;
|
||||||
|
;; All other text is copyright (C) Olin Shivers (1998, 1999). All Rights
|
||||||
|
;; Reserved.
|
||||||
|
;;
|
||||||
|
;; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
;; of this software and associated documentation files (the "Software"), to
|
||||||
|
;; deal in the Software without restriction, including without limitation the
|
||||||
|
;; rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
;; sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
;; furnished to do so, subject to the following conditions:
|
||||||
|
;;
|
||||||
|
;; The above copyright notice and this permission notice shall be included in
|
||||||
|
;; all copies or substantial portions of the Software.
|
||||||
|
;;
|
||||||
|
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
;; IN THE SOFTWARE.
|
||||||
|
|
||||||
|
(import (scheme base)
|
||||||
|
(srfi 1)
|
||||||
|
(picrin test))
|
||||||
|
|
||||||
|
(test-begin)
|
||||||
|
|
||||||
|
(test '(a) (cons 'a '()))
|
||||||
|
(test '((a) b c d) (cons '(a) '(b c d)))
|
||||||
|
(test '("a" b c) (cons "a" '(b c)))
|
||||||
|
(test '(a . 3) (cons 'a 3))
|
||||||
|
(test '((a b) . c) (cons '(a b) 'c))
|
||||||
|
|
||||||
|
(test '(a 7 c) (list 'a (+ 3 4) 'c))
|
||||||
|
(test '() (list))
|
||||||
|
|
||||||
|
(test '(a b c) (xcons '(b c) 'a))
|
||||||
|
|
||||||
|
; (test '(1 2 3 . 4) (cons* 1 2 3 4))
|
||||||
|
; (test 1 (cons* 1))
|
||||||
|
|
||||||
|
(test '(c c c c) (make-list 4 'c))
|
||||||
|
|
||||||
|
(test '(0 1 2 3) (list-tabulate 4 values))
|
||||||
|
|
||||||
|
; TODO: Test list-copy
|
||||||
|
|
||||||
|
; (test #0=(z q . #0#) (circular-list 'z 'q))
|
||||||
|
|
||||||
|
(test '(0 1 2 3 4) (iota 5))
|
||||||
|
(test '(0 -0.1 -0.2 -0.3 -0.4) (iota 5 0 -0.1))
|
||||||
|
|
||||||
|
; TODO: Test proper-list?
|
||||||
|
; TODO: Test circular-list?
|
||||||
|
; TODO: Test dotted-list?
|
||||||
|
|
||||||
|
(test #t (pair? '(a . b)))
|
||||||
|
(test #t (pair? '(a b c)))
|
||||||
|
(test #f (pair? '()))
|
||||||
|
(test #f (pair? '#(a b)))
|
||||||
|
(test #f (pair? 7))
|
||||||
|
(test #f (pair? 'a))
|
||||||
|
|
||||||
|
; TODO: Test null?
|
||||||
|
; TODO: Test null-list?
|
||||||
|
; TODO: Test not-pair?
|
||||||
|
|
||||||
|
(test #t (list= eq?))
|
||||||
|
(test #t (list= eq? '(a)))
|
||||||
|
; TODO: Add non-trivial test cases for list=
|
||||||
|
|
||||||
|
(test 'a (car '(a b c)))
|
||||||
|
(test '(a) (car '((a) b c d)))
|
||||||
|
(test 1 (car '(1 . 2)))
|
||||||
|
(test #t (error-object?
|
||||||
|
(guard (exn (else exn))
|
||||||
|
(car '()))))
|
||||||
|
|
||||||
|
(test '(b c) (cdr '(a b c)))
|
||||||
|
(test '(b c d) (cdr '((a) b c d)))
|
||||||
|
(test 2 (cdr '(1 . 2)))
|
||||||
|
(test #t (error-object?
|
||||||
|
(guard (exn (else exn))
|
||||||
|
(cdr '()))))
|
||||||
|
|
||||||
|
; TODO: Test /c[ad]{2,4}r/
|
||||||
|
|
||||||
|
(test 'c (list-ref '(a b c d) 2))
|
||||||
|
|
||||||
|
; TODO: Test first, second, ..., tenth
|
||||||
|
; TODO: Test car+cdr
|
||||||
|
|
||||||
|
(test '(a b) (take '(a b c d e) 2))
|
||||||
|
(test '(1 2) (take '(1 2 3 . d) 2))
|
||||||
|
(test '(1 2 3) (take '(1 2 3 . d) 3))
|
||||||
|
|
||||||
|
(test '(c d e) (drop '(a b c d e) 2))
|
||||||
|
(test '(3 . d) (drop '(1 2 3 . d) 2))
|
||||||
|
(test 'd (drop '(1 2 3 . d) 3))
|
||||||
|
|
||||||
|
(test '(d e) (take-right '(a b c d e) 2))
|
||||||
|
; (test '(2 3 . d) (take-right '(1 2 3 . d) 2))
|
||||||
|
; (test 'd (take-right '(1 2 3 . d) 0)
|
||||||
|
|
||||||
|
(test '(a b c) (drop-right '(a b c d e) 2))
|
||||||
|
; (test '(1) (drop-right '(1 2 3 . d) 2))
|
||||||
|
; (test '(1 2 3) (drop-right '(1 2 3 . d) 0))
|
||||||
|
|
||||||
|
(test '(1 3) (take! (circular-list 1 3 5) 8)) ; implementation dependent behavior
|
||||||
|
|
||||||
|
; TODO: Test split-at
|
||||||
|
; TODO: Test split-at!
|
||||||
|
|
||||||
|
(test 'c (last '(a b c)))
|
||||||
|
(test '(c) (last-pair '(a b c)))
|
||||||
|
|
||||||
|
; TODO: Test length
|
||||||
|
; TODO: Test length+
|
||||||
|
|
||||||
|
(test '(x y) (append '(x) '(y)))
|
||||||
|
(test '(a b c d) (append '(a) '(b c d)))
|
||||||
|
(test '(a (b) (c)) (append '(a (b)) '((c))))
|
||||||
|
(test '(a b c . d) (append '(a b) '(c . d)))
|
||||||
|
(test 'a (append '() 'a))
|
||||||
|
(test '(x y) (append '(x y)))
|
||||||
|
(test '() (append))
|
||||||
|
|
||||||
|
; TODO: Test append!
|
||||||
|
; TODO: Test concatenate
|
||||||
|
; TODO: Test concatenate!
|
||||||
|
|
||||||
|
(test '(c b a) (reverse '(a b c)))
|
||||||
|
(test '((e (f)) d (b c) a) (reverse '(a (b c) d (e (f)))))
|
||||||
|
|
||||||
|
; TODO: Test reverse!
|
||||||
|
; TODO: Test append-reverse
|
||||||
|
; TODO: Test append-reverse!
|
||||||
|
|
||||||
|
(test '((one 1 odd) (two 2 even) (three 3 odd))
|
||||||
|
(zip '(one two three)
|
||||||
|
'(1 2 3)
|
||||||
|
'(odd even odd even odd even odd even)))
|
||||||
|
(test '((1) (2) (3)) (zip '(1 2 3)))
|
||||||
|
(test '((3 #f) (1 #t) (4 #f) (1 #t)) (zip '(3 1 4 1) (circular-list #f #t)))
|
||||||
|
|
||||||
|
; TODO: Test /unzip[1-5]/
|
||||||
|
|
||||||
|
(test 3 (count even? '(3 1 4 1 5 9 2 5 6)))
|
||||||
|
(test 3 (count < '(1 2 4 8) '(2 4 6 8 10 12 14 16)))
|
||||||
|
(test 2 (count < '(3 1 4 1) (circular-list 1 10)))
|
||||||
|
|
||||||
|
; TODO: Test fold
|
||||||
|
; TODO: Test fold-right
|
||||||
|
; TODO: Test pair-fold
|
||||||
|
|
||||||
|
(test '((a b c) (b c) (c)) (pair-fold-right cons '() '(a b c)))
|
||||||
|
|
||||||
|
; TODO: Test reduce
|
||||||
|
; TODO: Test reduce-right
|
||||||
|
; TODO: Test unfold
|
||||||
|
; TODO: unfold-right
|
||||||
|
|
||||||
|
(test '(b e h) (map cadr '((a b) (d e) (g h))))
|
||||||
|
(test '(1 4 27 256 3125) (map (lambda (n) (expt n n))
|
||||||
|
'(1 2 3 4 5)))
|
||||||
|
(test '(5 7 9) (map + '(1 2 3) '(4 5 6)))
|
||||||
|
(test '(4 1 5 1) (map + '(3 1 4 1) (circular-list 1 0)))
|
||||||
|
|
||||||
|
(test #(0 1 4 9 16)
|
||||||
|
(let ((v (make-vector 5)))
|
||||||
|
(for-each (lambda (i)
|
||||||
|
(vector-set! v i (* i i)))
|
||||||
|
'(0 1 2 3 4))
|
||||||
|
v))
|
||||||
|
|
||||||
|
; TODO: Test append-map
|
||||||
|
; TODO: Test append-map!
|
||||||
|
; TODO: Test map!
|
||||||
|
; TODO: Test map-in-order
|
||||||
|
; TODO: Test pair-for-each
|
||||||
|
|
||||||
|
(test '(1 9 49) (filter-map (lambda (x) (and (number? x) (* x x))) '(a 1 b 3 c 7)))
|
||||||
|
|
||||||
|
(test '(0 8 8 -4) (filter even? '(0 7 8 8 43 -4)))
|
||||||
|
|
||||||
|
; TODO: Test partition
|
||||||
|
|
||||||
|
(test '(7 43) (remove even? '(0 7 8 8 43 -4)))
|
||||||
|
|
||||||
|
; TODO: Test filter!
|
||||||
|
; TODO: Test partition!
|
||||||
|
; TODO: Test remove!
|
||||||
|
|
||||||
|
(test 4 (find even? '(3 1 4 1 5 9)))
|
||||||
|
|
||||||
|
(test '(-8 -5 0 0) (find-tail even? '(3 1 37 -8 -5 0 0)))
|
||||||
|
(test #f (find-tail even? '(3 1 37 -5)))
|
||||||
|
|
||||||
|
(test '(2 18) (take-while even? '(2 18 3 10 22 9)))
|
||||||
|
|
||||||
|
; TODO: Test take-while!
|
||||||
|
|
||||||
|
(test '(3 10 22 9) (drop-while even? '(2 18 3 10 22 9)))
|
||||||
|
|
||||||
|
; TODO: Test span
|
||||||
|
; TODO: Test span!
|
||||||
|
; TODO: Test break
|
||||||
|
; TODO: Test break!
|
||||||
|
|
||||||
|
(test #t (any integer? '(a 3 b 2.7)))
|
||||||
|
(test #f (any integer? '(a 3.1 b 2.7)))
|
||||||
|
(test #t (any < '(3 1 4 1 5) '(2 7 1 8 2)))
|
||||||
|
|
||||||
|
; TODO: Test every
|
||||||
|
|
||||||
|
(test 2 (list-index even? '(3 1 4 1 5 9)))
|
||||||
|
; (test 1 (list-index < '(3 1 4 1 5 9 2 5 6) '(2 7 1 8 2)))
|
||||||
|
; (test #f (list-index = '(3 1 4 1 5 9 2 5 6) '(2 7 1 8 2)))
|
||||||
|
|
||||||
|
(test '((a) c) (member (list 'a) '(b (a) c)))
|
||||||
|
|
||||||
|
(test '(a b c) (memq 'a '(a b c)))
|
||||||
|
(test '(b c) (memq 'b '(a b c)))
|
||||||
|
(test #f (memq 'a '(b c d)))
|
||||||
|
(test #f (memq (list 'a) '(b (a) c)))
|
||||||
|
|
||||||
|
(test '(101 102) (memv 101 '(100 101 102)))
|
||||||
|
|
||||||
|
; TODO: Test delete
|
||||||
|
; TODO: Test delete!
|
||||||
|
|
||||||
|
(test '(a b c z) (delete-duplicates '(a b a c a b c z)))
|
||||||
|
(test '((a . 3) (b . 7) (c . 1))
|
||||||
|
(delete-duplicates '((a . 3) (b . 7) (a . 9) (c . 1))
|
||||||
|
(lambda (x y) (eq? (car x) (car y)))))
|
||||||
|
|
||||||
|
; TODO: Test delete-duplicates!
|
||||||
|
|
||||||
|
(test '((a)) (assoc (list 'a) '(((a)) ((b)) ((c)))))
|
||||||
|
|
||||||
|
(define e '((a 1) (b 2) (c 3)))
|
||||||
|
(test '(a 1) (assq 'a e))
|
||||||
|
(test '(b 2) (assq 'b e))
|
||||||
|
(test #f (assq 'd e))
|
||||||
|
(test #f (assq (list 'a) '(((a)) ((b)) ((c)))))
|
||||||
|
(test '(5 7) (assv 5 '((2 3) (5 7) (11 13))))
|
||||||
|
|
||||||
|
; TODO: Test alist-cons
|
||||||
|
; TODO: Test alist-copy
|
||||||
|
; TODO: Test alist-delete
|
||||||
|
; TODO: Test alist-delete!
|
||||||
|
|
||||||
|
(test #t (lset<= eq? '(a) '(a b a) '(a b c c)))
|
||||||
|
(test #t (lset<= eq?))
|
||||||
|
(test #t (lset<= eq? '(a)))
|
||||||
|
|
||||||
|
(test #t (lset= eq? '(b e a) '(a e b) '(e e b a)))
|
||||||
|
(test #t (lset= eq?))
|
||||||
|
(test #t (lset= eq? '(a)))
|
||||||
|
|
||||||
|
(test '(u o i a b c d c e) (lset-adjoin eq? '(a b c d c e) 'a 'e 'i 'o 'u))
|
||||||
|
|
||||||
|
(test '(u o i a b c d e) (lset-union eq? '(a b c d e) '(a e i o u)))
|
||||||
|
(test '(x a a c) (lset-union eq? '(a a c) '(x a x)))
|
||||||
|
(test '() (lset-union eq?))
|
||||||
|
(test '(a b c) (lset-union eq? '(a b c)))
|
||||||
|
|
||||||
|
(test '(a e) (lset-intersection eq? '(a b c d e) '(a e i o u)))
|
||||||
|
(test '(a x a) (lset-intersection eq? '(a x y a) '(x a x z)))
|
||||||
|
(test '(a b c) (lset-intersection eq? '(a b c)))
|
||||||
|
|
||||||
|
(test '(b c d) (lset-difference eq? '(a b c d e) '(a e i o u)))
|
||||||
|
(test '(a b c) (lset-difference eq? '(a b c)))
|
||||||
|
|
||||||
|
(test '(d c b i o u) (lset-xor eq? '(a b c d e) '(a e i o u)))
|
||||||
|
(test '() (lset-xor eq?))
|
||||||
|
(test '(a b c d e) (lset-xor eq? '(a b c d e)))
|
||||||
|
|
||||||
|
; TODO: Test lset-diff+intersection
|
||||||
|
; TODO: Test lset-union!
|
||||||
|
; TODO: Test lset-intersection!
|
||||||
|
; TODO: Test lset-difference!
|
||||||
|
; TODO: Test lset-xor!
|
||||||
|
; TODO: Test lset-diff+intersection!
|
||||||
|
; TODO: Test set-car!
|
||||||
|
; TODO: Test set-cdr!
|
||||||
|
|
||||||
|
(test-end)
|
|
@ -2,6 +2,8 @@
|
||||||
(srfi 106)
|
(srfi 106)
|
||||||
(picrin test))
|
(picrin test))
|
||||||
|
|
||||||
|
(test-begin)
|
||||||
|
|
||||||
; The number 9600 has no meaning. I just borrowed from Rust.
|
; The number 9600 has no meaning. I just borrowed from Rust.
|
||||||
(define *test-port* 9600)
|
(define *test-port* 9600)
|
||||||
(define (next-test-port)
|
(define (next-test-port)
|
||||||
|
@ -70,3 +72,5 @@
|
||||||
(test *shut-wr* (shutdown-method write))
|
(test *shut-wr* (shutdown-method write))
|
||||||
(test *shut-rdwr* (shutdown-method read write))
|
(test *shut-rdwr* (shutdown-method read write))
|
||||||
(test *shut-rdwr* (shutdown-method write read))
|
(test *shut-rdwr* (shutdown-method write read))
|
||||||
|
|
||||||
|
(test-end)
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
(define-library (picrin destructuring-bind)
|
||||||
|
(import (picrin base)
|
||||||
|
(picrin macro))
|
||||||
|
|
||||||
|
(define-syntax (destructuring-bind formal value . body)
|
||||||
|
(cond
|
||||||
|
((variable? formal)
|
||||||
|
#`(let ((#,formal #,value))
|
||||||
|
#,@body))
|
||||||
|
((pair? formal)
|
||||||
|
#`(let ((value #,value))
|
||||||
|
(destructuring-bind #,(car formal) (car value)
|
||||||
|
(destructuring-bind #,(cdr formal) (cdr value)
|
||||||
|
#,@body))))
|
||||||
|
((vector? formal)
|
||||||
|
;; TODO
|
||||||
|
(error "fixme"))
|
||||||
|
(else
|
||||||
|
#`(if (equal? #,value '#,formal)
|
||||||
|
(begin
|
||||||
|
#,@body)
|
||||||
|
(error "match failure" #,value '#,formal)))))
|
||||||
|
|
||||||
|
(export destructuring-bind))
|
|
@ -0,0 +1 @@
|
||||||
|
CONTRIB_LIBS += $(wildcard contrib/50.destructuring-bind/*.scm)
|
|
@ -3,5 +3,5 @@ CONTRIB_TESTS += test-for
|
||||||
|
|
||||||
test-for: bin/picrin
|
test-for: bin/picrin
|
||||||
for test in `ls contrib/50.for/t/*.scm`; do \
|
for test in `ls contrib/50.for/t/*.scm`; do \
|
||||||
bin/picrin "$$test"; \
|
$(TEST_RUNNER) "$$test"; \
|
||||||
done
|
done
|
||||||
|
|
|
@ -2,19 +2,29 @@
|
||||||
(import (scheme base)
|
(import (scheme base)
|
||||||
(picrin control))
|
(picrin control))
|
||||||
|
|
||||||
(define-syntax for
|
(define unit list)
|
||||||
|
|
||||||
|
(define (bind m f)
|
||||||
|
(apply append (map f m)))
|
||||||
|
|
||||||
|
(define-syntax reify
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((_ expr)
|
((_ expr)
|
||||||
(reset (lambda () expr)))))
|
(reset (unit expr)))))
|
||||||
|
|
||||||
(define (in m)
|
(define (reflect m)
|
||||||
(shift (lambda (k)
|
(shift k (bind m k)))
|
||||||
(apply append (map k m)))))
|
|
||||||
|
|
||||||
(define (yield x)
|
(define zero '())
|
||||||
(list x))
|
|
||||||
|
|
||||||
(define (null . x)
|
(define plus append)
|
||||||
'())
|
|
||||||
|
|
||||||
(export for in yield null))
|
(export unit
|
||||||
|
bind
|
||||||
|
zero
|
||||||
|
plus
|
||||||
|
reify
|
||||||
|
reflect
|
||||||
|
(rename reify for)
|
||||||
|
(rename reflect in)
|
||||||
|
(rename unit yield)))
|
||||||
|
|
|
@ -4,18 +4,20 @@
|
||||||
|
|
||||||
(test '(1 2 3)
|
(test '(1 2 3)
|
||||||
(for
|
(for
|
||||||
(yield (in '(1 2 3)))))
|
(in '(1 2 3))))
|
||||||
|
|
||||||
(test '((1 a) (1 b) (1 c) (2 a) (2 b) (2 c) (3 a) (3 b) (3 c))
|
(test '((1 . a) (1 . b) (1 . c) (2 . a) (2 . b) (2 . c) (3 . a) (3 . b) (3 . c))
|
||||||
(for
|
(for
|
||||||
(let ((n (in '(1 2 3)))
|
(let ((n (in '(1 2 3)))
|
||||||
(c (in '(a b c))))
|
(c (in '(a b c))))
|
||||||
(yield (list n c)))))
|
(cons n c))))
|
||||||
|
|
||||||
(test '((2 a) (2 b) (2 c))
|
(define (fail) (in zero))
|
||||||
|
|
||||||
|
(test '((2 . a) (2 . b) (2 . c))
|
||||||
(for
|
(for
|
||||||
(let ((n (in '(1 2 3)))
|
(let ((n (in '(1 2 3)))
|
||||||
(c (in '(a b c))))
|
(c (in '(a b c))))
|
||||||
(if (even? n)
|
(if (even? n)
|
||||||
(yield (list n c))
|
(cons n c)
|
||||||
(null)))))
|
(fail)))))
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
CONTRIB_LIBS += $(wildcard contrib/50.option/*.scm)
|
||||||
|
CONTRIB_TESTS += test-option
|
||||||
|
|
||||||
|
test-option: bin/picrin
|
||||||
|
for test in `ls contrib/50.option/t/*.scm`; do \
|
||||||
|
$(TEST_RUNNER) "$$test"; \
|
||||||
|
done
|
|
@ -0,0 +1,22 @@
|
||||||
|
(define-library (picrin control option)
|
||||||
|
(import (scheme base)
|
||||||
|
(picrin control)
|
||||||
|
(picrin procedure))
|
||||||
|
|
||||||
|
(define unit identity)
|
||||||
|
|
||||||
|
(define (bind m f)
|
||||||
|
(and m (f m)))
|
||||||
|
|
||||||
|
(define-syntax reify
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ expr)
|
||||||
|
(reset (unit expr)))))
|
||||||
|
|
||||||
|
(define (reflect m)
|
||||||
|
(shift k (bind m k)))
|
||||||
|
|
||||||
|
(export unit
|
||||||
|
bind
|
||||||
|
reify
|
||||||
|
reflect))
|
|
@ -0,0 +1,27 @@
|
||||||
|
(import (picrin base)
|
||||||
|
(picrin test)
|
||||||
|
(picrin control option))
|
||||||
|
|
||||||
|
(define phonebook
|
||||||
|
'(("Bob" . "01788 665242")
|
||||||
|
("Fred" . "01624 556442")
|
||||||
|
("Alice" . "01889 985333")
|
||||||
|
("Jane" . "01732 187565")))
|
||||||
|
|
||||||
|
(define nums
|
||||||
|
'((one . 1) (two . 2) (three . 3) (four . 19)))
|
||||||
|
|
||||||
|
(define num-dict
|
||||||
|
(alist->dictionary nums))
|
||||||
|
|
||||||
|
(test '("01889 985333" . 3)
|
||||||
|
(reify
|
||||||
|
(let* ((a (reflect (assoc "Alice" phonebook)))
|
||||||
|
(b (reflect (dictionary-ref num-dict 'three))))
|
||||||
|
(cons (cdr a) (cdr b)))))
|
||||||
|
|
||||||
|
(test '#f
|
||||||
|
(reify
|
||||||
|
(let* ((a (reflect (assoc "Alice" phonebook)))
|
||||||
|
(b (reflect (dictionary-ref num-dict 'five))))
|
||||||
|
(cons (cdr a) (cdr b)))))
|
|
@ -0,0 +1,131 @@
|
||||||
|
(define-library (picrin logic)
|
||||||
|
(import (scheme base)
|
||||||
|
(picrin control))
|
||||||
|
(export call/fresh
|
||||||
|
disj
|
||||||
|
conj
|
||||||
|
is
|
||||||
|
run-goal
|
||||||
|
run-goal*
|
||||||
|
zero
|
||||||
|
plus
|
||||||
|
unit
|
||||||
|
bind
|
||||||
|
reify
|
||||||
|
reflect)
|
||||||
|
|
||||||
|
(define (assp p alist)
|
||||||
|
(if (null? alist)
|
||||||
|
#f
|
||||||
|
(if (p (caar alist))
|
||||||
|
(car alist)
|
||||||
|
(assp p (cdr alist)))))
|
||||||
|
|
||||||
|
(define (force* $)
|
||||||
|
(if (procedure? $) (force* ($)) $))
|
||||||
|
|
||||||
|
;; fundation
|
||||||
|
|
||||||
|
(define (var c) (vector c))
|
||||||
|
(define (var? x) (vector? x))
|
||||||
|
(define (var=? x1 x2) (= (vector-ref x1 0) (vector-ref x2 0)))
|
||||||
|
|
||||||
|
(define (subst u s)
|
||||||
|
(let ((pr (and (var? u) (assp (lambda (v) (var=? u v)) s))))
|
||||||
|
(if pr (subst (cdr pr) s) u)))
|
||||||
|
|
||||||
|
(define (subst* v s)
|
||||||
|
(let ((v (subst v s)))
|
||||||
|
(cond
|
||||||
|
((var? v) v)
|
||||||
|
((pair? v) (cons (subst* (car v) s)
|
||||||
|
(subst* (cdr v) s)))
|
||||||
|
(else v))))
|
||||||
|
|
||||||
|
(define (ext-s x v s) `((,x . ,v) . ,s))
|
||||||
|
|
||||||
|
(define (unify u v s)
|
||||||
|
(let ((u (subst u s)) (v (subst v s)))
|
||||||
|
(cond
|
||||||
|
((and (var? u) (var? v) (var=? u v)) s)
|
||||||
|
((var? u) (ext-s u v s))
|
||||||
|
((var? v) (ext-s v u s))
|
||||||
|
((and (pair? u) (pair? v))
|
||||||
|
(let ((s (unify (car u) (car v) s)))
|
||||||
|
(and s (unify (cdr u) (cdr v) s))))
|
||||||
|
(else (and (eqv? u v) s)))))
|
||||||
|
|
||||||
|
;; klist monad
|
||||||
|
|
||||||
|
(define zero '())
|
||||||
|
(define (plus $1 $2)
|
||||||
|
(cond
|
||||||
|
((null? $1) $2)
|
||||||
|
((procedure? $1) (lambda () (plus $2 ($1))))
|
||||||
|
((pair? $1) (cons (car $1) (plus (cdr $1) $2)))))
|
||||||
|
|
||||||
|
(define (unit s/c) (list s/c))
|
||||||
|
(define (bind $ g)
|
||||||
|
(cond
|
||||||
|
((null? $) zero)
|
||||||
|
((procedure? $) (lambda () (bind ($) g)))
|
||||||
|
((pair? $) (plus (g (car $)) (bind (cdr $) g)))))
|
||||||
|
|
||||||
|
(define-syntax reify
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ expr)
|
||||||
|
(reset (unit expr)))))
|
||||||
|
|
||||||
|
(define (reflect m)
|
||||||
|
(shift k (bind m k)))
|
||||||
|
|
||||||
|
;; goal constructors
|
||||||
|
|
||||||
|
(define (call/fresh f)
|
||||||
|
(lambda (s/c)
|
||||||
|
(let ((s (car s/c)) (c (cdr s/c)))
|
||||||
|
((f (var c)) `(,s . ,(+ c 1))))))
|
||||||
|
|
||||||
|
(define (disj g1 g2) (lambda (s/c) (plus (g1 s/c) (g2 s/c))))
|
||||||
|
(define (conj g1 g2) (lambda (s/c) (bind (g1 s/c) g2)))
|
||||||
|
|
||||||
|
(define (is u v)
|
||||||
|
(lambda (s/c)
|
||||||
|
(let ((s (unify u v (car s/c))))
|
||||||
|
(if s (unit `(,s . ,(cdr s/c))) zero))))
|
||||||
|
|
||||||
|
;; goal runner
|
||||||
|
|
||||||
|
(define initial-state '(() . 0))
|
||||||
|
|
||||||
|
(define (run-goal n g)
|
||||||
|
(map reify-1st (take n (g initial-state))))
|
||||||
|
|
||||||
|
(define (run-goal* g)
|
||||||
|
(map reify-1st (take* (g initial-state))))
|
||||||
|
|
||||||
|
(define (take n $)
|
||||||
|
(if (zero? n) '()
|
||||||
|
(let (($ (force* $)))
|
||||||
|
(if (null? $) '() (cons (car $) (take (- n 1) (cdr $)))))))
|
||||||
|
|
||||||
|
(define (take* $)
|
||||||
|
(let (($ (force* $)))
|
||||||
|
(if (null? $) '() (cons (car $) (take* (cdr $))))))
|
||||||
|
|
||||||
|
(define (reify-1st s/c)
|
||||||
|
(let ((v (subst* (var 0) (car s/c))))
|
||||||
|
(subst* v (reify-s v '()))))
|
||||||
|
|
||||||
|
(define (reify-s v s)
|
||||||
|
(let ((v (subst v s)))
|
||||||
|
(cond
|
||||||
|
((var? v)
|
||||||
|
(let ((n (reify-name (length s))))
|
||||||
|
(cons `(,v . ,n) s)))
|
||||||
|
((pair? v) (reify-s (cdr v) (reify-s (car v) s)))
|
||||||
|
(else s))))
|
||||||
|
|
||||||
|
(define (reify-name n)
|
||||||
|
(string->symbol
|
||||||
|
(string-append "_" "." (number->string n)))))
|
|
@ -0,0 +1,7 @@
|
||||||
|
CONTRIB_LIBS += $(wildcard contrib/60.logic/*.scm)
|
||||||
|
CONTRIB_TESTS += test-logic
|
||||||
|
|
||||||
|
test-logic: bin/picrin
|
||||||
|
for test in `ls contrib/60.logic/t/*.scm`; do \
|
||||||
|
$(TEST_RUNNER) "$$test"; \
|
||||||
|
done
|
|
@ -0,0 +1,120 @@
|
||||||
|
(import (scheme base)
|
||||||
|
(scheme lazy)
|
||||||
|
(scheme write)
|
||||||
|
(picrin logic)
|
||||||
|
(picrin test))
|
||||||
|
|
||||||
|
(define-syntax Zzz
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ g) (lambda (s/c) (lambda () (g s/c))))))
|
||||||
|
|
||||||
|
(define-syntax conj+
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ g) (Zzz g))
|
||||||
|
((_ g0 g ...) (conj (Zzz g0) (conj+ g ...)))))
|
||||||
|
|
||||||
|
(define-syntax disj+
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ g) (Zzz g))
|
||||||
|
((_ g0 g ...) (disj (Zzz g0) (disj+ g ...)))))
|
||||||
|
|
||||||
|
(define-syntax fresh
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ () g0 g ...) (conj+ g0 g ...))
|
||||||
|
((_ (x0 x ...) g0 g ...)
|
||||||
|
(call/fresh
|
||||||
|
(lambda (x0)
|
||||||
|
(fresh (x ...) g0 g ...))))))
|
||||||
|
|
||||||
|
(define-syntax conde
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ (g0 g ...) ...) (disj+ (conj+ g0 g ...) ...))))
|
||||||
|
|
||||||
|
(define-syntax run
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ n (x ...) g0 g ...)
|
||||||
|
(run-goal n (fresh (x ...) g0 g ...)))))
|
||||||
|
|
||||||
|
(define-syntax run*
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ (x ...) g0 g ...)
|
||||||
|
(run-goal* (fresh (x ...) g0 g ...)))))
|
||||||
|
|
||||||
|
(define (appendo l s out)
|
||||||
|
(conde
|
||||||
|
((is '() l) (is s out))
|
||||||
|
((fresh (a d res)
|
||||||
|
(is `(,a . ,d) l)
|
||||||
|
(is `(,a . ,res) out)
|
||||||
|
(appendo d s res)))))
|
||||||
|
|
||||||
|
(test '((() (1 2 3 4 5))
|
||||||
|
((1) (2 3 4 5))
|
||||||
|
((1 2) (3 4 5))
|
||||||
|
((1 2 3) (4 5))
|
||||||
|
((1 2 3 4) (5))
|
||||||
|
((1 2 3 4 5) ()))
|
||||||
|
(run* (q) (fresh (x y) (is `(,x ,y) q) (appendo x y '(1 2 3 4 5)))))
|
||||||
|
|
||||||
|
(test '((() (1 2 3 4 5))
|
||||||
|
((1) (2 3 4 5))
|
||||||
|
((1 2) (3 4 5))
|
||||||
|
((1 2 3) (4 5))
|
||||||
|
((1 2 3 4) (5))
|
||||||
|
((1 2 3 4 5) ()))
|
||||||
|
(run* (q x y) (is `(,x ,y) q) (appendo x y '(1 2 3 4 5))))
|
||||||
|
|
||||||
|
(test '((1 2 8 3 4 5)
|
||||||
|
(1 2 8 3 4 5 8)
|
||||||
|
(1 2 8 3 4 8 5)
|
||||||
|
(1 2 8 3 8 4 5)
|
||||||
|
(1 2 8 8 3 4 5)
|
||||||
|
(1 2 8 8 3 4 5)
|
||||||
|
(1 8 2 8 3 4 5)
|
||||||
|
(8 1 2 8 3 4 5))
|
||||||
|
(letrec
|
||||||
|
((rember*o (lambda (tr o)
|
||||||
|
(conde
|
||||||
|
((is '() tr) (is '() o))
|
||||||
|
((fresh (a d)
|
||||||
|
(is `(,a . ,d) tr)
|
||||||
|
(conde
|
||||||
|
((fresh (aa da)
|
||||||
|
(is `(,aa . ,da) a)
|
||||||
|
(fresh (a^ d^)
|
||||||
|
(rember*o a a^)
|
||||||
|
(rember*o d d^)
|
||||||
|
(is `(,a^ . ,d^) o))))
|
||||||
|
((is a 8) (rember*o d o))
|
||||||
|
((fresh (d^)
|
||||||
|
(rember*o d d^)
|
||||||
|
(is `(,a . ,d^) o))))))))))
|
||||||
|
(run 8 (q) (rember*o q '(1 2 8 3 4 5)))))
|
||||||
|
|
||||||
|
(test '((1 (2 8 3 4) 5)
|
||||||
|
(1 (2 8 3 4) 5 8)
|
||||||
|
(1 (2 8 3 4) 5 8 8)
|
||||||
|
(1 (2 8 3 4) 8 5)
|
||||||
|
(1 8 (2 8 3 4) 5)
|
||||||
|
(8 1 (2 8 3 4) 5)
|
||||||
|
(1 (2 8 3 4) 5 8 8 8)
|
||||||
|
(1 (2 8 3 4) 5 8 8 8 8)
|
||||||
|
(1 (2 8 3 4) 5 8 8 8 8 8))
|
||||||
|
(letrec
|
||||||
|
((rember*o (lambda (tr o)
|
||||||
|
(conde
|
||||||
|
((is '() tr) (is '() o))
|
||||||
|
((fresh (a d)
|
||||||
|
(is `(,a . ,d) tr)
|
||||||
|
(conde
|
||||||
|
((fresh (aa da)
|
||||||
|
(is `(,aa . ,da) a)
|
||||||
|
(fresh (a^ d^)
|
||||||
|
(is `(,a^ . ,d^) o)
|
||||||
|
(rember*o d d^)
|
||||||
|
(rember*o a a^))))
|
||||||
|
((is a 8) (rember*o d o))
|
||||||
|
((fresh (d^)
|
||||||
|
(is `(,a . ,d^) o)
|
||||||
|
(rember*o d d^))))))))))
|
||||||
|
(run 9 (q) (rember*o q '(1 (2 8 3 4) 5)))))
|
|
@ -0,0 +1,2 @@
|
||||||
|
- memoize
|
||||||
|
- more procedures
|
|
@ -0,0 +1,8 @@
|
||||||
|
CONTRIB_LIBS += contrib/60.peg/picrin/parser.scm contrib/60.peg/picrin/parser/string.scm
|
||||||
|
|
||||||
|
CONTRIB_TESTS += test-peg
|
||||||
|
|
||||||
|
test-peg: bin/picrin
|
||||||
|
for test in `ls contrib/60.peg/t/*.scm`; do \
|
||||||
|
$(TEST_RUNNER) "$$test"; \
|
||||||
|
done
|
|
@ -0,0 +1,100 @@
|
||||||
|
(define-library (picrin parser)
|
||||||
|
(import (scheme base)
|
||||||
|
(picrin control)
|
||||||
|
(picrin procedure))
|
||||||
|
(export parse
|
||||||
|
;; monadic
|
||||||
|
reify
|
||||||
|
reflect
|
||||||
|
bind
|
||||||
|
unit
|
||||||
|
zero
|
||||||
|
plus
|
||||||
|
fapply
|
||||||
|
;; look ahead
|
||||||
|
with
|
||||||
|
without
|
||||||
|
;; eta
|
||||||
|
lazy
|
||||||
|
;; aux
|
||||||
|
choice
|
||||||
|
optional
|
||||||
|
many
|
||||||
|
between)
|
||||||
|
|
||||||
|
;; type Parser i r = i -> Maybe (r, i)
|
||||||
|
|
||||||
|
(define (parse rule input)
|
||||||
|
(rule input))
|
||||||
|
|
||||||
|
;; monadic operators
|
||||||
|
|
||||||
|
(define-syntax reify
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ expr)
|
||||||
|
(reset (unit expr)))))
|
||||||
|
|
||||||
|
(define (reflect x)
|
||||||
|
(shift k (bind x k)))
|
||||||
|
|
||||||
|
(define (bind m f)
|
||||||
|
(lambda (i)
|
||||||
|
(let ((x (m i)))
|
||||||
|
(and x ((f (car x)) (cdr x))))))
|
||||||
|
|
||||||
|
(define (unit x)
|
||||||
|
(lambda (i)
|
||||||
|
`(,x . ,i)))
|
||||||
|
|
||||||
|
(define zero
|
||||||
|
(lambda (i) #f))
|
||||||
|
|
||||||
|
(define (plus a b)
|
||||||
|
(lambda (i)
|
||||||
|
(or (a i) (b i))))
|
||||||
|
|
||||||
|
(define (fapply f . args)
|
||||||
|
(reify
|
||||||
|
(let loop ((args args) (ps '()))
|
||||||
|
(if (null? args)
|
||||||
|
(apply f (reverse ps))
|
||||||
|
(loop (cdr args) (cons (reflect (car args)) ps))))))
|
||||||
|
|
||||||
|
;; look ahead
|
||||||
|
|
||||||
|
(define (with a)
|
||||||
|
(lambda (i)
|
||||||
|
(and (a i) `(#f . ,i))))
|
||||||
|
|
||||||
|
(define (without a)
|
||||||
|
(lambda (i)
|
||||||
|
(and (not (a i)) `(#f . ,i))))
|
||||||
|
|
||||||
|
;; eta conversion
|
||||||
|
|
||||||
|
(define-syntax lazy
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ expr)
|
||||||
|
(lambda (i) (expr i)))))
|
||||||
|
|
||||||
|
;; aux
|
||||||
|
|
||||||
|
(define (choice . xs)
|
||||||
|
(if (null? xs)
|
||||||
|
zero
|
||||||
|
(plus (car xs) (apply choice (cdr xs)))))
|
||||||
|
|
||||||
|
(define (optional a)
|
||||||
|
(choice a (unit #f)))
|
||||||
|
|
||||||
|
(define (many a)
|
||||||
|
(lazy
|
||||||
|
(choice
|
||||||
|
(reify
|
||||||
|
(let* ((a (reflect a))
|
||||||
|
(b (reflect (many a))))
|
||||||
|
(cons a b)))
|
||||||
|
null)))
|
||||||
|
|
||||||
|
(define (between l x r)
|
||||||
|
(fapply (>> list cadr) l x r)))
|
|
@ -0,0 +1,28 @@
|
||||||
|
(define-library (picrin parser string)
|
||||||
|
(import (except (scheme base) string)
|
||||||
|
(picrin parser))
|
||||||
|
(export string
|
||||||
|
any-char
|
||||||
|
eof
|
||||||
|
parse-string)
|
||||||
|
|
||||||
|
;; string stream parser
|
||||||
|
|
||||||
|
(define (string str)
|
||||||
|
(lambda (i)
|
||||||
|
(let ((i (car i)) (input (cdr i)))
|
||||||
|
(let ((j (min (+ i (string-length str)) (string-length input))))
|
||||||
|
(and (equal? str (string-copy input i j))
|
||||||
|
`(,str . ,(cons j input)))))))
|
||||||
|
|
||||||
|
(define any-char
|
||||||
|
(lambda (i)
|
||||||
|
(let ((i (car i)) (input (cdr i)))
|
||||||
|
(and (< i (string-length input))
|
||||||
|
`(,(string-ref input i) . ,(cons (+ i 1) input))))))
|
||||||
|
|
||||||
|
(define eof
|
||||||
|
(without any-char))
|
||||||
|
|
||||||
|
(define (parse-string rule input)
|
||||||
|
(parse rule (cons 0 input))))
|
|
@ -0,0 +1,45 @@
|
||||||
|
;;; test case
|
||||||
|
|
||||||
|
(import (scheme base)
|
||||||
|
(picrin test)
|
||||||
|
(picrin procedure)
|
||||||
|
(picrin parser)
|
||||||
|
(picrin parser string))
|
||||||
|
|
||||||
|
(test-begin "(picrin parser) and (picrin parser string)")
|
||||||
|
|
||||||
|
(define LPAREN (string "("))
|
||||||
|
(define RPAREN (string ")"))
|
||||||
|
|
||||||
|
(define PLUS (string "+"))
|
||||||
|
(define MINUS (string "-"))
|
||||||
|
|
||||||
|
(define ONE (fapply (constant 1) (string "1")))
|
||||||
|
|
||||||
|
(define S (lazy
|
||||||
|
(fapply (>> list car) A eof)))
|
||||||
|
|
||||||
|
(define A (lazy
|
||||||
|
(choice
|
||||||
|
(fapply (lambda (p _ a) (list '+ p a)) P PLUS A)
|
||||||
|
(fapply (lambda (p _ a) (list '- p a)) P MINUS A)
|
||||||
|
P)))
|
||||||
|
|
||||||
|
(define P (lazy
|
||||||
|
(choice
|
||||||
|
(between LPAREN A RPAREN)
|
||||||
|
ONE)))
|
||||||
|
|
||||||
|
(define-syntax test-success
|
||||||
|
(syntax-rules ()
|
||||||
|
((_ expect str)
|
||||||
|
(test (cons expect (cons (string-length str) str))
|
||||||
|
(parse-string S str)))))
|
||||||
|
|
||||||
|
(test-success 1 "(1)")
|
||||||
|
(test-success '(- (+ 1 1) 1) "((1+1)-1)")
|
||||||
|
(test-success '(- (+ 1 1) 1) "((1+(1))-1)")
|
||||||
|
(test-success '(+ 1 (- 1 (+ 1 (- 1 (+ 1 1))))) "(1+(1-(1+(1-(1+1)))))")
|
||||||
|
(test-success '(+ 1 (+ 1(- 1 (+ 1 (- 1 (+ 1 1)))))) "(1+1+(1-(1+(1-(1+1)))))")
|
||||||
|
|
||||||
|
(test-end)
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
(define user-env (library-environment (find-library '(picrin user))))
|
(define user-env (library-environment (find-library '(picrin user))))
|
||||||
|
|
||||||
(begin
|
(define (init-env)
|
||||||
(current-library (find-library '(picrin user)))
|
(current-library (find-library '(picrin user)))
|
||||||
(eval
|
(eval
|
||||||
'(import (scheme base)
|
'(import (scheme base)
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
(current-library (find-library '(picrin repl))))
|
(current-library (find-library '(picrin repl))))
|
||||||
|
|
||||||
(define (repl)
|
(define (repl)
|
||||||
|
(init-env)
|
||||||
(let loop ((buf ""))
|
(let loop ((buf ""))
|
||||||
(let ((line (readline (if (equal? buf "") "> " ""))))
|
(let ((line (readline (if (equal? buf "") "> " ""))))
|
||||||
(if (eof-object? line)
|
(if (eof-object? line)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
(define-library (picrin array)
|
(define-library (picrin array)
|
||||||
(import (picrin base)
|
(import (scheme base))
|
||||||
(picrin record))
|
|
||||||
|
|
||||||
(define-record-type <array>
|
(define-record-type <array>
|
||||||
(create-array data size head tail)
|
(create-array data size head tail)
|
||||||
|
@ -10,11 +9,6 @@
|
||||||
(head array-head set-array-head!)
|
(head array-head set-array-head!)
|
||||||
(tail array-tail set-array-tail!))
|
(tail array-tail set-array-tail!))
|
||||||
|
|
||||||
(define (floor-remainder i j)
|
|
||||||
(call-with-values (lambda () (floor/ i j))
|
|
||||||
(lambda (q r)
|
|
||||||
r)))
|
|
||||||
|
|
||||||
(define (translate ary i)
|
(define (translate ary i)
|
||||||
(floor-remainder i (array-size ary)))
|
(floor-remainder i (array-size ary)))
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
CONTRIB_LIBS += $(wildcard contrib/90.array/*.scm)
|
||||||
|
|
||||||
|
CONTRIB_TESTS += test-array
|
||||||
|
|
||||||
|
test-array: bin/picrin
|
||||||
|
$(TEST_RUNNER) contrib/90.array/t/array.scm
|
|
@ -0,0 +1,26 @@
|
||||||
|
(import (scheme base)
|
||||||
|
(scheme write)
|
||||||
|
(picrin array)
|
||||||
|
(picrin test))
|
||||||
|
|
||||||
|
(test-begin)
|
||||||
|
|
||||||
|
(define ary (make-array))
|
||||||
|
|
||||||
|
(array-push! ary 1)
|
||||||
|
(array-push! ary 2)
|
||||||
|
(array-push! ary 3)
|
||||||
|
|
||||||
|
(test 3 (array-pop! ary))
|
||||||
|
(test 2 (array-pop! ary))
|
||||||
|
(test 1 (array-pop! ary))
|
||||||
|
|
||||||
|
(array-unshift! ary 1)
|
||||||
|
(array-unshift! ary 2)
|
||||||
|
(array-unshift! ary 3)
|
||||||
|
|
||||||
|
(test 3 (array-shift! ary))
|
||||||
|
(test 2 (array-shift! ary))
|
||||||
|
(test 1 (array-shift! ary))
|
||||||
|
|
||||||
|
(test-end)
|
|
@ -117,7 +117,7 @@ Symbol-to-object hash table.
|
||||||
|
|
||||||
- **(dictionary-ref dict key)**
|
- **(dictionary-ref dict key)**
|
||||||
|
|
||||||
Look up dictionary dict for a value associated with key. If dict has a slot for key `key`, the value stored in the slot is returned. Otherwise `#undefined` is returned.
|
Look up dictionary dict for a value associated with key. If dict has a slot for key `key`, a pair containing the key object and the associated value is returned. Otherwise `#f` is returned.
|
||||||
|
|
||||||
- **(dictionary-set! dict key obj)**
|
- **(dictionary-set! dict key obj)**
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
(define (time f)
|
(define (time f)
|
||||||
(let ((start (current-jiffy)))
|
(let ((start (current-jiffy)))
|
||||||
(f)
|
(f)
|
||||||
(/ (- (current-jiffy) start)
|
(inexact
|
||||||
(jiffies-per-second))))
|
(/ (- (current-jiffy) start)
|
||||||
|
(jiffies-per-second)))))
|
||||||
|
|
||||||
(define (tak x y z)
|
(define (tak x y z)
|
||||||
(if (> x y)
|
(if (> x y)
|
||||||
|
|
|
@ -22,13 +22,13 @@ pic_attr(pic_state *pic, pic_value obj)
|
||||||
pic_value
|
pic_value
|
||||||
pic_attr_ref(pic_state *pic, pic_value obj, const char *key)
|
pic_attr_ref(pic_state *pic, pic_value obj, const char *key)
|
||||||
{
|
{
|
||||||
return pic_dict_ref(pic, pic_attr(pic, obj), pic_intern_cstr(pic, key));
|
return pic_dict_ref(pic, pic_attr(pic, obj), pic_intern(pic, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_attr_set(pic_state *pic, pic_value obj, const char *key, pic_value v)
|
pic_attr_set(pic_state *pic, pic_value obj, const char *key, pic_value v)
|
||||||
{
|
{
|
||||||
pic_dict_set(pic, pic_attr(pic, obj), pic_intern_cstr(pic, key), v);
|
pic_dict_set(pic, pic_attr(pic, obj), pic_intern(pic, key), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
|
|
@ -186,13 +186,11 @@ pic_bool_boolean_eq_p(pic_state *pic)
|
||||||
void
|
void
|
||||||
pic_init_bool(pic_state *pic)
|
pic_init_bool(pic_state *pic)
|
||||||
{
|
{
|
||||||
void pic_defun_vm(pic_state *, const char *, pic_sym *, pic_func_t);
|
|
||||||
|
|
||||||
pic_defun(pic, "eq?", pic_bool_eq_p);
|
pic_defun(pic, "eq?", pic_bool_eq_p);
|
||||||
pic_defun(pic, "eqv?", pic_bool_eqv_p);
|
pic_defun(pic, "eqv?", pic_bool_eqv_p);
|
||||||
pic_defun(pic, "equal?", pic_bool_equal_p);
|
pic_defun(pic, "equal?", pic_bool_equal_p);
|
||||||
|
|
||||||
pic_defun_vm(pic, "not", pic->uNOT, pic_bool_not);
|
pic_defun(pic, "not", pic_bool_not);
|
||||||
|
|
||||||
pic_defun(pic, "boolean?", pic_bool_boolean_p);
|
pic_defun(pic, "boolean?", pic_bool_boolean_p);
|
||||||
pic_defun(pic, "boolean=?", pic_bool_boolean_eq_p);
|
pic_defun(pic, "boolean=?", pic_bool_boolean_eq_p);
|
||||||
|
|
|
@ -489,17 +489,17 @@ my $src = <<'EOL';
|
||||||
(letrec
|
(letrec
|
||||||
((wrap (lambda (var1)
|
((wrap (lambda (var1)
|
||||||
(let ((var2 (register1 var1)))
|
(let ((var2 (register1 var1)))
|
||||||
(if (undefined? var2)
|
(if var2
|
||||||
|
(cdr var2)
|
||||||
(let ((var2 (make-identifier var1 env)))
|
(let ((var2 (make-identifier var1 env)))
|
||||||
(register1 var1 var2)
|
(register1 var1 var2)
|
||||||
(register2 var2 var1)
|
(register2 var2 var1)
|
||||||
var2)
|
var2)))))
|
||||||
var2))))
|
|
||||||
(unwrap (lambda (var2)
|
(unwrap (lambda (var2)
|
||||||
(let ((var1 (register2 var2)))
|
(let ((var1 (register2 var2)))
|
||||||
(if (undefined? var1)
|
(if var1
|
||||||
var2
|
(cdr var1)
|
||||||
var1))))
|
var2))))
|
||||||
(walk (lambda (f form)
|
(walk (lambda (f form)
|
||||||
(cond
|
(cond
|
||||||
((variable? form)
|
((variable? form)
|
||||||
|
@ -600,8 +600,9 @@ my $src = <<'EOL';
|
||||||
(let ((alist (collect (cadr spec))))
|
(let ((alist (collect (cadr spec))))
|
||||||
(map (lambda (var) (assq var alist)) (cddr spec))))
|
(map (lambda (var) (assq var alist)) (cddr spec))))
|
||||||
((rename)
|
((rename)
|
||||||
(let ((alist (collect (cadr spec))))
|
(let ((alist (collect (cadr spec)))
|
||||||
(map (lambda (s) (or (assq (car s) (cddr spec)) s)) alist)))
|
(renames (map (lambda (x) `((car x) . (cadr x))) (cddr spec))))
|
||||||
|
(map (lambda (s) (or (assq (car s) renames) s)) alist)))
|
||||||
((prefix)
|
((prefix)
|
||||||
(let ((alist (collect (cadr spec))))
|
(let ((alist (collect (cadr spec))))
|
||||||
(map (lambda (s) (cons (prefix (caddr spec) (car s)) (cdr s))) alist)))
|
(map (lambda (s) (cons (prefix (caddr spec) (car s)) (cdr s))) alist)))
|
||||||
|
@ -645,12 +646,8 @@ my $src = <<'EOL';
|
||||||
(library-export (car slot) (cdr slot))))))
|
(library-export (car slot) (cdr slot))))))
|
||||||
(for-each export (cdr form)))))
|
(for-each export (cdr form)))))
|
||||||
|
|
||||||
(export define-library
|
(export define lambda quote set! if begin define-macro
|
||||||
cond-expand
|
let let* letrec letrec*
|
||||||
import
|
|
||||||
export)
|
|
||||||
|
|
||||||
(export let let* letrec letrec*
|
|
||||||
let-values let*-values define-values
|
let-values let*-values define-values
|
||||||
quasiquote unquote unquote-splicing
|
quasiquote unquote unquote-splicing
|
||||||
and or
|
and or
|
||||||
|
@ -926,84 +923,85 @@ const char pic_boot[][80] = {
|
||||||
"ap cdr renames)\n ,body))))))\n\n(define (transformer f)\n (lambda (form",
|
"ap cdr renames)\n ,body))))))\n\n(define (transformer f)\n (lambda (form",
|
||||||
" env)\n (let ((register1 (make-register))\n (register2 (make-register)",
|
" env)\n (let ((register1 (make-register))\n (register2 (make-register)",
|
||||||
"))\n (letrec\n ((wrap (lambda (var1)\n (let ((var2 ",
|
"))\n (letrec\n ((wrap (lambda (var1)\n (let ((var2 ",
|
||||||
"(register1 var1)))\n (if (undefined? var2)\n ",
|
"(register1 var1)))\n (if var2\n (cdr v",
|
||||||
" (let ((var2 (make-identifier var1 env)))\n (regi",
|
"ar2)\n (let ((var2 (make-identifier var1 env)))\n ",
|
||||||
"ster1 var1 var2)\n (register2 var2 var1)\n ",
|
" (register1 var1 var2)\n (register2 va",
|
||||||
" var2)\n var2))))\n (unwrap (lambda ",
|
"r2 var1)\n var2)))))\n (unwrap (lambda (var2)\n",
|
||||||
"(var2)\n (let ((var1 (register2 var2)))\n ",
|
" (let ((var1 (register2 var2)))\n (if v",
|
||||||
" (if (undefined? var1)\n var2\n ",
|
"ar1\n (cdr var1)\n var2))))\n ",
|
||||||
" var1))))\n (walk (lambda (f form)\n (cond\n ",
|
" (walk (lambda (f form)\n (cond\n ((v",
|
||||||
" ((variable? form)\n (f form))\n ",
|
"ariable? form)\n (f form))\n ((pair? form)\n",
|
||||||
"((pair? form)\n (cons (walk f (car form)) (walk f (cdr form))",
|
" (cons (walk f (car form)) (walk f (cdr form))))\n ",
|
||||||
"))\n ((vector? form)\n (list->vector (walk ",
|
" ((vector? form)\n (list->vector (walk f (vector->lis",
|
||||||
"f (vector->list form))))\n (else\n form))))",
|
"t form))))\n (else\n form)))))\n (let",
|
||||||
")\n (let ((form (cdr form)))\n (walk unwrap (apply f (walk wrap fo",
|
" ((form (cdr form)))\n (walk unwrap (apply f (walk wrap form))))))))\n\n(d",
|
||||||
"rm))))))))\n\n(define-macro define-syntax\n (lambda (form env)\n (let ((formal (",
|
"efine-macro define-syntax\n (lambda (form env)\n (let ((formal (car (cdr form)",
|
||||||
"car (cdr form)))\n (body (cdr (cdr form))))\n (if (pair? formal)\n ",
|
"))\n (body (cdr (cdr form))))\n (if (pair? formal)\n `(,(t",
|
||||||
" `(,(the 'define-syntax) ,(car formal) (,the-lambda ,(cdr formal) ,@body",
|
"he 'define-syntax) ,(car formal) (,the-lambda ,(cdr formal) ,@body))\n `",
|
||||||
"))\n `(,the-define-macro ,formal (,(the 'transformer) (,the-begin ,@body",
|
"(,the-define-macro ,formal (,(the 'transformer) (,the-begin ,@body)))))))\n\n(defi",
|
||||||
")))))))\n\n(define-macro letrec-syntax\n (lambda (form env)\n (let ((formal (car",
|
"ne-macro letrec-syntax\n (lambda (form env)\n (let ((formal (car (cdr form)))\n",
|
||||||
" (cdr form)))\n (body (cdr (cdr form))))\n `(let ()\n ,@(ma",
|
" (body (cdr (cdr form))))\n `(let ()\n ,@(map (lambda (x)\n",
|
||||||
"p (lambda (x)\n `(,(the 'define-syntax) ,(car x) ,(cadr x)))\n ",
|
" `(,(the 'define-syntax) ,(car x) ,(cadr x)))\n f",
|
||||||
" formal)\n ,@body))))\n\n(define-macro let-syntax\n (lambda (fo",
|
"ormal)\n ,@body))))\n\n(define-macro let-syntax\n (lambda (form env)\n `(",
|
||||||
"rm env)\n `(,(the 'letrec-syntax) ,@(cdr form))))\n\n\n;;; library primitives\n\n(d",
|
",(the 'letrec-syntax) ,@(cdr form))))\n\n\n;;; library primitives\n\n(define-macro de",
|
||||||
"efine-macro define-library\n (lambda (form _)\n (let ((name (cadr form))\n ",
|
"fine-library\n (lambda (form _)\n (let ((name (cadr form))\n (body (cd",
|
||||||
" (body (cddr form)))\n (let ((old-library (current-library))\n ",
|
"dr form)))\n (let ((old-library (current-library))\n (new-library ",
|
||||||
" (new-library (or (find-library name) (make-library name))))\n (let ((env ",
|
"(or (find-library name) (make-library name))))\n (let ((env (library-envir",
|
||||||
"(library-environment new-library)))\n (current-library new-library)\n ",
|
"onment new-library)))\n (current-library new-library)\n (for-eac",
|
||||||
" (for-each (lambda (expr) (eval expr env)) body)\n (current-library",
|
"h (lambda (expr) (eval expr env)) body)\n (current-library old-library))",
|
||||||
" old-library))))))\n\n(define-macro cond-expand\n (lambda (form _)\n (letrec\n ",
|
"))))\n\n(define-macro cond-expand\n (lambda (form _)\n (letrec\n ((test (l",
|
||||||
" ((test (lambda (form)\n (or\n (eq? form 'els",
|
"ambda (form)\n (or\n (eq? form 'else)\n ",
|
||||||
"e)\n (and (symbol? form)\n (memq form (feat",
|
" (and (symbol? form)\n (memq form (features)))\n ",
|
||||||
"ures)))\n (and (pair? form)\n (case (car fo",
|
" (and (pair? form)\n (case (car form)\n ",
|
||||||
"rm)\n ((library) (find-library (cadr form)))\n ",
|
" ((library) (find-library (cadr form)))\n (",
|
||||||
" ((not) (not (test (cadr form))))\n ((and) (l",
|
"(not) (not (test (cadr form))))\n ((and) (let loop ((form",
|
||||||
"et loop ((form (cdr form)))\n (or (null? form)\n ",
|
" (cdr form)))\n (or (null? form)\n ",
|
||||||
" (and (test (car form)) (loop (cdr form)))))",
|
" (and (test (car form)) (loop (cdr form))))))\n ",
|
||||||
")\n ((or) (let loop ((form (cdr form)))\n ",
|
" ((or) (let loop ((form (cdr form)))\n ",
|
||||||
" (and (pair? form)\n (or (tes",
|
" (and (pair? form)\n (or (test (car form)) ",
|
||||||
"t (car form)) (loop (cdr form))))))\n (else #f)))))))\n ",
|
"(loop (cdr form))))))\n (else #f)))))))\n (let loop (",
|
||||||
" (let loop ((clauses (cdr form)))\n (if (null? clauses)\n #und",
|
"(clauses (cdr form)))\n (if (null? clauses)\n #undefined\n ",
|
||||||
"efined\n (if (test (caar clauses))\n `(,the-begin ,@(cda",
|
" (if (test (caar clauses))\n `(,the-begin ,@(cdar clauses))\n ",
|
||||||
"r clauses))\n (loop (cdr clauses))))))))\n\n(define-macro import\n (",
|
" (loop (cdr clauses))))))))\n\n(define-macro import\n (lambda (form _",
|
||||||
"lambda (form _)\n (let ((caddr\n (lambda (x) (car (cdr (cdr x)))))\n ",
|
")\n (let ((caddr\n (lambda (x) (car (cdr (cdr x)))))\n (prefi",
|
||||||
" (prefix\n (lambda (prefix symbol)\n (string->symbol\n",
|
"x\n (lambda (prefix symbol)\n (string->symbol\n ",
|
||||||
" (string-append\n (symbol->string prefix)\n ",
|
"(string-append\n (symbol->string prefix)\n (symbol->st",
|
||||||
" (symbol->string symbol))))))\n (letrec\n ((extract\n (l",
|
"ring symbol))))))\n (letrec\n ((extract\n (lambda (spec)\n ",
|
||||||
"ambda (spec)\n (case (car spec)\n ((only rename prefix",
|
" (case (car spec)\n ((only rename prefix except)\n ",
|
||||||
" except)\n (extract (cadr spec)))\n (else\n ",
|
" (extract (cadr spec)))\n (else\n (or (f",
|
||||||
" (or (find-library spec) (error \"library not found\" spec))))))\n ",
|
"ind-library spec) (error \"library not found\" spec))))))\n (collect\n ",
|
||||||
" (collect\n (lambda (spec)\n (case (car spec)\n ",
|
" (lambda (spec)\n (case (car spec)\n ((only)\n ",
|
||||||
" ((only)\n (let ((alist (collect (cadr spec))))\n ",
|
" (let ((alist (collect (cadr spec))))\n (map (lam",
|
||||||
" (map (lambda (var) (assq var alist)) (cddr spec))))\n ((renam",
|
"bda (var) (assq var alist)) (cddr spec))))\n ((rename)\n ",
|
||||||
"e)\n (let ((alist (collect (cadr spec))))\n (map",
|
" (let ((alist (collect (cadr spec)))\n (renames (map (",
|
||||||
" (lambda (s) (or (assq (car s) (cddr spec)) s)) alist)))\n ((prefi",
|
"lambda (x) `((car x) . (cadr x))) (cddr spec))))\n (map (lambda",
|
||||||
"x)\n (let ((alist (collect (cadr spec))))\n (map",
|
" (s) (or (assq (car s) renames) s)) alist)))\n ((prefix)\n ",
|
||||||
" (lambda (s) (cons (prefix (caddr spec) (car s)) (cdr s))) alist)))\n ",
|
" (let ((alist (collect (cadr spec))))\n (map (lambda (s)",
|
||||||
" ((except)\n (let ((alist (collect (cadr spec))))\n ",
|
" (cons (prefix (caddr spec) (car s)) (cdr s))) alist)))\n ((except",
|
||||||
" (let loop ((alist alist))\n (if (null? alist)\n ",
|
")\n (let ((alist (collect (cadr spec))))\n (let ",
|
||||||
" '()\n (if (memq (caar alist) (cddr spec)",
|
"loop ((alist alist))\n (if (null? alist)\n ",
|
||||||
")\n (loop (cdr alist))\n (",
|
" '()\n (if (memq (caar alist) (cddr spec))\n ",
|
||||||
"cons (car alist) (loop (cdr alist))))))))\n (else\n ",
|
" (loop (cdr alist))\n (cons (car al",
|
||||||
" (let ((lib (or (find-library spec) (error \"library not found\" spec))))\n ",
|
"ist) (loop (cdr alist))))))))\n (else\n (let ((lib ",
|
||||||
" (map (lambda (x) (cons x x)) (library-exports lib))))))))\n (le",
|
"(or (find-library spec) (error \"library not found\" spec))))\n (",
|
||||||
"trec\n ((import\n (lambda (spec)\n (let ((",
|
"map (lambda (x) (cons x x)) (library-exports lib))))))))\n (letrec\n ",
|
||||||
"lib (extract spec))\n (alist (collect spec)))\n ",
|
" ((import\n (lambda (spec)\n (let ((lib (extract",
|
||||||
" (for-each\n (lambda (slot)\n (librar",
|
" spec))\n (alist (collect spec)))\n (for-e",
|
||||||
"y-import lib (cdr slot) (car slot)))\n alist)))))\n (f",
|
"ach\n (lambda (slot)\n (library-import lib",
|
||||||
"or-each import (cdr form)))))))\n\n(define-macro export\n (lambda (form _)\n (le",
|
" (cdr slot) (car slot)))\n alist)))))\n (for-each impo",
|
||||||
"trec\n ((collect\n (lambda (spec)\n (cond\n (",
|
"rt (cdr form)))))))\n\n(define-macro export\n (lambda (form _)\n (letrec\n ",
|
||||||
"(symbol? spec)\n `(,spec . ,spec))\n ((and (list? spec) (",
|
" ((collect\n (lambda (spec)\n (cond\n ((symbol? spe",
|
||||||
"= (length spec) 3) (eq? (car spec) 'rename))\n `(,(list-ref spec 1) ",
|
"c)\n `(,spec . ,spec))\n ((and (list? spec) (= (length sp",
|
||||||
". ,(list-ref spec 2)))\n (else\n (error \"malformed export",
|
"ec) 3) (eq? (car spec) 'rename))\n `(,(list-ref spec 1) . ,(list-ref",
|
||||||
"\")))))\n (export\n (lambda (spec)\n (let ((slot (coll",
|
" spec 2)))\n (else\n (error \"malformed export\")))))\n ",
|
||||||
"ect spec)))\n (library-export (car slot) (cdr slot))))))\n (for",
|
" (export\n (lambda (spec)\n (let ((slot (collect spec)))\n",
|
||||||
"-each export (cdr form)))))\n\n(export define-library\n cond-expand\n ",
|
" (library-export (car slot) (cdr slot))))))\n (for-each export",
|
||||||
"import\n export)\n\n(export let let* letrec letrec*\n let-values let*-",
|
" (cdr form)))))\n\n(export define lambda quote set! if begin define-macro\n ",
|
||||||
"values define-values\n quasiquote unquote unquote-splicing\n and or\n",
|
"let let* letrec letrec*\n let-values let*-values define-values\n qua",
|
||||||
" cond case else =>\n do when unless\n parameterize\n de",
|
"siquote unquote unquote-splicing\n and or\n cond case else =>\n ",
|
||||||
"fine-syntax\n syntax-quote syntax-unquote\n syntax-quasiquote syntax",
|
" do when unless\n parameterize\n define-syntax\n syntax-quote",
|
||||||
"-unquote-splicing\n let-syntax letrec-syntax\n syntax-error)\n\n\n",
|
" syntax-unquote\n syntax-quasiquote syntax-unquote-splicing\n let-sy",
|
||||||
|
"ntax letrec-syntax\n syntax-error)\n\n\n",
|
||||||
"",
|
"",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -79,6 +79,7 @@ pic_load_point(pic_state *pic, struct pic_cont *cont)
|
||||||
pic->arena_idx = cont->arena_idx;
|
pic->arena_idx = cont->arena_idx;
|
||||||
pic->ip = cont->ip;
|
pic->ip = cont->ip;
|
||||||
pic->ptable = cont->ptable;
|
pic->ptable = cont->ptable;
|
||||||
|
pic->cc = cont->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
@ -140,8 +141,6 @@ pic_callcc(pic_state *pic, struct pic_proc *proc)
|
||||||
pic_save_point(pic, &cont);
|
pic_save_point(pic, &cont);
|
||||||
|
|
||||||
if (PIC_SETJMP(pic, cont.jmp)) {
|
if (PIC_SETJMP(pic, cont.jmp)) {
|
||||||
pic->cc = pic->cc->prev;
|
|
||||||
|
|
||||||
return pic_values_by_list(pic, cont.results);
|
return pic_values_by_list(pic, cont.results);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -155,44 +154,62 @@ pic_callcc(pic_state *pic, struct pic_proc *proc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_va_values(pic_state *pic, size_t n, ...)
|
||||||
|
{
|
||||||
|
pic_vec *args = pic_make_vec(pic, n);
|
||||||
|
va_list ap;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
va_start(ap, n);
|
||||||
|
|
||||||
|
while (i < n) {
|
||||||
|
args->data[i++] = va_arg(ap, pic_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return pic_values(pic, n, args->data);
|
||||||
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_values0(pic_state *pic)
|
pic_values0(pic_state *pic)
|
||||||
{
|
{
|
||||||
return pic_values_by_list(pic, pic_nil_value());
|
return pic_va_values(pic, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_values1(pic_state *pic, pic_value arg1)
|
pic_values1(pic_state *pic, pic_value arg1)
|
||||||
{
|
{
|
||||||
return pic_values_by_list(pic, pic_list1(pic, arg1));
|
return pic_va_values(pic, 1, arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_values2(pic_state *pic, pic_value arg1, pic_value arg2)
|
pic_values2(pic_state *pic, pic_value arg1, pic_value arg2)
|
||||||
{
|
{
|
||||||
return pic_values_by_list(pic, pic_list2(pic, arg1, arg2));
|
return pic_va_values(pic, 2, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_values3(pic_state *pic, pic_value arg1, pic_value arg2, pic_value arg3)
|
pic_values3(pic_state *pic, pic_value arg1, pic_value arg2, pic_value arg3)
|
||||||
{
|
{
|
||||||
return pic_values_by_list(pic, pic_list3(pic, arg1, arg2, arg3));
|
return pic_va_values(pic, 3, arg1, arg2, arg3);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_values4(pic_state *pic, pic_value arg1, pic_value arg2, pic_value arg3, pic_value arg4)
|
pic_values4(pic_state *pic, pic_value arg1, pic_value arg2, pic_value arg3, pic_value arg4)
|
||||||
{
|
{
|
||||||
return pic_values_by_list(pic, pic_list4(pic, arg1, arg2, arg3, arg4));
|
return pic_va_values(pic, 4, arg1, arg2, arg3, arg4);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_values5(pic_state *pic, pic_value arg1, pic_value arg2, pic_value arg3, pic_value arg4, pic_value arg5)
|
pic_values5(pic_state *pic, pic_value arg1, pic_value arg2, pic_value arg3, pic_value arg4, pic_value arg5)
|
||||||
{
|
{
|
||||||
return pic_values_by_list(pic, pic_list5(pic, arg1, arg2, arg3, arg4, arg5));
|
return pic_va_values(pic, 5, arg1, arg2, arg3, arg4, arg5);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_values_by_array(pic_state *pic, size_t argc, pic_value *argv)
|
pic_values(pic_state *pic, size_t argc, pic_value *argv)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -264,7 +281,7 @@ pic_cont_values(pic_state *pic)
|
||||||
|
|
||||||
pic_get_args(pic, "*", &argc, &argv);
|
pic_get_args(pic, "*", &argc, &argv);
|
||||||
|
|
||||||
return pic_values_by_array(pic, argc, argv);
|
return pic_values(pic, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
@ -272,26 +289,28 @@ pic_cont_call_with_values(pic_state *pic)
|
||||||
{
|
{
|
||||||
struct pic_proc *producer, *consumer;
|
struct pic_proc *producer, *consumer;
|
||||||
size_t argc;
|
size_t argc;
|
||||||
pic_value args[256];
|
pic_vec *args;
|
||||||
|
|
||||||
pic_get_args(pic, "ll", &producer, &consumer);
|
pic_get_args(pic, "ll", &producer, &consumer);
|
||||||
|
|
||||||
pic_apply(pic, producer, pic_nil_value());
|
pic_apply(pic, producer, pic_nil_value());
|
||||||
|
|
||||||
argc = pic_receive(pic, 256, args);
|
argc = pic_receive(pic, 0, NULL);
|
||||||
|
args = pic_make_vec(pic, argc);
|
||||||
|
|
||||||
return pic_apply_trampoline(pic, consumer, pic_list_by_array(pic, argc, args));
|
pic_receive(pic, argc, args->data);
|
||||||
|
|
||||||
|
return pic_apply_trampoline(pic, consumer, argc, args->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_init_cont(pic_state *pic)
|
pic_init_cont(pic_state *pic)
|
||||||
{
|
{
|
||||||
void pic_defun_vm(pic_state *, const char *, pic_sym *, pic_func_t);
|
|
||||||
|
|
||||||
pic_defun(pic, "call-with-current-continuation", pic_cont_callcc);
|
pic_defun(pic, "call-with-current-continuation", pic_cont_callcc);
|
||||||
pic_defun(pic, "call/cc", pic_cont_callcc);
|
pic_defun(pic, "call/cc", pic_cont_callcc);
|
||||||
|
pic_defun(pic, "escape", pic_cont_callcc);
|
||||||
pic_defun(pic, "dynamic-wind", pic_cont_dynamic_wind);
|
pic_defun(pic, "dynamic-wind", pic_cont_dynamic_wind);
|
||||||
|
|
||||||
pic_defun_vm(pic, "values", pic->uVALUES, pic_cont_values);
|
pic_defun(pic, "values", pic_cont_values);
|
||||||
pic_defun_vm(pic, "call-with-values", pic->uCALL_WITH_VALUES, pic_cont_call_with_values);
|
pic_defun(pic, "call-with-values", pic_cont_call_with_values);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ pic_print_backtrace(pic_state *pic, xFILE *file)
|
||||||
pic_value elem, it;
|
pic_value elem, it;
|
||||||
|
|
||||||
e = pic_error_ptr(pic->err);
|
e = pic_error_ptr(pic->err);
|
||||||
if (e->type != pic_intern_cstr(pic, "")) {
|
if (e->type != pic_intern(pic, "")) {
|
||||||
pic_fwrite(pic, pic_obj_value(e->type), file);
|
pic_fwrite(pic, pic_obj_value(e->type), file);
|
||||||
xfprintf(pic, file, " ");
|
xfprintf(pic, file, " ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,9 +116,9 @@ pic_dict_dictionary_ref(pic_state *pic)
|
||||||
pic_get_args(pic, "dm", &dict, &key);
|
pic_get_args(pic, "dm", &dict, &key);
|
||||||
|
|
||||||
if (! pic_dict_has(pic, dict, key)) {
|
if (! pic_dict_has(pic, dict, key)) {
|
||||||
return pic_undef_value();
|
return pic_false_value();
|
||||||
}
|
}
|
||||||
return pic_dict_ref(pic, dict, key);
|
return pic_cons(pic, pic_obj_value(key), pic_dict_ref(pic, dict, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
@ -155,42 +155,19 @@ static pic_value
|
||||||
pic_dict_dictionary_map(pic_state *pic)
|
pic_dict_dictionary_map(pic_state *pic)
|
||||||
{
|
{
|
||||||
struct pic_proc *proc;
|
struct pic_proc *proc;
|
||||||
size_t argc, i;
|
struct pic_dict *dict;
|
||||||
pic_value *args;
|
khiter_t it;
|
||||||
pic_value arg_list, ret = pic_nil_value();
|
khash_t(dict) *kh;
|
||||||
|
pic_value ret = pic_nil_value();
|
||||||
|
|
||||||
pic_get_args(pic, "l*", &proc, &argc, &args);
|
pic_get_args(pic, "ld", &proc, &dict);
|
||||||
|
|
||||||
if (argc != 0) {
|
kh = &dict->hash;
|
||||||
khiter_t it[argc];
|
|
||||||
khash_t(dict) *kh[argc];
|
|
||||||
|
|
||||||
for (i = 0; i < argc; ++i) {
|
for (it = kh_begin(kh); it != kh_end(kh); ++it) {
|
||||||
if (! pic_dict_p(args[i])) {
|
if (kh_exist(kh, it)) {
|
||||||
pic_errorf(pic, "expected dict, but got %s", pic_type_repr(pic_type(args[i])));
|
pic_push(pic, pic_apply1(pic, proc, pic_obj_value(kh_key(kh, it))), ret);
|
||||||
}
|
|
||||||
kh[i] = &pic_dict_ptr(args[i])->hash;
|
|
||||||
it[i] = kh_begin(kh[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
|
||||||
arg_list = pic_nil_value();
|
|
||||||
for (i = 0; i < argc; ++i) {
|
|
||||||
while (it[i] != kh_end(kh[i])) { /* find next available */
|
|
||||||
if (kh_exist(kh[i], it[i]))
|
|
||||||
break;
|
|
||||||
it[i]++;
|
|
||||||
}
|
|
||||||
if (it[i] == kh_end(kh[i])) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pic_push(pic, pic_obj_value(kh_key(kh[i], it[i]++)), arg_list);
|
|
||||||
}
|
|
||||||
if (i != argc) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pic_push(pic, pic_apply(pic, proc, pic_reverse(pic, arg_list)), ret);
|
|
||||||
} while (1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pic_reverse(pic, ret);
|
return pic_reverse(pic, ret);
|
||||||
|
@ -200,42 +177,18 @@ static pic_value
|
||||||
pic_dict_dictionary_for_each(pic_state *pic)
|
pic_dict_dictionary_for_each(pic_state *pic)
|
||||||
{
|
{
|
||||||
struct pic_proc *proc;
|
struct pic_proc *proc;
|
||||||
size_t argc, i;
|
struct pic_dict *dict;
|
||||||
pic_value *args;
|
khiter_t it;
|
||||||
pic_value arg_list;
|
khash_t(dict) *kh;
|
||||||
|
|
||||||
pic_get_args(pic, "l*", &proc, &argc, &args);
|
pic_get_args(pic, "ld", &proc, &dict);
|
||||||
|
|
||||||
if (argc != 0) {
|
kh = &dict->hash;
|
||||||
khiter_t it[argc];
|
|
||||||
khash_t(dict) *kh[argc];
|
|
||||||
|
|
||||||
for (i = 0; i < argc; ++i) {
|
for (it = kh_begin(kh); it != kh_end(kh); ++it) {
|
||||||
if (! pic_dict_p(args[i])) {
|
if (kh_exist(kh, it)) {
|
||||||
pic_errorf(pic, "expected dict, but got %s", pic_type_repr(pic_type(args[i])));
|
pic_apply1(pic, proc, pic_obj_value(kh_key(kh, it)));
|
||||||
}
|
|
||||||
kh[i] = &pic_dict_ptr(args[i])->hash;
|
|
||||||
it[i] = kh_begin(kh[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
|
||||||
arg_list = pic_nil_value();
|
|
||||||
for (i = 0; i < argc; ++i) {
|
|
||||||
while (it[i] != kh_end(kh[i])) { /* find next available */
|
|
||||||
if (kh_exist(kh[i], it[i]))
|
|
||||||
break;
|
|
||||||
it[i]++;
|
|
||||||
}
|
|
||||||
if (it[i] == kh_end(kh[i])) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pic_push(pic, pic_obj_value(kh_key(kh[i], it[i]++)), arg_list);
|
|
||||||
}
|
|
||||||
if (i != argc) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pic_void(pic_apply(pic, proc, pic_reverse(pic, arg_list)));
|
|
||||||
} while (1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pic_undef_value();
|
return pic_undef_value();
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
void
|
void
|
||||||
pic_panic(pic_state PIC_UNUSED(*pic), const char *msg)
|
pic_panic(pic_state PIC_UNUSED(*pic), const char *msg)
|
||||||
{
|
{
|
||||||
extern void abort();
|
extern PIC_NORETURN void abort();
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
fprintf(stderr, "abort: %s\n", msg);
|
fprintf(stderr, "abort: %s\n", msg);
|
||||||
|
@ -47,22 +47,6 @@ pic_errorf(pic_state *pic, const char *fmt, ...)
|
||||||
pic_error(pic, msg, irrs);
|
pic_error(pic, msg, irrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
|
||||||
pic_errmsg(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_str *str;
|
|
||||||
|
|
||||||
assert(! pic_invalid_p(pic->err));
|
|
||||||
|
|
||||||
if (! pic_error_p(pic->err)) {
|
|
||||||
str = pic_format(pic, "~s", pic->err);
|
|
||||||
} else {
|
|
||||||
str = pic_error_ptr(pic->err)->msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pic_str_cstr(pic, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_native_exception_handler(pic_state *pic)
|
pic_native_exception_handler(pic_state *pic)
|
||||||
{
|
{
|
||||||
|
@ -158,7 +142,7 @@ pic_error(pic_state *pic, const char *msg, pic_value irrs)
|
||||||
{
|
{
|
||||||
struct pic_error *e;
|
struct pic_error *e;
|
||||||
|
|
||||||
e = pic_make_error(pic, pic_intern_cstr(pic, ""), msg, irrs);
|
e = pic_make_error(pic, pic_intern(pic, ""), msg, irrs);
|
||||||
|
|
||||||
pic_raise(pic, pic_obj_value(e));
|
pic_raise(pic, pic_obj_value(e));
|
||||||
}
|
}
|
||||||
|
@ -212,22 +196,6 @@ pic_error_error(pic_state *pic)
|
||||||
pic_error(pic, str, pic_list_by_array(pic, argc, argv));
|
pic_error(pic, str, pic_list_by_array(pic, argc, argv));
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_error_make_error_object(pic_state *pic)
|
|
||||||
{
|
|
||||||
struct pic_error *e;
|
|
||||||
pic_sym *type;
|
|
||||||
pic_str *msg;
|
|
||||||
size_t argc;
|
|
||||||
pic_value *argv;
|
|
||||||
|
|
||||||
pic_get_args(pic, "ms*", &type, &msg, &argc, &argv);
|
|
||||||
|
|
||||||
e = pic_make_error(pic, type, pic_str_cstr(pic, msg), pic_list_by_array(pic, argc, argv));
|
|
||||||
|
|
||||||
return pic_obj_value(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
pic_error_error_object_p(pic_state *pic)
|
pic_error_error_object_p(pic_state *pic)
|
||||||
{
|
{
|
||||||
|
@ -275,7 +243,6 @@ pic_init_error(pic_state *pic)
|
||||||
pic_defun(pic, "raise", pic_error_raise);
|
pic_defun(pic, "raise", pic_error_raise);
|
||||||
pic_defun(pic, "raise-continuable", pic_error_raise_continuable);
|
pic_defun(pic, "raise-continuable", pic_error_raise_continuable);
|
||||||
pic_defun(pic, "error", pic_error_error);
|
pic_defun(pic, "error", pic_error_error);
|
||||||
pic_defun(pic, "make-error-object", pic_error_make_error_object);
|
|
||||||
pic_defun(pic, "error-object?", pic_error_error_object_p);
|
pic_defun(pic, "error-object?", pic_error_error_object_p);
|
||||||
pic_defun(pic, "error-object-message", pic_error_error_object_message);
|
pic_defun(pic, "error-object-message", pic_error_error_object_message);
|
||||||
pic_defun(pic, "error-object-irritants", pic_error_error_object_irritants);
|
pic_defun(pic, "error-object-irritants", pic_error_error_object_irritants);
|
||||||
|
|
|
@ -330,9 +330,6 @@ int xvfprintf(pic_state *pic, xFILE *stream, const char *fmt, va_list ap) {
|
||||||
const char *p;
|
const char *p;
|
||||||
char *sval;
|
char *sval;
|
||||||
int ival;
|
int ival;
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
double dval;
|
|
||||||
#endif
|
|
||||||
void *vp;
|
void *vp;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
|
@ -348,24 +345,43 @@ int xvfprintf(pic_state *pic, xFILE *stream, const char *fmt, va_list ap) {
|
||||||
ival = va_arg(ap, int);
|
ival = va_arg(ap, int);
|
||||||
cnt += print_int(pic, stream, ival, 10);
|
cnt += print_int(pic, stream, ival, 10);
|
||||||
break;
|
break;
|
||||||
#if PIC_ENABLE_FLOAT
|
#if PIC_ENABLE_LIBC
|
||||||
case 'f':
|
case 'f': {
|
||||||
dval = va_arg(ap, double);
|
char buf[100];
|
||||||
cnt += print_int(pic, stream, dval, 10);
|
sprintf(buf, "%g", va_arg(ap, double));
|
||||||
|
cnt += xfputs(pic, buf, stream);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define fabs(x) ((x) >= 0 ? (x) : -(x))
|
||||||
|
case 'f': {
|
||||||
|
double dval = va_arg(ap, double);
|
||||||
|
long lval;
|
||||||
|
if (dval < 0) {
|
||||||
|
dval = -dval;
|
||||||
|
xputc(pic, '-', stream);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
lval = (long)dval;
|
||||||
|
cnt += print_int(pic, stream, lval, 10);
|
||||||
xputc(pic, '.', stream);
|
xputc(pic, '.', stream);
|
||||||
cnt++;
|
cnt++;
|
||||||
if ((ival = fabs((dval - floor(dval)) * 1e4) + 0.5) == 0) {
|
dval -= lval;
|
||||||
|
if ((ival = fabs(dval) * 1e4 + 0.5) == 0) {
|
||||||
cnt += xfputs(pic, "0000", stream);
|
cnt += xfputs(pic, "0000", stream);
|
||||||
} else {
|
} else {
|
||||||
int i;
|
if (ival < 1000) xputc(pic, '0', stream); cnt++;
|
||||||
for (i = 0; i < 3 - (int)log10(ival); ++i) {
|
if (ival < 100) xputc(pic, '0', stream); cnt++;
|
||||||
xputc(pic, '0', stream);
|
if (ival < 10) xputc(pic, '0', stream); cnt++;
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
cnt += print_int(pic, stream, ival, 10);
|
cnt += print_int(pic, stream, ival, 10);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
case 'c':
|
||||||
|
ival = va_arg(ap, int);
|
||||||
|
cnt += xfputc(pic, ival, stream);
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
sval = va_arg(ap, char*);
|
sval = va_arg(ap, char*);
|
||||||
cnt += xfputs(pic, sval, stream);
|
cnt += xfputs(pic, sval, stream);
|
||||||
|
|
664
extlib/benz/gc.c
664
extlib/benz/gc.c
File diff suppressed because it is too large
Load Diff
|
@ -38,16 +38,15 @@ extern "C" {
|
||||||
#include "picrin/kvec.h"
|
#include "picrin/kvec.h"
|
||||||
#include "picrin/khash.h"
|
#include "picrin/khash.h"
|
||||||
|
|
||||||
#include "picrin/value.h"
|
|
||||||
|
|
||||||
typedef struct pic_state pic_state;
|
typedef struct pic_state pic_state;
|
||||||
|
|
||||||
|
#include "picrin/type.h"
|
||||||
#include "picrin/irep.h"
|
#include "picrin/irep.h"
|
||||||
#include "picrin/file.h"
|
#include "picrin/file.h"
|
||||||
#include "picrin/read.h"
|
#include "picrin/read.h"
|
||||||
#include "picrin/gc.h"
|
#include "picrin/gc.h"
|
||||||
|
|
||||||
KHASH_DECLARE(s, const char *, pic_sym *);
|
KHASH_DECLARE(s, const char *, pic_sym *)
|
||||||
|
|
||||||
typedef struct pic_checkpoint {
|
typedef struct pic_checkpoint {
|
||||||
PIC_OBJECT_HEADER
|
PIC_OBJECT_HEADER
|
||||||
|
@ -61,6 +60,7 @@ typedef struct {
|
||||||
int argc, retc;
|
int argc, retc;
|
||||||
pic_code *ip;
|
pic_code *ip;
|
||||||
pic_value *fp;
|
pic_value *fp;
|
||||||
|
struct pic_irep *irep;
|
||||||
struct pic_context *cxt;
|
struct pic_context *cxt;
|
||||||
int regc;
|
int regc;
|
||||||
pic_value *regs;
|
pic_value *regs;
|
||||||
|
@ -95,32 +95,21 @@ struct pic_state {
|
||||||
|
|
||||||
struct pic_lib *lib, *prev_lib;
|
struct pic_lib *lib, *prev_lib;
|
||||||
|
|
||||||
pic_sym *sDEFINE, *sLAMBDA, *sIF, *sBEGIN, *sQUOTE, *sSETBANG;
|
pic_sym *sQUOTE, *sQUASIQUOTE, *sUNQUOTE, *sUNQUOTE_SPLICING;
|
||||||
pic_sym *sQUASIQUOTE, *sUNQUOTE, *sUNQUOTE_SPLICING;
|
pic_sym *sSYNTAX_QUOTE, *sSYNTAX_QUASIQUOTE, *sSYNTAX_UNQUOTE, *sSYNTAX_UNQUOTE_SPLICING;
|
||||||
pic_sym *sSYNTAX_QUOTE, *sSYNTAX_QUASIQUOTE, *sSYNTAX_UNQUOTE;
|
pic_sym *sDEFINE_LIBRARY, *sIMPORT, *sEXPORT, *sCOND_EXPAND;
|
||||||
pic_sym *sSYNTAX_UNQUOTE_SPLICING;
|
pic_sym *sGREF, *sCREF, *sLREF, *sCALL;
|
||||||
pic_sym *sDEFINE_MACRO, *sIMPORT, *sEXPORT;
|
|
||||||
pic_sym *sDEFINE_LIBRARY;
|
|
||||||
pic_sym *sCOND_EXPAND, *sAND, *sOR, *sELSE, *sLIBRARY;
|
|
||||||
pic_sym *sONLY, *sRENAME, *sPREFIX, *sEXCEPT;
|
|
||||||
pic_sym *sCONS, *sCAR, *sCDR, *sNILP;
|
|
||||||
pic_sym *sSYMBOLP, *sPAIRP;
|
|
||||||
pic_sym *sADD, *sSUB, *sMUL, *sDIV, *sMINUS;
|
|
||||||
pic_sym *sEQ, *sLT, *sLE, *sGT, *sGE, *sNOT;
|
|
||||||
pic_sym *sREAD, *sFILE;
|
|
||||||
pic_sym *sGREF, *sCREF, *sLREF;
|
|
||||||
pic_sym *sCALL, *sTAILCALL, *sRETURN;
|
|
||||||
pic_sym *sCALL_WITH_VALUES, *sTAILCALL_WITH_VALUES;
|
|
||||||
|
|
||||||
pic_sym *uDEFINE, *uLAMBDA, *uIF, *uBEGIN, *uQUOTE, *uSETBANG;
|
pic_sym *uDEFINE, *uLAMBDA, *uIF, *uBEGIN, *uQUOTE, *uSETBANG, *uDEFINE_MACRO;
|
||||||
pic_sym *uDEFINE_MACRO, *uIMPORT, *uEXPORT;
|
pic_sym *uDEFINE_LIBRARY, *uIMPORT, *uEXPORT, *uCOND_EXPAND;
|
||||||
pic_sym *uDEFINE_LIBRARY;
|
pic_sym *uCONS, *uCAR, *uCDR, *uNILP, *uSYMBOLP, *uPAIRP;
|
||||||
pic_sym *uCOND_EXPAND;
|
pic_sym *uADD, *uSUB, *uMUL, *uDIV, *uEQ, *uLT, *uLE, *uGT, *uGE, *uNOT;
|
||||||
pic_sym *uCONS, *uCAR, *uCDR, *uNILP;
|
|
||||||
pic_sym *uSYMBOLP, *uPAIRP;
|
pic_value pCONS, pCAR, pCDR, pNILP, pPAIRP, pSYMBOLP, pNOT;
|
||||||
pic_sym *uADD, *uSUB, *uMUL, *uDIV;
|
pic_value pADD, pSUB, pMUL, pDIV, pEQ, pLT, pLE, pGT, pGE;
|
||||||
pic_sym *uEQ, *uLT, *uLE, *uGT, *uGE, *uNOT;
|
|
||||||
pic_sym *uVALUES, *uCALL_WITH_VALUES;
|
pic_value cCONS, cCAR, cCDR, cNILP, cPAIRP, cSYMBOLP, cNOT;
|
||||||
|
pic_value cADD, cSUB, cMUL, cDIV, cEQ, cLT, cLE, cGT, cGE;
|
||||||
|
|
||||||
struct pic_lib *PICRIN_BASE;
|
struct pic_lib *PICRIN_BASE;
|
||||||
struct pic_lib *PICRIN_USER;
|
struct pic_lib *PICRIN_USER;
|
||||||
|
@ -155,7 +144,6 @@ void *pic_malloc(pic_state *, size_t);
|
||||||
void *pic_realloc(pic_state *, void *, size_t);
|
void *pic_realloc(pic_state *, void *, size_t);
|
||||||
void *pic_calloc(pic_state *, size_t, size_t);
|
void *pic_calloc(pic_state *, size_t, size_t);
|
||||||
struct pic_object *pic_obj_alloc(pic_state *, size_t, enum pic_tt);
|
struct pic_object *pic_obj_alloc(pic_state *, size_t, enum pic_tt);
|
||||||
struct pic_object *pic_obj_alloc_unsafe(pic_state *, size_t, enum pic_tt);
|
|
||||||
void pic_free(pic_state *, void *);
|
void pic_free(pic_state *, void *);
|
||||||
|
|
||||||
void pic_gc_run(pic_state *);
|
void pic_gc_run(pic_state *);
|
||||||
|
@ -184,14 +172,14 @@ bool pic_eq_p(pic_value, pic_value);
|
||||||
bool pic_eqv_p(pic_value, pic_value);
|
bool pic_eqv_p(pic_value, pic_value);
|
||||||
bool pic_equal_p(pic_state *, pic_value, pic_value);
|
bool pic_equal_p(pic_state *, pic_value, pic_value);
|
||||||
|
|
||||||
pic_sym *pic_intern(pic_state *, pic_str *);
|
pic_sym *pic_intern(pic_state *, const char *);
|
||||||
pic_sym *pic_intern_cstr(pic_state *, const char *);
|
pic_sym *pic_intern_str(pic_state *, pic_str *);
|
||||||
const char *pic_symbol_name(pic_state *, pic_sym *);
|
const char *pic_symbol_name(pic_state *, pic_sym *);
|
||||||
|
|
||||||
pic_value pic_read(pic_state *, struct pic_port *);
|
pic_value pic_read(pic_state *, struct pic_port *);
|
||||||
pic_value pic_read_cstr(pic_state *, const char *);
|
pic_value pic_read_cstr(pic_state *, const char *);
|
||||||
|
|
||||||
void pic_load_port(pic_state *, struct pic_port *);
|
void pic_load(pic_state *, struct pic_port *);
|
||||||
void pic_load_cstr(pic_state *, const char *);
|
void pic_load_cstr(pic_state *, const char *);
|
||||||
|
|
||||||
void pic_define(pic_state *, const char *, pic_value);
|
void pic_define(pic_state *, const char *, pic_value);
|
||||||
|
@ -217,9 +205,9 @@ pic_value pic_apply2(pic_state *, struct pic_proc *, pic_value, pic_value);
|
||||||
pic_value pic_apply3(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value);
|
pic_value pic_apply3(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value);
|
||||||
pic_value pic_apply4(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value, pic_value);
|
pic_value pic_apply4(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value, pic_value);
|
||||||
pic_value pic_apply5(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value, pic_value, pic_value);
|
pic_value pic_apply5(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value, pic_value, pic_value);
|
||||||
pic_value pic_apply_trampoline(pic_state *, struct pic_proc *, pic_value);
|
pic_value pic_apply_trampoline(pic_state *, struct pic_proc *, size_t, pic_value *);
|
||||||
|
pic_value pic_apply_trampoline_list(pic_state *, struct pic_proc *, pic_value);
|
||||||
pic_value pic_eval(pic_state *, pic_value, struct pic_env *);
|
pic_value pic_eval(pic_state *, pic_value, struct pic_env *);
|
||||||
struct pic_proc *pic_compile(pic_state *, pic_value, struct pic_env *);
|
|
||||||
|
|
||||||
struct pic_proc *pic_make_var(pic_state *, pic_value, struct pic_proc *);
|
struct pic_proc *pic_make_var(pic_state *, pic_value, struct pic_proc *);
|
||||||
|
|
||||||
|
@ -243,9 +231,9 @@ void pic_export(pic_state *, pic_sym *);
|
||||||
PIC_NORETURN void pic_panic(pic_state *, const char *);
|
PIC_NORETURN void pic_panic(pic_state *, const char *);
|
||||||
PIC_NORETURN void pic_errorf(pic_state *, const char *, ...);
|
PIC_NORETURN void pic_errorf(pic_state *, const char *, ...);
|
||||||
void pic_warnf(pic_state *, const char *, ...);
|
void pic_warnf(pic_state *, const char *, ...);
|
||||||
const char *pic_errmsg(pic_state *);
|
|
||||||
pic_str *pic_get_backtrace(pic_state *);
|
pic_str *pic_get_backtrace(pic_state *);
|
||||||
void pic_print_backtrace(pic_state *, xFILE *);
|
void pic_print_backtrace(pic_state *, xFILE *);
|
||||||
|
|
||||||
struct pic_dict *pic_attr(pic_state *, pic_value);
|
struct pic_dict *pic_attr(pic_state *, pic_value);
|
||||||
pic_value pic_attr_ref(pic_state *, pic_value, const char *);
|
pic_value pic_attr_ref(pic_state *, pic_value, const char *);
|
||||||
void pic_attr_set(pic_state *, pic_value, const char *, pic_value);
|
void pic_attr_set(pic_state *, pic_value, const char *, pic_value);
|
||||||
|
|
|
@ -89,7 +89,7 @@ extern "C" {
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# define assert(v) 0
|
# define assert(v) (void)0
|
||||||
|
|
||||||
PIC_INLINE int
|
PIC_INLINE int
|
||||||
isspace(int c)
|
isspace(int c)
|
||||||
|
@ -205,10 +205,6 @@ strcpy(char *dst, const char *src)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
# include <math.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PIC_ENABLE_STDIO
|
#if PIC_ENABLE_STDIO
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,9 +11,6 @@
|
||||||
/** enable word boxing */
|
/** enable word boxing */
|
||||||
/* #define PIC_WORD_BOXING 0 */
|
/* #define PIC_WORD_BOXING 0 */
|
||||||
|
|
||||||
/** enable floating point number support */
|
|
||||||
/* #define PIC_ENABLE_FLOAT 1 */
|
|
||||||
|
|
||||||
/** no dependency on libc */
|
/** no dependency on libc */
|
||||||
/* #define PIC_ENABLE_LIBC 1 */
|
/* #define PIC_ENABLE_LIBC 1 */
|
||||||
|
|
||||||
|
@ -33,6 +30,8 @@
|
||||||
|
|
||||||
/* #define PIC_HEAP_PAGE_SIZE 10000 */
|
/* #define PIC_HEAP_PAGE_SIZE 10000 */
|
||||||
|
|
||||||
|
/* #define PIC_PAGE_REQUEST_THRESHOLD(total) ((total) * 77 / 100) */
|
||||||
|
|
||||||
/* #define PIC_STACK_SIZE 1024 */
|
/* #define PIC_STACK_SIZE 1024 */
|
||||||
|
|
||||||
/* #define PIC_RESCUE_SIZE 30 */
|
/* #define PIC_RESCUE_SIZE 30 */
|
||||||
|
@ -66,10 +65,6 @@
|
||||||
# error cannot enable both PIC_NAN_BOXING and PIC_WORD_BOXING simultaneously
|
# error cannot enable both PIC_NAN_BOXING and PIC_WORD_BOXING simultaneously
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PIC_WORD_BOXING && PIC_ENABLE_FLOAT
|
|
||||||
# error cannot enable both PIC_WORD_BOXING and PIC_ENABLE_FLOAT simultaneously
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PIC_WORD_BOXING
|
#ifndef PIC_WORD_BOXING
|
||||||
# define PIC_WORD_BOXING 0
|
# define PIC_WORD_BOXING 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -82,20 +77,10 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PIC_ENABLE_FLOAT
|
|
||||||
# if ! PIC_WORD_BOXING
|
|
||||||
# define PIC_ENABLE_FLOAT 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PIC_ENABLE_LIBC
|
#ifndef PIC_ENABLE_LIBC
|
||||||
# define PIC_ENABLE_LIBC 1
|
# define PIC_ENABLE_LIBC 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PIC_NAN_BOXING && defined(PIC_ENABLE_FLOAT) && ! PIC_ENABLE_FLOAT
|
|
||||||
# error cannot disable float support when nan boxing is on
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PIC_ENABLE_STDIO
|
#ifndef PIC_ENABLE_STDIO
|
||||||
# define PIC_ENABLE_STDIO 1
|
# define PIC_ENABLE_STDIO 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -124,11 +109,15 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PIC_HEAP_PAGE_SIZE
|
#ifndef PIC_HEAP_PAGE_SIZE
|
||||||
# define PIC_HEAP_PAGE_SIZE (2 * 1024 * 1024)
|
# define PIC_HEAP_PAGE_SIZE (4 * 1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PIC_PAGE_REQUEST_THRESHOLD
|
||||||
|
# define PIC_PAGE_REQUEST_THRESHOLD(total) ((total) * 77 / 100)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PIC_STACK_SIZE
|
#ifndef PIC_STACK_SIZE
|
||||||
# define PIC_STACK_SIZE 1024
|
# define PIC_STACK_SIZE 2048
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PIC_RESCUE_SIZE
|
#ifndef PIC_RESCUE_SIZE
|
||||||
|
|
|
@ -41,7 +41,7 @@ pic_value pic_values2(pic_state *, pic_value, pic_value);
|
||||||
pic_value pic_values3(pic_state *, pic_value, pic_value, pic_value);
|
pic_value pic_values3(pic_state *, pic_value, pic_value, pic_value);
|
||||||
pic_value pic_values4(pic_state *, pic_value, pic_value, pic_value, pic_value);
|
pic_value pic_values4(pic_state *, pic_value, pic_value, pic_value, pic_value);
|
||||||
pic_value pic_values5(pic_state *, pic_value, pic_value, pic_value, pic_value, pic_value);
|
pic_value pic_values5(pic_state *, pic_value, pic_value, pic_value, pic_value, pic_value);
|
||||||
pic_value pic_values_by_array(pic_state *, size_t, pic_value *);
|
pic_value pic_values(pic_state *, size_t, pic_value *);
|
||||||
pic_value pic_values_by_list(pic_state *, pic_value);
|
pic_value pic_values_by_list(pic_state *, pic_value);
|
||||||
size_t pic_receive(pic_state *, size_t, pic_value *);
|
size_t pic_receive(pic_state *, size_t, pic_value *);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct pic_dict {
|
||||||
struct pic_dict *pic_make_dict(pic_state *);
|
struct pic_dict *pic_make_dict(pic_state *);
|
||||||
|
|
||||||
#define pic_dict_for_each(sym, dict, it) \
|
#define pic_dict_for_each(sym, dict, it) \
|
||||||
pic_dict_for_each_help(sym, (&dict->hash), it)
|
pic_dict_for_each_help(sym, (&(dict)->hash), it)
|
||||||
#define pic_dict_for_each_help(sym, h, it) \
|
#define pic_dict_for_each_help(sym, h, it) \
|
||||||
for (it = kh_begin(h); it != kh_end(h); ++it) \
|
for (it = kh_begin(h); it != kh_end(h); ++it) \
|
||||||
if ((sym = kh_key(h, it)), kh_exist(h, it))
|
if ((sym = kh_key(h, it)), kh_exist(h, it))
|
||||||
|
|
|
@ -44,7 +44,6 @@ struct pic_error *pic_make_error(pic_state *, pic_sym *, const char *, pic_list)
|
||||||
} while (0); \
|
} while (0); \
|
||||||
pic->cc = pic->cc->prev; \
|
pic->cc = pic->cc->prev; \
|
||||||
} else { \
|
} else { \
|
||||||
pic->cc = pic->cc->prev; \
|
|
||||||
goto label; \
|
goto label; \
|
||||||
} \
|
} \
|
||||||
} while (0); \
|
} while (0); \
|
||||||
|
|
|
@ -9,48 +9,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum pic_opcode {
|
|
||||||
OP_NOP,
|
|
||||||
OP_POP,
|
|
||||||
OP_PUSHUNDEF,
|
|
||||||
OP_PUSHNIL,
|
|
||||||
OP_PUSHTRUE,
|
|
||||||
OP_PUSHFALSE,
|
|
||||||
OP_PUSHINT,
|
|
||||||
OP_PUSHCHAR,
|
|
||||||
OP_PUSHCONST,
|
|
||||||
OP_GREF,
|
|
||||||
OP_GSET,
|
|
||||||
OP_LREF,
|
|
||||||
OP_LSET,
|
|
||||||
OP_CREF,
|
|
||||||
OP_CSET,
|
|
||||||
OP_JMP,
|
|
||||||
OP_JMPIF,
|
|
||||||
OP_NOT,
|
|
||||||
OP_CALL,
|
|
||||||
OP_TAILCALL,
|
|
||||||
OP_RET,
|
|
||||||
OP_LAMBDA,
|
|
||||||
OP_CONS,
|
|
||||||
OP_CAR,
|
|
||||||
OP_CDR,
|
|
||||||
OP_NILP,
|
|
||||||
OP_SYMBOLP,
|
|
||||||
OP_PAIRP,
|
|
||||||
OP_ADD,
|
|
||||||
OP_SUB,
|
|
||||||
OP_MUL,
|
|
||||||
OP_DIV,
|
|
||||||
OP_MINUS,
|
|
||||||
OP_EQ,
|
|
||||||
OP_LT,
|
|
||||||
OP_LE,
|
|
||||||
OP_STOP
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum pic_opcode insn;
|
int insn;
|
||||||
union {
|
union {
|
||||||
int i;
|
int i;
|
||||||
char c;
|
char c;
|
||||||
|
@ -61,11 +21,6 @@ typedef struct {
|
||||||
} u;
|
} u;
|
||||||
} pic_code;
|
} pic_code;
|
||||||
|
|
||||||
#define PIC_INIT_CODE_I(code, op, ival) do { \
|
|
||||||
code.insn = op; \
|
|
||||||
code.u.i = ival; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
struct pic_irep {
|
struct pic_irep {
|
||||||
PIC_OBJECT_HEADER
|
PIC_OBJECT_HEADER
|
||||||
pic_code *code;
|
pic_code *code;
|
||||||
|
@ -73,7 +28,6 @@ struct pic_irep {
|
||||||
bool varg;
|
bool varg;
|
||||||
struct pic_irep **irep;
|
struct pic_irep **irep;
|
||||||
pic_value *pool;
|
pic_value *pool;
|
||||||
pic_sym **syms;
|
|
||||||
size_t clen, ilen, plen, slen;
|
size_t clen, ilen, plen, slen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,146 +35,7 @@ pic_sym *pic_resolve(pic_state *, pic_value, struct pic_env *);
|
||||||
pic_value pic_expand(pic_state *, pic_value, struct pic_env *);
|
pic_value pic_expand(pic_state *, pic_value, struct pic_env *);
|
||||||
pic_value pic_analyze(pic_state *, pic_value);
|
pic_value pic_analyze(pic_state *, pic_value);
|
||||||
struct pic_irep *pic_codegen(pic_state *, pic_value);
|
struct pic_irep *pic_codegen(pic_state *, pic_value);
|
||||||
|
struct pic_proc *pic_compile(pic_state *, pic_value, struct pic_env *);
|
||||||
#if DEBUG
|
|
||||||
|
|
||||||
PIC_INLINE void
|
|
||||||
pic_dump_code(pic_code c)
|
|
||||||
{
|
|
||||||
printf("[%2d] ", c.insn);
|
|
||||||
switch (c.insn) {
|
|
||||||
case OP_NOP:
|
|
||||||
puts("OP_NOP");
|
|
||||||
break;
|
|
||||||
case OP_POP:
|
|
||||||
puts("OP_POP");
|
|
||||||
break;
|
|
||||||
case OP_PUSHUNDEF:
|
|
||||||
puts("OP_PUSHUNDEF");
|
|
||||||
break;
|
|
||||||
case OP_PUSHNIL:
|
|
||||||
puts("OP_PUSHNIL");
|
|
||||||
break;
|
|
||||||
case OP_PUSHTRUE:
|
|
||||||
puts("OP_PUSHTRUE");
|
|
||||||
break;
|
|
||||||
case OP_PUSHFALSE:
|
|
||||||
puts("OP_PUSHFALSE");
|
|
||||||
break;
|
|
||||||
case OP_PUSHINT:
|
|
||||||
printf("OP_PUSHINT\t%d\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_PUSHCHAR:
|
|
||||||
printf("OP_PUSHCHAR\t%c\n", c.u.c);
|
|
||||||
break;
|
|
||||||
case OP_PUSHCONST:
|
|
||||||
printf("OP_PUSHCONST\t%d\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_GREF:
|
|
||||||
printf("OP_GREF\t%i\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_GSET:
|
|
||||||
printf("OP_GSET\t%i\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_LREF:
|
|
||||||
printf("OP_LREF\t%d\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_LSET:
|
|
||||||
printf("OP_LSET\t%d\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_CREF:
|
|
||||||
printf("OP_CREF\t%d\t%d\n", c.u.r.depth, c.u.r.idx);
|
|
||||||
break;
|
|
||||||
case OP_CSET:
|
|
||||||
printf("OP_CSET\t%d\t%d\n", c.u.r.depth, c.u.r.idx);
|
|
||||||
break;
|
|
||||||
case OP_JMP:
|
|
||||||
printf("OP_JMP\t%x\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_JMPIF:
|
|
||||||
printf("OP_JMPIF\t%x\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_NOT:
|
|
||||||
puts("OP_NOT");
|
|
||||||
break;
|
|
||||||
case OP_CALL:
|
|
||||||
printf("OP_CALL\t%d\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_TAILCALL:
|
|
||||||
printf("OP_TAILCALL\t%d\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_RET:
|
|
||||||
printf("OP_RET\t%d\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_LAMBDA:
|
|
||||||
printf("OP_LAMBDA\t%d\n", c.u.i);
|
|
||||||
break;
|
|
||||||
case OP_CONS:
|
|
||||||
puts("OP_CONS");
|
|
||||||
break;
|
|
||||||
case OP_CAR:
|
|
||||||
puts("OP_CAR");
|
|
||||||
break;
|
|
||||||
case OP_NILP:
|
|
||||||
puts("OP_NILP");
|
|
||||||
break;
|
|
||||||
case OP_SYMBOLP:
|
|
||||||
puts("OP_SYMBOLP");
|
|
||||||
break;
|
|
||||||
case OP_PAIRP:
|
|
||||||
puts("OP_PAIRP");
|
|
||||||
break;
|
|
||||||
case OP_CDR:
|
|
||||||
puts("OP_CDR");
|
|
||||||
break;
|
|
||||||
case OP_ADD:
|
|
||||||
puts("OP_ADD");
|
|
||||||
break;
|
|
||||||
case OP_SUB:
|
|
||||||
puts("OP_SUB");
|
|
||||||
break;
|
|
||||||
case OP_MUL:
|
|
||||||
puts("OP_MUL");
|
|
||||||
break;
|
|
||||||
case OP_DIV:
|
|
||||||
puts("OP_DIV");
|
|
||||||
break;
|
|
||||||
case OP_MINUS:
|
|
||||||
puts("OP_MINUS");
|
|
||||||
break;
|
|
||||||
case OP_EQ:
|
|
||||||
puts("OP_EQ");
|
|
||||||
break;
|
|
||||||
case OP_LT:
|
|
||||||
puts("OP_LT");
|
|
||||||
break;
|
|
||||||
case OP_LE:
|
|
||||||
puts("OP_LE");
|
|
||||||
break;
|
|
||||||
case OP_STOP:
|
|
||||||
puts("OP_STOP");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PIC_INLINE void
|
|
||||||
pic_dump_irep(struct pic_irep *irep)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
printf("## irep %p\n", (void *)irep);
|
|
||||||
printf("[clen = %zd, argc = %d, localc = %d, capturec = %d]\n", irep->clen, irep->argc, irep->localc, irep->capturec);
|
|
||||||
for (i = 0; i < irep->clen; ++i) {
|
|
||||||
printf("%02x ", i);
|
|
||||||
pic_dump_code(irep->code[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < irep->ilen; ++i) {
|
|
||||||
pic_dump_irep(irep->irep[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,21 +27,7 @@
|
||||||
#ifndef AC_KHASH_H
|
#ifndef AC_KHASH_H
|
||||||
#define AC_KHASH_H
|
#define AC_KHASH_H
|
||||||
|
|
||||||
#include <limits.h>
|
typedef int khint_t;
|
||||||
|
|
||||||
#if UINT_MAX == 0xffffffffu
|
|
||||||
typedef unsigned int khint32_t;
|
|
||||||
#elif ULONG_MAX == 0xffffffffu
|
|
||||||
typedef unsigned long khint32_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ULONG_MAX == ULLONG_MAX
|
|
||||||
typedef unsigned long khint64_t;
|
|
||||||
#else
|
|
||||||
typedef unsigned long long khint64_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef khint32_t khint_t;
|
|
||||||
typedef khint_t khiter_t;
|
typedef khint_t khiter_t;
|
||||||
|
|
||||||
#define ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
|
#define ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
|
||||||
|
@ -78,7 +64,7 @@ PIC_INLINE khint_t ac_Wang_hash(khint_t key)
|
||||||
#define KHASH_DECLARE(name, khkey_t, khval_t) \
|
#define KHASH_DECLARE(name, khkey_t, khval_t) \
|
||||||
typedef struct { \
|
typedef struct { \
|
||||||
khint_t n_buckets, size, n_occupied, upper_bound; \
|
khint_t n_buckets, size, n_occupied, upper_bound; \
|
||||||
khint32_t *flags; \
|
int *flags; \
|
||||||
khkey_t *keys; \
|
khkey_t *keys; \
|
||||||
khval_t *vals; \
|
khval_t *vals; \
|
||||||
} kh_##name##_t; \
|
} kh_##name##_t; \
|
||||||
|
@ -105,7 +91,7 @@ PIC_INLINE khint_t ac_Wang_hash(khint_t key)
|
||||||
void kh_clear_##name(kh_##name##_t *h) \
|
void kh_clear_##name(kh_##name##_t *h) \
|
||||||
{ \
|
{ \
|
||||||
if (h->flags) { \
|
if (h->flags) { \
|
||||||
memset(h->flags, 0xaa, ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
|
memset(h->flags, 0xaa, ac_fsize(h->n_buckets) * sizeof(int)); \
|
||||||
h->size = h->n_occupied = 0; \
|
h->size = h->n_occupied = 0; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
@ -125,15 +111,15 @@ PIC_INLINE khint_t ac_Wang_hash(khint_t key)
|
||||||
} \
|
} \
|
||||||
void kh_resize_##name(pic_state *pic, kh_##name##_t *h, khint_t new_n_buckets) \
|
void kh_resize_##name(pic_state *pic, kh_##name##_t *h, khint_t new_n_buckets) \
|
||||||
{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
|
{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
|
||||||
khint32_t *new_flags = 0; \
|
int *new_flags = 0; \
|
||||||
khint_t j = 1; \
|
khint_t j = 1; \
|
||||||
{ \
|
{ \
|
||||||
ac_roundup32(new_n_buckets); \
|
ac_roundup32(new_n_buckets); \
|
||||||
if (new_n_buckets < 4) new_n_buckets = 4; \
|
if (new_n_buckets < 4) new_n_buckets = 4; \
|
||||||
if (h->size >= ac_hash_upper(new_n_buckets)) j = 0; /* requested size is too small */ \
|
if (h->size >= ac_hash_upper(new_n_buckets)) j = 0; /* requested size is too small */ \
|
||||||
else { /* hash table size to be changed (shrink or expand); rehash */ \
|
else { /* hash table size to be changed (shrink or expand); rehash */ \
|
||||||
new_flags = pic_malloc(pic, ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
|
new_flags = pic_malloc(pic, ac_fsize(new_n_buckets) * sizeof(int)); \
|
||||||
memset(new_flags, 0xaa, ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
|
memset(new_flags, 0xaa, ac_fsize(new_n_buckets) * sizeof(int)); \
|
||||||
if (h->n_buckets < new_n_buckets) { /* expand */ \
|
if (h->n_buckets < new_n_buckets) { /* expand */ \
|
||||||
h->keys = pic_realloc(pic, (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
|
h->keys = pic_realloc(pic, (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
|
||||||
if (kh_is_map) { \
|
if (kh_is_map) { \
|
||||||
|
@ -230,12 +216,10 @@ PIC_INLINE khint_t ac_Wang_hash(khint_t key)
|
||||||
|
|
||||||
/* --- BEGIN OF HASH FUNCTIONS --- */
|
/* --- BEGIN OF HASH FUNCTIONS --- */
|
||||||
|
|
||||||
#define kh_ptr_hash_func(key) (khint32_t)(long)(key)
|
#define kh_ptr_hash_func(key) (int)(long)(key)
|
||||||
#define kh_ptr_hash_equal(a, b) ((a) == (b))
|
#define kh_ptr_hash_equal(a, b) ((a) == (b))
|
||||||
#define kh_int_hash_func(key) (khint32_t)(key)
|
#define kh_int_hash_func(key) (int)(key)
|
||||||
#define kh_int_hash_equal(a, b) ((a) == (b))
|
#define kh_int_hash_equal(a, b) ((a) == (b))
|
||||||
#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
|
|
||||||
#define kh_int64_hash_equal(a, b) ((a) == (b))
|
|
||||||
#define kh_str_hash_func(key) ac_X31_hash_string(key)
|
#define kh_str_hash_func(key) ac_X31_hash_string(key)
|
||||||
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
|
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
|
||||||
#define kh_int_hash_func2(k) ac_Wang_hash((khint_t)key)
|
#define kh_int_hash_func2(k) ac_Wang_hash((khint_t)key)
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
/**
|
||||||
|
* See Copyright Notice in picrin.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PICRIN_OPCODE_H
|
||||||
|
#define PICRIN_OPCODE_H
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum pic_opcode {
|
||||||
|
OP_NOP,
|
||||||
|
OP_POP,
|
||||||
|
OP_PUSHUNDEF,
|
||||||
|
OP_PUSHNIL,
|
||||||
|
OP_PUSHTRUE,
|
||||||
|
OP_PUSHFALSE,
|
||||||
|
OP_PUSHINT,
|
||||||
|
OP_PUSHCHAR,
|
||||||
|
OP_PUSHCONST,
|
||||||
|
OP_GREF,
|
||||||
|
OP_GSET,
|
||||||
|
OP_LREF,
|
||||||
|
OP_LSET,
|
||||||
|
OP_CREF,
|
||||||
|
OP_CSET,
|
||||||
|
OP_JMP,
|
||||||
|
OP_JMPIF,
|
||||||
|
OP_NOT,
|
||||||
|
OP_CALL,
|
||||||
|
OP_TAILCALL,
|
||||||
|
OP_RET,
|
||||||
|
OP_LAMBDA,
|
||||||
|
OP_CONS,
|
||||||
|
OP_CAR,
|
||||||
|
OP_CDR,
|
||||||
|
OP_NILP,
|
||||||
|
OP_SYMBOLP,
|
||||||
|
OP_PAIRP,
|
||||||
|
OP_ADD,
|
||||||
|
OP_SUB,
|
||||||
|
OP_MUL,
|
||||||
|
OP_DIV,
|
||||||
|
OP_EQ,
|
||||||
|
OP_LT,
|
||||||
|
OP_LE,
|
||||||
|
OP_GT,
|
||||||
|
OP_GE,
|
||||||
|
OP_STOP
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PIC_INIT_CODE_I(code, op, ival) do { \
|
||||||
|
code.insn = op; \
|
||||||
|
code.u.i = ival; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
PIC_INLINE void
|
||||||
|
pic_dump_code(pic_code c)
|
||||||
|
{
|
||||||
|
printf("[%2d] ", c.insn);
|
||||||
|
switch (c.insn) {
|
||||||
|
case OP_NOP:
|
||||||
|
puts("OP_NOP");
|
||||||
|
break;
|
||||||
|
case OP_POP:
|
||||||
|
puts("OP_POP");
|
||||||
|
break;
|
||||||
|
case OP_PUSHUNDEF:
|
||||||
|
puts("OP_PUSHUNDEF");
|
||||||
|
break;
|
||||||
|
case OP_PUSHNIL:
|
||||||
|
puts("OP_PUSHNIL");
|
||||||
|
break;
|
||||||
|
case OP_PUSHTRUE:
|
||||||
|
puts("OP_PUSHTRUE");
|
||||||
|
break;
|
||||||
|
case OP_PUSHFALSE:
|
||||||
|
puts("OP_PUSHFALSE");
|
||||||
|
break;
|
||||||
|
case OP_PUSHINT:
|
||||||
|
printf("OP_PUSHINT\t%d\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_PUSHCHAR:
|
||||||
|
printf("OP_PUSHCHAR\t%c\n", c.u.c);
|
||||||
|
break;
|
||||||
|
case OP_PUSHCONST:
|
||||||
|
printf("OP_PUSHCONST\t%d\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_GREF:
|
||||||
|
printf("OP_GREF\t%i\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_GSET:
|
||||||
|
printf("OP_GSET\t%i\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_LREF:
|
||||||
|
printf("OP_LREF\t%d\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_LSET:
|
||||||
|
printf("OP_LSET\t%d\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_CREF:
|
||||||
|
printf("OP_CREF\t%d\t%d\n", c.u.r.depth, c.u.r.idx);
|
||||||
|
break;
|
||||||
|
case OP_CSET:
|
||||||
|
printf("OP_CSET\t%d\t%d\n", c.u.r.depth, c.u.r.idx);
|
||||||
|
break;
|
||||||
|
case OP_JMP:
|
||||||
|
printf("OP_JMP\t%x\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_JMPIF:
|
||||||
|
printf("OP_JMPIF\t%x\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_NOT:
|
||||||
|
puts("OP_NOT");
|
||||||
|
break;
|
||||||
|
case OP_CALL:
|
||||||
|
printf("OP_CALL\t%d\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_TAILCALL:
|
||||||
|
printf("OP_TAILCALL\t%d\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_RET:
|
||||||
|
puts("OP_RET");
|
||||||
|
break;
|
||||||
|
case OP_LAMBDA:
|
||||||
|
printf("OP_LAMBDA\t%d\n", c.u.i);
|
||||||
|
break;
|
||||||
|
case OP_CONS:
|
||||||
|
puts("OP_CONS");
|
||||||
|
break;
|
||||||
|
case OP_CAR:
|
||||||
|
puts("OP_CAR");
|
||||||
|
break;
|
||||||
|
case OP_NILP:
|
||||||
|
puts("OP_NILP");
|
||||||
|
break;
|
||||||
|
case OP_SYMBOLP:
|
||||||
|
puts("OP_SYMBOLP");
|
||||||
|
break;
|
||||||
|
case OP_PAIRP:
|
||||||
|
puts("OP_PAIRP");
|
||||||
|
break;
|
||||||
|
case OP_CDR:
|
||||||
|
puts("OP_CDR");
|
||||||
|
break;
|
||||||
|
case OP_ADD:
|
||||||
|
puts("OP_ADD");
|
||||||
|
break;
|
||||||
|
case OP_SUB:
|
||||||
|
puts("OP_SUB");
|
||||||
|
break;
|
||||||
|
case OP_MUL:
|
||||||
|
puts("OP_MUL");
|
||||||
|
break;
|
||||||
|
case OP_DIV:
|
||||||
|
puts("OP_DIV");
|
||||||
|
break;
|
||||||
|
case OP_EQ:
|
||||||
|
puts("OP_EQ");
|
||||||
|
break;
|
||||||
|
case OP_LT:
|
||||||
|
puts("OP_LT");
|
||||||
|
break;
|
||||||
|
case OP_LE:
|
||||||
|
puts("OP_LE");
|
||||||
|
break;
|
||||||
|
case OP_GT:
|
||||||
|
puts("OP_GT");
|
||||||
|
break;
|
||||||
|
case OP_GE:
|
||||||
|
puts("OP_GE");
|
||||||
|
break;
|
||||||
|
case OP_STOP:
|
||||||
|
puts("OP_STOP");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PIC_INLINE void
|
||||||
|
pic_dump_irep(struct pic_irep *irep)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
printf("## irep %p\n", (void *)irep);
|
||||||
|
printf("[clen = %zd, argc = %d, localc = %d, capturec = %d]\n", irep->clen, irep->argc, irep->localc, irep->capturec);
|
||||||
|
for (i = 0; i < irep->clen; ++i) {
|
||||||
|
printf("%02x ", i);
|
||||||
|
pic_dump_code(irep->code[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < irep->ilen; ++i) {
|
||||||
|
pic_dump_irep(irep->irep[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -22,7 +22,6 @@ void pic_rope_decref(pic_state *, struct pic_rope *);
|
||||||
|
|
||||||
pic_str *pic_make_str(pic_state *, const char * /* nullable */, size_t);
|
pic_str *pic_make_str(pic_state *, const char * /* nullable */, size_t);
|
||||||
pic_str *pic_make_str_cstr(pic_state *, const char *);
|
pic_str *pic_make_str_cstr(pic_state *, const char *);
|
||||||
pic_str *pic_make_str_fill(pic_state *, size_t, char);
|
|
||||||
|
|
||||||
char pic_str_ref(pic_state *, pic_str *, size_t);
|
char pic_str_ref(pic_state *, pic_str *, size_t);
|
||||||
size_t pic_str_len(pic_str *);
|
size_t pic_str_len(pic_str *);
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* See Copyright Notice in picrin.h
|
* See Copyright Notice in picrin.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PICRIN_VALUE_H
|
#ifndef PICRIN_TYPE_H
|
||||||
#define PICRIN_VALUE_H
|
#define PICRIN_TYPE_H
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -20,9 +20,7 @@ enum pic_vtype {
|
||||||
PIC_VTYPE_FALSE,
|
PIC_VTYPE_FALSE,
|
||||||
PIC_VTYPE_UNDEF,
|
PIC_VTYPE_UNDEF,
|
||||||
PIC_VTYPE_INVALID,
|
PIC_VTYPE_INVALID,
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
PIC_VTYPE_FLOAT,
|
PIC_VTYPE_FLOAT,
|
||||||
#endif
|
|
||||||
PIC_VTYPE_INT,
|
PIC_VTYPE_INT,
|
||||||
PIC_VTYPE_CHAR,
|
PIC_VTYPE_CHAR,
|
||||||
PIC_VTYPE_EOF,
|
PIC_VTYPE_EOF,
|
||||||
|
@ -116,9 +114,7 @@ typedef struct {
|
||||||
enum pic_vtype type;
|
enum pic_vtype type;
|
||||||
union {
|
union {
|
||||||
void *data;
|
void *data;
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
double f;
|
double f;
|
||||||
#endif
|
|
||||||
int i;
|
int i;
|
||||||
char c;
|
char c;
|
||||||
} u;
|
} u;
|
||||||
|
@ -128,9 +124,7 @@ typedef struct {
|
||||||
#define pic_vtype(v) ((v).type)
|
#define pic_vtype(v) ((v).type)
|
||||||
#define pic_init_value(v,vtype) ((v).type = (vtype), (v).u.data = NULL)
|
#define pic_init_value(v,vtype) ((v).type = (vtype), (v).u.data = NULL)
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
#define pic_float(v) ((v).u.f)
|
||||||
# define pic_float(v) ((v).u.f)
|
|
||||||
#endif
|
|
||||||
#define pic_int(v) ((v).u.i)
|
#define pic_int(v) ((v).u.i)
|
||||||
#define pic_char(v) ((v).u.c)
|
#define pic_char(v) ((v).u.c)
|
||||||
|
|
||||||
|
@ -140,9 +134,7 @@ enum pic_tt {
|
||||||
/* immediate */
|
/* immediate */
|
||||||
PIC_TT_NIL,
|
PIC_TT_NIL,
|
||||||
PIC_TT_BOOL,
|
PIC_TT_BOOL,
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
PIC_TT_FLOAT,
|
PIC_TT_FLOAT,
|
||||||
#endif
|
|
||||||
PIC_TT_INT,
|
PIC_TT_INT,
|
||||||
PIC_TT_CHAR,
|
PIC_TT_CHAR,
|
||||||
PIC_TT_EOF,
|
PIC_TT_EOF,
|
||||||
|
@ -218,21 +210,12 @@ PIC_INLINE const char *pic_type_repr(enum pic_tt);
|
||||||
pic_errorf(pic, "expected " #type ", but got ~s", v); \
|
pic_errorf(pic, "expected " #type ", but got ~s", v); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
PIC_INLINE bool
|
PIC_INLINE bool
|
||||||
pic_valid_int(double v)
|
pic_valid_int(double v)
|
||||||
{
|
{
|
||||||
return INT_MIN <= v && v <= INT_MAX;
|
return INT_MIN <= v && v <= INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
PIC_INLINE bool
|
|
||||||
pic_valid_int(int PIC_UNUSED(v))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PIC_INLINE pic_value pic_nil_value();
|
PIC_INLINE pic_value pic_nil_value();
|
||||||
PIC_INLINE pic_value pic_true_value();
|
PIC_INLINE pic_value pic_true_value();
|
||||||
PIC_INLINE pic_value pic_false_value();
|
PIC_INLINE pic_value pic_false_value();
|
||||||
|
@ -240,9 +223,7 @@ PIC_INLINE pic_value pic_bool_value(bool);
|
||||||
PIC_INLINE pic_value pic_undef_value();
|
PIC_INLINE pic_value pic_undef_value();
|
||||||
PIC_INLINE pic_value pic_invalid_value();
|
PIC_INLINE pic_value pic_invalid_value();
|
||||||
PIC_INLINE pic_value pic_obj_value(void *);
|
PIC_INLINE pic_value pic_obj_value(void *);
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
PIC_INLINE pic_value pic_float_value(double);
|
PIC_INLINE pic_value pic_float_value(double);
|
||||||
#endif
|
|
||||||
PIC_INLINE pic_value pic_int_value(int);
|
PIC_INLINE pic_value pic_int_value(int);
|
||||||
PIC_INLINE pic_value pic_size_value(size_t);
|
PIC_INLINE pic_value pic_size_value(size_t);
|
||||||
PIC_INLINE pic_value pic_char_value(char c);
|
PIC_INLINE pic_value pic_char_value(char c);
|
||||||
|
@ -264,10 +245,8 @@ pic_type(pic_value v)
|
||||||
return PIC_TT_UNDEF;
|
return PIC_TT_UNDEF;
|
||||||
case PIC_VTYPE_INVALID:
|
case PIC_VTYPE_INVALID:
|
||||||
return PIC_TT_INVALID;
|
return PIC_TT_INVALID;
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
case PIC_VTYPE_FLOAT:
|
case PIC_VTYPE_FLOAT:
|
||||||
return PIC_TT_FLOAT;
|
return PIC_TT_FLOAT;
|
||||||
#endif
|
|
||||||
case PIC_VTYPE_INT:
|
case PIC_VTYPE_INT:
|
||||||
return PIC_TT_INT;
|
return PIC_TT_INT;
|
||||||
case PIC_VTYPE_CHAR:
|
case PIC_VTYPE_CHAR:
|
||||||
|
@ -289,10 +268,8 @@ pic_type_repr(enum pic_tt tt)
|
||||||
return "nil";
|
return "nil";
|
||||||
case PIC_TT_BOOL:
|
case PIC_TT_BOOL:
|
||||||
return "boolean";
|
return "boolean";
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
case PIC_TT_FLOAT:
|
case PIC_TT_FLOAT:
|
||||||
return "float";
|
return "float";
|
||||||
#endif
|
|
||||||
case PIC_TT_INT:
|
case PIC_TT_INT:
|
||||||
return "int";
|
return "int";
|
||||||
case PIC_TT_SYMBOL:
|
case PIC_TT_SYMBOL:
|
||||||
|
@ -382,13 +359,11 @@ pic_bool_value(bool b)
|
||||||
PIC_INLINE pic_value
|
PIC_INLINE pic_value
|
||||||
pic_size_value(size_t s)
|
pic_size_value(size_t s)
|
||||||
{
|
{
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
if (sizeof(unsigned) < sizeof(size_t)) {
|
if (sizeof(unsigned) < sizeof(size_t)) {
|
||||||
if (s > (size_t)INT_MAX) {
|
if (s > (size_t)INT_MAX) {
|
||||||
return pic_float_value(s);
|
return pic_float_value(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return pic_int_value((int)s);
|
return pic_int_value((int)s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,8 +447,6 @@ pic_obj_value(void *ptr)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
|
|
||||||
PIC_INLINE pic_value
|
PIC_INLINE pic_value
|
||||||
pic_float_value(double f)
|
pic_float_value(double f)
|
||||||
{
|
{
|
||||||
|
@ -484,8 +457,6 @@ pic_float_value(double f)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PIC_INLINE pic_value
|
PIC_INLINE pic_value
|
||||||
pic_int_value(int i)
|
pic_int_value(int i)
|
||||||
{
|
{
|
||||||
|
@ -569,10 +540,8 @@ pic_eqv_p(pic_value x, pic_value y)
|
||||||
return true;
|
return true;
|
||||||
case PIC_TT_BOOL:
|
case PIC_TT_BOOL:
|
||||||
return pic_vtype(x) == pic_vtype(y);
|
return pic_vtype(x) == pic_vtype(y);
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
case PIC_TT_FLOAT:
|
case PIC_TT_FLOAT:
|
||||||
return pic_float(x) == pic_float(y);
|
return pic_float(x) == pic_float(y);
|
||||||
#endif
|
|
||||||
case PIC_TT_INT:
|
case PIC_TT_INT:
|
||||||
return pic_int(x) == pic_int(y);
|
return pic_int(x) == pic_int(y);
|
||||||
default:
|
default:
|
||||||
|
@ -582,6 +551,59 @@ pic_eqv_p(pic_value x, pic_value y)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define pic_define_aop(name, op, guard) \
|
||||||
|
PIC_INLINE pic_value \
|
||||||
|
name(pic_state *pic, pic_value a, pic_value b) \
|
||||||
|
{ \
|
||||||
|
PIC_NORETURN void pic_errorf(pic_state *, const char *, ...); \
|
||||||
|
double f; \
|
||||||
|
if (pic_int_p(a) && pic_int_p(b)) { \
|
||||||
|
f = (double)pic_int(a) op (double)pic_int(b); \
|
||||||
|
return (INT_MIN <= f && f <= INT_MAX && guard) \
|
||||||
|
? pic_int_value((int)f) \
|
||||||
|
: pic_float_value(f); \
|
||||||
|
} else if (pic_float_p(a) && pic_float_p(b)) { \
|
||||||
|
return pic_float_value(pic_float(a) op pic_float(b)); \
|
||||||
|
} else if (pic_int_p(a) && pic_float_p(b)) { \
|
||||||
|
return pic_float_value(pic_int(a) op pic_float(b)); \
|
||||||
|
} else if (pic_float_p(a) && pic_int_p(b)) { \
|
||||||
|
return pic_float_value(pic_float(a) op pic_int(b)); \
|
||||||
|
} else { \
|
||||||
|
pic_errorf(pic, #name ": non-number operand given"); \
|
||||||
|
} \
|
||||||
|
PIC_UNREACHABLE(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
pic_define_aop(pic_add, +, true)
|
||||||
|
pic_define_aop(pic_sub, -, true)
|
||||||
|
pic_define_aop(pic_mul, *, true)
|
||||||
|
pic_define_aop(pic_div, /, f == (int)f)
|
||||||
|
|
||||||
|
#define pic_define_cmp(name, op) \
|
||||||
|
PIC_INLINE bool \
|
||||||
|
name(pic_state *pic, pic_value a, pic_value b) \
|
||||||
|
{ \
|
||||||
|
PIC_NORETURN void pic_errorf(pic_state *, const char *, ...); \
|
||||||
|
if (pic_int_p(a) && pic_int_p(b)) { \
|
||||||
|
return pic_int(a) op pic_int(b); \
|
||||||
|
} else if (pic_float_p(a) && pic_float_p(b)) { \
|
||||||
|
return pic_float(a) op pic_float(b); \
|
||||||
|
} else if (pic_int_p(a) && pic_float_p(b)) { \
|
||||||
|
return pic_int(a) op pic_float(b); \
|
||||||
|
} else if (pic_float_p(a) && pic_int_p(b)) { \
|
||||||
|
return pic_float(a) op pic_int(b); \
|
||||||
|
} else { \
|
||||||
|
pic_errorf(pic, #name ": non-number operand given"); \
|
||||||
|
} \
|
||||||
|
PIC_UNREACHABLE(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
pic_define_cmp(pic_eq, ==)
|
||||||
|
pic_define_cmp(pic_lt, <)
|
||||||
|
pic_define_cmp(pic_le, <=)
|
||||||
|
pic_define_cmp(pic_gt, >)
|
||||||
|
pic_define_cmp(pic_ge, >=)
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -18,8 +18,7 @@ struct pic_vector {
|
||||||
#define pic_vec_p(v) (pic_type(v) == PIC_TT_VECTOR)
|
#define pic_vec_p(v) (pic_type(v) == PIC_TT_VECTOR)
|
||||||
#define pic_vec_ptr(o) ((struct pic_vector *)pic_ptr(o))
|
#define pic_vec_ptr(o) ((struct pic_vector *)pic_ptr(o))
|
||||||
|
|
||||||
struct pic_vector *pic_make_vec(pic_state *, size_t);
|
pic_vec *pic_make_vec(pic_state *, size_t);
|
||||||
struct pic_vector *pic_make_vec_from_list(pic_state *, pic_value);
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "picrin.h"
|
#include "picrin.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_load_port(pic_state *pic, struct pic_port *port)
|
pic_load(pic_state *pic, struct pic_port *port)
|
||||||
{
|
{
|
||||||
pic_value form;
|
pic_value form;
|
||||||
size_t ai = pic_gc_arena_preserve(pic);
|
size_t ai = pic_gc_arena_preserve(pic);
|
||||||
|
@ -23,7 +23,7 @@ pic_load_cstr(pic_state *pic, const char *src)
|
||||||
struct pic_port *port = pic_open_input_string(pic, src);
|
struct pic_port *port = pic_open_input_string(pic, src);
|
||||||
|
|
||||||
pic_try {
|
pic_try {
|
||||||
pic_load_port(pic, port);
|
pic_load(pic, port);
|
||||||
}
|
}
|
||||||
pic_catch {
|
pic_catch {
|
||||||
pic_close_port(pic, port);
|
pic_close_port(pic, port);
|
||||||
|
|
|
@ -56,7 +56,7 @@ pic_uniq(pic_state *pic, pic_value var)
|
||||||
|
|
||||||
str = pic_format(pic, "%s.%d", pic_symbol_name(pic, pic_var_name(pic, var)), pic->ucnt++);
|
str = pic_format(pic, "%s.%d", pic_symbol_name(pic, pic_var_name(pic, var)), pic->ucnt++);
|
||||||
|
|
||||||
return pic_intern(pic, str);
|
return pic_intern_str(pic, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_sym *
|
pic_sym *
|
||||||
|
|
|
@ -4,23 +4,119 @@
|
||||||
|
|
||||||
#include "picrin.h"
|
#include "picrin.h"
|
||||||
|
|
||||||
#if ! PIC_ENABLE_FLOAT
|
|
||||||
static pic_value
|
static pic_value
|
||||||
pic_number_id(pic_state *pic)
|
pic_number_number_p(pic_state *pic)
|
||||||
{
|
{
|
||||||
int i;
|
pic_value v;
|
||||||
|
|
||||||
pic_get_args(pic, "i", &i);
|
pic_get_args(pic, "o", &v);
|
||||||
|
|
||||||
return pic_int_value(i);
|
return pic_bool_value(pic_float_p(v) || pic_int_p(v));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
static pic_value
|
||||||
* Returns the length of string representing val.
|
pic_number_exact_p(pic_state *pic)
|
||||||
* radix is between 2 and 36 (inclusive).
|
{
|
||||||
* No error checks are performed in this function.
|
pic_value v;
|
||||||
*/
|
|
||||||
|
pic_get_args(pic, "o", &v);
|
||||||
|
|
||||||
|
return pic_bool_value(pic_int_p(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_inexact_p(pic_state *pic)
|
||||||
|
{
|
||||||
|
pic_value v;
|
||||||
|
|
||||||
|
pic_get_args(pic, "o", &v);
|
||||||
|
|
||||||
|
return pic_bool_value(pic_float_p(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_inexact(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
|
||||||
|
return pic_float_value(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
pic_number_exact(pic_state *pic)
|
||||||
|
{
|
||||||
|
double f;
|
||||||
|
|
||||||
|
pic_get_args(pic, "f", &f);
|
||||||
|
|
||||||
|
return pic_int_value((int)f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_CMP(op) \
|
||||||
|
static pic_value \
|
||||||
|
pic_number_##op(pic_state *pic) \
|
||||||
|
{ \
|
||||||
|
size_t argc, i; \
|
||||||
|
pic_value *argv; \
|
||||||
|
\
|
||||||
|
pic_get_args(pic, "*", &argc, &argv); \
|
||||||
|
\
|
||||||
|
if (argc < 2) { \
|
||||||
|
return pic_true_value(); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
for (i = 1; i < argc; ++i) { \
|
||||||
|
if (! pic_##op(pic, argv[i - 1], argv[i])) { \
|
||||||
|
return pic_false_value(); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
return pic_true_value(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_CMP(eq)
|
||||||
|
DEFINE_CMP(lt)
|
||||||
|
DEFINE_CMP(le)
|
||||||
|
DEFINE_CMP(gt)
|
||||||
|
DEFINE_CMP(ge)
|
||||||
|
|
||||||
|
#define DEFINE_AOP(op, v1, c0) \
|
||||||
|
static pic_value \
|
||||||
|
pic_number_##op(pic_state *pic) \
|
||||||
|
{ \
|
||||||
|
size_t argc, i; \
|
||||||
|
pic_value *argv, tmp; \
|
||||||
|
\
|
||||||
|
pic_get_args(pic, "*", &argc, &argv); \
|
||||||
|
\
|
||||||
|
if (argc == 0) { \
|
||||||
|
c0; \
|
||||||
|
} \
|
||||||
|
else if (argc == 1) { \
|
||||||
|
return v1; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
tmp = argv[0]; \
|
||||||
|
for (i = 1; i < argc; ++i) { \
|
||||||
|
tmp = pic_##op(pic, tmp, argv[i]); \
|
||||||
|
} \
|
||||||
|
return tmp; \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_AOP(add, argv[0], do {
|
||||||
|
return pic_int_value(0);
|
||||||
|
} while (0))
|
||||||
|
DEFINE_AOP(mul, argv[0], do {
|
||||||
|
return pic_int_value(1);
|
||||||
|
} while (0))
|
||||||
|
DEFINE_AOP(sub, pic_sub(pic, pic_int_value(0), argv[0]), do {
|
||||||
|
pic_errorf(pic, "-: at least one argument required");
|
||||||
|
} while (0))
|
||||||
|
DEFINE_AOP(div, pic_div(pic, pic_int_value(1), argv[0]), do {
|
||||||
|
pic_errorf(pic, "/: at least one argument required");
|
||||||
|
} while (0))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
number_string_length(int val, int radix)
|
number_string_length(int val, int radix)
|
||||||
{
|
{
|
||||||
|
@ -40,12 +136,6 @@ number_string_length(int val, int radix)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the string representing val.
|
|
||||||
* radix is between 2 and 36 (inclusive).
|
|
||||||
* This function overwrites buffer and stores the result.
|
|
||||||
* No error checks are performed in this function. It is caller's responsibility to avoid buffer-overrun.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
number_string(int val, int radix, int length, char *buffer) {
|
number_string(int val, int radix, int length, char *buffer) {
|
||||||
const char digits[37] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
const char digits[37] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
@ -69,485 +159,9 @@ number_string(int val, int radix, int length, char *buffer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_real_p(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
pic_get_args(pic, "o", &v);
|
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
return pic_bool_value(pic_float_p(v) || pic_int_p(v));
|
|
||||||
#else
|
|
||||||
return pic_bool_value(pic_int_p(v));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_integer_p(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
pic_get_args(pic, "o", &v);
|
|
||||||
|
|
||||||
if (pic_int_p(v)) {
|
|
||||||
return pic_true_value();
|
|
||||||
}
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
if (pic_float_p(v)) {
|
|
||||||
double f = pic_float(v);
|
|
||||||
|
|
||||||
if (isinf(f)) {
|
|
||||||
return pic_false_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f == round(f)) {
|
|
||||||
return pic_true_value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return pic_false_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_exact_p(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
pic_get_args(pic, "o", &v);
|
|
||||||
|
|
||||||
return pic_bool_value(pic_int_p(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_inexact_p(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
pic_get_args(pic, "o", &v);
|
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
return pic_bool_value(pic_float_p(v));
|
|
||||||
#else
|
|
||||||
return pic_false_value();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_ARITH_CMP(op, name) \
|
|
||||||
static pic_value \
|
|
||||||
pic_number_##name(pic_state *pic) \
|
|
||||||
{ \
|
|
||||||
size_t argc, i; \
|
|
||||||
pic_value *argv; \
|
|
||||||
double f,g; \
|
|
||||||
\
|
|
||||||
pic_get_args(pic, "ff*", &f, &g, &argc, &argv); \
|
|
||||||
\
|
|
||||||
if (! (f op g)) \
|
|
||||||
return pic_false_value(); \
|
|
||||||
\
|
|
||||||
for (i = 0; i < argc; ++i) { \
|
|
||||||
f = g; \
|
|
||||||
if (pic_float_p(argv[i])) \
|
|
||||||
g = pic_float(argv[i]); \
|
|
||||||
else if (pic_int_p(argv[i])) \
|
|
||||||
g = pic_int(argv[i]); \
|
|
||||||
else \
|
|
||||||
pic_errorf(pic, #op ": number required"); \
|
|
||||||
\
|
|
||||||
if (! (f op g)) \
|
|
||||||
return pic_false_value(); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return pic_true_value(); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_ARITH_CMP2(op, name) \
|
|
||||||
static pic_value \
|
|
||||||
pic_number_##name(pic_state *pic) \
|
|
||||||
{ \
|
|
||||||
size_t argc, i; \
|
|
||||||
pic_value *argv; \
|
|
||||||
int f,g; \
|
|
||||||
\
|
|
||||||
pic_get_args(pic, "ii*", &f, &g, &argc, &argv); \
|
|
||||||
\
|
|
||||||
if (! (f op g)) \
|
|
||||||
return pic_false_value(); \
|
|
||||||
\
|
|
||||||
for (i = 0; i < argc; ++i) { \
|
|
||||||
f = g; \
|
|
||||||
if (pic_int_p(argv[i])) \
|
|
||||||
g = pic_int(argv[i]); \
|
|
||||||
else \
|
|
||||||
pic_errorf(pic, #op ": number required"); \
|
|
||||||
\
|
|
||||||
if (! (f op g)) \
|
|
||||||
return pic_false_value(); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return pic_true_value(); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
DEFINE_ARITH_CMP(==, eq)
|
|
||||||
DEFINE_ARITH_CMP(<, lt)
|
|
||||||
DEFINE_ARITH_CMP(>, gt)
|
|
||||||
DEFINE_ARITH_CMP(<=, le)
|
|
||||||
DEFINE_ARITH_CMP(>=, ge)
|
|
||||||
#else
|
|
||||||
DEFINE_ARITH_CMP2(==, eq)
|
|
||||||
DEFINE_ARITH_CMP2(<, lt)
|
|
||||||
DEFINE_ARITH_CMP2(>, gt)
|
|
||||||
DEFINE_ARITH_CMP2(<=, le)
|
|
||||||
DEFINE_ARITH_CMP2(>=, ge)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEFINE_ARITH_OP(op, name, unit) \
|
|
||||||
static pic_value \
|
|
||||||
pic_number_##name(pic_state *pic) \
|
|
||||||
{ \
|
|
||||||
size_t argc, i; \
|
|
||||||
pic_value *argv; \
|
|
||||||
double f; \
|
|
||||||
bool e = true; \
|
|
||||||
\
|
|
||||||
pic_get_args(pic, "*", &argc, &argv); \
|
|
||||||
\
|
|
||||||
f = unit; \
|
|
||||||
for (i = 0; i < argc; ++i) { \
|
|
||||||
if (pic_int_p(argv[i])) { \
|
|
||||||
f op##= pic_int(argv[i]); \
|
|
||||||
} \
|
|
||||||
else if (pic_float_p(argv[i])) { \
|
|
||||||
e = false; \
|
|
||||||
f op##= pic_float(argv[i]); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
pic_errorf(pic, #op ": number required"); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return e ? pic_int_value((int)f) : pic_float_value(f); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_ARITH_OP2(op, name, unit) \
|
|
||||||
static pic_value \
|
|
||||||
pic_number_##name(pic_state *pic) \
|
|
||||||
{ \
|
|
||||||
size_t argc, i; \
|
|
||||||
pic_value *argv; \
|
|
||||||
int f; \
|
|
||||||
\
|
|
||||||
pic_get_args(pic, "*", &argc, &argv); \
|
|
||||||
\
|
|
||||||
f = unit; \
|
|
||||||
for (i = 0; i < argc; ++i) { \
|
|
||||||
if (pic_int_p(argv[i])) { \
|
|
||||||
f op##= pic_int(argv[i]); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
pic_errorf(pic, #op ": number required"); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return pic_int_value(f); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
DEFINE_ARITH_OP(+, add, 0)
|
|
||||||
DEFINE_ARITH_OP(*, mul, 1)
|
|
||||||
#else
|
|
||||||
DEFINE_ARITH_OP2(+, add, 0)
|
|
||||||
DEFINE_ARITH_OP2(*, mul, 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEFINE_ARITH_INV_OP(op, name, unit, exact) \
|
|
||||||
static pic_value \
|
|
||||||
pic_number_##name(pic_state *pic) \
|
|
||||||
{ \
|
|
||||||
size_t argc, i; \
|
|
||||||
pic_value *argv; \
|
|
||||||
double f; \
|
|
||||||
bool e = true; \
|
|
||||||
\
|
|
||||||
pic_get_args(pic, "F*", &f, &e, &argc, &argv); \
|
|
||||||
\
|
|
||||||
e = e && exact; \
|
|
||||||
\
|
|
||||||
if (argc == 0) { \
|
|
||||||
f = unit op f; \
|
|
||||||
} \
|
|
||||||
for (i = 0; i < argc; ++i) { \
|
|
||||||
if (pic_int_p(argv[i])) { \
|
|
||||||
f op##= pic_int(argv[i]); \
|
|
||||||
} \
|
|
||||||
else if (pic_float_p(argv[i])) { \
|
|
||||||
e = false; \
|
|
||||||
f op##= pic_float(argv[i]); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
pic_errorf(pic, #op ": number required"); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return e ? pic_int_value((int)f) : pic_float_value(f); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_ARITH_INV_OP2(op, name, unit) \
|
|
||||||
static pic_value \
|
|
||||||
pic_number_##name(pic_state *pic) \
|
|
||||||
{ \
|
|
||||||
size_t argc, i; \
|
|
||||||
pic_value *argv; \
|
|
||||||
int f; \
|
|
||||||
\
|
|
||||||
pic_get_args(pic, "i*", &f, &argc, &argv); \
|
|
||||||
\
|
|
||||||
if (argc == 0) { \
|
|
||||||
f = unit op f; \
|
|
||||||
} \
|
|
||||||
for (i = 0; i < argc; ++i) { \
|
|
||||||
if (pic_int_p(argv[i])) { \
|
|
||||||
f op##= pic_int(argv[i]); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
pic_errorf(pic, #op ": number required"); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return pic_int_value(f); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
DEFINE_ARITH_INV_OP(-, sub, 0, true)
|
|
||||||
DEFINE_ARITH_INV_OP(/, div, 1, false)
|
|
||||||
#else
|
|
||||||
DEFINE_ARITH_INV_OP2(-, sub, 0)
|
|
||||||
DEFINE_ARITH_INV_OP2(/, div, 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_abs(pic_state *pic)
|
|
||||||
{
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
double f;
|
|
||||||
bool e;
|
|
||||||
|
|
||||||
pic_get_args(pic, "F", &f, &e);
|
|
||||||
|
|
||||||
if (e) {
|
|
||||||
return pic_int_value(f < 0 ? -f : f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return pic_float_value(fabs(f));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int i;
|
|
||||||
|
|
||||||
pic_get_args(pic, "i", &i);
|
|
||||||
|
|
||||||
return pic_int_value(i < 0 ? -i : i);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_expt(pic_state *pic)
|
|
||||||
{
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
double f, g, h;
|
|
||||||
bool e1, e2;
|
|
||||||
|
|
||||||
pic_get_args(pic, "FF", &f, &e1, &g, &e2);
|
|
||||||
|
|
||||||
h = pow(f, g);
|
|
||||||
if (e1 && e2) {
|
|
||||||
if (h <= INT_MAX) {
|
|
||||||
return pic_int_value((int)h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pic_float_value(h);
|
|
||||||
#else
|
|
||||||
int x, y, i, e = 1, r = 1, s = 0;
|
|
||||||
|
|
||||||
pic_get_args(pic, "ii", &x, &y);
|
|
||||||
|
|
||||||
if (y < 0) {
|
|
||||||
s = 1;
|
|
||||||
y = -y;
|
|
||||||
}
|
|
||||||
e = x;
|
|
||||||
for (i = 0; y; ++i) {
|
|
||||||
if ((y & 1) != 0) {
|
|
||||||
r *= e;
|
|
||||||
}
|
|
||||||
e *= e;
|
|
||||||
y >>= 1;
|
|
||||||
}
|
|
||||||
if (s != 0) {
|
|
||||||
r = 1 / r;
|
|
||||||
}
|
|
||||||
return pic_int_value(r);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_floor2(pic_state *pic)
|
|
||||||
{
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
int i, j;
|
|
||||||
bool e1, e2;
|
|
||||||
|
|
||||||
pic_get_args(pic, "II", &i, &e1, &j, &e2);
|
|
||||||
|
|
||||||
if (e1 && e2) {
|
|
||||||
int k;
|
|
||||||
|
|
||||||
k = (i < 0 && j < 0) || (0 <= i && 0 <= j)
|
|
||||||
? i / j
|
|
||||||
: (i / j) - 1;
|
|
||||||
|
|
||||||
return pic_values2(pic, pic_int_value(k), pic_int_value(i - k * j));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
double q, r;
|
|
||||||
|
|
||||||
q = floor((double)i/j);
|
|
||||||
r = i - j * q;
|
|
||||||
return pic_values2(pic, pic_float_value(q), pic_float_value(r));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int i, j, k;
|
|
||||||
|
|
||||||
pic_get_args(pic, "ii", &i, &j);
|
|
||||||
|
|
||||||
k = (i < 0 && j < 0) || (0 <= i && 0 <= j)
|
|
||||||
? i / j
|
|
||||||
: (i / j) - 1;
|
|
||||||
|
|
||||||
return pic_values2(pic, pic_int_value(k), pic_int_value(i - k * j));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_trunc2(pic_state *pic)
|
|
||||||
{
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
int i, j;
|
|
||||||
bool e1, e2;
|
|
||||||
|
|
||||||
pic_get_args(pic, "II", &i, &e1, &j, &e2);
|
|
||||||
|
|
||||||
if (e1 && e2) {
|
|
||||||
return pic_values2(pic, pic_int_value(i/j), pic_int_value(i - (i/j) * j));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
double q, r;
|
|
||||||
|
|
||||||
q = trunc((double)i/j);
|
|
||||||
r = i - j * q;
|
|
||||||
|
|
||||||
return pic_values2(pic, pic_float_value(q), pic_float_value(r));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
pic_get_args(pic, "ii", &i, &j);
|
|
||||||
|
|
||||||
return pic_values2(pic, pic_int_value(i/j), pic_int_value(i - (i/j) * j));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
static pic_value
|
|
||||||
pic_number_floor(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
bool e;
|
|
||||||
|
|
||||||
pic_get_args(pic, "F", &f, &e);
|
|
||||||
|
|
||||||
if (e) {
|
|
||||||
return pic_int_value((int)f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return pic_float_value(floor(f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_ceil(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
bool e;
|
|
||||||
|
|
||||||
pic_get_args(pic, "F", &f, &e);
|
|
||||||
|
|
||||||
if (e) {
|
|
||||||
return pic_int_value((int)f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return pic_float_value(ceil(f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_trunc(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
bool e;
|
|
||||||
|
|
||||||
pic_get_args(pic, "F", &f, &e);
|
|
||||||
|
|
||||||
if (e) {
|
|
||||||
return pic_int_value((int)f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return pic_float_value(trunc(f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_round(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
bool e;
|
|
||||||
|
|
||||||
pic_get_args(pic, "F", &f, &e);
|
|
||||||
|
|
||||||
if (e) {
|
|
||||||
return pic_int_value((int)f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return pic_float_value(round(f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_inexact(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
|
|
||||||
return pic_float_value(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_exact(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
|
|
||||||
return pic_int_value((int)(round(f)));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
pic_number_number_to_string(pic_state *pic)
|
pic_number_number_to_string(pic_state *pic)
|
||||||
{
|
{
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
double f;
|
double f;
|
||||||
bool e;
|
bool e;
|
||||||
int radix = 10;
|
int radix = 10;
|
||||||
|
@ -582,46 +196,16 @@ pic_number_number_to_string(pic_state *pic)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pic_obj_value(str);
|
return pic_obj_value(str);
|
||||||
#else
|
|
||||||
int f;
|
|
||||||
bool e;
|
|
||||||
int radix = 10;
|
|
||||||
pic_str *str;
|
|
||||||
size_t s;
|
|
||||||
char *buf;
|
|
||||||
int ival, ilen;
|
|
||||||
|
|
||||||
pic_get_args(pic, "i|i", &f, &e, &radix);
|
|
||||||
|
|
||||||
if (radix < 2 || radix > 36) {
|
|
||||||
pic_errorf(pic, "number->string: invalid radix %d (between 2 and 36, inclusive)", radix);
|
|
||||||
}
|
|
||||||
|
|
||||||
ival = f;
|
|
||||||
ilen = number_string_length(ival, radix);
|
|
||||||
s = ilen + 1;
|
|
||||||
|
|
||||||
buf = pic_malloc(pic, s);
|
|
||||||
|
|
||||||
number_string(ival, radix, ilen, buf);
|
|
||||||
|
|
||||||
str = pic_make_str(pic, buf, s - 1);
|
|
||||||
|
|
||||||
pic_free(pic, buf);
|
|
||||||
|
|
||||||
return pic_obj_value(str);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
pic_number_string_to_number(pic_state *pic)
|
pic_number_string_to_number(pic_state *pic)
|
||||||
{
|
{
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
const char *str;
|
const char *str;
|
||||||
int radix = 10;
|
int radix = 10;
|
||||||
long num;
|
long num;
|
||||||
char *eptr;
|
char *eptr;
|
||||||
double flo;
|
pic_value flo;
|
||||||
|
|
||||||
pic_get_args(pic, "z|i", &str, &radix);
|
pic_get_args(pic, "z|i", &str, &radix);
|
||||||
|
|
||||||
|
@ -632,246 +216,44 @@ pic_number_string_to_number(pic_state *pic)
|
||||||
: pic_float_value(num);
|
: pic_float_value(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
flo = strtod(str, &eptr);
|
flo = pic_read_cstr(pic, str);
|
||||||
if (*eptr == '\0') {
|
if (pic_int_p(flo) || pic_float_p(flo)) {
|
||||||
return pic_float_value(flo);
|
return flo;
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_errorf(pic, "invalid string given: %s", str);
|
pic_errorf(pic, "invalid string given: %s", str);
|
||||||
#else
|
|
||||||
const char *str;
|
|
||||||
int radix = 10;
|
|
||||||
long num;
|
|
||||||
char *eptr;
|
|
||||||
|
|
||||||
pic_get_args(pic, "z|i", &str, &radix);
|
|
||||||
|
|
||||||
num = strtol(str, &eptr, radix);
|
|
||||||
if (*eptr == '\0') {
|
|
||||||
return pic_int_value(num);
|
|
||||||
}
|
|
||||||
|
|
||||||
pic_errorf(pic, "invalid string given: %s", str);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
static pic_value
|
|
||||||
pic_number_finite_p(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
pic_get_args(pic, "o", &v);
|
|
||||||
|
|
||||||
if (pic_int_p(v))
|
|
||||||
return pic_true_value();
|
|
||||||
if (pic_float_p(v) && ! (isinf(pic_float(v)) || isnan(pic_float(v))))
|
|
||||||
return pic_true_value();
|
|
||||||
else
|
|
||||||
return pic_false_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_infinite_p(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
pic_get_args(pic, "o", &v);
|
|
||||||
|
|
||||||
if (pic_float_p(v) && isinf(pic_float(v)))
|
|
||||||
return pic_true_value();
|
|
||||||
else
|
|
||||||
return pic_false_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_nan_p(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
pic_get_args(pic, "o", &v);
|
|
||||||
|
|
||||||
if (pic_float_p(v) && isnan(pic_float(v)))
|
|
||||||
return pic_true_value();
|
|
||||||
else
|
|
||||||
return pic_false_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_exp(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
return pic_float_value(exp(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_log(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f,g;
|
|
||||||
int argc;
|
|
||||||
|
|
||||||
argc = pic_get_args(pic, "f|f", &f, &g);
|
|
||||||
if (argc == 1) {
|
|
||||||
return pic_float_value(log(f));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return pic_float_value(log(f) / log(g));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_sin(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
f = sin(f);
|
|
||||||
return pic_float_value(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_cos(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
f = cos(f);
|
|
||||||
return pic_float_value(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_tan(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
f = tan(f);
|
|
||||||
return pic_float_value(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_acos(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
f = acos(f);
|
|
||||||
return pic_float_value(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_asin(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
f = asin(f);
|
|
||||||
return pic_float_value(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_atan(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f,g;
|
|
||||||
int argc;
|
|
||||||
|
|
||||||
argc = pic_get_args(pic, "f|f", &f, &g);
|
|
||||||
if (argc == 1) {
|
|
||||||
f = atan(f);
|
|
||||||
return pic_float_value(f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return pic_float_value(atan2(f,g));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_number_sqrt(pic_state *pic)
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
|
|
||||||
pic_get_args(pic, "f", &f);
|
|
||||||
|
|
||||||
return pic_float_value(sqrt(f));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_init_number(pic_state *pic)
|
pic_init_number(pic_state *pic)
|
||||||
{
|
{
|
||||||
void pic_defun_vm(pic_state *, const char *, pic_sym *, pic_func_t);
|
|
||||||
|
|
||||||
size_t ai = pic_gc_arena_preserve(pic);
|
size_t ai = pic_gc_arena_preserve(pic);
|
||||||
|
|
||||||
pic_defun(pic, "number?", pic_number_real_p);
|
pic_defun(pic, "number?", pic_number_number_p);
|
||||||
pic_defun(pic, "complex?", pic_number_real_p);
|
|
||||||
pic_defun(pic, "real?", pic_number_real_p);
|
|
||||||
pic_defun(pic, "rational?", pic_number_real_p);
|
|
||||||
pic_defun(pic, "integer?", pic_number_integer_p);
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
|
||||||
pic_defun(pic, "exact?", pic_number_exact_p);
|
pic_defun(pic, "exact?", pic_number_exact_p);
|
||||||
pic_defun(pic, "inexact?", pic_number_inexact_p);
|
pic_defun(pic, "inexact?", pic_number_inexact_p);
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
|
||||||
pic_defun_vm(pic, "=", pic->uEQ, pic_number_eq);
|
|
||||||
pic_defun_vm(pic, "<", pic->uLT, pic_number_lt);
|
|
||||||
pic_defun_vm(pic, ">", pic->uGT, pic_number_gt);
|
|
||||||
pic_defun_vm(pic, "<=", pic->uLE, pic_number_le);
|
|
||||||
pic_defun_vm(pic, ">=", pic->uGE, pic_number_ge);
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
|
||||||
|
|
||||||
pic_defun_vm(pic, "+", pic->uADD, pic_number_add);
|
|
||||||
pic_defun_vm(pic, "-", pic->uSUB, pic_number_sub);
|
|
||||||
pic_defun_vm(pic, "*", pic->uMUL, pic_number_mul);
|
|
||||||
pic_defun_vm(pic, "/", pic->uDIV, pic_number_div);
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
|
||||||
|
|
||||||
pic_defun(pic, "abs", pic_number_abs);
|
|
||||||
pic_defun(pic, "expt", pic_number_expt);
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
|
||||||
|
|
||||||
pic_defun(pic, "floor/", pic_number_floor2);
|
|
||||||
pic_defun(pic, "truncate/", pic_number_trunc2);
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
pic_defun(pic, "floor", pic_number_floor);
|
|
||||||
pic_defun(pic, "ceiling", pic_number_ceil);
|
|
||||||
pic_defun(pic, "truncate", pic_number_trunc);
|
|
||||||
pic_defun(pic, "round", pic_number_round);
|
|
||||||
pic_defun(pic, "inexact", pic_number_inexact);
|
pic_defun(pic, "inexact", pic_number_inexact);
|
||||||
pic_defun(pic, "exact", pic_number_exact);
|
pic_defun(pic, "exact", pic_number_exact);
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
#else
|
|
||||||
pic_defun(pic, "floor", pic_number_id);
|
pic_defun(pic, "=", pic_number_eq);
|
||||||
pic_defun(pic, "ceiling", pic_number_id);
|
pic_defun(pic, "<", pic_number_lt);
|
||||||
pic_defun(pic, "truncate", pic_number_id);
|
pic_defun(pic, ">", pic_number_gt);
|
||||||
pic_defun(pic, "round", pic_number_id);
|
pic_defun(pic, "<=", pic_number_le);
|
||||||
pic_defun(pic, "inexact", pic_number_id);
|
pic_defun(pic, ">=", pic_number_ge);
|
||||||
pic_defun(pic, "exact", pic_number_id);
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
|
||||||
|
pic_defun(pic, "+", pic_number_add);
|
||||||
|
pic_defun(pic, "-", pic_number_sub);
|
||||||
|
pic_defun(pic, "*", pic_number_mul);
|
||||||
|
pic_defun(pic, "/", pic_number_div);
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
#endif
|
|
||||||
|
|
||||||
pic_defun(pic, "number->string", pic_number_number_to_string);
|
pic_defun(pic, "number->string", pic_number_number_to_string);
|
||||||
pic_defun(pic, "string->number", pic_number_string_to_number);
|
pic_defun(pic, "string->number", pic_number_string_to_number);
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
pic_defun(pic, "finite?", pic_number_finite_p);
|
|
||||||
pic_defun(pic, "infinite?", pic_number_infinite_p);
|
|
||||||
pic_defun(pic, "nan?", pic_number_nan_p);
|
|
||||||
pic_defun(pic, "sqrt", pic_number_sqrt);
|
|
||||||
pic_defun(pic, "exp", pic_number_exp);
|
|
||||||
pic_defun(pic, "log", pic_number_log);
|
|
||||||
pic_defun(pic, "sin", pic_number_sin);
|
|
||||||
pic_defun(pic, "cos", pic_number_cos);
|
|
||||||
pic_defun(pic, "tan", pic_number_tan);
|
|
||||||
pic_defun(pic, "acos", pic_number_acos);
|
|
||||||
pic_defun(pic, "asin", pic_number_asin);
|
|
||||||
pic_defun(pic, "atan", pic_number_atan);
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -760,13 +760,11 @@ pic_pair_assoc(pic_state *pic)
|
||||||
void
|
void
|
||||||
pic_init_pair(pic_state *pic)
|
pic_init_pair(pic_state *pic)
|
||||||
{
|
{
|
||||||
void pic_defun_vm(pic_state *, const char *, pic_sym *, pic_func_t);
|
pic_defun(pic, "pair?", pic_pair_pair_p);
|
||||||
|
pic_defun(pic, "cons", pic_pair_cons);
|
||||||
pic_defun_vm(pic, "pair?", pic->uPAIRP, pic_pair_pair_p);
|
pic_defun(pic, "car", pic_pair_car);
|
||||||
pic_defun_vm(pic, "cons", pic->uCONS, pic_pair_cons);
|
pic_defun(pic, "cdr", pic_pair_cdr);
|
||||||
pic_defun_vm(pic, "car", pic->uCAR, pic_pair_car);
|
pic_defun(pic, "null?", pic_pair_null_p);
|
||||||
pic_defun_vm(pic, "cdr", pic->uCDR, pic_pair_cdr);
|
|
||||||
pic_defun_vm(pic, "null?", pic->uNILP, pic_pair_null_p);
|
|
||||||
|
|
||||||
pic_defun(pic, "set-car!", pic_pair_set_car);
|
pic_defun(pic, "set-car!", pic_pair_set_car);
|
||||||
pic_defun(pic, "set-cdr!", pic_pair_set_cdr);
|
pic_defun(pic, "set-cdr!", pic_pair_set_cdr);
|
||||||
|
|
|
@ -98,6 +98,16 @@ file_open(pic_state *pic, const char *name, const char *mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PIC_NORETURN static void
|
||||||
|
file_error(pic_state *pic, const char *msg)
|
||||||
|
{
|
||||||
|
struct pic_error *e;
|
||||||
|
|
||||||
|
e = pic_make_error(pic, pic_intern(pic, "file"), msg, pic_nil_value());
|
||||||
|
|
||||||
|
pic_raise(pic, pic_obj_value(e));
|
||||||
|
}
|
||||||
|
|
||||||
struct pic_port *
|
struct pic_port *
|
||||||
pic_open_file(pic_state *pic, const char *name, int flags) {
|
pic_open_file(pic_state *pic, const char *name, int flags) {
|
||||||
struct pic_port *port;
|
struct pic_port *port;
|
||||||
|
@ -108,8 +118,7 @@ pic_open_file(pic_state *pic, const char *name, int flags) {
|
||||||
mode = 'w';
|
mode = 'w';
|
||||||
}
|
}
|
||||||
if ((file = file_open(pic, name, &mode)) == NULL) {
|
if ((file = file_open(pic, name, &mode)) == NULL) {
|
||||||
pic_str *msg = pic_format(pic, "could not open file '%s'", name);
|
file_error(pic, pic_str_cstr(pic, pic_format(pic, "could not open file '%s'", name)));
|
||||||
pic_raise(pic, pic_obj_value(pic_make_error(pic, pic->sFILE, pic_str_cstr(pic, msg), pic_nil_value())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
port = (struct pic_port *)pic_obj_alloc(pic, sizeof(struct pic_port), PIC_TT_PORT);
|
port = (struct pic_port *)pic_obj_alloc(pic, sizeof(struct pic_port), PIC_TT_PORT);
|
||||||
|
|
|
@ -42,19 +42,19 @@ pic_proc_env(pic_state *pic, struct pic_proc *proc)
|
||||||
bool
|
bool
|
||||||
pic_proc_env_has(pic_state *pic, struct pic_proc *proc, const char *key)
|
pic_proc_env_has(pic_state *pic, struct pic_proc *proc, const char *key)
|
||||||
{
|
{
|
||||||
return pic_dict_has(pic, pic_proc_env(pic, proc), pic_intern_cstr(pic, key));
|
return pic_dict_has(pic, pic_proc_env(pic, proc), pic_intern(pic, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_proc_env_ref(pic_state *pic, struct pic_proc *proc, const char *key)
|
pic_proc_env_ref(pic_state *pic, struct pic_proc *proc, const char *key)
|
||||||
{
|
{
|
||||||
return pic_dict_ref(pic, pic_proc_env(pic, proc), pic_intern_cstr(pic, key));
|
return pic_dict_ref(pic, pic_proc_env(pic, proc), pic_intern(pic, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_proc_env_set(pic_state *pic, struct pic_proc *proc, const char *key, pic_value val)
|
pic_proc_env_set(pic_state *pic, struct pic_proc *proc, const char *key, pic_value val)
|
||||||
{
|
{
|
||||||
pic_dict_set(pic, pic_proc_env(pic, proc), pic_intern_cstr(pic, key), val);
|
pic_dict_set(pic, pic_proc_env(pic, proc), pic_intern(pic, key), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
@ -86,7 +86,7 @@ pic_proc_apply(pic_state *pic)
|
||||||
arg_list = pic_cons(pic, args[argc], arg_list);
|
arg_list = pic_cons(pic, args[argc], arg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pic_apply_trampoline(pic, proc, arg_list);
|
return pic_apply_trampoline_list(pic, proc, arg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -14,7 +14,7 @@ read_error(pic_state *pic, const char *msg)
|
||||||
{
|
{
|
||||||
struct pic_error *e;
|
struct pic_error *e;
|
||||||
|
|
||||||
e = pic_make_error(pic, pic->sREAD, msg, pic_nil_value());
|
e = pic_make_error(pic, pic_intern(pic, "read"), msg, pic_nil_value());
|
||||||
|
|
||||||
pic_raise(pic, pic_obj_value(e));
|
pic_raise(pic, pic_obj_value(e));
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,6 @@ isdelim(int c)
|
||||||
return c == EOF || strchr("();,|\" \t\n\r", c) != NULL; /* ignores "#", "'" */
|
return c == EOF || strchr("();,|\" \t\n\r", c) != NULL; /* ignores "#", "'" */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
static bool
|
static bool
|
||||||
strcaseeq(const char *s1, const char *s2)
|
strcaseeq(const char *s1, const char *s2)
|
||||||
{
|
{
|
||||||
|
@ -76,7 +75,6 @@ strcaseeq(const char *s1, const char *s2)
|
||||||
}
|
}
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
case_fold(pic_state *pic, int c)
|
case_fold(pic_state *pic, int c)
|
||||||
|
@ -216,7 +214,7 @@ read_symbol(pic_state *pic, struct pic_port *port, int c)
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sym = pic_intern_cstr(pic, buf);
|
sym = pic_intern(pic, buf);
|
||||||
pic_free(pic, buf);
|
pic_free(pic, buf);
|
||||||
|
|
||||||
return pic_obj_value(sym);
|
return pic_obj_value(sym);
|
||||||
|
@ -267,22 +265,35 @@ read_unsigned(pic_state *pic, struct pic_port *port, int c)
|
||||||
{
|
{
|
||||||
unsigned u;
|
unsigned u;
|
||||||
int exp, s, i, e;
|
int exp, s, i, e;
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
double f, g;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u = read_uinteger(pic, port, c);
|
u = read_uinteger(pic, port, c);
|
||||||
|
|
||||||
switch (peek(pic, port)) {
|
switch (peek(pic, port)) {
|
||||||
#if PIC_ENABLE_FLOAT
|
#if PIC_ENABLE_LIBC
|
||||||
case '.':
|
case '.': {
|
||||||
|
char buf[256];
|
||||||
|
i = sprintf(buf, "%d", u);
|
||||||
|
buf[i++] = next(pic, port);
|
||||||
|
while (isdigit(c = peek(pic, port))) {
|
||||||
|
buf[i++] = next(pic, port);
|
||||||
|
}
|
||||||
|
sprintf(buf + i, "e%d", read_suffix(pic, port));
|
||||||
|
return pic_float_value(atof(buf));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
case '.': {
|
||||||
|
double f, g, h;
|
||||||
next(pic, port);
|
next(pic, port);
|
||||||
g = 0, e = 0;
|
g = 0, e = 0;
|
||||||
while (isdigit(c = peek(pic, port))) {
|
while (isdigit(c = peek(pic, port))) {
|
||||||
g = g * 10 + (next(pic, port) - '0');
|
g = g * 10 + (next(pic, port) - '0');
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
f = u + g * pow(10, -e);
|
h = 1.0;
|
||||||
|
while (e-- > 0) {
|
||||||
|
h /= 10;
|
||||||
|
}
|
||||||
|
f = u + g * h;
|
||||||
|
|
||||||
exp = read_suffix(pic, port);
|
exp = read_suffix(pic, port);
|
||||||
if (exp >= 0) {
|
if (exp >= 0) {
|
||||||
|
@ -301,6 +312,7 @@ read_unsigned(pic_state *pic, struct pic_port *port, int c)
|
||||||
exp >>= 1;
|
exp >>= 1;
|
||||||
}
|
}
|
||||||
return pic_float_value(f);
|
return pic_float_value(f);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -334,15 +346,11 @@ read_number(pic_state *pic, struct pic_port *port, int c)
|
||||||
static pic_value
|
static pic_value
|
||||||
negate(pic_value n)
|
negate(pic_value n)
|
||||||
{
|
{
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
if (pic_int_p(n)) {
|
if (pic_int_p(n)) {
|
||||||
return pic_int_value(-pic_int(n));
|
return pic_int_value(-pic_int(n));
|
||||||
} else {
|
} else {
|
||||||
return pic_float_value(-pic_float(n));
|
return pic_float_value(-pic_float(n));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return pic_int_value(-pic_int(n));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
@ -355,14 +363,12 @@ read_minus(pic_state *pic, struct pic_port *port, int c)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sym = read_symbol(pic, port, c);
|
sym = read_symbol(pic, port, c);
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
if (strcaseeq(pic_symbol_name(pic, pic_sym_ptr(sym)), "-inf.0")) {
|
if (strcaseeq(pic_symbol_name(pic, pic_sym_ptr(sym)), "-inf.0")) {
|
||||||
return pic_float_value(-INFINITY);
|
return pic_float_value(-(1.0 / 0.0));
|
||||||
}
|
}
|
||||||
if (strcaseeq(pic_symbol_name(pic, pic_sym_ptr(sym)), "-nan.0")) {
|
if (strcaseeq(pic_symbol_name(pic, pic_sym_ptr(sym)), "-nan.0")) {
|
||||||
return pic_float_value(-NAN);
|
return pic_float_value(-(0.0 / 0.0));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,14 +383,12 @@ read_plus(pic_state *pic, struct pic_port *port, int c)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sym = read_symbol(pic, port, c);
|
sym = read_symbol(pic, port, c);
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
if (strcaseeq(pic_symbol_name(pic, pic_sym_ptr(sym)), "+inf.0")) {
|
if (strcaseeq(pic_symbol_name(pic, pic_sym_ptr(sym)), "+inf.0")) {
|
||||||
return pic_float_value(INFINITY);
|
return pic_float_value(1.0 / 0.0);
|
||||||
}
|
}
|
||||||
if (strcaseeq(pic_symbol_name(pic, pic_sym_ptr(sym)), "+nan.0")) {
|
if (strcaseeq(pic_symbol_name(pic, pic_sym_ptr(sym)), "+nan.0")) {
|
||||||
return pic_float_value(NAN);
|
return pic_float_value(0.0 / 0.0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -525,7 +529,7 @@ read_pipe(pic_state *pic, struct pic_port *port, int c)
|
||||||
}
|
}
|
||||||
buf[cnt] = '\0';
|
buf[cnt] = '\0';
|
||||||
|
|
||||||
sym = pic_intern_cstr(pic, buf);
|
sym = pic_intern(pic, buf);
|
||||||
pic_free(pic, buf);
|
pic_free(pic, buf);
|
||||||
|
|
||||||
return pic_obj_value(sym);
|
return pic_obj_value(sym);
|
||||||
|
@ -631,11 +635,19 @@ read_pair(pic_state *pic, struct pic_port *port, int c)
|
||||||
static pic_value
|
static pic_value
|
||||||
read_vector(pic_state *pic, struct pic_port *port, int c)
|
read_vector(pic_state *pic, struct pic_port *port, int c)
|
||||||
{
|
{
|
||||||
pic_value list;
|
pic_value list, it, elem;
|
||||||
|
pic_vec *vec;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
list = read(pic, port, c);
|
list = read(pic, port, c);
|
||||||
|
|
||||||
return pic_obj_value(pic_make_vec_from_list(pic, list));
|
vec = pic_make_vec(pic, pic_length(pic, list));
|
||||||
|
|
||||||
|
pic_for_each (elem, list, it) {
|
||||||
|
vec->data[i++] = elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pic_obj_value(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
@ -855,24 +867,24 @@ pic_reader_destroy(pic_state *pic)
|
||||||
pic_value
|
pic_value
|
||||||
pic_read(pic_state *pic, struct pic_port *port)
|
pic_read(pic_state *pic, struct pic_port *port)
|
||||||
{
|
{
|
||||||
|
size_t ai = pic_gc_arena_preserve(pic);
|
||||||
pic_value val;
|
pic_value val;
|
||||||
int c = next(pic, port);
|
int c;
|
||||||
|
|
||||||
retry:
|
while ((c = skip(pic, port, next(pic, port))) != EOF) {
|
||||||
c = skip(pic, port, c);
|
val = read_nullable(pic, port, c);
|
||||||
|
|
||||||
|
if (! pic_invalid_p(val)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
}
|
||||||
if (c == EOF) {
|
if (c == EOF) {
|
||||||
return pic_eof_object();
|
return pic_eof_object();
|
||||||
}
|
}
|
||||||
|
|
||||||
val = read_nullable(pic, port, c);
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
return pic_gc_protect(pic, val);
|
||||||
if (pic_invalid_p(val)) {
|
|
||||||
c = next(pic, port);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
|
|
|
@ -15,7 +15,7 @@ pic_make_record(pic_state *pic, pic_value rectype)
|
||||||
rec = (struct pic_record *)pic_obj_alloc(pic, sizeof(struct pic_record), PIC_TT_RECORD);
|
rec = (struct pic_record *)pic_obj_alloc(pic, sizeof(struct pic_record), PIC_TT_RECORD);
|
||||||
rec->data = data;
|
rec->data = data;
|
||||||
|
|
||||||
pic_record_set(pic, rec, pic_intern_cstr(pic, "@@type"), rectype);
|
pic_record_set(pic, rec, pic_intern(pic, "@@type"), rectype);
|
||||||
|
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ pic_make_record(pic_state *pic, pic_value rectype)
|
||||||
pic_value
|
pic_value
|
||||||
pic_record_type(pic_state *pic, struct pic_record *rec)
|
pic_record_type(pic_state *pic, struct pic_record *rec)
|
||||||
{
|
{
|
||||||
return pic_record_ref(pic, rec, pic_intern_cstr(pic, "@@type"));
|
return pic_record_ref(pic, rec, pic_intern(pic, "@@type"));
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
|
|
|
@ -66,9 +66,9 @@ static pic_value
|
||||||
reg_get(pic_state *pic, struct pic_reg *reg, void *key)
|
reg_get(pic_state *pic, struct pic_reg *reg, void *key)
|
||||||
{
|
{
|
||||||
if (! pic_reg_has(pic, reg, key)) {
|
if (! pic_reg_has(pic, reg, key)) {
|
||||||
return pic_undef_value();
|
return pic_false_value();
|
||||||
}
|
}
|
||||||
return pic_reg_ref(pic, reg, key);
|
return pic_cons(pic, pic_obj_value(key), pic_reg_ref(pic, reg, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
|
|
@ -15,10 +15,9 @@ pic_set_argv(pic_state *pic, int argc, char *argv[], char **envp)
|
||||||
void
|
void
|
||||||
pic_add_feature(pic_state *pic, const char *feature)
|
pic_add_feature(pic_state *pic, const char *feature)
|
||||||
{
|
{
|
||||||
pic_push(pic, pic_obj_value(pic_intern_cstr(pic, feature)), pic->features);
|
pic_push(pic, pic_obj_value(pic_intern(pic, feature)), pic->features);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pic_init_undef(pic_state *);
|
|
||||||
void pic_init_bool(pic_state *);
|
void pic_init_bool(pic_state *);
|
||||||
void pic_init_pair(pic_state *);
|
void pic_init_pair(pic_state *);
|
||||||
void pic_init_port(pic_state *);
|
void pic_init_port(pic_state *);
|
||||||
|
@ -48,7 +47,10 @@ static void
|
||||||
pic_init_features(pic_state *pic)
|
pic_init_features(pic_state *pic)
|
||||||
{
|
{
|
||||||
pic_add_feature(pic, "picrin");
|
pic_add_feature(pic, "picrin");
|
||||||
|
|
||||||
|
#if __STDC_IEC_559__
|
||||||
pic_add_feature(pic, "ieee-float");
|
pic_add_feature(pic, "ieee-float");
|
||||||
|
#endif
|
||||||
|
|
||||||
#if _POSIX_SOURCE
|
#if _POSIX_SOURCE
|
||||||
pic_add_feature(pic, "posix");
|
pic_add_feature(pic, "posix");
|
||||||
|
@ -110,12 +112,22 @@ pic_features(pic_state *pic)
|
||||||
#define DONE pic_gc_arena_restore(pic, ai);
|
#define DONE pic_gc_arena_restore(pic, ai);
|
||||||
|
|
||||||
#define define_builtin_syntax(uid, name) \
|
#define define_builtin_syntax(uid, name) \
|
||||||
pic_define_syntactic_keyword_(pic, pic->lib->env, pic_intern_cstr(pic, name), uid)
|
pic_define_syntactic_keyword_(pic, pic->lib->env, pic_intern(pic, name), uid)
|
||||||
|
|
||||||
|
#define VM(uid, name) \
|
||||||
|
pic_define_syntactic_keyword_(pic, pic->lib->env, pic_intern(pic, name), uid)
|
||||||
|
|
||||||
|
#define VM3(name) \
|
||||||
|
pic->c##name = pic_vm_gref_slot(pic, pic->u##name);
|
||||||
|
|
||||||
|
#define VM2(proc, name) \
|
||||||
|
proc = pic_ref(pic, pic->lib, name)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pic_init_core(pic_state *pic)
|
pic_init_core(pic_state *pic)
|
||||||
{
|
{
|
||||||
void pic_define_syntactic_keyword_(pic_state *, struct pic_env *, pic_sym *, pic_sym *);
|
void pic_define_syntactic_keyword_(pic_state *, struct pic_env *, pic_sym *, pic_sym *);
|
||||||
|
pic_value pic_vm_gref_slot(pic_state *, pic_sym *);
|
||||||
|
|
||||||
pic_init_features(pic);
|
pic_init_features(pic);
|
||||||
|
|
||||||
|
@ -132,7 +144,23 @@ pic_init_core(pic_state *pic)
|
||||||
|
|
||||||
pic_defun(pic, "features", pic_features);
|
pic_defun(pic, "features", pic_features);
|
||||||
|
|
||||||
pic_init_undef(pic); DONE;
|
VM(pic->uCONS, "cons");
|
||||||
|
VM(pic->uCAR, "car");
|
||||||
|
VM(pic->uCDR, "cdr");
|
||||||
|
VM(pic->uNILP, "null?");
|
||||||
|
VM(pic->uSYMBOLP, "symbol?");
|
||||||
|
VM(pic->uPAIRP, "pair?");
|
||||||
|
VM(pic->uNOT, "not");
|
||||||
|
VM(pic->uADD, "+");
|
||||||
|
VM(pic->uSUB, "-");
|
||||||
|
VM(pic->uMUL, "*");
|
||||||
|
VM(pic->uDIV, "/");
|
||||||
|
VM(pic->uEQ, "=");
|
||||||
|
VM(pic->uLT, "<");
|
||||||
|
VM(pic->uLE, "<=");
|
||||||
|
VM(pic->uGT, ">");
|
||||||
|
VM(pic->uGE, ">=");
|
||||||
|
|
||||||
pic_init_bool(pic); DONE;
|
pic_init_bool(pic); DONE;
|
||||||
pic_init_pair(pic); DONE;
|
pic_init_pair(pic); DONE;
|
||||||
pic_init_port(pic); DONE;
|
pic_init_port(pic); DONE;
|
||||||
|
@ -156,10 +184,48 @@ pic_init_core(pic_state *pic)
|
||||||
pic_init_attr(pic); DONE;
|
pic_init_attr(pic); DONE;
|
||||||
pic_init_reg(pic); DONE;
|
pic_init_reg(pic); DONE;
|
||||||
|
|
||||||
pic_load_cstr(pic, &pic_boot[0][0]);
|
VM3(CONS);
|
||||||
}
|
VM3(CAR);
|
||||||
|
VM3(CDR);
|
||||||
|
VM3(NILP);
|
||||||
|
VM3(SYMBOLP);
|
||||||
|
VM3(PAIRP);
|
||||||
|
VM3(NOT);
|
||||||
|
VM3(ADD);
|
||||||
|
VM3(SUB);
|
||||||
|
VM3(MUL);
|
||||||
|
VM3(DIV);
|
||||||
|
VM3(EQ);
|
||||||
|
VM3(LT);
|
||||||
|
VM3(LE);
|
||||||
|
VM3(GT);
|
||||||
|
VM3(GE);
|
||||||
|
|
||||||
pic_import(pic, pic->PICRIN_BASE);
|
VM2(pic->pCONS, "cons");
|
||||||
|
VM2(pic->pCAR, "car");
|
||||||
|
VM2(pic->pCDR, "cdr");
|
||||||
|
VM2(pic->pNILP, "null?");
|
||||||
|
VM2(pic->pSYMBOLP, "symbol?");
|
||||||
|
VM2(pic->pPAIRP, "pair?");
|
||||||
|
VM2(pic->pNOT, "not");
|
||||||
|
VM2(pic->pADD, "+");
|
||||||
|
VM2(pic->pSUB, "-");
|
||||||
|
VM2(pic->pMUL, "*");
|
||||||
|
VM2(pic->pDIV, "/");
|
||||||
|
VM2(pic->pEQ, "=");
|
||||||
|
VM2(pic->pLT, "<");
|
||||||
|
VM2(pic->pLE, "<=");
|
||||||
|
VM2(pic->pGT, ">");
|
||||||
|
VM2(pic->pGE, ">=");
|
||||||
|
|
||||||
|
pic_try {
|
||||||
|
pic_load_cstr(pic, &pic_boot[0][0]);
|
||||||
|
}
|
||||||
|
pic_catch {
|
||||||
|
pic_print_backtrace(pic, xstdout);
|
||||||
|
pic_panic(pic, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_state *
|
pic_state *
|
||||||
|
@ -273,13 +339,8 @@ pic_open(pic_allocf allocf, void *userdata)
|
||||||
|
|
||||||
ai = pic_gc_arena_preserve(pic);
|
ai = pic_gc_arena_preserve(pic);
|
||||||
|
|
||||||
#define S(slot,name) pic->slot = pic_intern_cstr(pic, name)
|
#define S(slot,name) pic->slot = pic_intern(pic, name)
|
||||||
|
|
||||||
S(sDEFINE, "define");
|
|
||||||
S(sLAMBDA, "lambda");
|
|
||||||
S(sIF, "if");
|
|
||||||
S(sBEGIN, "begin");
|
|
||||||
S(sSETBANG, "set!");
|
|
||||||
S(sQUOTE, "quote");
|
S(sQUOTE, "quote");
|
||||||
S(sQUASIQUOTE, "quasiquote");
|
S(sQUASIQUOTE, "quasiquote");
|
||||||
S(sUNQUOTE, "unquote");
|
S(sUNQUOTE, "unquote");
|
||||||
|
@ -288,50 +349,18 @@ pic_open(pic_allocf allocf, void *userdata)
|
||||||
S(sSYNTAX_QUASIQUOTE, "syntax-quasiquote");
|
S(sSYNTAX_QUASIQUOTE, "syntax-quasiquote");
|
||||||
S(sSYNTAX_UNQUOTE, "syntax-unquote");
|
S(sSYNTAX_UNQUOTE, "syntax-unquote");
|
||||||
S(sSYNTAX_UNQUOTE_SPLICING, "syntax-unquote-splicing");
|
S(sSYNTAX_UNQUOTE_SPLICING, "syntax-unquote-splicing");
|
||||||
S(sDEFINE_MACRO, "define-macro");
|
|
||||||
S(sIMPORT, "import");
|
S(sIMPORT, "import");
|
||||||
S(sEXPORT, "export");
|
S(sEXPORT, "export");
|
||||||
S(sDEFINE_LIBRARY, "define-library");
|
S(sDEFINE_LIBRARY, "define-library");
|
||||||
S(sCOND_EXPAND, "cond-expand");
|
S(sCOND_EXPAND, "cond-expand");
|
||||||
S(sAND, "and");
|
|
||||||
S(sOR, "or");
|
|
||||||
S(sELSE, "else");
|
|
||||||
S(sLIBRARY, "library");
|
|
||||||
S(sONLY, "only");
|
|
||||||
S(sRENAME, "rename");
|
|
||||||
S(sPREFIX, "prefix");
|
|
||||||
S(sEXCEPT, "except");
|
|
||||||
S(sCONS, "cons");
|
|
||||||
S(sCAR, "car");
|
|
||||||
S(sCDR, "cdr");
|
|
||||||
S(sNILP, "null?");
|
|
||||||
S(sSYMBOLP, "symbol?");
|
|
||||||
S(sPAIRP, "pair?");
|
|
||||||
S(sADD, "+");
|
|
||||||
S(sSUB, "-");
|
|
||||||
S(sMUL, "*");
|
|
||||||
S(sDIV, "/");
|
|
||||||
S(sMINUS, "minus");
|
|
||||||
S(sEQ, "=");
|
|
||||||
S(sLT, "<");
|
|
||||||
S(sLE, "<=");
|
|
||||||
S(sGT, ">");
|
|
||||||
S(sGE, ">=");
|
|
||||||
S(sNOT, "not");
|
|
||||||
S(sREAD, "read");
|
|
||||||
S(sFILE, "file");
|
|
||||||
S(sCALL, "call");
|
S(sCALL, "call");
|
||||||
S(sTAILCALL, "tail-call");
|
|
||||||
S(sGREF, "gref");
|
S(sGREF, "gref");
|
||||||
S(sLREF, "lref");
|
S(sLREF, "lref");
|
||||||
S(sCREF, "cref");
|
S(sCREF, "cref");
|
||||||
S(sRETURN, "return");
|
|
||||||
S(sCALL_WITH_VALUES, "call-with-values");
|
|
||||||
S(sTAILCALL_WITH_VALUES, "tailcall-with-values");
|
|
||||||
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
|
||||||
#define U(slot,name) pic->slot = pic_uniq(pic, pic_obj_value(pic_intern_cstr(pic, name)))
|
#define U(slot,name) pic->slot = pic_uniq(pic, pic_obj_value(pic_intern(pic, name)))
|
||||||
|
|
||||||
U(uDEFINE, "define");
|
U(uDEFINE, "define");
|
||||||
U(uLAMBDA, "lambda");
|
U(uLAMBDA, "lambda");
|
||||||
|
@ -360,10 +389,26 @@ pic_open(pic_allocf allocf, void *userdata)
|
||||||
U(uGT, ">");
|
U(uGT, ">");
|
||||||
U(uGE, ">=");
|
U(uGE, ">=");
|
||||||
U(uNOT, "not");
|
U(uNOT, "not");
|
||||||
U(uVALUES, "values");
|
|
||||||
U(uCALL_WITH_VALUES, "call-with-values");
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
|
||||||
|
/* system procedures */
|
||||||
|
pic->pCONS = pic_invalid_value();
|
||||||
|
pic->pCAR = pic_invalid_value();
|
||||||
|
pic->pCDR = pic_invalid_value();
|
||||||
|
pic->pNILP = pic_invalid_value();
|
||||||
|
pic->pSYMBOLP = pic_invalid_value();
|
||||||
|
pic->pPAIRP = pic_invalid_value();
|
||||||
|
pic->pNOT = pic_invalid_value();
|
||||||
|
pic->pADD = pic_invalid_value();
|
||||||
|
pic->pSUB = pic_invalid_value();
|
||||||
|
pic->pMUL = pic_invalid_value();
|
||||||
|
pic->pDIV = pic_invalid_value();
|
||||||
|
pic->pEQ = pic_invalid_value();
|
||||||
|
pic->pLT = pic_invalid_value();
|
||||||
|
pic->pLE = pic_invalid_value();
|
||||||
|
pic->pGT = pic_invalid_value();
|
||||||
|
pic->pGE = pic_invalid_value();
|
||||||
|
|
||||||
/* root tables */
|
/* root tables */
|
||||||
pic->globals = pic_make_dict(pic);
|
pic->globals = pic_make_dict(pic);
|
||||||
pic->macros = pic_make_dict(pic);
|
pic->macros = pic_make_dict(pic);
|
||||||
|
@ -392,6 +437,23 @@ pic_open(pic_allocf allocf, void *userdata)
|
||||||
/* turn on GC */
|
/* turn on GC */
|
||||||
pic->gc_enable = true;
|
pic->gc_enable = true;
|
||||||
|
|
||||||
|
pic->cCONS = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cCAR = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cCDR = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cNILP = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cSYMBOLP = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cPAIRP = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cNOT = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cADD = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cSUB = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cMUL = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cDIV = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cEQ = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cLT = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cLE = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cGT = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
pic->cGE = pic_cons(pic, pic_false_value(), pic_invalid_value());
|
||||||
|
|
||||||
pic_init_core(pic);
|
pic_init_core(pic);
|
||||||
|
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
|
|
|
@ -240,25 +240,6 @@ pic_make_str_cstr(pic_state *pic, const char *cstr)
|
||||||
return pic_make_str(pic, cstr, strlen(cstr));
|
return pic_make_str(pic, cstr, strlen(cstr));
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_str *
|
|
||||||
pic_make_str_fill(pic_state *pic, size_t len, char fill)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
char *buf = pic_malloc(pic, len);
|
|
||||||
pic_str *str;
|
|
||||||
|
|
||||||
for (i = 0; i < len; ++i) {
|
|
||||||
buf[i] = fill;
|
|
||||||
}
|
|
||||||
buf[i] = '\0';
|
|
||||||
|
|
||||||
str = pic_make_str(pic, buf, len);
|
|
||||||
|
|
||||||
pic_free(pic, buf);
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
pic_str_len(pic_str *str)
|
pic_str_len(pic_str *str)
|
||||||
{
|
{
|
||||||
|
@ -335,11 +316,9 @@ pic_xvfformat(pic_state *pic, xFILE *file, const char *fmt, va_list ap)
|
||||||
case 'p':
|
case 'p':
|
||||||
xfprintf(pic, file, "%p", va_arg(ap, void *));
|
xfprintf(pic, file, "%p", va_arg(ap, void *));
|
||||||
break;
|
break;
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
case 'f':
|
case 'f':
|
||||||
xfprintf(pic, file, "%f", va_arg(ap, double));
|
xfprintf(pic, file, "%f", va_arg(ap, double));
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '~':
|
case '~':
|
||||||
|
@ -471,10 +450,18 @@ pic_str_make_string(pic_state *pic)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char c = ' ';
|
char c = ' ';
|
||||||
|
char *buf;
|
||||||
|
pic_value ret;
|
||||||
|
|
||||||
pic_get_args(pic, "k|c", &len, &c);
|
pic_get_args(pic, "k|c", &len, &c);
|
||||||
|
|
||||||
return pic_obj_value(pic_make_str_fill(pic, len, c));
|
buf = pic_malloc(pic, len);
|
||||||
|
memset(buf, c, len);
|
||||||
|
|
||||||
|
ret = pic_obj_value(pic_make_str(pic, buf, len));
|
||||||
|
|
||||||
|
pic_free(pic, buf);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
KHASH_DEFINE(s, const char *, pic_sym *, kh_str_hash_func, kh_str_hash_equal)
|
KHASH_DEFINE(s, const char *, pic_sym *, kh_str_hash_func, kh_str_hash_equal)
|
||||||
|
|
||||||
pic_sym *
|
pic_sym *
|
||||||
pic_intern(pic_state *pic, pic_str *str)
|
pic_intern_str(pic_state *pic, pic_str *str)
|
||||||
{
|
{
|
||||||
return pic_intern_cstr(pic, pic_str_cstr(pic, str));
|
return pic_intern(pic, pic_str_cstr(pic, str));
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_sym *
|
pic_sym *
|
||||||
pic_intern_cstr(pic_state *pic, const char *cstr)
|
pic_intern(pic_state *pic, const char *cstr)
|
||||||
{
|
{
|
||||||
khash_t(s) *h = &pic->syms;
|
khash_t(s) *h = &pic->syms;
|
||||||
pic_sym *sym;
|
pic_sym *sym;
|
||||||
|
@ -32,6 +32,8 @@ pic_intern_cstr(pic_state *pic, const char *cstr)
|
||||||
strcpy(copy, cstr);
|
strcpy(copy, cstr);
|
||||||
kh_key(h, it) = copy;
|
kh_key(h, it) = copy;
|
||||||
|
|
||||||
|
kh_val(h, it) = pic->sQUOTE; /* insert dummy */
|
||||||
|
|
||||||
sym = (pic_sym *)pic_obj_alloc(pic, sizeof(pic_sym), PIC_TT_SYMBOL);
|
sym = (pic_sym *)pic_obj_alloc(pic, sizeof(pic_sym), PIC_TT_SYMBOL);
|
||||||
sym->cstr = copy;
|
sym->cstr = copy;
|
||||||
kh_val(h, it) = sym;
|
kh_val(h, it) = sym;
|
||||||
|
@ -91,15 +93,13 @@ pic_symbol_string_to_symbol(pic_state *pic)
|
||||||
|
|
||||||
pic_get_args(pic, "s", &str);
|
pic_get_args(pic, "s", &str);
|
||||||
|
|
||||||
return pic_obj_value(pic_intern(pic, str));
|
return pic_obj_value(pic_intern_str(pic, str));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_init_symbol(pic_state *pic)
|
pic_init_symbol(pic_state *pic)
|
||||||
{
|
{
|
||||||
void pic_defun_vm(pic_state *, const char *, pic_sym *, pic_func_t);
|
pic_defun(pic, "symbol?", pic_symbol_symbol_p);
|
||||||
|
|
||||||
pic_defun_vm(pic, "symbol?", pic->uSYMBOLP, pic_symbol_symbol_p);
|
|
||||||
|
|
||||||
pic_defun(pic, "symbol->string", pic_symbol_symbol_to_string);
|
pic_defun(pic, "symbol->string", pic_symbol_symbol_to_string);
|
||||||
pic_defun(pic, "string->symbol", pic_symbol_string_to_symbol);
|
pic_defun(pic, "string->symbol", pic_symbol_string_to_symbol);
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* See Copyright Notice in picrin.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "picrin.h"
|
|
||||||
|
|
||||||
static pic_value
|
|
||||||
pic_undef_undefined_p(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
pic_get_args(pic, "o", &v);
|
|
||||||
|
|
||||||
return pic_undef_p(v) ? pic_true_value() : pic_false_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pic_init_undef(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_defun(pic, "undefined?", pic_undef_undefined_p);
|
|
||||||
}
|
|
|
@ -19,22 +19,6 @@ pic_make_vec(pic_state *pic, size_t len)
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pic_vector *
|
|
||||||
pic_make_vec_from_list(pic_state *pic, pic_value data)
|
|
||||||
{
|
|
||||||
struct pic_vector *vec;
|
|
||||||
size_t len, i;
|
|
||||||
|
|
||||||
len = pic_length(pic, data);
|
|
||||||
|
|
||||||
vec = pic_make_vec(pic, len);
|
|
||||||
for (i = 0; i < len; ++i) {
|
|
||||||
vec->data[i] = pic_car(pic, data);
|
|
||||||
data = pic_cdr(pic, data);
|
|
||||||
}
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
static pic_value
|
static pic_value
|
||||||
pic_vec_vector_p(pic_state *pic)
|
pic_vec_vector_p(pic_state *pic)
|
||||||
{
|
{
|
||||||
|
|
393
extlib/benz/vm.c
393
extlib/benz/vm.c
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "picrin.h"
|
#include "picrin.h"
|
||||||
|
#include "picrin/opcode.h"
|
||||||
|
|
||||||
#define GET_OPERAND(pic,n) ((pic)->ci->fp[(n)])
|
#define GET_OPERAND(pic,n) ((pic)->ci->fp[(n)])
|
||||||
|
|
||||||
|
@ -102,7 +103,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
*p = GET_OPERAND(pic,i);
|
*p = GET_OPERAND(pic,i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
case 'f': {
|
case 'f': {
|
||||||
double *f;
|
double *f;
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
@ -168,7 +168,6 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
case 'i': {
|
case 'i': {
|
||||||
int *k;
|
int *k;
|
||||||
pic_value v;
|
pic_value v;
|
||||||
|
@ -177,11 +176,9 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
|
|
||||||
v = GET_OPERAND(pic, i);
|
v = GET_OPERAND(pic, i);
|
||||||
switch (pic_type(v)) {
|
switch (pic_type(v)) {
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
case PIC_TT_FLOAT:
|
case PIC_TT_FLOAT:
|
||||||
*k = (int)pic_float(v);
|
*k = (int)pic_float(v);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case PIC_TT_INT:
|
case PIC_TT_INT:
|
||||||
*k = pic_int(v);
|
*k = pic_int(v);
|
||||||
break;
|
break;
|
||||||
|
@ -389,6 +386,34 @@ pic_get_args(pic_state *pic, const char *format, ...)
|
||||||
return argc;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pic_value
|
||||||
|
pic_vm_gref_slot(pic_state *pic, pic_sym *uid)
|
||||||
|
{
|
||||||
|
pic_value slot;
|
||||||
|
|
||||||
|
if (pic_dict_has(pic, pic->globals, uid)) {
|
||||||
|
return pic_dict_ref(pic, pic->globals, uid);
|
||||||
|
}
|
||||||
|
slot = pic_cons(pic, pic_obj_value(uid), pic_invalid_value());
|
||||||
|
pic_dict_set(pic, pic->globals, uid, slot);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static pic_value
|
||||||
|
vm_gref(pic_state *pic, pic_value slot)
|
||||||
|
{
|
||||||
|
if (pic_invalid_p(pic_cdr(pic, slot))) {
|
||||||
|
pic_errorf(pic, "uninitialized global variable: ~a", pic_car(pic, slot));
|
||||||
|
}
|
||||||
|
return pic_cdr(pic, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vm_gset(pic_state *pic, pic_value slot, pic_value value)
|
||||||
|
{
|
||||||
|
pic_set_cdr(pic, slot, value);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vm_push_cxt(pic_state *pic)
|
vm_push_cxt(pic_state *pic)
|
||||||
{
|
{
|
||||||
|
@ -431,23 +456,6 @@ pic_vm_tear_off(pic_state *pic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pic_irep *
|
|
||||||
vm_get_irep(pic_state *pic)
|
|
||||||
{
|
|
||||||
pic_value self;
|
|
||||||
struct pic_irep *irep;
|
|
||||||
|
|
||||||
self = pic->ci->fp[0];
|
|
||||||
if (! pic_proc_p(self)) {
|
|
||||||
pic_errorf(pic, "logic flaw");
|
|
||||||
}
|
|
||||||
irep = pic_proc_ptr(self)->u.i.irep;
|
|
||||||
if (! pic_proc_irep_p(pic_proc_ptr(self))) {
|
|
||||||
pic_errorf(pic, "logic flaw");
|
|
||||||
}
|
|
||||||
return irep;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if VM_DEBUG
|
#if VM_DEBUG
|
||||||
# define OPCODE_EXEC_HOOK pic_dump_code(c)
|
# define OPCODE_EXEC_HOOK pic_dump_code(c)
|
||||||
#else
|
#else
|
||||||
|
@ -552,8 +560,8 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
&&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_NOT, &&L_OP_CALL, &&L_OP_TAILCALL, &&L_OP_RET,
|
&&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_NOT, &&L_OP_CALL, &&L_OP_TAILCALL, &&L_OP_RET,
|
||||||
&&L_OP_LAMBDA, &&L_OP_CONS, &&L_OP_CAR, &&L_OP_CDR, &&L_OP_NILP,
|
&&L_OP_LAMBDA, &&L_OP_CONS, &&L_OP_CAR, &&L_OP_CDR, &&L_OP_NILP,
|
||||||
&&L_OP_SYMBOLP, &&L_OP_PAIRP,
|
&&L_OP_SYMBOLP, &&L_OP_PAIRP,
|
||||||
&&L_OP_ADD, &&L_OP_SUB, &&L_OP_MUL, &&L_OP_DIV, &&L_OP_MINUS,
|
&&L_OP_ADD, &&L_OP_SUB, &&L_OP_MUL, &&L_OP_DIV,
|
||||||
&&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_STOP
|
&&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE, &&L_OP_STOP
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -618,31 +626,16 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_PUSHCONST) {
|
CASE(OP_PUSHCONST) {
|
||||||
struct pic_irep *irep = vm_get_irep(pic);
|
PUSH(pic->ci->irep->pool[c.u.i]);
|
||||||
|
|
||||||
PUSH(irep->pool[c.u.i]);
|
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_GREF) {
|
CASE(OP_GREF) {
|
||||||
struct pic_irep *irep = vm_get_irep(pic);
|
PUSH(vm_gref(pic, pic->ci->irep->pool[c.u.i]));
|
||||||
pic_sym *sym;
|
|
||||||
|
|
||||||
sym = irep->syms[c.u.i];
|
|
||||||
if (! pic_dict_has(pic, pic->globals, sym)) {
|
|
||||||
pic_errorf(pic, "uninitialized global variable: %s", pic_symbol_name(pic, sym));
|
|
||||||
}
|
|
||||||
PUSH(pic_dict_ref(pic, pic->globals, sym));
|
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_GSET) {
|
CASE(OP_GSET) {
|
||||||
struct pic_irep *irep = vm_get_irep(pic);
|
vm_gset(pic, pic->ci->irep->pool[c.u.i], POP());
|
||||||
pic_sym *sym;
|
PUSH(pic_undef_value());
|
||||||
pic_value val;
|
|
||||||
|
|
||||||
sym = irep->syms[c.u.i];
|
|
||||||
|
|
||||||
val = POP();
|
|
||||||
pic_dict_set(pic, pic->globals, sym, val);
|
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_LREF) {
|
CASE(OP_LREF) {
|
||||||
|
@ -667,10 +660,12 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
irep = pic_get_proc(pic)->u.i.irep;
|
irep = pic_get_proc(pic)->u.i.irep;
|
||||||
if (c.u.i >= irep->argc + irep->localc) {
|
if (c.u.i >= irep->argc + irep->localc) {
|
||||||
ci->cxt->regs[c.u.i - (ci->regs - ci->fp)] = POP();
|
ci->cxt->regs[c.u.i - (ci->regs - ci->fp)] = POP();
|
||||||
|
PUSH(pic_undef_value());
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pic->ci->fp[c.u.i] = POP();
|
pic->ci->fp[c.u.i] = POP();
|
||||||
|
PUSH(pic_undef_value());
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_CREF) {
|
CASE(OP_CREF) {
|
||||||
|
@ -693,6 +688,7 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
cxt = cxt->up;
|
cxt = cxt->up;
|
||||||
}
|
}
|
||||||
cxt->regs[c.u.r.idx] = POP();
|
cxt->regs[c.u.r.idx] = POP();
|
||||||
|
PUSH(pic_undef_value());
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_JMP) {
|
CASE(OP_JMP) {
|
||||||
|
@ -709,13 +705,6 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
}
|
}
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_NOT) {
|
|
||||||
pic_value v;
|
|
||||||
|
|
||||||
v = pic_false_p(POP()) ? pic_true_value() : pic_false_value();
|
|
||||||
PUSH(v);
|
|
||||||
NEXT;
|
|
||||||
}
|
|
||||||
CASE(OP_CALL) {
|
CASE(OP_CALL) {
|
||||||
pic_value x, v;
|
pic_value x, v;
|
||||||
pic_callinfo *ci;
|
pic_callinfo *ci;
|
||||||
|
@ -743,6 +732,7 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
ci->retc = 1;
|
ci->retc = 1;
|
||||||
ci->ip = pic->ip;
|
ci->ip = pic->ip;
|
||||||
ci->fp = pic->sp - c.u.i;
|
ci->fp = pic->sp - c.u.i;
|
||||||
|
ci->irep = NULL;
|
||||||
ci->cxt = NULL;
|
ci->cxt = NULL;
|
||||||
if (pic_proc_func_p(pic_proc_ptr(x))) {
|
if (pic_proc_func_p(pic_proc_ptr(x))) {
|
||||||
|
|
||||||
|
@ -759,6 +749,7 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
int i;
|
int i;
|
||||||
pic_value rest;
|
pic_value rest;
|
||||||
|
|
||||||
|
ci->irep = irep;
|
||||||
if (ci->argc != irep->argc) {
|
if (ci->argc != irep->argc) {
|
||||||
if (! (irep->varg && ci->argc >= irep->argc)) {
|
if (! (irep->varg && ci->argc >= irep->argc)) {
|
||||||
pic_errorf(pic, "wrong number of arguments (%d for %s%d)", ci->argc - 1, (irep->varg ? "at least " : ""), irep->argc - 1);
|
pic_errorf(pic, "wrong number of arguments (%d for %s%d)", ci->argc - 1, (irep->varg ? "at least " : ""), irep->argc - 1);
|
||||||
|
@ -833,7 +824,7 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
vm_tear_off(pic->ci);
|
vm_tear_off(pic->ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic->ci->retc = c.u.i;
|
assert(pic->ci->retc == 1);
|
||||||
|
|
||||||
L_RET:
|
L_RET:
|
||||||
retc = pic->ci->retc;
|
retc = pic->ci->retc;
|
||||||
|
@ -851,186 +842,163 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_LAMBDA) {
|
CASE(OP_LAMBDA) {
|
||||||
pic_value self;
|
|
||||||
struct pic_irep *irep;
|
|
||||||
|
|
||||||
self = pic->ci->fp[0];
|
|
||||||
if (! pic_proc_p(self)) {
|
|
||||||
pic_errorf(pic, "logic flaw");
|
|
||||||
}
|
|
||||||
irep = pic_proc_ptr(self)->u.i.irep;
|
|
||||||
if (! pic_proc_irep_p(pic_proc_ptr(self))) {
|
|
||||||
pic_errorf(pic, "logic flaw");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pic->ci->cxt == NULL) {
|
if (pic->ci->cxt == NULL) {
|
||||||
vm_push_cxt(pic);
|
vm_push_cxt(pic);
|
||||||
}
|
}
|
||||||
|
|
||||||
proc = pic_make_proc_irep(pic, irep->irep[c.u.i], pic->ci->cxt);
|
proc = pic_make_proc_irep(pic, pic->ci->irep->irep[c.u.i], pic->ci->cxt);
|
||||||
PUSH(pic_obj_value(proc));
|
PUSH(pic_obj_value(proc));
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define check_condition(name, n) do { \
|
||||||
|
if (! pic_eq_p(pic->p##name, pic_cdr(pic, pic->c##name))) \
|
||||||
|
goto L_CALL; \
|
||||||
|
if (c.u.i != n + 1) \
|
||||||
|
goto L_CALL; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
CASE(OP_CONS) {
|
CASE(OP_CONS) {
|
||||||
pic_value a, b;
|
pic_value a, b;
|
||||||
|
check_condition(CONS, 2);
|
||||||
pic_gc_protect(pic, b = POP());
|
pic_gc_protect(pic, b = POP());
|
||||||
pic_gc_protect(pic, a = POP());
|
pic_gc_protect(pic, a = POP());
|
||||||
|
(void)POP();
|
||||||
PUSH(pic_cons(pic, a, b));
|
PUSH(pic_cons(pic, a, b));
|
||||||
pic_gc_arena_restore(pic, ai);
|
pic_gc_arena_restore(pic, ai);
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_CAR) {
|
CASE(OP_CAR) {
|
||||||
pic_value p;
|
pic_value p;
|
||||||
|
check_condition(CAR, 1);
|
||||||
p = POP();
|
p = POP();
|
||||||
|
(void)POP();
|
||||||
PUSH(pic_car(pic, p));
|
PUSH(pic_car(pic, p));
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_CDR) {
|
CASE(OP_CDR) {
|
||||||
pic_value p;
|
pic_value p;
|
||||||
|
check_condition(CDR, 1);
|
||||||
p = POP();
|
p = POP();
|
||||||
|
(void)POP();
|
||||||
PUSH(pic_cdr(pic, p));
|
PUSH(pic_cdr(pic, p));
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
CASE(OP_NILP) {
|
CASE(OP_NILP) {
|
||||||
pic_value p;
|
pic_value p;
|
||||||
|
check_condition(NILP, 1);
|
||||||
p = POP();
|
p = POP();
|
||||||
|
(void)POP();
|
||||||
PUSH(pic_bool_value(pic_nil_p(p)));
|
PUSH(pic_bool_value(pic_nil_p(p)));
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(OP_SYMBOLP) {
|
CASE(OP_SYMBOLP) {
|
||||||
pic_value p;
|
pic_value p;
|
||||||
|
check_condition(SYMBOLP, 1);
|
||||||
p = POP();
|
p = POP();
|
||||||
|
(void)POP();
|
||||||
PUSH(pic_bool_value(pic_sym_p(p)));
|
PUSH(pic_bool_value(pic_sym_p(p)));
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(OP_PAIRP) {
|
CASE(OP_PAIRP) {
|
||||||
pic_value p;
|
pic_value p;
|
||||||
|
check_condition(PAIRP, 1);
|
||||||
p = POP();
|
p = POP();
|
||||||
|
(void)POP();
|
||||||
PUSH(pic_bool_value(pic_pair_p(p)));
|
PUSH(pic_bool_value(pic_pair_p(p)));
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
CASE(OP_NOT) {
|
||||||
#define DEFINE_ARITH_OP(opcode, op, guard) \
|
pic_value v;
|
||||||
CASE(opcode) { \
|
check_condition(NOT, 1);
|
||||||
pic_value a, b; \
|
v = pic_false_p(POP()) ? pic_true_value() : pic_false_value();
|
||||||
b = POP(); \
|
(void)POP();
|
||||||
a = POP(); \
|
PUSH(v);
|
||||||
if (pic_int_p(a) && pic_int_p(b)) { \
|
|
||||||
double f = (double)pic_int(a) op (double)pic_int(b); \
|
|
||||||
if (INT_MIN <= f && f <= INT_MAX && (guard)) { \
|
|
||||||
PUSH(pic_int_value((int)f)); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
PUSH(pic_float_value(f)); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else if (pic_float_p(a) && pic_float_p(b)) { \
|
|
||||||
PUSH(pic_float_value(pic_float(a) op pic_float(b))); \
|
|
||||||
} \
|
|
||||||
else if (pic_int_p(a) && pic_float_p(b)) { \
|
|
||||||
PUSH(pic_float_value(pic_int(a) op pic_float(b))); \
|
|
||||||
} \
|
|
||||||
else if (pic_float_p(a) && pic_int_p(b)) { \
|
|
||||||
PUSH(pic_float_value(pic_float(a) op pic_int(b))); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
pic_errorf(pic, #op " got non-number operands"); \
|
|
||||||
} \
|
|
||||||
NEXT; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_ARITH_OP2(opcode, op) \
|
|
||||||
CASE(opcode) { \
|
|
||||||
pic_value a, b; \
|
|
||||||
b = POP(); \
|
|
||||||
a = POP(); \
|
|
||||||
if (pic_int_p(a) && pic_int_p(b)) { \
|
|
||||||
PUSH(pic_int_value(pic_int(a) op pic_int(b))); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
pic_errorf(pic, #op " got non-number operands"); \
|
|
||||||
} \
|
|
||||||
NEXT; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
DEFINE_ARITH_OP(OP_ADD, +, true);
|
|
||||||
DEFINE_ARITH_OP(OP_SUB, -, true);
|
|
||||||
DEFINE_ARITH_OP(OP_MUL, *, true);
|
|
||||||
DEFINE_ARITH_OP(OP_DIV, /, f == round(f));
|
|
||||||
#else
|
|
||||||
DEFINE_ARITH_OP2(OP_ADD, +);
|
|
||||||
DEFINE_ARITH_OP2(OP_SUB, -);
|
|
||||||
DEFINE_ARITH_OP2(OP_MUL, *);
|
|
||||||
DEFINE_ARITH_OP2(OP_DIV, /);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CASE(OP_MINUS) {
|
|
||||||
pic_value n;
|
|
||||||
n = POP();
|
|
||||||
if (pic_int_p(n)) {
|
|
||||||
PUSH(pic_int_value(-pic_int(n)));
|
|
||||||
}
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
else if (pic_float_p(n)) {
|
|
||||||
PUSH(pic_float_value(-pic_float(n)));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else {
|
|
||||||
pic_errorf(pic, "unary - got a non-number operand");
|
|
||||||
}
|
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_COMP_OP(opcode, op) \
|
CASE(OP_ADD) {
|
||||||
CASE(opcode) { \
|
pic_value a, b;
|
||||||
pic_value a, b; \
|
check_condition(ADD, 2);
|
||||||
b = POP(); \
|
b = POP();
|
||||||
a = POP(); \
|
a = POP();
|
||||||
if (pic_int_p(a) && pic_int_p(b)) { \
|
(void)POP();
|
||||||
PUSH(pic_bool_value(pic_int(a) op pic_int(b))); \
|
PUSH(pic_add(pic, a, b));
|
||||||
} \
|
NEXT;
|
||||||
else if (pic_float_p(a) && pic_float_p(b)) { \
|
|
||||||
PUSH(pic_bool_value(pic_float(a) op pic_float(b))); \
|
|
||||||
} \
|
|
||||||
else if (pic_int_p(a) && pic_float_p(b)) { \
|
|
||||||
PUSH(pic_bool_value(pic_int(a) op pic_float(b))); \
|
|
||||||
} \
|
|
||||||
else if (pic_float_p(a) && pic_int_p(b)) { \
|
|
||||||
PUSH(pic_bool_value(pic_float(a) op pic_int(b))); \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
pic_errorf(pic, #op " got non-number operands"); \
|
|
||||||
} \
|
|
||||||
NEXT; \
|
|
||||||
}
|
}
|
||||||
|
CASE(OP_SUB) {
|
||||||
#define DEFINE_COMP_OP2(opcode, op) \
|
pic_value a, b;
|
||||||
CASE(opcode) { \
|
check_condition(SUB, 2);
|
||||||
pic_value a, b; \
|
b = POP();
|
||||||
b = POP(); \
|
a = POP();
|
||||||
a = POP(); \
|
(void)POP();
|
||||||
if (pic_int_p(a) && pic_int_p(b)) { \
|
PUSH(pic_sub(pic, a, b));
|
||||||
PUSH(pic_bool_value(pic_int(a) op pic_int(b))); \
|
NEXT;
|
||||||
} \
|
}
|
||||||
else { \
|
CASE(OP_MUL) {
|
||||||
pic_errorf(pic, #op " got non-number operands"); \
|
pic_value a, b;
|
||||||
} \
|
check_condition(MUL, 2);
|
||||||
NEXT; \
|
b = POP();
|
||||||
|
a = POP();
|
||||||
|
(void)POP();
|
||||||
|
PUSH(pic_mul(pic, a, b));
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
CASE(OP_DIV) {
|
||||||
|
pic_value a, b;
|
||||||
|
check_condition(DIV, 2);
|
||||||
|
b = POP();
|
||||||
|
a = POP();
|
||||||
|
(void)POP();
|
||||||
|
PUSH(pic_div(pic, a, b));
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
CASE(OP_EQ) {
|
||||||
|
pic_value a, b;
|
||||||
|
check_condition(EQ, 2);
|
||||||
|
b = POP();
|
||||||
|
a = POP();
|
||||||
|
(void)POP();
|
||||||
|
PUSH(pic_bool_value(pic_eq(pic, a, b)));
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
CASE(OP_LE) {
|
||||||
|
pic_value a, b;
|
||||||
|
check_condition(LT, 2);
|
||||||
|
b = POP();
|
||||||
|
a = POP();
|
||||||
|
(void)POP();
|
||||||
|
PUSH(pic_bool_value(pic_le(pic, a, b)));
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
CASE(OP_LT) {
|
||||||
|
pic_value a, b;
|
||||||
|
check_condition(LE, 2);
|
||||||
|
b = POP();
|
||||||
|
a = POP();
|
||||||
|
(void)POP();
|
||||||
|
PUSH(pic_bool_value(pic_lt(pic, a, b)));
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
CASE(OP_GE) {
|
||||||
|
pic_value a, b;
|
||||||
|
check_condition(LT, 2);
|
||||||
|
b = POP();
|
||||||
|
a = POP();
|
||||||
|
(void)POP();
|
||||||
|
PUSH(pic_bool_value(pic_ge(pic, a, b)));
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
CASE(OP_GT) {
|
||||||
|
pic_value a, b;
|
||||||
|
check_condition(LE, 2);
|
||||||
|
b = POP();
|
||||||
|
a = POP();
|
||||||
|
(void)POP();
|
||||||
|
PUSH(pic_bool_value(pic_gt(pic, a, b)));
|
||||||
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
DEFINE_COMP_OP(OP_EQ, ==);
|
|
||||||
DEFINE_COMP_OP(OP_LT, <);
|
|
||||||
DEFINE_COMP_OP(OP_LE, <=);
|
|
||||||
#else
|
|
||||||
DEFINE_COMP_OP2(OP_EQ, ==);
|
|
||||||
DEFINE_COMP_OP2(OP_LT, <);
|
|
||||||
DEFINE_COMP_OP2(OP_LE, <=);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CASE(OP_STOP) {
|
CASE(OP_STOP) {
|
||||||
|
|
||||||
|
@ -1042,10 +1010,11 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_apply_trampoline(pic_state *pic, struct pic_proc *proc, pic_value args)
|
pic_apply_trampoline(pic_state *pic, struct pic_proc *proc, size_t argc, pic_value *args)
|
||||||
{
|
{
|
||||||
pic_value v, it, *sp;
|
pic_value *sp;
|
||||||
pic_callinfo *ci;
|
pic_callinfo *ci;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
PIC_INIT_CODE_I(pic->iseq[0], OP_NOP, 0);
|
PIC_INIT_CODE_I(pic->iseq[0], OP_NOP, 0);
|
||||||
PIC_INIT_CODE_I(pic->iseq[1], OP_TAILCALL, -1);
|
PIC_INIT_CODE_I(pic->iseq[1], OP_TAILCALL, -1);
|
||||||
|
@ -1053,22 +1022,37 @@ pic_apply_trampoline(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
*pic->sp++ = pic_obj_value(proc);
|
*pic->sp++ = pic_obj_value(proc);
|
||||||
|
|
||||||
sp = pic->sp;
|
sp = pic->sp;
|
||||||
pic_for_each (v, args, it) {
|
for (i = 0; i < argc; ++i) {
|
||||||
*sp++ = v;
|
*sp++ = args[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ci = PUSHCI();
|
ci = PUSHCI();
|
||||||
ci->ip = pic->iseq;
|
ci->ip = pic->iseq;
|
||||||
ci->fp = pic->sp;
|
ci->fp = pic->sp;
|
||||||
ci->retc = (int)pic_length(pic, args);
|
ci->retc = (int)argc;
|
||||||
|
|
||||||
if (ci->retc == 0) {
|
if (ci->retc == 0) {
|
||||||
return pic_undef_value();
|
return pic_undef_value();
|
||||||
} else {
|
} else {
|
||||||
return pic_car(pic, args);
|
return args[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pic_value
|
||||||
|
pic_apply_trampoline_list(pic_state *pic, struct pic_proc *proc, pic_value args)
|
||||||
|
{
|
||||||
|
size_t i, argc = pic_length(pic, args);
|
||||||
|
pic_value val, it;
|
||||||
|
pic_vec *argv = pic_make_vec(pic, argc);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
pic_for_each (val, args, it) {
|
||||||
|
argv->data[i++] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pic_apply_trampoline(pic, proc, argc, argv->data);
|
||||||
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
pic_apply0(pic_state *pic, struct pic_proc *proc)
|
pic_apply0(pic_state *pic, struct pic_proc *proc)
|
||||||
{
|
{
|
||||||
|
@ -1121,44 +1105,29 @@ pic_define_syntactic_keyword(pic_state *pic, struct pic_env *env, pic_sym *sym,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
pic_defun_vm(pic_state *pic, const char *name, pic_sym *uid, pic_func_t func)
|
|
||||||
{
|
|
||||||
struct pic_proc *proc;
|
|
||||||
pic_sym *sym;
|
|
||||||
|
|
||||||
proc = pic_make_proc(pic, func);
|
|
||||||
|
|
||||||
sym = pic_intern_cstr(pic, name);
|
|
||||||
|
|
||||||
pic_put_variable(pic, pic->lib->env, pic_obj_value(sym), uid);
|
|
||||||
|
|
||||||
pic_dict_set(pic, pic->globals, uid, pic_obj_value(proc));
|
|
||||||
|
|
||||||
pic_export(pic, sym);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_define_(pic_state *pic, const char *name, pic_value val)
|
pic_define_(pic_state *pic, const char *name, pic_value val)
|
||||||
{
|
{
|
||||||
pic_sym *sym, *uid;
|
pic_sym *sym, *uid;
|
||||||
|
|
||||||
sym = pic_intern_cstr(pic, name);
|
sym = pic_intern(pic, name);
|
||||||
|
|
||||||
if ((uid = pic_find_variable(pic, pic->lib->env, pic_obj_value(sym))) == NULL) {
|
if ((uid = pic_find_variable(pic, pic->lib->env, pic_obj_value(sym))) == NULL) {
|
||||||
uid = pic_add_variable(pic, pic->lib->env, pic_obj_value(sym));
|
uid = pic_add_variable(pic, pic->lib->env, pic_obj_value(sym));
|
||||||
} else {
|
} else {
|
||||||
pic_warnf(pic, "redefining global");
|
if (pic_dict_has(pic, pic->globals, uid)) {
|
||||||
|
pic_warnf(pic, "redefining variable: ~s", pic_obj_value(uid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_dict_set(pic, pic->globals, uid, val);
|
pic_set(pic, pic->lib, name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_define(pic_state *pic, const char *name, pic_value val)
|
pic_define(pic_state *pic, const char *name, pic_value val)
|
||||||
{
|
{
|
||||||
pic_define_(pic, name, val);
|
pic_define_(pic, name, val);
|
||||||
pic_export(pic, pic_intern_cstr(pic, name));
|
pic_export(pic, pic_intern(pic, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1171,7 +1140,7 @@ void
|
||||||
pic_defun(pic_state *pic, const char *name, pic_func_t cfunc)
|
pic_defun(pic_state *pic, const char *name, pic_func_t cfunc)
|
||||||
{
|
{
|
||||||
pic_defun_(pic, name, cfunc);
|
pic_defun_(pic, name, cfunc);
|
||||||
pic_export(pic, pic_intern_cstr(pic, name));
|
pic_export(pic, pic_intern(pic, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1184,7 +1153,7 @@ void
|
||||||
pic_defvar(pic_state *pic, const char *name, pic_value init, struct pic_proc *conv)
|
pic_defvar(pic_state *pic, const char *name, pic_value init, struct pic_proc *conv)
|
||||||
{
|
{
|
||||||
pic_defvar_(pic, name, init, conv);
|
pic_defvar_(pic, name, init, conv);
|
||||||
pic_export(pic, pic_intern_cstr(pic, name));
|
pic_export(pic, pic_intern(pic, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
|
@ -1192,13 +1161,13 @@ pic_ref(pic_state *pic, struct pic_lib *lib, const char *name)
|
||||||
{
|
{
|
||||||
pic_sym *sym, *uid;
|
pic_sym *sym, *uid;
|
||||||
|
|
||||||
sym = pic_intern_cstr(pic, name);
|
sym = pic_intern(pic, name);
|
||||||
|
|
||||||
if ((uid = pic_find_variable(pic, lib->env, pic_obj_value(sym))) == NULL) {
|
if ((uid = pic_find_variable(pic, lib->env, pic_obj_value(sym))) == NULL) {
|
||||||
pic_errorf(pic, "symbol \"%s\" not defined in library ~s", name, lib->name);
|
pic_errorf(pic, "symbol \"%s\" not defined in library ~s", name, lib->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pic_dict_ref(pic, pic->globals, uid);
|
return vm_gref(pic, pic_vm_gref_slot(pic, uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1206,13 +1175,13 @@ pic_set(pic_state *pic, struct pic_lib *lib, const char *name, pic_value val)
|
||||||
{
|
{
|
||||||
pic_sym *sym, *uid;
|
pic_sym *sym, *uid;
|
||||||
|
|
||||||
sym = pic_intern_cstr(pic, name);
|
sym = pic_intern(pic, name);
|
||||||
|
|
||||||
if ((uid = pic_find_variable(pic, lib->env, pic_obj_value(sym))) == NULL) {
|
if ((uid = pic_find_variable(pic, lib->env, pic_obj_value(sym))) == NULL) {
|
||||||
pic_errorf(pic, "symbol \"%s\" not defined in library ~s", name, lib->name);
|
pic_errorf(pic, "symbol \"%s\" not defined in library ~s", name, lib->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_dict_set(pic, pic->globals, uid, val);
|
vm_gset(pic, pic_vm_gref_slot(pic, uid), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_value
|
pic_value
|
||||||
|
|
|
@ -101,19 +101,19 @@ write_str(pic_state *pic, pic_str *str, xFILE *file, int mode)
|
||||||
xfprintf(pic, file, "\"");
|
xfprintf(pic, file, "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
static void
|
static void
|
||||||
write_float(pic_state *pic, double f, xFILE *file)
|
write_float(pic_state *pic, double f, xFILE *file)
|
||||||
{
|
{
|
||||||
if (isnan(f)) {
|
if (f != f) {
|
||||||
xfprintf(pic, file, signbit(f) ? "-nan.0" : "+nan.0");
|
xfprintf(pic, file, "+nan.0");
|
||||||
} else if (isinf(f)) {
|
} else if (f == 1.0 / 0.0) {
|
||||||
xfprintf(pic, file, signbit(f) ? "-inf.0" : "+inf.0");
|
xfprintf(pic, file, "+inf.0");
|
||||||
|
} else if (f == -1.0 / 0.0) {
|
||||||
|
xfprintf(pic, file, "-inf.0");
|
||||||
} else {
|
} else {
|
||||||
xfprintf(pic, file, "%f", f);
|
xfprintf(pic, file, "%f", f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void write_core(struct writer_control *p, pic_value);
|
static void write_core(struct writer_control *p, pic_value);
|
||||||
|
|
||||||
|
@ -291,11 +291,9 @@ write_core(struct writer_control *p, pic_value obj)
|
||||||
case PIC_TT_INT:
|
case PIC_TT_INT:
|
||||||
xfprintf(pic, file, "%d", pic_int(obj));
|
xfprintf(pic, file, "%d", pic_int(obj));
|
||||||
break;
|
break;
|
||||||
#if PIC_ENABLE_FLOAT
|
|
||||||
case PIC_TT_FLOAT:
|
case PIC_TT_FLOAT:
|
||||||
write_float(pic, pic_float(obj), file);
|
write_float(pic, pic_float(obj), file);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case PIC_TT_SYMBOL:
|
case PIC_TT_SYMBOL:
|
||||||
xfprintf(pic, file, "%s", pic_symbol_name(pic, pic_sym_ptr(obj)));
|
xfprintf(pic, file, "%s", pic_symbol_name(pic, pic_sym_ptr(obj)));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,290 +0,0 @@
|
||||||
(define-library (picrin base)
|
|
||||||
|
|
||||||
(export define
|
|
||||||
lambda
|
|
||||||
if
|
|
||||||
quote
|
|
||||||
set!
|
|
||||||
begin
|
|
||||||
define-macro)
|
|
||||||
|
|
||||||
(export syntax-error
|
|
||||||
define-syntax
|
|
||||||
let-syntax
|
|
||||||
letrec-syntax
|
|
||||||
syntax-quote
|
|
||||||
syntax-quasiquote
|
|
||||||
syntax-unquote
|
|
||||||
syntax-unquote-splicing)
|
|
||||||
|
|
||||||
(export let
|
|
||||||
let*
|
|
||||||
letrec
|
|
||||||
letrec*
|
|
||||||
quasiquote
|
|
||||||
unquote
|
|
||||||
unquote-splicing
|
|
||||||
and
|
|
||||||
or
|
|
||||||
cond
|
|
||||||
case
|
|
||||||
=>
|
|
||||||
else
|
|
||||||
do
|
|
||||||
when
|
|
||||||
unless)
|
|
||||||
|
|
||||||
(export let-values
|
|
||||||
let*-values
|
|
||||||
define-values)
|
|
||||||
|
|
||||||
(export eq?
|
|
||||||
eqv?
|
|
||||||
equal?)
|
|
||||||
|
|
||||||
(export undefined?)
|
|
||||||
|
|
||||||
(export boolean?
|
|
||||||
boolean=?
|
|
||||||
not)
|
|
||||||
|
|
||||||
(export symbol?
|
|
||||||
symbol->string
|
|
||||||
string->symbol
|
|
||||||
symbol=?)
|
|
||||||
|
|
||||||
(export char?
|
|
||||||
char->integer
|
|
||||||
integer->char
|
|
||||||
char=?
|
|
||||||
char<?
|
|
||||||
char>?
|
|
||||||
char<=?
|
|
||||||
char>=?)
|
|
||||||
|
|
||||||
(export number?
|
|
||||||
complex?
|
|
||||||
real?
|
|
||||||
rational?
|
|
||||||
integer?
|
|
||||||
exact?
|
|
||||||
inexact?
|
|
||||||
=
|
|
||||||
<
|
|
||||||
>
|
|
||||||
<=
|
|
||||||
>=
|
|
||||||
+
|
|
||||||
-
|
|
||||||
*
|
|
||||||
/
|
|
||||||
abs
|
|
||||||
floor/
|
|
||||||
truncate/
|
|
||||||
floor
|
|
||||||
ceiling
|
|
||||||
truncate
|
|
||||||
round
|
|
||||||
expt
|
|
||||||
number->string
|
|
||||||
string->number
|
|
||||||
finite?
|
|
||||||
infinite?
|
|
||||||
nan?
|
|
||||||
exp
|
|
||||||
log
|
|
||||||
sin
|
|
||||||
cos
|
|
||||||
tan
|
|
||||||
acos
|
|
||||||
asin
|
|
||||||
atan
|
|
||||||
sqrt)
|
|
||||||
|
|
||||||
(export pair?
|
|
||||||
cons
|
|
||||||
car
|
|
||||||
cdr
|
|
||||||
set-car!
|
|
||||||
set-cdr!
|
|
||||||
null?
|
|
||||||
caar
|
|
||||||
cadr
|
|
||||||
cdar
|
|
||||||
cddr)
|
|
||||||
|
|
||||||
(export list?
|
|
||||||
make-list
|
|
||||||
list
|
|
||||||
length
|
|
||||||
append
|
|
||||||
reverse
|
|
||||||
list-tail
|
|
||||||
list-ref
|
|
||||||
list-set!
|
|
||||||
list-copy
|
|
||||||
map
|
|
||||||
for-each
|
|
||||||
memq
|
|
||||||
memv
|
|
||||||
member
|
|
||||||
assq
|
|
||||||
assv
|
|
||||||
assoc)
|
|
||||||
|
|
||||||
(export bytevector?
|
|
||||||
bytevector
|
|
||||||
make-bytevector
|
|
||||||
bytevector-length
|
|
||||||
bytevector-u8-ref
|
|
||||||
bytevector-u8-set!
|
|
||||||
bytevector-copy
|
|
||||||
bytevector-copy!
|
|
||||||
bytevector-append
|
|
||||||
bytevector->list
|
|
||||||
list->bytevector)
|
|
||||||
|
|
||||||
(export vector?
|
|
||||||
vector
|
|
||||||
make-vector
|
|
||||||
vector-length
|
|
||||||
vector-ref
|
|
||||||
vector-set!
|
|
||||||
vector-copy!
|
|
||||||
vector-copy
|
|
||||||
vector-append
|
|
||||||
vector-fill!
|
|
||||||
vector-map
|
|
||||||
vector-for-each
|
|
||||||
list->vector
|
|
||||||
vector->list
|
|
||||||
string->vector
|
|
||||||
vector->string)
|
|
||||||
|
|
||||||
(export string?
|
|
||||||
string
|
|
||||||
make-string
|
|
||||||
string-length
|
|
||||||
string-ref
|
|
||||||
string-copy
|
|
||||||
string-append
|
|
||||||
string-map
|
|
||||||
string-for-each
|
|
||||||
string->list
|
|
||||||
list->string
|
|
||||||
string=?
|
|
||||||
string<?
|
|
||||||
string>?
|
|
||||||
string<=?
|
|
||||||
string>=?)
|
|
||||||
|
|
||||||
(export make-dictionary
|
|
||||||
dictionary?
|
|
||||||
dictionary
|
|
||||||
dictionary-ref
|
|
||||||
dictionary-set!
|
|
||||||
dictionary-size
|
|
||||||
dictionary-map
|
|
||||||
dictionary-for-each
|
|
||||||
dictionary->plist
|
|
||||||
plist->dictionary
|
|
||||||
dictionary->alist
|
|
||||||
alist->dictionary)
|
|
||||||
|
|
||||||
(export make-record
|
|
||||||
record?
|
|
||||||
record-type
|
|
||||||
record-ref
|
|
||||||
record-set!)
|
|
||||||
|
|
||||||
(export current-input-port
|
|
||||||
current-output-port
|
|
||||||
current-error-port
|
|
||||||
|
|
||||||
call-with-port
|
|
||||||
|
|
||||||
port?
|
|
||||||
input-port?
|
|
||||||
output-port?
|
|
||||||
textual-port?
|
|
||||||
binary-port?
|
|
||||||
|
|
||||||
port-open?
|
|
||||||
close-port
|
|
||||||
|
|
||||||
open-input-string
|
|
||||||
open-output-string
|
|
||||||
get-output-string
|
|
||||||
open-input-bytevector
|
|
||||||
open-output-bytevector
|
|
||||||
get-output-bytevector
|
|
||||||
|
|
||||||
eof-object?
|
|
||||||
eof-object
|
|
||||||
|
|
||||||
read-char
|
|
||||||
peek-char
|
|
||||||
char-ready?
|
|
||||||
read-line
|
|
||||||
read-string
|
|
||||||
|
|
||||||
read-u8
|
|
||||||
peek-u8
|
|
||||||
u8-ready?
|
|
||||||
read-bytevector
|
|
||||||
read-bytevector!
|
|
||||||
|
|
||||||
newline
|
|
||||||
write-char
|
|
||||||
write-string
|
|
||||||
write-u8
|
|
||||||
write-bytevector
|
|
||||||
flush-output-port)
|
|
||||||
|
|
||||||
(export make-parameter
|
|
||||||
parameterize)
|
|
||||||
|
|
||||||
(export make-identifier
|
|
||||||
identifier?
|
|
||||||
identifier-variable
|
|
||||||
identifier-environment
|
|
||||||
|
|
||||||
variable?
|
|
||||||
variable=?)
|
|
||||||
|
|
||||||
(export make-library
|
|
||||||
find-library
|
|
||||||
current-library
|
|
||||||
library-exports
|
|
||||||
library-environment)
|
|
||||||
|
|
||||||
(export call-with-current-continuation
|
|
||||||
call/cc
|
|
||||||
dynamic-wind
|
|
||||||
values
|
|
||||||
call-with-values)
|
|
||||||
|
|
||||||
(export with-exception-handler
|
|
||||||
raise
|
|
||||||
raise-continuable
|
|
||||||
error
|
|
||||||
make-error-object
|
|
||||||
error-object?
|
|
||||||
error-object-message
|
|
||||||
error-object-irritants
|
|
||||||
error-object-type)
|
|
||||||
|
|
||||||
(export procedure?
|
|
||||||
apply
|
|
||||||
attribute)
|
|
||||||
|
|
||||||
(export read)
|
|
||||||
|
|
||||||
(export write
|
|
||||||
write-simple
|
|
||||||
write-shared
|
|
||||||
display)
|
|
||||||
|
|
||||||
(export eval)
|
|
||||||
|
|
||||||
(export features))
|
|
|
@ -1,6 +0,0 @@
|
||||||
(define-library (picrin control)
|
|
||||||
(import (picrin base))
|
|
||||||
|
|
||||||
(define escape call/cc) ; create a new global variable slot
|
|
||||||
|
|
||||||
(export escape))
|
|
|
@ -1,37 +0,0 @@
|
||||||
(define-library (picrin experimental lambda)
|
|
||||||
(import (picrin base)
|
|
||||||
(picrin macro))
|
|
||||||
|
|
||||||
(define-syntax (destructuring-let formal value . body)
|
|
||||||
(cond
|
|
||||||
((variable? formal)
|
|
||||||
#`(let ((#,formal #,value))
|
|
||||||
#,@body))
|
|
||||||
((pair? formal)
|
|
||||||
#`(let ((value #,value))
|
|
||||||
(destructuring-let #,(car formal) (car value)
|
|
||||||
(destructuring-let #,(cdr formal) (cdr value)
|
|
||||||
#,@body))))
|
|
||||||
((vector? formal)
|
|
||||||
;; TODO
|
|
||||||
(error "fixme"))
|
|
||||||
(else
|
|
||||||
#`(if (equal? #,value '#,formal)
|
|
||||||
(begin
|
|
||||||
#,@body)
|
|
||||||
(error "match failure" #,value '#,formal)))))
|
|
||||||
|
|
||||||
(define-syntax (destructuring-lambda formal . body)
|
|
||||||
#`(lambda args
|
|
||||||
(destructuring-let #,formal args #,@body)))
|
|
||||||
|
|
||||||
(define-syntax (destructuring-define formal . body)
|
|
||||||
(if (variable? formal)
|
|
||||||
#`(define #,formal #,@body)
|
|
||||||
#`(destructuring-define #,(car formal)
|
|
||||||
(destructuring-lambda #,(cdr formal)
|
|
||||||
#,@body))))
|
|
||||||
|
|
||||||
(export (rename destructuring-let let)
|
|
||||||
(rename destructuring-lambda lambda)
|
|
||||||
(rename destructuring-define define)))
|
|
|
@ -1,59 +0,0 @@
|
||||||
(define-library (picrin record)
|
|
||||||
(import (picrin base)
|
|
||||||
(picrin macro))
|
|
||||||
|
|
||||||
;; record meta type
|
|
||||||
|
|
||||||
(define ((boot-make-record-type <meta-type>) name)
|
|
||||||
(let ((rectype (make-record <meta-type>)))
|
|
||||||
(record-set! rectype 'name name)
|
|
||||||
rectype))
|
|
||||||
|
|
||||||
(define <record-type>
|
|
||||||
(let ((<record-type> ((boot-make-record-type #t) 'record-type)))
|
|
||||||
(record-set! <record-type> '@@type <record-type>)
|
|
||||||
<record-type>))
|
|
||||||
|
|
||||||
(define make-record-type (boot-make-record-type <record-type>))
|
|
||||||
|
|
||||||
;; define-record-type
|
|
||||||
|
|
||||||
(define-syntax (define-record-constructor type name . fields)
|
|
||||||
(let ((record #'record))
|
|
||||||
#`(define (#,name . #,fields)
|
|
||||||
(let ((#,record (make-record #,type)))
|
|
||||||
#,@(map (lambda (field) #`(record-set! #,record '#,field #,field)) fields)
|
|
||||||
#,record))))
|
|
||||||
|
|
||||||
(define-syntax (define-record-predicate type name)
|
|
||||||
#`(define (#,name obj)
|
|
||||||
(and (record? obj)
|
|
||||||
(eq? (record-type obj) #,type))))
|
|
||||||
|
|
||||||
(define-syntax (define-record-accessor pred field accessor)
|
|
||||||
#`(define (#,accessor record)
|
|
||||||
(if (#,pred record)
|
|
||||||
(record-ref record '#,field)
|
|
||||||
(error (string-append (symbol->string '#,accessor) ": wrong record type") record))))
|
|
||||||
|
|
||||||
(define-syntax (define-record-modifier pred field modifier)
|
|
||||||
#`(define (#,modifier record val)
|
|
||||||
(if (#,pred record)
|
|
||||||
(record-set! record '#,field val)
|
|
||||||
(error (string-append (symbol->string '#,modifier) ": wrong record type") record))))
|
|
||||||
|
|
||||||
(define-syntax (define-record-field pred field accessor . modifier-opt)
|
|
||||||
(if (null? modifier-opt)
|
|
||||||
#`(define-record-accessor #,pred #,field #,accessor)
|
|
||||||
#`(begin
|
|
||||||
(define-record-accessor #,pred #,field #,accessor)
|
|
||||||
(define-record-modifier #,pred #,field #,(car modifier-opt)))))
|
|
||||||
|
|
||||||
(define-syntax (define-record-type name ctor pred . fields)
|
|
||||||
#`(begin
|
|
||||||
(define #,name (make-record-type '#,name))
|
|
||||||
(define-record-constructor #,name #,@ctor)
|
|
||||||
(define-record-predicate #,name #,pred)
|
|
||||||
#,@(map (lambda (field) #`(define-record-field #,pred #,@field)) fields)))
|
|
||||||
|
|
||||||
(export define-record-type))
|
|
|
@ -1,244 +0,0 @@
|
||||||
(define-library (picrin syntax-rules)
|
|
||||||
(import (picrin base)
|
|
||||||
(picrin macro))
|
|
||||||
|
|
||||||
(define-syntax (define-auxiliary-syntax var)
|
|
||||||
#`(define-macro #,var
|
|
||||||
(lambda _
|
|
||||||
(error "invalid use of auxiliary syntax" '#,var))))
|
|
||||||
|
|
||||||
(define-auxiliary-syntax _)
|
|
||||||
(define-auxiliary-syntax ...)
|
|
||||||
|
|
||||||
(define (succ n)
|
|
||||||
(+ n 1))
|
|
||||||
|
|
||||||
(define (pred n)
|
|
||||||
(if (= n 0)
|
|
||||||
0
|
|
||||||
(- n 1)))
|
|
||||||
|
|
||||||
(define (every? args)
|
|
||||||
(if (null? args)
|
|
||||||
#t
|
|
||||||
(if (car args)
|
|
||||||
(every? (cdr args))
|
|
||||||
#f)))
|
|
||||||
|
|
||||||
(define (filter f list)
|
|
||||||
(if (null? list)
|
|
||||||
'()
|
|
||||||
(if (f (car list))
|
|
||||||
(cons (car list)
|
|
||||||
(filter f (cdr list)))
|
|
||||||
(filter f (cdr list)))))
|
|
||||||
|
|
||||||
(define (take-tail n list)
|
|
||||||
(let drop ((n (- (length list) n)) (list list))
|
|
||||||
(if (= n 0)
|
|
||||||
list
|
|
||||||
(drop (- n 1) (cdr list)))))
|
|
||||||
|
|
||||||
(define (drop-tail n list)
|
|
||||||
(let take ((n (- (length list) n)) (list list))
|
|
||||||
(if (= n 0)
|
|
||||||
'()
|
|
||||||
(cons (car list) (take (- n 1) (cdr list))))))
|
|
||||||
|
|
||||||
(define (map-keys f assoc)
|
|
||||||
(map (lambda (s) `(,(f (car s)) . ,(cdr s))) assoc))
|
|
||||||
|
|
||||||
(define (map-values f assoc)
|
|
||||||
(map (lambda (s) `(,(car s) . ,(f (cdr s)))) assoc))
|
|
||||||
|
|
||||||
;; TODO
|
|
||||||
;; - placeholder
|
|
||||||
;; - vector
|
|
||||||
;; - (... template) pattern
|
|
||||||
|
|
||||||
;; p ::= constant
|
|
||||||
;; | var
|
|
||||||
;; | (p ... . p) (in input pattern, tail p should be a proper list)
|
|
||||||
;; | (p . p)
|
|
||||||
|
|
||||||
(define (compile ellipsis literals rules)
|
|
||||||
|
|
||||||
(define (constant? obj)
|
|
||||||
(and (not (pair? obj))
|
|
||||||
(not (variable? obj))))
|
|
||||||
|
|
||||||
(define (literal? obj)
|
|
||||||
(and (variable? obj)
|
|
||||||
(memq obj literals)))
|
|
||||||
|
|
||||||
(define (many? pat)
|
|
||||||
(and (pair? pat)
|
|
||||||
(pair? (cdr pat))
|
|
||||||
(variable? (cadr pat))
|
|
||||||
(variable=? (cadr pat) ellipsis)))
|
|
||||||
|
|
||||||
(define (pattern-validator pat) ; pattern -> validator
|
|
||||||
(letrec
|
|
||||||
((pattern-validator
|
|
||||||
(lambda (pat form)
|
|
||||||
(cond
|
|
||||||
((constant? pat)
|
|
||||||
#`(equal? '#,pat #,form))
|
|
||||||
((literal? pat)
|
|
||||||
#`(and (variable? #,form) (variable=? #'#,pat #,form)))
|
|
||||||
((variable? pat)
|
|
||||||
#t)
|
|
||||||
((many? pat)
|
|
||||||
(let ((head #`(drop-tail #,(length (cddr pat)) #,form))
|
|
||||||
(tail #`(take-tail #,(length (cddr pat)) #,form)))
|
|
||||||
#`(and (list? #,form)
|
|
||||||
(>= (length #,form) #,(length (cddr pat)))
|
|
||||||
(every? (map (lambda (#,'it) #,(pattern-validator (car pat) 'it)) #,head))
|
|
||||||
#,(pattern-validator (cddr pat) tail))))
|
|
||||||
((pair? pat)
|
|
||||||
#`(and (pair? #,form)
|
|
||||||
#,(pattern-validator (car pat) #`(car #,form))
|
|
||||||
#,(pattern-validator (cdr pat) #`(cdr #,form))))
|
|
||||||
(else
|
|
||||||
#f)))))
|
|
||||||
(pattern-validator pat 'it)))
|
|
||||||
|
|
||||||
(define (pattern-variables pat) ; pattern -> (freevar)
|
|
||||||
(cond
|
|
||||||
((constant? pat)
|
|
||||||
'())
|
|
||||||
((literal? pat)
|
|
||||||
'())
|
|
||||||
((variable? pat)
|
|
||||||
`(,pat))
|
|
||||||
((many? pat)
|
|
||||||
(append (pattern-variables (car pat))
|
|
||||||
(pattern-variables (cddr pat))))
|
|
||||||
((pair? pat)
|
|
||||||
(append (pattern-variables (car pat))
|
|
||||||
(pattern-variables (cdr pat))))))
|
|
||||||
|
|
||||||
(define (pattern-levels pat) ; pattern -> ((var * int))
|
|
||||||
(cond
|
|
||||||
((constant? pat)
|
|
||||||
'())
|
|
||||||
((literal? pat)
|
|
||||||
'())
|
|
||||||
((variable? pat)
|
|
||||||
`((,pat . 0)))
|
|
||||||
((many? pat)
|
|
||||||
(append (map-values succ (pattern-levels (car pat)))
|
|
||||||
(pattern-levels (cddr pat))))
|
|
||||||
((pair? pat)
|
|
||||||
(append (pattern-levels (car pat))
|
|
||||||
(pattern-levels (cdr pat))))))
|
|
||||||
|
|
||||||
(define (pattern-selectors pat) ; pattern -> ((var * selector))
|
|
||||||
(letrec
|
|
||||||
((pattern-selectors
|
|
||||||
(lambda (pat form)
|
|
||||||
(cond
|
|
||||||
((constant? pat)
|
|
||||||
'())
|
|
||||||
((literal? pat)
|
|
||||||
'())
|
|
||||||
((variable? pat)
|
|
||||||
`((,pat . ,form)))
|
|
||||||
((many? pat)
|
|
||||||
(let ((head #`(drop-tail #,(length (cddr pat)) #,form))
|
|
||||||
(tail #`(take-tail #,(length (cddr pat)) #,form)))
|
|
||||||
(let ((envs (pattern-selectors (car pat) 'it)))
|
|
||||||
(append
|
|
||||||
(map-values (lambda (s) #`(map (lambda (#,'it) #,s) #,head)) envs)
|
|
||||||
(pattern-selectors (cddr pat) tail)))))
|
|
||||||
((pair? pat)
|
|
||||||
(append (pattern-selectors (car pat) #`(car #,form))
|
|
||||||
(pattern-selectors (cdr pat) #`(cdr #,form))))))))
|
|
||||||
(pattern-selectors pat 'it)))
|
|
||||||
|
|
||||||
(define (template-representation pat levels selectors)
|
|
||||||
(cond
|
|
||||||
((constant? pat)
|
|
||||||
pat)
|
|
||||||
((variable? pat)
|
|
||||||
(let ((it (assq pat levels)))
|
|
||||||
(if it
|
|
||||||
(if (= 0 (cdr it))
|
|
||||||
(cdr (assq pat selectors))
|
|
||||||
(error "unmatched pattern variable level" pat))
|
|
||||||
#`(#,'rename '#,pat))))
|
|
||||||
((many? pat)
|
|
||||||
(letrec*
|
|
||||||
((inner-pat
|
|
||||||
(car pat))
|
|
||||||
(inner-levels
|
|
||||||
(map (lambda (s) `(,(car s) . ,(pred (cdr s)))) levels))
|
|
||||||
(inner-freevars
|
|
||||||
(filter (lambda (v) (assq v levels)) (pattern-variables inner-pat)))
|
|
||||||
(inner-vars
|
|
||||||
;; select only vars declared with ellipsis
|
|
||||||
(filter (lambda (v) (> (cdr (assq v levels)) 0)) inner-freevars))
|
|
||||||
(inner-tmps
|
|
||||||
(map (lambda (v) #'it) inner-vars))
|
|
||||||
(inner-selectors
|
|
||||||
;; first env '(map cons ...)' shadows second env 'selectors'
|
|
||||||
(append (map cons inner-vars inner-tmps) selectors))
|
|
||||||
(inner-rep
|
|
||||||
(template-representation inner-pat inner-levels inner-selectors))
|
|
||||||
(sorted-selectors
|
|
||||||
(map (lambda (v) (assq v selectors)) inner-vars))
|
|
||||||
(list-of-selectors
|
|
||||||
;; ((a . xs) (b . ys) (c . zs)) -> (xs ys zs)
|
|
||||||
(map cdr sorted-selectors)))
|
|
||||||
(let ((rep1 #`(map (lambda #,inner-tmps #,inner-rep) #,@list-of-selectors))
|
|
||||||
(rep2 (template-representation (cddr pat) levels selectors)))
|
|
||||||
#`(append #,rep1 #,rep2))))
|
|
||||||
((pair? pat)
|
|
||||||
#`(cons #,(template-representation (car pat) levels selectors)
|
|
||||||
#,(template-representation (cdr pat) levels selectors)))))
|
|
||||||
|
|
||||||
(define (compile-rule pattern template)
|
|
||||||
(let ((levels
|
|
||||||
(pattern-levels pattern))
|
|
||||||
(selectors
|
|
||||||
(pattern-selectors pattern)))
|
|
||||||
(template-representation template levels selectors)))
|
|
||||||
|
|
||||||
(define (compile-rules rules)
|
|
||||||
(if (null? rules)
|
|
||||||
#`(error "unmatch")
|
|
||||||
(let ((pattern (car (car rules)))
|
|
||||||
(template (cadr (car rules))))
|
|
||||||
#`(if #,(pattern-validator pattern)
|
|
||||||
#,(compile-rule pattern template)
|
|
||||||
#,(compile-rules (cdr rules))))))
|
|
||||||
|
|
||||||
(define (compile rules)
|
|
||||||
#`(call-with-current-environment
|
|
||||||
(lambda (env)
|
|
||||||
(letrec
|
|
||||||
((#,'rename (let ((reg (make-register)))
|
|
||||||
(lambda (x)
|
|
||||||
(if (undefined? (reg x))
|
|
||||||
(let ((id (make-identifier x env)))
|
|
||||||
(reg x id)
|
|
||||||
id)
|
|
||||||
(reg x))))))
|
|
||||||
(lambda #,'it
|
|
||||||
#,(compile-rules rules))))))
|
|
||||||
|
|
||||||
(let ((rules (map-keys cdr rules))) ; TODO: check pattern head is a variable
|
|
||||||
(compile rules)))
|
|
||||||
|
|
||||||
(define-syntax (syntax-rules . args)
|
|
||||||
(if (list? (car args))
|
|
||||||
#`(syntax-rules ... #,@args)
|
|
||||||
(let ((ellipsis (car args))
|
|
||||||
(literals (car (cdr args)))
|
|
||||||
(rules (cdr (cdr args))))
|
|
||||||
(compile ellipsis literals rules))))
|
|
||||||
|
|
||||||
|
|
||||||
(export syntax-rules
|
|
||||||
_
|
|
||||||
...))
|
|
42
t/array.scm
42
t/array.scm
|
@ -1,42 +0,0 @@
|
||||||
(import (scheme base)
|
|
||||||
(scheme write)
|
|
||||||
(picrin array))
|
|
||||||
|
|
||||||
(define ary (make-array))
|
|
||||||
|
|
||||||
(write ary)
|
|
||||||
(newline)
|
|
||||||
(array-push! ary 1)
|
|
||||||
(write ary)
|
|
||||||
(newline)
|
|
||||||
(array-push! ary 2)
|
|
||||||
(write ary)
|
|
||||||
(newline)
|
|
||||||
(array-push! ary 3)
|
|
||||||
(write ary)
|
|
||||||
(newline)
|
|
||||||
(write (array-pop! ary))
|
|
||||||
(newline)
|
|
||||||
(write (array-pop! ary))
|
|
||||||
(newline)
|
|
||||||
(write (array-pop! ary))
|
|
||||||
(newline)
|
|
||||||
|
|
||||||
(write ary)
|
|
||||||
(newline)
|
|
||||||
(array-unshift! ary 1)
|
|
||||||
(write ary)
|
|
||||||
(newline)
|
|
||||||
(array-unshift! ary 2)
|
|
||||||
(write ary)
|
|
||||||
(newline)
|
|
||||||
(array-unshift! ary 3)
|
|
||||||
(write ary)
|
|
||||||
(newline)
|
|
||||||
(write (array-shift! ary))
|
|
||||||
(newline)
|
|
||||||
(write (array-shift! ary))
|
|
||||||
(newline)
|
|
||||||
(write (array-shift! ary))
|
|
||||||
(newline)
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue