altos/scheme: Move ao-scheme to a separate repository
[fw/altos] / src / scheme / ao_scheme_builtin.c
diff --git a/src/scheme/ao_scheme_builtin.c b/src/scheme/ao_scheme_builtin.c
deleted file mode 100644 (file)
index 2b0c394..0000000
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*
- * 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.
- */
-
-#define _GNU_SOURCE
-#include "ao_scheme.h"
-#include <limits.h>
-#include <math.h>
-#include <stdarg.h>
-
-static int
-builtin_size(void *addr)
-{
-       (void) addr;
-       return sizeof (struct ao_scheme_builtin);
-}
-
-static void
-builtin_mark(void *addr)
-{
-       (void) addr;
-}
-
-static void
-builtin_move(void *addr)
-{
-       (void) addr;
-}
-
-const struct ao_scheme_type ao_scheme_builtin_type = {
-       .size = builtin_size,
-       .mark = builtin_mark,
-       .move = builtin_move
-};
-
-#ifdef AO_SCHEME_MAKE_CONST
-
-#define AO_SCHEME_BUILTIN_CASENAME
-#include "ao_scheme_builtin.h"
-
-char *ao_scheme_args_name(uint8_t args) {
-       args &= AO_SCHEME_FUNC_MASK;
-       switch (args) {
-       case AO_SCHEME_FUNC_LAMBDA: return ao_scheme_poly_atom(_ao_scheme_atom_lambda)->name;
-       case AO_SCHEME_FUNC_NLAMBDA: return ao_scheme_poly_atom(_ao_scheme_atom_nlambda)->name;
-       case AO_SCHEME_FUNC_MACRO: return ao_scheme_poly_atom(_ao_scheme_atom_macro)->name;
-       default: return (char *) "???";
-       }
-}
-#else
-
-#define AO_SCHEME_BUILTIN_ARRAYNAME
-#include "ao_scheme_builtin.h"
-
-static char *
-ao_scheme_builtin_name(enum ao_scheme_builtin_id b) {
-       if (b < _builtin_last)
-               return ao_scheme_poly_atom(builtin_names[b])->name;
-       return (char *) "???";
-}
-
-static const ao_poly ao_scheme_args_atoms[] = {
-       [AO_SCHEME_FUNC_LAMBDA] = _ao_scheme_atom_lambda,
-       [AO_SCHEME_FUNC_NLAMBDA] = _ao_scheme_atom_nlambda,
-       [AO_SCHEME_FUNC_MACRO] = _ao_scheme_atom_macro,
-};
-
-char *
-ao_scheme_args_name(uint8_t args)
-{
-       args &= AO_SCHEME_FUNC_MASK;
-       if (args < sizeof ao_scheme_args_atoms / sizeof ao_scheme_args_atoms[0])
-               return ao_scheme_poly_atom(ao_scheme_args_atoms[args])->name;
-       return (char *) "(unknown)";
-}
-#endif
-
-void
-ao_scheme_builtin_write(FILE *out, ao_poly b, bool write)
-{
-       struct ao_scheme_builtin *builtin = ao_scheme_poly_builtin(b);
-       (void) write;
-       fputs(ao_scheme_builtin_name(builtin->func), out);
-}
-
-static bool
-ao_scheme_typecheck(ao_poly actual, int formal_type) {
-       int     actual_type;
-
-       if ((formal_type & AO_SCHEME_ARG_MASK) == AO_SCHEME_POLY)
-               return true;
-
-       /* allow nil? */
-       if (actual == AO_SCHEME_NIL)
-               return (formal_type & AO_SCHEME_ARG_NIL_OK) != 0;
-
-       actual_type = ao_scheme_poly_type(actual);
-       formal_type &= AO_SCHEME_ARG_MASK;
-
-       if (actual_type == formal_type)
-               return true;
-       if (actual_type == AO_SCHEME_BUILTIN && formal_type == AO_SCHEME_LAMBDA)
-               return true;
-
-#ifdef AO_SCHEME_FEATURE_BIGINT
-       if (ao_scheme_integer_typep(actual_type) && formal_type == AO_SCHEME_INT)
-               return true;
-#endif
-#ifdef AO_SCHEME_FEATURE_FLOAT
-       if (ao_scheme_number_typep(actual_type) && formal_type == AO_SCHEME_FLOAT)
-               return true;
-#endif
-       return false;
-}
-
-int
-ao_scheme_parse_args(ao_poly name, struct ao_scheme_cons *cons, ...)
-{
-       va_list ap;
-       int formal;
-       int argc = 0;
-       ao_poly car;
-
-       va_start(ap, cons);
-       while ((formal = va_arg(ap, int)) != AO_SCHEME_ARG_END) {
-               if (formal & AO_SCHEME_ARG_OPTIONAL)
-                       car = (ao_poly) va_arg(ap, int);
-               if (cons) {
-                       car = cons->car;
-                       cons = ao_scheme_cons_cdr(cons);
-                       if (!ao_scheme_typecheck(car, formal)) {
-                               ao_scheme_error(AO_SCHEME_INVALID, "%v: arg %d invalid type %v", name, argc, car);
-                               return 0;
-                       }
-               } else if (!(formal & AO_SCHEME_ARG_OPTIONAL)) {
-                       goto bad_args;
-               }
-               if (formal & AO_SCHEME_ARG_RET_POLY)
-                       formal = AO_SCHEME_POLY;
-
-               switch (formal & AO_SCHEME_ARG_MASK) {
-               case AO_SCHEME_INT:
-#ifdef AO_SCHEME_FEATURE_BIGINT
-               case AO_SCHEME_BIGINT:
-#endif
-                       *(va_arg(ap, int32_t *)) = ao_scheme_poly_integer(car);
-                       break;
-#ifdef AO_SCHEME_FEATURE_FLOAT
-               case AO_SCHEME_FLOAT:
-                       *(va_arg(ap, float *)) = ao_scheme_poly_number(car);
-                       break;
-#endif
-               case AO_SCHEME_POLY:
-                       *(va_arg(ap, ao_poly *)) = car;
-                       break;
-               default:
-                       *(va_arg(ap, void **)) = ao_scheme_ref(car);
-                       break;
-               }
-               argc++;
-       }
-       if (cons) {
-       bad_args:
-               ao_scheme_error(AO_SCHEME_INVALID, "%v: invalid arg count", name);
-               return 0;
-       }
-       return 1;
-}
-
-ao_poly
-ao_scheme_arg(struct ao_scheme_cons *cons, int argc)
-{
-       for (;;) {
-               if (!cons)
-                       return AO_SCHEME_NIL;
-               if (argc == 0)
-                       return cons->car;
-               cons = ao_scheme_cons_cdr(cons);
-               argc--;
-       }
-}
-
-ao_poly
-ao_scheme_do_quote(struct ao_scheme_cons *cons)
-{
-       ao_poly val;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_quote, cons,
-                                 AO_SCHEME_POLY, &val,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       return val;
-}
-
-ao_poly
-ao_scheme_do_cond(struct ao_scheme_cons *cons)
-{
-       ao_scheme_set_cond(cons);
-       return AO_SCHEME_NIL;
-}
-
-ao_poly
-ao_scheme_do_begin(struct ao_scheme_cons *cons)
-{
-       ao_scheme_stack->state = eval_begin;
-       ao_scheme_stack->sexprs = ao_scheme_cons_poly(cons);
-       return AO_SCHEME_NIL;
-}
-
-ao_poly
-ao_scheme_do_while(struct ao_scheme_cons *cons)
-{
-       ao_scheme_stack->state = eval_while;
-       ao_scheme_stack->sexprs = ao_scheme_cons_poly(cons);
-       return AO_SCHEME_NIL;
-}
-
-static ao_poly
-ao_scheme_do_display_or_write(ao_poly proc, struct ao_scheme_cons *cons, bool write)
-{
-#ifndef AO_SCHEME_FEATURE_PORT
-       ao_poly val;
-       ao_poly port;
-
-       if (!ao_scheme_parse_args(proc, cons,
-                                 AO_SCHEME_POLY, &val,
-                                 AO_SCHEME_POLY | AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       ao_scheme_poly_write(stdout, val, write);
-#else
-       ao_poly                 val;
-       struct ao_scheme_port   *port;
-       FILE                    *file = stdout;
-
-       if (!ao_scheme_parse_args(proc, cons,
-                                 AO_SCHEME_POLY, &val,
-                                 AO_SCHEME_PORT | AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (port) {
-               file = port->file;
-               if (!file)
-                       return _ao_scheme_bool_true;
-       }
-       ao_scheme_poly_write(file, val, write);
-#endif
-       return _ao_scheme_bool_true;
-}
-
-ao_poly
-ao_scheme_do_write(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_do_display_or_write(_ao_scheme_atom_write, cons, true);
-}
-
-ao_poly
-ao_scheme_do_display(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_do_display_or_write(_ao_scheme_atom_display, cons, false);
-}
-
-static ao_poly
-ao_scheme_math(struct ao_scheme_cons *orig_cons, enum ao_scheme_builtin_id op)
-{
-       struct ao_scheme_cons *cons;
-       ao_poly ret = AO_SCHEME_NIL;
-
-       for (cons = orig_cons; cons; cons = ao_scheme_cons_cdr(cons)) {
-               ao_poly         car = cons->car;
-               uint8_t         rt = ao_scheme_poly_type(ret);
-               uint8_t         ct = ao_scheme_poly_type(car);
-
-               if (cons == orig_cons) {
-                       ret = car;
-                       ao_scheme_cons_stash(cons);
-                       if (cons->cdr == AO_SCHEME_NIL) {
-                               switch (op) {
-                               case builtin_minus:
-                                       if (ao_scheme_integer_typep(ct))
-                                               ret = ao_scheme_integer_poly(-ao_scheme_poly_integer(ret));
-#ifdef AO_SCHEME_FEATURE_FLOAT
-                                       else if (ct == AO_SCHEME_FLOAT)
-                                               ret = ao_scheme_float_get(-ao_scheme_poly_number(ret));
-#endif
-                                       break;
-                               case builtin_divide:
-                                       if (ao_scheme_poly_integer(ret) == 1) {
-                                       } else {
-#ifdef AO_SCHEME_FEATURE_FLOAT
-                                               if (ao_scheme_number_typep(ct)) {
-                                                       float   v = ao_scheme_poly_number(ret);
-                                                       ret = ao_scheme_float_get(1/v);
-                                               }
-#else
-                                               ret = ao_scheme_integer_poly(0);
-#endif
-                                       }
-                                       break;
-                               default:
-                                       break;
-                               }
-                       }
-                       cons = ao_scheme_cons_fetch();
-               } else if (ao_scheme_integer_typep(rt) && ao_scheme_integer_typep(ct)) {
-                       int32_t r = ao_scheme_poly_integer(ret);
-                       int32_t c = ao_scheme_poly_integer(car);
-#ifdef AO_SCHEME_FEATURE_FLOAT
-                       int64_t t;
-#endif
-
-                       switch(op) {
-                       case builtin_plus:
-                               r += c;
-                       check_overflow:
-#ifdef AO_SCHEME_FEATURE_FLOAT
-                               if (r < AO_SCHEME_MIN_BIGINT || AO_SCHEME_MAX_BIGINT < r)
-                                       goto inexact;
-#endif
-                               break;
-                       case builtin_minus:
-                               r -= c;
-                               goto check_overflow;
-                               break;
-                       case builtin_times:
-#ifdef AO_SCHEME_FEATURE_FLOAT
-                               t = (int64_t) r * (int64_t) c;
-                               if (t < AO_SCHEME_MIN_BIGINT || AO_SCHEME_MAX_BIGINT < t)
-                                       goto inexact;
-                               r = (int32_t) t;
-#else
-                               r = r * c;
-#endif
-                               break;
-                       case builtin_divide:
-#ifdef AO_SCHEME_FEATURE_FLOAT
-                               if (c != 0 && (r % c) == 0)
-                                       r /= c;
-                               else
-                                       goto inexact;
-#else
-                               r /= c;
-#endif
-                               break;
-                       case builtin_quotient:
-                               if (c == 0)
-                                       return ao_scheme_error(AO_SCHEME_DIVIDE_BY_ZERO, "quotient by zero");
-                               r = r / c;
-                               break;
-                       case builtin_floor_quotient:
-                               if (c == 0)
-                                       return ao_scheme_error(AO_SCHEME_DIVIDE_BY_ZERO, "floor-quotient by zero");
-                               if (r % c != 0 && (c < 0) != (r < 0))
-                                       r = r / c - 1;
-                               else
-                                       r = r / c;
-                               break;
-                       case builtin_remainder:
-                               if (c == 0)
-                                       return ao_scheme_error(AO_SCHEME_DIVIDE_BY_ZERO, "remainder by zero");
-                               r %= c;
-                               break;
-                       case builtin_modulo:
-                               if (c == 0)
-                                       return ao_scheme_error(AO_SCHEME_DIVIDE_BY_ZERO, "modulo by zero");
-                               r %= c;
-                               if ((r < 0) != (c < 0))
-                                       r += c;
-                               break;
-                       default:
-                               break;
-                       }
-                       ao_scheme_cons_stash(cons);
-                       ret = ao_scheme_integer_poly(r);
-                       cons = ao_scheme_cons_fetch();
-#ifdef AO_SCHEME_FEATURE_FLOAT
-               } else if (ao_scheme_number_typep(rt) && ao_scheme_number_typep(ct)) {
-                       float r, c;
-               inexact:
-                       r = ao_scheme_poly_number(ret);
-                       c = ao_scheme_poly_number(car);
-                       switch(op) {
-                       case builtin_plus:
-                               r += c;
-                               break;
-                       case builtin_minus:
-                               r -= c;
-                               break;
-                       case builtin_times:
-                               r *= c;
-                               break;
-                       case builtin_divide:
-                               r /= c;
-                               break;
-                       case builtin_quotient:
-                       case builtin_floor_quotient:
-                       case builtin_remainder:
-                       case builtin_modulo:
-                               return ao_scheme_error(AO_SCHEME_INVALID, "non-integer value in integer divide");
-                       default:
-                               break;
-                       }
-                       ao_scheme_cons_stash(cons);
-                       ret = ao_scheme_float_get(r);
-                       cons = ao_scheme_cons_fetch();
-#endif
-               }
-               else if (rt == AO_SCHEME_STRING && ct == AO_SCHEME_STRING && op == builtin_plus) {
-                       ao_scheme_cons_stash(cons);
-                       ret = ao_scheme_string_poly(ao_scheme_string_cat(ao_scheme_poly_string(ret),
-                                                                        ao_scheme_poly_string(car)));
-                       cons = ao_scheme_cons_fetch();
-                       if (!ret)
-                               return ret;
-               }
-               else
-                       return ao_scheme_error(AO_SCHEME_INVALID, "invalid args");
-       }
-       return ret;
-}
-
-ao_poly
-ao_scheme_do_plus(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_math(cons, builtin_plus);
-}
-
-ao_poly
-ao_scheme_do_minus(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_math(cons, builtin_minus);
-}
-
-ao_poly
-ao_scheme_do_times(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_math(cons, builtin_times);
-}
-
-ao_poly
-ao_scheme_do_divide(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_math(cons, builtin_divide);
-}
-
-ao_poly
-ao_scheme_do_quotient(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_math(cons, builtin_quotient);
-}
-
-ao_poly
-ao_scheme_do_floor_quotient(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_math(cons, builtin_floor_quotient);
-}
-
-ao_poly
-ao_scheme_do_modulo(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_math(cons, builtin_modulo);
-}
-
-ao_poly
-ao_scheme_do_remainder(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_math(cons, builtin_remainder);
-}
-
-static ao_poly
-ao_scheme_compare(struct ao_scheme_cons *cons, enum ao_scheme_builtin_id op)
-{
-       ao_poly left;
-
-       if (!cons)
-               return _ao_scheme_bool_true;
-
-       left = cons->car;
-       for (cons = ao_scheme_cons_cdr(cons); cons; cons = ao_scheme_cons_cdr(cons)) {
-               ao_poly right = cons->car;
-
-               if (op == builtin_equal && left == right) {
-                       ;
-               } else {
-                       uint8_t lt = ao_scheme_poly_type(left);
-                       uint8_t rt = ao_scheme_poly_type(right);
-                       if (ao_scheme_integer_typep(lt) && ao_scheme_integer_typep(rt)) {
-                               int32_t l = ao_scheme_poly_integer(left);
-                               int32_t r = ao_scheme_poly_integer(right);
-
-                               switch (op) {
-                               case builtin_less:
-                                       if (!(l < r))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_greater:
-                                       if (!(l > r))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_less_equal:
-                                       if (!(l <= r))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_greater_equal:
-                                       if (!(l >= r))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_equal:
-                                       if (!(l == r))
-                                               return _ao_scheme_bool_false;
-                               default:
-                                       break;
-                               }
-#ifdef AO_SCHEME_FEATURE_FLOAT
-                       } else if (ao_scheme_number_typep(lt) && ao_scheme_number_typep(rt)) {
-                               float l, r;
-
-                               l = ao_scheme_poly_number(left);
-                               r = ao_scheme_poly_number(right);
-
-                               switch (op) {
-                               case builtin_less:
-                                       if (!(l < r))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_greater:
-                                       if (!(l > r))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_less_equal:
-                                       if (!(l <= r))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_greater_equal:
-                                       if (!(l >= r))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_equal:
-                                       if (!(l == r))
-                                               return _ao_scheme_bool_false;
-                               default:
-                                       break;
-                               }
-#endif /* AO_SCHEME_FEATURE_FLOAT */
-                       } else if (lt == AO_SCHEME_STRING && rt == AO_SCHEME_STRING) {
-                               int c = strcmp(ao_scheme_poly_string(left)->val,
-                                              ao_scheme_poly_string(right)->val);
-                               switch (op) {
-                               case builtin_less:
-                                       if (!(c < 0))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_greater:
-                                       if (!(c > 0))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_less_equal:
-                                       if (!(c <= 0))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_greater_equal:
-                                       if (!(c >= 0))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               case builtin_equal:
-                                       if (!(c == 0))
-                                               return _ao_scheme_bool_false;
-                                       break;
-                               default:
-                                       break;
-                               }
-                       } else
-                               return _ao_scheme_bool_false;
-               }
-               left = right;
-       }
-       return _ao_scheme_bool_true;
-}
-
-ao_poly
-ao_scheme_do_equal(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_compare(cons, builtin_equal);
-}
-
-ao_poly
-ao_scheme_do_less(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_compare(cons, builtin_less);
-}
-
-ao_poly
-ao_scheme_do_greater(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_compare(cons, builtin_greater);
-}
-
-ao_poly
-ao_scheme_do_less_equal(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_compare(cons, builtin_less_equal);
-}
-
-ao_poly
-ao_scheme_do_greater_equal(struct ao_scheme_cons *cons)
-{
-       return ao_scheme_compare(cons, builtin_greater_equal);
-}
-
-ao_poly
-ao_scheme_do_flush_output(struct ao_scheme_cons *cons)
-{
-#ifndef AO_SCHEME_FEATURE_PORT
-       ao_poly port;
-       if (!ao_scheme_parse_args(_ao_scheme_atom_flush2doutput, cons,
-                                 AO_SCHEME_POLY|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       fflush(stdout);
-#else
-       struct ao_scheme_port   *port;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_flush2doutput, cons,
-                                 AO_SCHEME_PORT|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       fflush(stdout);
-       if (port) {
-               if (port->file)
-                       fflush(port->file);
-       } else
-               fflush(stdout);
-#endif
-       return _ao_scheme_bool_true;
-}
-
-#ifdef AO_SCHEME_FEATURE_GPIO
-
-ao_poly
-ao_scheme_do_led(struct ao_scheme_cons *cons)
-{
-       int32_t led;
-       if (!ao_scheme_parse_args(_ao_scheme_atom_led, cons,
-                                 AO_SCHEME_INT, &led,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       ao_scheme_os_led(led);
-       return _ao_scheme_bool_true;
-}
-
-#endif
-
-ao_poly
-ao_scheme_do_eval(struct ao_scheme_cons *cons)
-{
-       ao_poly expr;
-       ao_poly env;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_eval, cons,
-                                 AO_SCHEME_POLY, &expr,
-                                 AO_SCHEME_POLY|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &env,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       ao_scheme_stack->state = eval_sexpr;
-       ao_scheme_stack->frame = AO_SCHEME_NIL;
-       ao_scheme_frame_current = NULL;
-       return expr;
-}
-
-ao_poly
-ao_scheme_do_apply(struct ao_scheme_cons *cons)
-{
-       ao_scheme_stack->state = eval_apply;
-       return ao_scheme_cons_poly(cons);
-}
-
-ao_poly
-ao_scheme_do_read(struct ao_scheme_cons *cons)
-{
-       FILE    *file = stdin;
-#ifndef AO_SCHEME_FEATURE_PORT
-       ao_poly port;
-       if (!ao_scheme_parse_args(_ao_scheme_atom_read, cons,
-                                 AO_SCHEME_POLY|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-#else
-       struct ao_scheme_port   *port;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_read, cons,
-                                 AO_SCHEME_PORT|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (port) {
-               file = port->file;
-               if (!file)
-                       return _ao_scheme_atom_eof;
-       }
-#endif
-       return ao_scheme_read(file);
-}
-
-ao_poly
-ao_scheme_do_collect(struct ao_scheme_cons *cons)
-{
-       int     free;
-       (void) cons;
-       free = ao_scheme_collect(AO_SCHEME_COLLECT_FULL);
-       return ao_scheme_integer_poly(free);
-}
-
-ao_poly
-ao_scheme_do_nullp(struct ao_scheme_cons *cons)
-{
-       ao_poly val;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_not, cons,
-                                 AO_SCHEME_POLY, &val,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (val == AO_SCHEME_NIL)
-               return _ao_scheme_bool_true;
-       else
-               return _ao_scheme_bool_false;
-}
-
-ao_poly
-ao_scheme_do_not(struct ao_scheme_cons *cons)
-{
-       ao_poly val;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_not, cons,
-                                 AO_SCHEME_POLY, &val,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (val == _ao_scheme_bool_false)
-               return _ao_scheme_bool_true;
-       else
-               return _ao_scheme_bool_false;
-}
-
-ao_poly
-ao_scheme_do_typep(ao_poly proc, int type, struct ao_scheme_cons *cons)
-{
-       ao_poly val;
-
-       if (!ao_scheme_parse_args(proc, cons,
-                                 AO_SCHEME_POLY, &val,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (ao_scheme_poly_type(val) == type)
-               return _ao_scheme_bool_true;
-       return _ao_scheme_bool_false;
-}
-
-ao_poly
-ao_scheme_do_procedurep(struct ao_scheme_cons *cons)
-{
-       ao_poly val;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_pair3f, cons,
-                                 AO_SCHEME_POLY, &val,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       switch (ao_scheme_poly_type(val)) {
-       case AO_SCHEME_BUILTIN:
-       case AO_SCHEME_LAMBDA:
-               return _ao_scheme_bool_true;
-       default:
-               return _ao_scheme_bool_false;
-       }
-}
-
-ao_poly
-ao_scheme_do_read_char(struct ao_scheme_cons *cons)
-{
-       int     c;
-#ifndef AO_SCHEME_FEATURE_PORT
-       ao_poly port;
-       if (!ao_scheme_parse_args(_ao_scheme_atom_read2dchar, cons,
-                                 AO_SCHEME_POLY|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       c = getchar();
-#else
-       struct ao_scheme_port   *port;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_read2dchar, cons,
-                                 AO_SCHEME_PORT|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (port)
-               c = ao_scheme_port_getc(port);
-       else
-               c = getchar();
-#endif
-       if (c == EOF)
-               return _ao_scheme_atom_eof;
-       return ao_scheme_integer_poly(c);
-}
-
-ao_poly
-ao_scheme_do_write_char(struct ao_scheme_cons *cons)
-{
-       int32_t c;
-#ifndef AO_SCHEME_FEATURE_PORT
-       ao_poly port;
-       if (!ao_scheme_parse_args(_ao_scheme_atom_write2dchar, cons,
-                                 AO_SCHEME_INT, &c,
-                                 AO_SCHEME_POLY|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       putchar(c);
-#else
-       struct ao_scheme_port   *port;
-       if (!ao_scheme_parse_args(_ao_scheme_atom_write2dchar, cons,
-                                 AO_SCHEME_INT, &c,
-                                 AO_SCHEME_PORT|AO_SCHEME_ARG_OPTIONAL, AO_SCHEME_NIL, &port,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (port)
-               ao_scheme_port_putc(port, c);
-       else
-               putchar(c);
-#endif
-       return _ao_scheme_bool_true;
-}
-
-ao_poly
-ao_scheme_do_exit(struct ao_scheme_cons *cons)
-{
-       ao_poly val;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_exit, cons,
-                                 AO_SCHEME_POLY|AO_SCHEME_ARG_OPTIONAL, _ao_scheme_bool_true, &val,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       ao_scheme_exception |= AO_SCHEME_EXIT;
-       return val;
-}
-
-#ifdef AO_SCHEME_FEATURE_TIME
-
-ao_poly
-ao_scheme_do_current_jiffy(struct ao_scheme_cons *cons)
-{
-       if (!ao_scheme_parse_args(_ao_scheme_atom_current2djiffy, cons,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       return ao_scheme_integer_poly(ao_scheme_os_jiffy());
-}
-
-ao_poly
-ao_scheme_do_jiffies_per_second(struct ao_scheme_cons *cons)
-{
-       if (!ao_scheme_parse_args(_ao_scheme_atom_jiffies2dper2dsecond, cons,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       return ao_scheme_integer_poly(AO_SCHEME_JIFFIES_PER_SECOND);
-}
-
-ao_poly
-ao_scheme_do_delay(struct ao_scheme_cons *cons)
-{
-       int32_t delay;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_delay, cons,
-                                 AO_SCHEME_INT, &delay,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       ao_scheme_os_delay(delay);
-       return cons->car;
-}
-#endif
-
-#ifdef AO_SCHEME_FEATURE_POSIX
-
-#include <unistd.h>
-
-static char    **ao_scheme_argv;
-
-void
-ao_scheme_set_argv(char **argv)
-{
-       ao_scheme_argv = argv;
-}
-
-ao_poly
-ao_scheme_do_command_line(struct ao_scheme_cons *cons)
-{
-       ao_poly args = AO_SCHEME_NIL;
-       ao_poly arg;
-       int     i;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_command2dline, cons,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-
-       for (i = 0; ao_scheme_argv[i]; i++);
-
-       while (--i >= 0) {
-               ao_scheme_poly_stash(args);
-               arg = ao_scheme_string_poly(ao_scheme_string_new(ao_scheme_argv[i]));
-               args = ao_scheme_poly_fetch();
-               if (!arg)
-                       return AO_SCHEME_NIL;
-               args = ao_scheme_cons(arg, args);
-               if (!args)
-                       return AO_SCHEME_NIL;
-       }
-       return args;
-}
-
-ao_poly
-ao_scheme_do_get_environment_variables(struct ao_scheme_cons *cons)
-{
-       ao_poly envs = AO_SCHEME_NIL;
-       ao_poly env;
-       int     i;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_get2denvironment2dvariables, cons,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       for (i = 0; environ[i]; i++);
-
-       while (--i >= 0) {
-               ao_scheme_poly_stash(envs);
-               env = ao_scheme_string_poly(ao_scheme_string_new(environ[i]));
-               envs = ao_scheme_poly_fetch();
-               if (!env)
-                       return AO_SCHEME_NIL;
-               envs = ao_scheme_cons(env, envs);
-               if (!envs)
-                       return AO_SCHEME_NIL;
-       }
-       return envs;
-}
-
-ao_poly
-ao_scheme_do_get_environment_variable(struct ao_scheme_cons *cons)
-{
-       struct ao_scheme_string *name;
-       char                    *val;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_get2denvironment2dvariable, cons,
-                                 AO_SCHEME_STRING, &name,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       val = secure_getenv(name->val);
-       if (!val)
-               return _ao_scheme_bool_false;
-       return ao_scheme_string_poly(ao_scheme_string_new(val));
-}
-
-ao_poly
-ao_scheme_do_file_existsp(struct ao_scheme_cons *cons)
-{
-       struct ao_scheme_string *name;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_file2dexists3f, cons,
-                                 AO_SCHEME_STRING, &name,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (access(name->val, F_OK) == 0)
-               return _ao_scheme_bool_true;
-       return _ao_scheme_bool_false;
-}
-
-ao_poly
-ao_scheme_do_delete_file(struct ao_scheme_cons *cons)
-{
-       struct ao_scheme_string *name;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_delete2dfile, cons,
-                                 AO_SCHEME_STRING, &name,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       if (unlink(name->val) == 0)
-               return _ao_scheme_bool_true;
-       return _ao_scheme_bool_false;
-}
-
-ao_poly
-ao_scheme_do_current_second(struct ao_scheme_cons *cons)
-{
-       int32_t second;
-
-       if (!ao_scheme_parse_args(_ao_scheme_atom_current2dsecond, cons,
-                                 AO_SCHEME_ARG_END))
-               return AO_SCHEME_NIL;
-       second = (int32_t) time(NULL);
-       return ao_scheme_integer_poly(second);
-}
-
-#endif /* AO_SCHEME_FEATURE_POSIX */
-
-#define AO_SCHEME_BUILTIN_FUNCS
-#include "ao_scheme_builtin.h"