hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit da7d90f25d12fa4447770d9541d9072866469a34
parent 81a06f9bb51481b711cab50d462aa9541200a6ab
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 13 Apr 2022 14:01:32 +0200

datetime: rename mock => builder

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mdatetime/datetime.ha | 44+++++++++++++++++++++-----------------------
Mdatetime/parse.ha | 54+++++++++++++++++++++++++++---------------------------
2 files changed, 48 insertions(+), 50 deletions(-)

diff --git a/datetime/datetime.ha b/datetime/datetime.ha @@ -103,7 +103,7 @@ export fn new( // TODO: improve variety of errors. // `invaliddatetime = !void` ? -// `invaliddatetime = !datetime::mock` ? +// `invaliddatetime = !datetime::builder` ? ) (datetime | invalid) = { let defaults: [_]int = [ 0, 1, 1, // year month day @@ -205,10 +205,9 @@ export fn to_instant(dt: datetime) time::instant = { // Creates a [[datetime]] from a string, parsed according to a layout, // using [[strategy::ALL]], or fails otherwise. -// -// TODO: allow the user to specify [[strategy]] for security? export fn from_str(layout: str, s: str) (datetime | insufficient | invalid) = { - const b = newmock(); + // XXX: Should we allow the user to specify [[strategy]] for security? + const b = newbuilder(); parse(&b, layout, s)?; return finish(&b)?; }; @@ -223,28 +222,27 @@ export fn to_moment(dt: datetime) chrono::moment = { }; }; -// A [[mock]] has insufficient information and cannot create a valid datetime. +// A [[builder]] has insufficient information and cannot create a valid datetime. export type insufficient = !void; -// Constructs a new datetime. Start with [[newmock]]. Collect enough datetime -// information incrementally by direct field assignments or multiple calls to -// [[parse]]. Finish with [[finish]]. -// -// let mock = datetime::newmock(); -// datetime::parse(&mock, "Year: %Y", "Year: 2038"); -// datetime::parse(&mock, "Month: %m", "Month: 01"); -// mock.day = 19; -// let dt = datetime::finish(&mock, datetime::strategy::YMD); +// Constructs a new datetime. Start with [[newbuilder]], then collect enough +// datetime information incrementally by direct field assignments and/or one or +// more calls to [[parse]]. Finish with [[finish]]. // -export type mock = datetime; - -// Creates a new [[mock]] -export fn newmock() mock = init(): mock; - -// Returns a datetime from a mock. The provided [[strategy]]s will be tried in -// order until a valid datetime is produced, or fail otherwise. The default +// let builder = datetime::newbuilder(); +// datetime::parse(&builder, "Year: %Y", "Year: 2038"); +// datetime::parse(&builder, "Month: %m", "Month: 01"); +// builder.day = 19; +// let dt = datetime::finish(&builder, datetime::strategy::YMD); +export type builder = datetime; + +// Creates a new [[builder]] +export fn newbuilder() builder = init(): builder; + +// Returns a datetime from a builder. The provided [[strategy]]s will be tried +// in order until a valid datetime is produced, or fail otherwise. The default // strategy is [[strategy::ALL]]. -export fn finish(f: *mock, m: strategy...) (datetime | insufficient | invalid) = { +export fn finish(f: *builder, m: strategy...) (datetime | insufficient | invalid) = { if (len(m) == 0) { m = [strategy::ALL]; }; @@ -297,7 +295,7 @@ export fn finish(f: *mock, m: strategy...) (datetime | insufficient | invalid) = return insufficient; }; -// Specifies which [[mock]] fields (and what strategy) to use to calculate the +// Specifies which [[builder]] fields (and what strategy) to use to calculate the // epochal, and thus a valid datetime. export type strategy = enum uint { // year, month, day diff --git a/datetime/parse.ha b/datetime/parse.ha @@ -1,14 +1,14 @@ use errors; use strings; -// Parses a datetime string into a [[mock]], using a "layout" format string +// Parses a datetime string into a [[builder]], using a "layout" format string // with a subset of specifiers from POSIX strptime(3). Partial, incremental // parsing is possible. // -// datetime::parse(&mok, "%Y-%m-%d", "2038-01-19"); -// datetime::parse(&mok, "%H:%M:%S", "03:14:07"); +// datetime::parse(&builder, "%Y-%m-%d", "2038-01-19"); +// datetime::parse(&builder, "%H:%M:%S", "03:14:07"); // -export fn parse(mok: *mock, layout: str, s: str) (void | invalid) = { +export fn parse(build: *builder, layout: str, s: str) (void | invalid) = { const format_iter = strings::iter(layout); const s_iter = strings::iter(s); let escaped = false; @@ -42,29 +42,29 @@ export fn parse(mok: *mock, layout: str, s: str) (void | invalid) = { switch (format_r) { // Basic specifiers case 'a' => - mok.weekday = get_default_locale_string_index( + build.weekday = get_default_locale_string_index( &s_iter, WEEKDAYS_SHORT[..])?; case 'A' => - mok.weekday = get_default_locale_string_index( + build.weekday = get_default_locale_string_index( &s_iter, WEEKDAYS[..])?; case 'b' => - mok.month = get_default_locale_string_index( + build.month = get_default_locale_string_index( &s_iter, MONTHS_SHORT[..])?; case 'B' => - mok.month = get_default_locale_string_index( + build.month = get_default_locale_string_index( &s_iter, MONTHS[..])?; case 'd' => let max_n_digits = 2u; - mok.day = clamp_int( + build.day = clamp_int( get_max_n_digits(&s_iter, max_n_digits)?, 1, 31); case 'H' => let max_n_digits = 2u; - mok.hour = clamp_int( + build.hour = clamp_int( get_max_n_digits(&s_iter, max_n_digits)?, 0, 23); case 'I' => let max_n_digits = 2u; const hour = get_max_n_digits(&s_iter, max_n_digits); - mok.hour = match (hour) { + build.hour = match (hour) { case let hour: int => yield if (hour > 12) { yield clamp_int(hour - 12, 1, 12); @@ -75,38 +75,38 @@ export fn parse(mok: *mock, layout: str, s: str) (void | invalid) = { return invalid; }; case 'j' => - mok.yearday = clamp_int( + build.yearday = clamp_int( get_max_n_digits(&s_iter, 3)?, 1, 366); case 'm' => - mok.month = clamp_int( + build.month = clamp_int( get_max_n_digits(&s_iter, 2)?, 1, 12); case 'M' => - mok.min = clamp_int( + build.min = clamp_int( get_max_n_digits(&s_iter, 2)?, 0, 59); case 'N' => - mok.nsec = clamp_int( + build.nsec = clamp_int( get_max_n_digits(&s_iter, 3)?, 0, 999); case 'p' => - if (mok.hour is void) { + if (build.hour is void) { // We can't change the hour's am/pm because we // have no hour. return invalid; }; const rest = strings::iterstr(&s_iter); if (strings::hasprefix(rest, "AM")) { - if (mok.hour as int > 12) { + if (build.hour as int > 12) { // 13 AM? return invalid; - } else if (mok.hour as int == 12) { - mok.hour = 0; + } else if (build.hour as int == 12) { + build.hour = 0; }; } else if (strings::hasprefix(rest, "PM")) { - if (mok.hour as int > 12) { + if (build.hour as int > 12) { // 13 PM? return invalid; - } else if (mok.hour as int < 12) { - mok.hour = - (mok.hour as int) + 12; + } else if (build.hour as int < 12) { + build.hour = + (build.hour as int) + 12; }; } else { return invalid; @@ -114,10 +114,10 @@ export fn parse(mok: *mock, layout: str, s: str) (void | invalid) = { strings::next(&s_iter); strings::next(&s_iter); case 'S' => - mok.sec = clamp_int( + build.sec = clamp_int( get_max_n_digits(&s_iter, 2)?, 0, 61); case 'u', 'w' => - mok.weekday = match (get_max_n_digits(&s_iter, 1)) { + build.weekday = match (get_max_n_digits(&s_iter, 1)) { case let i: int => yield if (format_r == 'w') { yield if (i == 0) { @@ -132,10 +132,10 @@ export fn parse(mok: *mock, layout: str, s: str) (void | invalid) = { return invalid; }; case 'U', 'W' => - mok.week = clamp_int( + build.week = clamp_int( get_max_n_digits(&s_iter, 2)?, 0, 53); case 'Y' => - mok.year = get_max_n_digits(&s_iter, 4)?; + build.year = get_max_n_digits(&s_iter, 4)?; case 'z' => // TODO continue;