+++ /dev/null
-/*
- * 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"