jets: first pass as (scow %da ...)

When trying to hook this up to +scot, I can reliably crash vere,
so there's still a bug here around memory.
This commit is contained in:
Elliot Glaysher 2020-05-01 14:10:47 -07:00
parent d61a54d52a
commit e097bdda58

View File

@ -5,6 +5,167 @@
#include <ctype.h> #include <ctype.h>
static
c3_y to_digit(u3_atom tig)
{
if (tig >= 10) {
return 87 + tig;
} else {
return '0' + tig;
}
}
// gives the characters for a four 'digit' small hex atom.
static
void
_x_co_four(u3_atom src, c3_y* a, c3_y* b, c3_y* c, c3_y* d)
{
*d = to_digit(src & 0xF);
src >>= 4;
*c = to_digit(src & 0xF);
src >>= 4;
*b = to_digit(src & 0xF);
src >>= 4;
*a = to_digit(src & 0xF);
}
// The parser always prints two digits on 0 in y-co.
static
void
_y_co_two(u3_atom src, c3_y* a, c3_y* b)
{
*b = to_digit(src % 10);
*a = to_digit(src / 10);
}
//
static
u3_noun
_add_year(u3_atom year, u3_noun out)
{
while (year > 0) {
out = u3nc(to_digit(year % 10), out);
year = year / 10;
}
return out;
}
static
u3_noun
_print_da(u3_atom cor, u3_atom raw_da)
{
u3_noun hok = u3j_cook("u3we_scow_print_da", u3k(cor), "yore");
u3_noun yod = u3n_slam_on(hok, u3k(raw_da));
u3_noun out = 0;
u3m_p("yod", yod);
u3_atom age, year, month, day, hour, min, sec, f;
if (c3n == u3r_mean(yod, 4, &age,
5, &year,
6, &month,
14, &day,
30, &hour,
62, &min,
126, &sec,
127, &f,
0)) {
return u3m_bail(c3__exit);
}
if (c3n == u3r_sing(f, 0)) {
u3_noun f_list = u3qb_flop(f);
for (u3_noun cur = f_list;
_(u3a_is_cell(cur));
cur = u3t(cur)) {
if (_(u3a_is_cat(u3h(cur)))) {
c3_y a, b, c, d;
_x_co_four(u3h(cur), &a, &b, &c, &d);
out = u3nq('.', a, b, u3nt(c, d, out));
} else {
// No way to deal with big atoms. fall back.
u3z(yod);
u3z(out);
u3z(f_list);
return u3_none;
}
}
u3z(f_list);
out = u3nc('.', out);
}
// if there isn't a hex list and the h/m/s are all 0, skip printing hours.
if (c3n == u3r_sing(f, 0) ||
c3n == u3r_sing(hour, 0) ||
c3n == u3r_sing(min, 0) ||
c3n == u3r_sing(sec, 0)) {
if (!_(u3a_is_cat(hour)) ||
!_(u3a_is_cat(min)) ||
!_(u3a_is_cat(sec))) {
// Input is weird, fallback to nock.
u3z(yod);
u3z(out);
return u3_none;
}
c3_y sa, sb, ma, mb, ha, hb;
_y_co_two(sec, &sa, &sb);
out = u3nq('.', sa, sb, out);
_y_co_two(min, &ma, &mb);
out = u3nq('.', ma, mb, out);
_y_co_two(hour, &ha, &hb);
out = u3nq('.', ha, hb, out);
out = u3nc('.', out);
}
// We always print the Y.M.D. Unlike others, these numbers are unconstrained
// by length, but in practice, the month number and day number can only be up
// to two digits because of +yore. We still need to remove 0 prefixes,
// though.
if (!_(u3a_is_cat(day)) || day > 99 ||
!_(u3a_is_cat(month)) || month > 99 ||
!_(u3a_is_cat(year))) {
// Input is weird, fallback to nock.
u3z(yod);
u3z(out);
return u3_none;
}
c3_y da, db;
_y_co_two(day, &da, &db);
out = u3nc(db, out);
if (da != '0')
out = u3nc(da, out);
out = u3nc('.', out);
c3_y ma, mb;
_y_co_two(month, &ma, &mb);
out = u3nc(mb, out);
if (ma != '0')
out = u3nc(ma, out);
out = u3nc('.', out);
// suffix the year with a '-' for BC dates
if (age == c3n) {
out = u3nc('-', out);
}
// The year part is the only place where we have to explicitly loop over the
// input because it can be arbitrarily large or small.
out = _add_year(year, out);
out = u3nc('~', out);
u3z(yod);
return out;
}
static static
u3_noun u3_noun
_print_p(u3_atom p) _print_p(u3_atom p)
@ -83,12 +244,13 @@ u3we_scow(u3_noun cor)
if (c3n == u3r_mean(cor, u3x_sam_2, &mod, if (c3n == u3r_mean(cor, u3x_sam_2, &mod,
u3x_sam_3, &atom, 0) || u3x_sam_3, &atom, 0) ||
!_(u3a_is_cat(mod))) { !_(u3a_is_cat(mod))) {
u3l_log("u3we_scow fail\r\n");
return u3m_bail(c3__fail); return u3m_bail(c3__fail);
} }
switch (mod) { switch (mod) {
/* case c3__da: */ case c3__da:
/* return _parse_da(cor, txt); */ return _print_da(cor, atom);
case 'p': case 'p':
return _print_p(atom); return _print_p(atom);
@ -115,10 +277,21 @@ u3we_scot(u3_noun cor)
if (c3n == u3r_mean(cor, u3x_sam_2, &mod, if (c3n == u3r_mean(cor, u3x_sam_2, &mod,
u3x_sam_3, &atom, 0) || u3x_sam_3, &atom, 0) ||
!_(u3a_is_cat(mod))) { !_(u3a_is_cat(mod))) {
u3l_log("u3we_scot fail\r\n");
return u3m_bail(c3__fail); return u3m_bail(c3__fail);
} }
switch (mod) { switch (mod) {
// TODO: This causes a bail fail. why?
/* case c3__da: { */
/* u3_noun x = _print_da(cor, atom); */
/* if (x == u3_none) { */
/* return x; */
/* } */
/* return u3qc_rap(3, x); */
/* } */
case 'p': case 'p':
return u3qc_rap(3, _print_p(atom)); return u3qc_rap(3, _print_p(atom));