X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fscheme%2Fao_scheme_builtin.c;fp=src%2Fscheme%2Fao_scheme_builtin.c;h=0000000000000000000000000000000000000000;hp=2b0c394bfc4da127389f135761c4af245522e319;hb=f26cc1a677f577da533425a15485fcaa24626b23;hpb=4b52fc6eea9a478cb3dd42dcd32c92838df39734 diff --git a/src/scheme/ao_scheme_builtin.c b/src/scheme/ao_scheme_builtin.c deleted file mode 100644 index 2b0c394b..00000000 --- a/src/scheme/ao_scheme_builtin.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * Copyright © 2016 Keith Packard - * - * 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 -#include -#include - -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 - -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"