summaryrefslogtreecommitdiff
path: root/src/scheme/test
diff options
context:
space:
mode:
authorBdale Garbee <bdale@gag.com>2017-12-11 21:37:48 -0700
committerBdale Garbee <bdale@gag.com>2017-12-11 21:37:48 -0700
commitea0aa97fb93e669868a6f2c49c5d4b46e7615b1f (patch)
treef16b9a9ccd8b4a7bcde7d5cc64e6f0a52c4f3436 /src/scheme/test
parent216ea6388a75c46891dc4687a2eb0c97dc63b136 (diff)
parent9adf8b23aac8256f230b10adcab9dd323266caaa (diff)
Merge branch 'master' into branch-1.8
Diffstat (limited to 'src/scheme/test')
-rw-r--r--src/scheme/test/.gitignore1
-rw-r--r--src/scheme/test/Makefile22
-rw-r--r--src/scheme/test/ao_scheme_os.h68
-rw-r--r--src/scheme/test/ao_scheme_test.c139
-rw-r--r--src/scheme/test/hanoi.scheme174
5 files changed, 404 insertions, 0 deletions
diff --git a/src/scheme/test/.gitignore b/src/scheme/test/.gitignore
new file mode 100644
index 00000000..3cdae594
--- /dev/null
+++ b/src/scheme/test/.gitignore
@@ -0,0 +1 @@
+ao_scheme_test
diff --git a/src/scheme/test/Makefile b/src/scheme/test/Makefile
new file mode 100644
index 00000000..c48add1f
--- /dev/null
+++ b/src/scheme/test/Makefile
@@ -0,0 +1,22 @@
+include ../Makefile-inc
+
+vpath %.o .
+vpath %.c ..
+vpath %.h ..
+
+SRCS=$(SCHEME_SRCS) ao_scheme_test.c
+
+OBJS=$(SRCS:.c=.o)
+
+CFLAGS=-O2 -g -Wall -Wextra -I. -I..
+
+ao_scheme_test: $(OBJS)
+ cc $(CFLAGS) -o $@ $(OBJS) -lm
+
+$(OBJS): $(SCHEME_HDRS)
+
+clean::
+ rm -f $(OBJS) ao_scheme_test
+
+install: ao_scheme_test
+ cp ao_scheme_test $$HOME/bin/ao-scheme
diff --git a/src/scheme/test/ao_scheme_os.h b/src/scheme/test/ao_scheme_os.h
new file mode 100644
index 00000000..ea363fb3
--- /dev/null
+++ b/src/scheme/test/ao_scheme_os.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_SCHEME_OS_H_
+#define _AO_SCHEME_OS_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define AO_SCHEME_POOL_TOTAL 32768
+#define AO_SCHEME_SAVE 1
+#define DBG_MEM_STATS 1
+
+extern int ao_scheme_getc(void);
+
+static inline void
+ao_scheme_os_flush() {
+ fflush(stdout);
+}
+
+static inline void
+ao_scheme_abort(void)
+{
+ abort();
+}
+
+static inline void
+ao_scheme_os_led(int led)
+{
+ printf("leds set to 0x%x\n", led);
+}
+
+#define AO_SCHEME_JIFFIES_PER_SECOND 100
+
+static inline void
+ao_scheme_os_delay(int jiffies)
+{
+ struct timespec ts = {
+ .tv_sec = jiffies / AO_SCHEME_JIFFIES_PER_SECOND,
+ .tv_nsec = (jiffies % AO_SCHEME_JIFFIES_PER_SECOND) * (1000000000L / AO_SCHEME_JIFFIES_PER_SECOND)
+ };
+ nanosleep(&ts, NULL);
+}
+
+static inline int
+ao_scheme_os_jiffy(void)
+{
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ return tp.tv_sec * AO_SCHEME_JIFFIES_PER_SECOND + (tp.tv_nsec / (1000000000L / AO_SCHEME_JIFFIES_PER_SECOND));
+}
+
+#endif
diff --git a/src/scheme/test/ao_scheme_test.c b/src/scheme/test/ao_scheme_test.c
new file mode 100644
index 00000000..0c77d8d5
--- /dev/null
+++ b/src/scheme/test/ao_scheme_test.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao_scheme.h"
+#include <stdio.h>
+
+static FILE *ao_scheme_file;
+static int newline = 1;
+
+static char save_file[] = "scheme.image";
+
+int
+ao_scheme_os_save(void)
+{
+ FILE *save = fopen(save_file, "w");
+
+ if (!save) {
+ perror(save_file);
+ return 0;
+ }
+ fwrite(ao_scheme_pool, 1, AO_SCHEME_POOL_TOTAL, save);
+ fclose(save);
+ return 1;
+}
+
+int
+ao_scheme_os_restore_save(struct ao_scheme_os_save *save, int offset)
+{
+ FILE *restore = fopen(save_file, "r");
+ size_t ret;
+
+ if (!restore) {
+ perror(save_file);
+ return 0;
+ }
+ fseek(restore, offset, SEEK_SET);
+ ret = fread(save, sizeof (struct ao_scheme_os_save), 1, restore);
+ fclose(restore);
+ if (ret != 1)
+ return 0;
+ return 1;
+}
+
+int
+ao_scheme_os_restore(void)
+{
+ FILE *restore = fopen(save_file, "r");
+ size_t ret;
+
+ if (!restore) {
+ perror(save_file);
+ return 0;
+ }
+ ret = fread(ao_scheme_pool, 1, AO_SCHEME_POOL_TOTAL, restore);
+ fclose(restore);
+ if (ret != AO_SCHEME_POOL_TOTAL)
+ return 0;
+ return 1;
+}
+
+int
+ao_scheme_getc(void)
+{
+ int c;
+
+ if (ao_scheme_file)
+ return getc(ao_scheme_file);
+
+ if (newline) {
+ if (ao_scheme_read_list)
+ printf("+ ");
+ else
+ printf("> ");
+ newline = 0;
+ }
+ c = getchar();
+ if (c == '\n')
+ newline = 1;
+ return c;
+}
+
+int
+main (int argc, char **argv)
+{
+ (void) argc;
+
+ while (*++argv) {
+ ao_scheme_file = fopen(*argv, "r");
+ if (!ao_scheme_file) {
+ perror(*argv);
+ exit(1);
+ }
+ ao_scheme_read_eval_print();
+ fclose(ao_scheme_file);
+ ao_scheme_file = NULL;
+ }
+ ao_scheme_read_eval_print();
+
+ printf ("collects: full: %lu incremental %lu\n",
+ ao_scheme_collects[AO_SCHEME_COLLECT_FULL],
+ ao_scheme_collects[AO_SCHEME_COLLECT_INCREMENTAL]);
+
+ printf ("freed: full %lu incremental %lu\n",
+ ao_scheme_freed[AO_SCHEME_COLLECT_FULL],
+ ao_scheme_freed[AO_SCHEME_COLLECT_INCREMENTAL]);
+
+ printf("loops: full %lu incremental %lu\n",
+ ao_scheme_loops[AO_SCHEME_COLLECT_FULL],
+ ao_scheme_loops[AO_SCHEME_COLLECT_INCREMENTAL]);
+
+ printf("loops per collect: full %f incremental %f\n",
+ (double) ao_scheme_loops[AO_SCHEME_COLLECT_FULL] /
+ (double) ao_scheme_collects[AO_SCHEME_COLLECT_FULL],
+ (double) ao_scheme_loops[AO_SCHEME_COLLECT_INCREMENTAL] /
+ (double) ao_scheme_collects[AO_SCHEME_COLLECT_INCREMENTAL]);
+
+ printf("freed per collect: full %f incremental %f\n",
+ (double) ao_scheme_freed[AO_SCHEME_COLLECT_FULL] /
+ (double) ao_scheme_collects[AO_SCHEME_COLLECT_FULL],
+ (double) ao_scheme_freed[AO_SCHEME_COLLECT_INCREMENTAL] /
+ (double) ao_scheme_collects[AO_SCHEME_COLLECT_INCREMENTAL]);
+
+ printf("freed per loop: full %f incremental %f\n",
+ (double) ao_scheme_freed[AO_SCHEME_COLLECT_FULL] /
+ (double) ao_scheme_loops[AO_SCHEME_COLLECT_FULL],
+ (double) ao_scheme_freed[AO_SCHEME_COLLECT_INCREMENTAL] /
+ (double) ao_scheme_loops[AO_SCHEME_COLLECT_INCREMENTAL]);
+}
diff --git a/src/scheme/test/hanoi.scheme b/src/scheme/test/hanoi.scheme
new file mode 100644
index 00000000..c4ae7378
--- /dev/null
+++ b/src/scheme/test/hanoi.scheme
@@ -0,0 +1,174 @@
+;
+; Towers of Hanoi
+;
+; Copyright © 2016 Keith Packard <keithp@keithp.com>
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation, either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+
+ ; ANSI control sequences
+
+(define (move-to col row)
+ (for-each display (list "\033[" row ";" col "H"))
+ )
+
+(define (clear)
+ (display "\033[2J")
+ )
+
+(define (display-string x y str)
+ (move-to x y)
+ (display str)
+ )
+
+(define (make-piece num max)
+ ; A piece for position 'num'
+ ; is num + 1 + num stars
+ ; centered in a field of max *
+ ; 2 + 1 characters with spaces
+ ; on either side. This way,
+ ; every piece is the same
+ ; number of characters
+
+ (define (chars n c)
+ (if (zero? n) ""
+ (+ c (chars (- n 1) c))
+ )
+ )
+ (+ (chars (- max num 1) " ")
+ (chars (+ (* num 2) 1) "*")
+ (chars (- max num 1) " ")
+ )
+ )
+
+(define (make-pieces max)
+ ; Make a list of numbers from 0 to max-1
+ (define (nums cur max)
+ (if (= cur max) ()
+ (cons cur (nums (+ cur 1) max))
+ )
+ )
+ ; Create a list of pieces
+
+ (map (lambda (x) (make-piece x max)) (nums 0 max))
+ )
+
+ ; Here's all of the towers of pieces
+ ; This is generated when the program is run
+
+(define towers ())
+
+ ; position of the bottom of
+ ; the stacks set at runtime
+(define bottom-y 0)
+(define left-x 0)
+
+(define move-delay 25)
+
+ ; Display one tower, clearing any
+ ; space above it
+
+(define (display-tower x y clear tower)
+ (cond ((= 0 clear)
+ (cond ((not (null? tower))
+ (display-string x y (car tower))
+ (display-tower x (+ y 1) 0 (cdr tower))
+ )
+ )
+ )
+ (else
+ (display-string x y " ")
+ (display-tower x (+ y 1) (- clear 1) tower)
+ )
+ )
+ )
+
+ ; Position of the top of the tower on the screen
+ ; Shorter towers start further down the screen
+
+(define (tower-pos tower)
+ (- bottom-y (length tower))
+ )
+
+ ; Display all of the towers, spaced 20 columns apart
+
+(define (display-towers x towers)
+ (cond ((not (null? towers))
+ (display-tower x 0 (tower-pos (car towers)) (car towers))
+ (display-towers (+ x 20) (cdr towers)))
+ )
+ )
+
+ ; Display all of the towers, then move the cursor
+ ; out of the way and flush the output
+
+(define (display-hanoi)
+ (display-towers left-x towers)
+ (move-to 1 23)
+ (flush-output)
+ (delay move-delay)
+ )
+
+ ; Reset towers to the starting state, with
+ ; all of the pieces in the first tower and the
+ ; other two empty
+
+(define (reset-towers len)
+ (set! towers (list (make-pieces len) () ()))
+ (set! bottom-y (+ len 3))
+ )
+
+ ; Move a piece from the top of one tower
+ ; to the top of another
+
+(define (move-piece from to)
+
+ ; references to the cons holding the two towers
+
+ (define from-tower (list-tail towers from))
+ (define to-tower (list-tail towers to))
+
+ ; stick the car of from-tower onto to-tower
+
+ (set-car! to-tower (cons (caar from-tower) (car to-tower)))
+
+ ; remove the car of from-tower
+
+ (set-car! from-tower (cdar from-tower))
+ )
+
+ ; The implementation of the game
+
+(define (_hanoi n from to use)
+ (cond ((= 1 n)
+ (move-piece from to)
+ (display-hanoi)
+ )
+ (else
+ (_hanoi (- n 1) from use to)
+ (_hanoi 1 from to use)
+ (_hanoi (- n 1) use to from)
+ )
+ )
+ )
+
+ ; A pretty interface which
+ ; resets the state of the game,
+ ; clears the screen and runs
+ ; the program
+
+(define (hanoi len)
+ (reset-towers len)
+ (clear)
+ (display-hanoi)
+ (_hanoi len 0 1 2)
+ #t
+ )