ao_poly car = ao_lisp_arg(cons, argc);
if ((!car && !nil_ok) || ao_lisp_poly_type(car) != type)
- return ao_lisp_error(AO_LISP_INVALID, "%s: invalid type for arg %d", ao_lisp_poly_atom(name)->name, argc);
+ return ao_lisp_error(AO_LISP_INVALID, "%s: arg %d invalid type %v", ao_lisp_poly_atom(name)->name, argc, car);
return _ao_lisp_bool_true;
}
return ao_lisp_atom_set(ao_lisp_arg(cons, 0), ao_lisp_arg(cons, 1));
}
+ao_poly
+ao_lisp_do_def(struct ao_lisp_cons *cons)
+{
+ if (!ao_lisp_check_argc(_ao_lisp_atom_def, cons, 2, 2))
+ return AO_LISP_NIL;
+ if (!ao_lisp_check_argt(_ao_lisp_atom_def, cons, 0, AO_LISP_ATOM, 0))
+ return AO_LISP_NIL;
+
+ return ao_lisp_atom_def(ao_lisp_arg(cons, 0), ao_lisp_arg(cons, 1));
+}
+
ao_poly
ao_lisp_do_setq(struct ao_lisp_cons *cons)
{
return AO_LISP_NIL;
name = cons->car;
if (ao_lisp_poly_type(name) != AO_LISP_ATOM)
- return ao_lisp_error(AO_LISP_INVALID, "set! of non-atom");
- if (!ao_lisp_atom_ref(ao_lisp_frame_current, name))
- return ao_lisp_error(AO_LISP_INVALID, "atom not defined");
+ return ao_lisp_error(AO_LISP_INVALID, "set! of non-atom %v", name);
+ if (!ao_lisp_atom_ref(name))
+ return ao_lisp_error(AO_LISP_INVALID, "atom %v not defined", name);
return ao_lisp__cons(_ao_lisp_atom_set,
ao_lisp__cons(ao_lisp__cons(_ao_lisp_atom_quote,
ao_lisp__cons(name, AO_LISP_NIL)),
}
ao_poly
-ao_lisp_do_progn(struct ao_lisp_cons *cons)
+ao_lisp_do_begin(struct ao_lisp_cons *cons)
{
- ao_lisp_stack->state = eval_progn;
+ ao_lisp_stack->state = eval_begin;
ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons);
return AO_LISP_NIL;
}
} else if (ao_lisp_integer_typep(rt) && ao_lisp_integer_typep(ct)) {
int32_t r = ao_lisp_poly_integer(ret);
int32_t c = ao_lisp_poly_integer(car);
+ int64_t t;
switch(op) {
case builtin_plus:
r += c;
+ check_overflow:
+ if (r < AO_LISP_MIN_BIGINT || AO_LISP_MAX_BIGINT < r)
+ goto inexact;
break;
case builtin_minus:
r -= c;
+ goto check_overflow;
break;
case builtin_times:
- r *= c;
+ t = (int64_t) r * (int64_t) c;
+ if (t < AO_LISP_MIN_BIGINT || AO_LISP_MAX_BIGINT < t)
+ goto inexact;
+ r = (int32_t) t;
break;
case builtin_divide:
if (c != 0 && (r % c) == 0)
r /= c;
- else {
- ret = ao_lisp_float_get((float) r / (float) c);
- continue;
- }
+ else
+ goto inexact;
break;
case builtin_quotient:
if (c == 0)
}
ret = ao_lisp_integer_poly(r);
} else if (ao_lisp_number_typep(rt) && ao_lisp_number_typep(ct)) {
- float r = ao_lisp_poly_number(ret);
- float c = ao_lisp_poly_number(car);
+ float r, c;
+ inexact:
+ r = ao_lisp_poly_number(ret);
+ c = ao_lisp_poly_number(car);
switch(op) {
case builtin_plus:
r += c;
case builtin_divide:
r /= c;
break;
-#if 0
case builtin_quotient:
- if (c == 0)
- return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "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_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "remainder by zero");
- r %= c;
- break;
case builtin_modulo:
- if (c == 0)
- return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "modulo by zero");
- r %= c;
- if ((r < 0) != (c < 0))
- r += c;
- break;
-#endif
+ return ao_lisp_error(AO_LISP_INVALID, "non-integer value in integer divide");
default:
break;
}
ao_poly
ao_lisp_do_pairp(struct ao_lisp_cons *cons)
{
- return ao_lisp_do_typep(AO_LISP_CONS, cons);
+ ao_poly v;
+ if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
+ return AO_LISP_NIL;
+ v = ao_lisp_arg(cons, 0);
+ if (v != AO_LISP_NIL && ao_lisp_poly_type(v) == AO_LISP_CONS)
+ return _ao_lisp_bool_true;
+ return _ao_lisp_bool_false;
}
ao_poly