aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c1
-rw-r--r--src/ast.h4
-rw-r--r--src/compile.c39
-rw-r--r--src/environment.c41
-rw-r--r--src/parse.c55
-rw-r--r--src/stdlib/datatypes.h3
-rw-r--r--src/stdlib/integers.c16
-rw-r--r--src/stdlib/integers.h2
-rw-r--r--src/stdlib/moments.c323
-rw-r--r--src/stdlib/moments.h44
-rw-r--r--src/stdlib/optionals.c1
-rw-r--r--src/stdlib/optionals.h1
-rw-r--r--src/stdlib/paths.c18
-rw-r--r--src/stdlib/paths.h6
-rw-r--r--src/stdlib/tomo.h1
-rw-r--r--src/typecheck.c3
-rw-r--r--src/types.c8
-rw-r--r--src/types.h3
18 files changed, 38 insertions, 531 deletions
diff --git a/src/ast.c b/src/ast.c
index d04fa437..00f03a6d 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -163,7 +163,6 @@ CORD ast_to_xml(ast_t *ast)
T(FieldAccess, "<FieldAccess field=\"%s\">%r</FieldAccess>", data.field, ast_to_xml(data.fielded))
T(Optional, "<Optional>%r</Optional>", ast_to_xml(data.value))
T(NonOptional, "<NonOptional>%r</NonOptional>", ast_to_xml(data.value))
- T(Moment, "<Moment/>")
T(DocTest, "<DocTest>%r%r</DocTest>", optional_tagged("expression", data.expr), optional_tagged("expected", data.expected))
T(Use, "<Use>%r%r</Use>", optional_tagged("var", data.var), xml_escape(data.path))
T(InlineCCode, "<InlineCode>%r</InlineCode>", xml_escape(data.code))
diff --git a/src/ast.h b/src/ast.h
index aa218334..2260436f 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -140,7 +140,6 @@ typedef enum {
Extern,
StructDef, EnumDef, LangDef,
Index, FieldAccess, Optional, NonOptional,
- Moment,
DocTest,
Use,
InlineCCode,
@@ -319,9 +318,6 @@ struct ast_s {
ast_t *value;
} Optional, NonOptional;
struct {
- Moment_t moment;
- } Moment;
- struct {
ast_t *expr, *expected;
bool skip_source:1;
} DocTest;
diff --git a/src/compile.c b/src/compile.c
index 18a1e9a1..9073de5e 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -39,18 +39,18 @@ static CORD compile_string_literal(CORD literal);
CORD promote_to_optional(type_t *t, CORD code)
{
- if (t == THREAD_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE || t == MATCH_TYPE || t->tag == MomentType) {
+ if (t == THREAD_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE || t == MATCH_TYPE) {
return code;
} else if (t->tag == IntType) {
switch (Match(t, IntType)->bits) {
- case TYPE_IBITS8: return CORD_all("((OptionalInt8_t){", code, "})");
- case TYPE_IBITS16: return CORD_all("((OptionalInt16_t){", code, "})");
- case TYPE_IBITS32: return CORD_all("((OptionalInt32_t){", code, "})");
- case TYPE_IBITS64: return CORD_all("((OptionalInt64_t){", code, "})");
+ case TYPE_IBITS8: return CORD_all("((OptionalInt8_t){.value=", code, "})");
+ case TYPE_IBITS16: return CORD_all("((OptionalInt16_t){.value=", code, "})");
+ case TYPE_IBITS32: return CORD_all("((OptionalInt32_t){.value=", code, "})");
+ case TYPE_IBITS64: return CORD_all("((OptionalInt64_t){.value=", code, "})");
default: errx(1, "Unsupported in type: ", type_to_str(t));
}
} else if (t->tag == ByteType) {
- return CORD_all("((OptionalByte_t){", code, "})");
+ return CORD_all("((OptionalByte_t){.value=", code, "})");
} else if (t->tag == StructType) {
return CORD_all("({ ", compile_type(Type(OptionalType, .type=t)), " nonnull = {.value=", code, "}; nonnull.is_none = false; nonnull; })");
} else {
@@ -516,7 +516,6 @@ CORD compile_type(type_t *t)
case BoolType: return "Bool_t";
case ByteType: return "Byte_t";
case CStringType: return "const char*";
- case MomentType: return "Moment_t";
case BigIntType: return "Int_t";
case IntType: return CORD_asprintf("Int%ld_t", Match(t, IntType)->bits);
case NumType: return Match(t, NumType)->bits == TYPE_NBITS64 ? "Num_t" : CORD_asprintf("Num%ld_t", Match(t, NumType)->bits);
@@ -563,7 +562,7 @@ CORD compile_type(type_t *t)
case TextType:
return Match(nonnull, TextType)->lang ? compile_type(nonnull) : "OptionalText_t";
case IntType: case BigIntType: case NumType: case BoolType: case ByteType:
- case ArrayType: case TableType: case SetType: case MomentType:
+ case ArrayType: case TableType: case SetType:
return CORD_all("Optional", compile_type(nonnull));
case StructType: {
if (nonnull == THREAD_TYPE)
@@ -688,7 +687,7 @@ CORD optional_into_nonnone(type_t *t, CORD value)
if (t->tag == OptionalType) t = Match(t, OptionalType)->type;
switch (t->tag) {
case IntType:
- return CORD_all(value, ".i");
+ return CORD_all(value, ".value");
case StructType:
if (t == THREAD_TYPE || t == MATCH_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE)
return value;
@@ -730,8 +729,6 @@ CORD check_none(type_t *t, CORD value)
return CORD_all("(", value, ").is_none");
else if (t->tag == EnumType)
return CORD_all("({(", value, ").$tag == 0;})");
- else if (t->tag == MomentType)
- return CORD_all("({(", value, ").tv_usec < 0;})");
else if (t->tag == MutexedType)
return CORD_all("({", value, " == NULL;})");
print_err("Optional check not implemented for: ", type_to_str(t));
@@ -1803,7 +1800,6 @@ CORD expr_as_text(CORD expr, type_t *t, CORD color)
// NOTE: this cannot use stack(), since bools may actually be bit fields:
return CORD_asprintf("Bool$as_text((Bool_t[1]){%r}, %r, &Bool$info)", expr, color);
case CStringType: return CORD_asprintf("CString$as_text(stack(%r), %r, &CString$info)", expr, color);
- case MomentType: return CORD_asprintf("Moment$as_text(stack(%r), %r, &Moment$info)", expr, color);
case BigIntType: case IntType: case ByteType: case NumType: {
CORD name = type_to_cord(t);
return CORD_asprintf("%r$as_text(stack(%r), %r, &%r$info)", name, expr, color, name);
@@ -2227,7 +2223,6 @@ CORD compile_none(type_t *t)
case SetType: return "NONE_TABLE";
case TextType: return "NONE_TEXT";
case CStringType: return "NULL";
- case MomentType: return "NONE_MOMENT";
case PointerType: return CORD_all("((", compile_type(t), ")NULL)");
case ClosureType: return "NONE_CLOSURE";
case NumType: return "nan(\"null\")";
@@ -2268,10 +2263,6 @@ CORD compile(env_t *env, ast_t *ast)
return compile_none(t);
}
case Bool: return Match(ast, Bool)->b ? "yes" : "no";
- case Moment: {
- auto moment = Match(ast, Moment)->moment;
- return CORD_asprintf("((Moment_t){.tv_sec=%ld, .tv_usec=%ld})", moment.tv_sec, moment.tv_usec);
- }
case Var: {
binding_t *b = get_binding(env, Match(ast, Var)->name);
if (b)
@@ -3748,14 +3739,6 @@ CORD compile(env_t *env, ast_t *ast)
env_t *module_env = Table$str_get(*env->imports, name);
return compile(module_env, WrapAST(ast, Var, f->field));
}
- case MomentType: {
- if (streq(f->field, "seconds")) {
- return CORD_all("I64((", compile_to_pointer_depth(env, f->fielded, 0, false), ").tv_sec)");
- } else if (streq(f->field, "microseconds")) {
- return CORD_all("I64((", compile_to_pointer_depth(env, f->fielded, 0, false), ").tv_usec)");
- }
- code_err(ast, "There is no '", f->field, "' field on Moments");
- }
default:
code_err(ast, "Field accesses are not supported on ", type_to_str(fielded_t), " values");
}
@@ -3853,7 +3836,7 @@ CORD compile_type_info(type_t *t)
else if (t == PATH_TYPE_TYPE) return "&PathType$info";
switch (t->tag) {
- case BoolType: case ByteType: case IntType: case BigIntType: case NumType: case CStringType: case MomentType:
+ case BoolType: case ByteType: case IntType: case BigIntType: case NumType: case CStringType:
return CORD_all("&", type_to_cord(t), "$info");
case TextType: {
auto text = Match(t, TextType);
@@ -4134,8 +4117,8 @@ CORD compile_function(env_t *env, CORD name_code, ast_t *ast, CORD *staticdefs)
assert(args);
OptionalInt64_t cache_size = Int64$parse(Text$from_str(Match(cache, Int)->str));
CORD pop_code = CORD_EMPTY;
- if (cache->tag == Int && !cache_size.is_none && cache_size.i > 0) {
- pop_code = CORD_all("if (cache.entries.length > ", CORD_asprintf("%ld", cache_size.i),
+ if (cache->tag == Int && !cache_size.is_none && cache_size.value > 0) {
+ pop_code = CORD_all("if (cache.entries.length > ", CORD_asprintf("%ld", cache_size.value),
") Table$remove(&cache, cache.entries.data + cache.entries.stride*RNG$int64(default_rng, 0, cache.entries.length-1), table_type);\n");
}
diff --git a/src/environment.c b/src/environment.c
index 97672f2d..77f91f10 100644
--- a/src/environment.c
+++ b/src/environment.c
@@ -288,41 +288,13 @@ env_t *global_env(void)
{"escape_int", "Int$value_as_text", "func(i:Int -> Pattern)"},
{"escape_text", "Pattern$escape_text", "func(text:Text -> Pattern)"},
)},
- {"Moment", Type(MomentType), "Moment_t", "Moment", TypedArray(ns_entry_t,
- // Used as a default for functions below:
- {"now", "Moment$now", "func(->Moment)"},
-
- {"after", "Moment$after", "func(moment:Moment,seconds,minutes,hours=0.0,days,weeks,months,years=0,timezone=none:Text -> Moment)"},
- {"date", "Moment$date", "func(moment:Moment,timezone=none:Text -> Text)"},
- {"day_of_month", "Moment$day_of_month", "func(moment:Moment,timezone=none:Text -> Int)"},
- {"day_of_week", "Moment$day_of_week", "func(moment:Moment,timezone=none:Text -> Int)"},
- {"day_of_year", "Moment$day_of_year", "func(moment:Moment,timezone=none:Text -> Int)"},
- {"format", "Moment$format", "func(moment:Moment,format=\"%Y-%m-%dT%H:%M:%S%z\",timezone=none:Text -> Text)"},
- {"from_unix_timestamp", "Moment$from_unix_timestamp", "func(timestamp:Int64 -> Moment)"},
- {"get_local_timezone", "Moment$get_local_timezone", "func(->Text)"},
- {"hour", "Moment$hour", "func(moment:Moment,timezone=none:Text -> Int)"},
- {"hours_till", "Moment$hours_till", "func(now,then:Moment -> Num)"},
- {"minute", "Moment$minute", "func(moment:Moment,timezone=none:Text -> Int)"},
- {"minutes_till", "Moment$minutes_till", "func(now,then:Moment -> Num)"},
- {"month", "Moment$month", "func(moment:Moment,timezone=none:Text -> Int)"},
- {"microsecond", "Moment$microsecond", "func(moment:Moment,timezone=none:Text -> Int)"},
- {"new", "Moment$new", "func(year,month,day:Int,hour,minute=0,second=0.0,timezone=none:Text -> Moment)"},
- {"parse", "Moment$parse", "func(text:Text, format=\"%Y-%m-%dT%H:%M:%S%z\" -> Moment?)"},
- {"relative", "Moment$relative", "func(moment:Moment,relative_to=Moment.now(),timezone=none:Text -> Text)"},
- {"second", "Moment$second", "func(moment:Moment,timezone=none:Text -> Int)"},
- {"seconds_till", "Moment$seconds_till", "func(now:Moment,then:Moment -> Num)"},
- {"set_local_timezone", "Moment$set_local_timezone", "func(timezone=none:Text)"},
- {"time", "Moment$time", "func(moment:Moment,seconds=no,am_pm=yes,timezone=none:Text -> Text)"},
- {"unix_timestamp", "Moment$unix_timestamp", "func(moment:Moment -> Int64)"},
- {"year", "Moment$year", "func(moment:Moment,timezone=none:Text -> Int)"},
- )},
{"PathType", PATH_TYPE_TYPE, "PathType_t", "PathType$info", TypedArray(ns_entry_t,
{"Relative", "((PathType_t){.$tag=PATH_RELATIVE})", "PathType"},
{"Absolute", "((PathType_t){.$tag=PATH_ABSOLUTE})", "PathType"},
{"Home", "((PathType_t){.$tag=PATH_HOME})", "PathType"},
)},
{"Path", PATH_TYPE, "Path_t", "Path$info", TypedArray(ns_entry_t,
- {"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes -> Moment?)"},
+ {"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes -> Int64?)"},
{"append", "Path$append", "func(path:Path, text:Text, permissions=Int32(0o644))"},
{"append_bytes", "Path$append_bytes", "func(path:Path, bytes:[Byte], permissions=Int32(0o644))"},
{"base_name", "Path$base_name", "func(path:Path -> Text)"},
@@ -330,7 +302,7 @@ env_t *global_env(void)
{"can_execute", "Path$can_execute", "func(path:Path -> Bool)"},
{"can_read", "Path$can_read", "func(path:Path -> Bool)"},
{"can_write", "Path$can_write", "func(path:Path -> Bool)"},
- {"changed", "Path$changed", "func(path:Path, follow_symlinks=yes -> Moment?)"},
+ {"changed", "Path$changed", "func(path:Path, follow_symlinks=yes -> Int64?)"},
{"child", "Path$with_component", "func(path:Path, child:Text -> Path)"},
{"children", "Path$children", "func(path:Path, include_hidden=no -> [Path])"},
{"concatenated_with", "Path$concat", "func(a,b:Path -> Path)"},
@@ -347,7 +319,7 @@ env_t *global_env(void)
{"is_pipe", "Path$is_pipe", "func(path:Path, follow_symlinks=yes -> Bool)"},
{"is_socket", "Path$is_socket", "func(path:Path, follow_symlinks=yes -> Bool)"},
{"is_symlink", "Path$is_symlink", "func(path:Path -> Bool)"},
- {"modified", "Path$modified", "func(path:Path, follow_symlinks=yes -> Moment?)"},
+ {"modified", "Path$modified", "func(path:Path, follow_symlinks=yes -> Int64?)"},
{"owner", "Path$owner", "func(path:Path, follow_symlinks=yes -> Text?)"},
{"parent", "Path$parent", "func(path:Path -> Path)"},
{"read", "Path$read", "func(path:Path -> Text?)"},
@@ -562,10 +534,6 @@ env_t *global_env(void)
{"Path$escape_path", "func(path:Path -> Path)"},
{"Int$value_as_text", "func(i:Int -> Path)"});
ADD_CONSTRUCTORS("CString", {"Text$as_c_string", "func(text:Text -> CString)"});
- ADD_CONSTRUCTORS("Moment",
- {"Moment$now", "func(-> Moment)"},
- {"Moment$new", "func(year,month,day:Int,hour,minute=0,second=0.0,timezone=none:Text -> Moment)"},
- {"Moment$from_unix_timestamp", "func(timestamp:Int64 -> Moment)"});
ADD_CONSTRUCTORS("RNG", {"RNG$new", "func(-> RNG)"});
ADD_CONSTRUCTORS("Thread", {"Thread$new", "func(fn:func() -> Thread)"});
#undef ADD_CONSTRUCTORS
@@ -591,7 +559,6 @@ env_t *global_env(void)
{"exit", "tomo_exit", "func(message=none:Text, code=Int32(1) -> Abort)"},
{"fail", "fail_text", "func(message:Text -> Abort)"},
{"sleep", "sleep_num", "func(seconds:Num)"},
- {"now", "Moment$now", "func(->Moment)"},
};
for (size_t i = 0; i < sizeof(global_vars)/sizeof(global_vars[0]); i++) {
@@ -756,7 +723,7 @@ env_t *get_namespace_by_type(env_t *env, type_t *t)
switch (t->tag) {
case ArrayType: return NULL;
case TableType: return NULL;
- case CStringType: case MomentType:
+ case CStringType:
case BoolType: case IntType: case BigIntType: case NumType: case ByteType: {
binding_t *b = get_binding(env, CORD_to_const_char_star(type_to_cord(t)));
assert(b);
diff --git a/src/parse.c b/src/parse.c
index 5e2894f0..5190d92c 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -120,7 +120,6 @@ static PARSER(parse_holding);
static PARSER(parse_if);
static PARSER(parse_inline_c);
static PARSER(parse_int);
-static PARSER(parse_moment);
static PARSER(parse_lambda);
static PARSER(parse_lang_def);
static PARSER(parse_mutexed);
@@ -498,59 +497,6 @@ PARSER(parse_int) {
return NewAST(ctx->file, start, pos, Int, .str=str);
}
-PARSER(parse_moment) {
- const char *start = pos;
- bool negative = match(&pos, "-");
- if (!isdigit(*pos)) return NULL;
-
- struct tm info = {.tm_isdst=-1};
- char *after = strptime(pos, "%Y-%m-%d", &info);
- if (!after) return NULL;
- if (negative) info.tm_year = -(info.tm_year + 1900) - 1900;
- pos = after;
- if (match(&pos, "T") || spaces(&pos) >= 1) {
- after = strptime(pos, "%H:%M", &info);
- if (after) {
- pos = after;
- after = strptime(pos, ":%S", &info);
- if (after) pos = after;
- // TODO parse nanoseconds
- }
- }
-
- const char *before_spaces = pos;
- spaces(&pos);
- Moment_t moment;
- if (match(&pos, "[")) {
- size_t tz_len = strcspn(pos, "\r\n]");
- const char *tz = heap_strf("%.*s", tz_len, pos);
- // TODO: check that tz is a valid timezone
- pos += tz_len;
- expect_closing(ctx, &pos, "]", "I wasn't able to parse the rest of this moment timezone");
- const char *old_tz = getenv("TZ");
- setenv("TZ", tz, 1);
- tzset();
- moment = (Moment_t){.tv_sec=mktime(&info)};
- if (old_tz) setenv("TZ", old_tz, 1);
- else unsetenv("TZ");
- } else if (*pos == 'Z' || *pos == '-' || *pos == '+') {
- after = strptime(pos, "%z", &info);
- if (after) {
- pos = after;
- long offset = info.tm_gmtoff; // Need to cache this because mktime() mutates it to local timezone >:(
- time_t t = mktime(&info);
- moment = (Moment_t){.tv_sec=t + offset - info.tm_gmtoff};
- } else {
- moment = (Moment_t){.tv_sec=mktime(&info)};
- }
- } else {
- pos = before_spaces;
- moment = (Moment_t){.tv_sec=mktime(&info)};
- }
-
- return NewAST(ctx->file, start, pos, Moment, .moment=moment);
-}
-
type_ast_t *parse_table_type(parse_ctx_t *ctx, const char *pos) {
const char *start = pos;
if (!match(&pos, "{")) return NULL;
@@ -1590,7 +1536,6 @@ PARSER(parse_term_no_suffix) {
ast_t *term = NULL;
(void)(
false
- || (term=parse_moment(ctx, pos)) // Must come before num/int
|| (term=parse_none(ctx, pos))
|| (term=parse_num(ctx, pos)) // Must come before int
|| (term=parse_int(ctx, pos))
diff --git a/src/stdlib/datatypes.h b/src/stdlib/datatypes.h
index 40b4712a..22cee673 100644
--- a/src/stdlib/datatypes.h
+++ b/src/stdlib/datatypes.h
@@ -109,9 +109,6 @@ typedef struct {
} Path_t;
#define OptionalPath_t Path_t
-typedef struct timeval Moment_t;
-#define OptionalMoment_t Moment_t
-
typedef struct RNGState_t* RNG_t;
typedef struct MutexedData_s {
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c
index c5764d46..8086239d 100644
--- a/src/stdlib/integers.c
+++ b/src/stdlib/integers.c
@@ -597,24 +597,24 @@ public void Int32$deserialize(FILE *in, void *outval, Array_t*, const TypeInfo_t
{ \
Optional##KindOfInt##_t i = info->current; \
if (!i.is_none) { \
- KindOfInt##_t next; bool overflow = __builtin_add_overflow(i.i, info->step, &next); \
- if (overflow || (!info->last.is_none && (info->step >= 0 ? next > info->last.i : next < info->last.i))) \
+ KindOfInt##_t next; bool overflow = __builtin_add_overflow(i.value, info->step, &next); \
+ if (overflow || (!info->last.is_none && (info->step >= 0 ? next > info->last.value : next < info->last.value))) \
info->current = (Optional##KindOfInt##_t){.is_none=true}; \
else \
- info->current = (Optional##KindOfInt##_t){.i=next}; \
+ info->current = (Optional##KindOfInt##_t){.value=next}; \
} \
return i; \
} \
public to_attr Closure_t KindOfInt ## $to(c_type first, c_type last, Optional ## KindOfInt ## _t step) { \
KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
- range->current = (Optional##KindOfInt##_t){.i=first}; \
- range->last = (Optional##KindOfInt##_t){.i=last}; \
- range->step = step.is_none ? (last >= first ? 1 : -1) : step.i; \
+ range->current = (Optional##KindOfInt##_t){.value=first}; \
+ range->last = (Optional##KindOfInt##_t){.value=last}; \
+ range->step = step.is_none ? (last >= first ? 1 : -1) : step.value; \
return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \
} \
public to_attr Closure_t KindOfInt ## $onward(c_type first, c_type step) { \
KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
- range->current = (Optional##KindOfInt##_t){.i=first}; \
+ range->current = (Optional##KindOfInt##_t){.value=first}; \
range->last = (Optional##KindOfInt##_t){.is_none=true}; \
range->step = step; \
return (Closure_t){.fn=_next_##KindOfInt, .userdata=range}; \
@@ -628,7 +628,7 @@ public void Int32$deserialize(FILE *in, void *outval, Array_t*, const TypeInfo_t
if (Int$compare_value(full_int, I(max_val)) > 0) { \
return (Optional ## KindOfInt ## _t){.is_none=true}; \
} \
- return (Optional ## KindOfInt ## _t){.i=KindOfInt##$from_int(full_int, true)}; \
+ return (Optional ## KindOfInt ## _t){.value=KindOfInt##$from_int(full_int, true)}; \
} \
public CONSTFUNC c_type KindOfInt ## $gcd(c_type x, c_type y) { \
if (x == 0 || y == 0) return 0; \
diff --git a/src/stdlib/integers.h b/src/stdlib/integers.h
index 779bee1f..a057327b 100644
--- a/src/stdlib/integers.h
+++ b/src/stdlib/integers.h
@@ -20,7 +20,7 @@
#define DEFINE_INT_TYPE(c_type, type_name) \
typedef struct { \
- c_type i; \
+ c_type value; \
bool is_none:1; \
} Optional ## type_name ## _t; \
Text_t type_name ## $as_text(const void *i, bool colorize, const TypeInfo_t *type); \
diff --git a/src/stdlib/moments.c b/src/stdlib/moments.c
deleted file mode 100644
index d1abdfbe..00000000
--- a/src/stdlib/moments.c
+++ /dev/null
@@ -1,323 +0,0 @@
-// Moment methods/type info
-#include <ctype.h>
-#include <gc.h>
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "datatypes.h"
-#include "math.h"
-#include "moments.h"
-#include "optionals.h"
-#include "patterns.h"
-#include "stdlib.h"
-#include "text.h"
-#include "util.h"
-
-static OptionalText_t _local_timezone = NONE_TEXT;
-
-#define WITH_TIMEZONE(tz, body) ({ if (tz.length >= 0) { \
- OptionalText_t old_timezone = _local_timezone; \
- Moment$set_local_timezone(tz); \
- body; \
- Moment$set_local_timezone(old_timezone); \
- } else { \
- body; \
- }})
-
-public Text_t Moment$as_text(const void *moment, bool colorize, const TypeInfo_t*)
-{
- if (!moment)
- return Text("Moment");
-
- struct tm info;
- struct tm *final_info = localtime_r(&((Moment_t*)moment)->tv_sec, &info);
- static char buf[256];
- size_t len = strftime(buf, sizeof(buf), "%c %Z", final_info);
- Text_t text = Text$format("%.*s", (int)len, buf);
- if (colorize)
- text = Text$concat(Text("\x1b[36m"), text, Text("\x1b[m"));
- return text;
-}
-
-PUREFUNC public int32_t Moment$compare(const void *va, const void *vb, const TypeInfo_t*)
-{
- Moment_t *a = (Moment_t*)va, *b = (Moment_t*)vb;
- if (a->tv_sec != b->tv_sec)
- return (a->tv_sec > b->tv_sec) - (a->tv_sec < b->tv_sec);
- return (a->tv_usec > b->tv_usec) - (a->tv_usec < b->tv_usec);
-}
-
-CONSTFUNC public bool Moment$is_none(const void *m, const TypeInfo_t*)
-{
- return ((Moment_t*)m)->tv_usec < 0;
-}
-
-public Moment_t Moment$now(void)
-{
- struct timespec ts;
- if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
- fail("Couldn't get the time!");
- return (Moment_t){.tv_sec=ts.tv_sec, .tv_usec=ts.tv_nsec/1000};
-}
-
-public Moment_t Moment$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second, OptionalText_t tz)
-{
- struct tm info = {
- .tm_min=Int32$from_int(minute, false),
- .tm_hour=Int32$from_int(hour, false),
- .tm_mday=Int32$from_int(day, false),
- .tm_mon=Int32$from_int(month, false) - 1,
- .tm_year=Int32$from_int(year, false) - 1900,
- .tm_isdst=-1,
- };
-
- time_t t;
- WITH_TIMEZONE(tz, t = mktime(&info));
- return (Moment_t){.tv_sec=t + (time_t)second, .tv_usec=(suseconds_t)(fmod(second, 1.0) * 1e9)};
-}
-
-public Moment_t Moment$after(Moment_t moment, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, OptionalText_t tz)
-{
- double offset = seconds + 60.*minutes + 3600.*hours;
- moment.tv_sec += (time_t)offset;
-
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
-
- info.tm_mday += Int32$from_int(days, false) + 7*Int32$from_int(weeks, false);
- info.tm_mon += Int32$from_int(months, false);
- info.tm_year += Int32$from_int(years, false);
-
- time_t t = mktime(&info);
- return (Moment_t){
- .tv_sec=t,
- .tv_usec=moment.tv_usec + (suseconds_t)(fmod(offset, 1.0) * 1e9),
- };
-}
-
-CONSTFUNC public double Moment$seconds_till(Moment_t now, Moment_t then)
-{
- return (double)(then.tv_sec - now.tv_sec) + 1e-9*(double)(then.tv_usec - now.tv_usec);
-}
-
-CONSTFUNC public double Moment$minutes_till(Moment_t now, Moment_t then)
-{
- return Moment$seconds_till(now, then)/60.;
-}
-
-CONSTFUNC public double Moment$hours_till(Moment_t now, Moment_t then)
-{
- return Moment$seconds_till(now, then)/3600.;
-}
-
-public void Moment$get(
- Moment_t moment, Int_t *year, Int_t *month, Int_t *day, Int_t *hour, Int_t *minute, Int_t *second,
- Int_t *nanosecond, Int_t *weekday, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
-
- if (year) *year = I(info.tm_year + 1900);
- if (month) *month = I(info.tm_mon + 1);
- if (day) *day = I(info.tm_mday);
- if (hour) *hour = I(info.tm_hour);
- if (minute) *minute = I(info.tm_min);
- if (second) *second = I(info.tm_sec);
- if (nanosecond) *nanosecond = I(moment.tv_usec);
- if (weekday) *weekday = I(info.tm_wday + 1);
-}
-
-public Int_t Moment$year(Moment_t moment, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- return I(info.tm_year + 1900);
-}
-
-public Int_t Moment$month(Moment_t moment, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- return I(info.tm_mon + 1);
-}
-
-public Int_t Moment$day_of_week(Moment_t moment, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- return I(info.tm_wday + 1);
-}
-
-public Int_t Moment$day_of_month(Moment_t moment, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- return I(info.tm_mday);
-}
-
-public Int_t Moment$day_of_year(Moment_t moment, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- return I(info.tm_yday);
-}
-
-public Int_t Moment$hour(Moment_t moment, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- return I(info.tm_hour);
-}
-
-public Int_t Moment$minute(Moment_t moment, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- return I(info.tm_min);
-}
-
-public Int_t Moment$second(Moment_t moment, OptionalText_t tz)
-{
- struct tm info = {};
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- return I(info.tm_sec);
-}
-
-public Int_t Moment$microsecond(Moment_t moment, OptionalText_t tz)
-{
- (void)tz;
- return I(moment.tv_usec);
-}
-
-public Text_t Moment$format(Moment_t moment, Text_t fmt, OptionalText_t tz)
-{
- struct tm info;
- WITH_TIMEZONE(tz, localtime_r(&moment.tv_sec, &info));
- static char buf[256];
- size_t len = strftime(buf, sizeof(buf), Text$as_c_string(fmt), &info);
- return Text$format("%.*s", (int)len, buf);
-}
-
-public Text_t Moment$date(Moment_t moment, OptionalText_t tz)
-{
- return Moment$format(moment, Text("%F"), tz);
-}
-
-public Text_t Moment$time(Moment_t moment, bool seconds, bool am_pm, OptionalText_t tz)
-{
- Text_t text;
- if (seconds)
- text = Moment$format(moment, am_pm ? Text("%l:%M:%S%P") : Text("%T"), tz);
- else
- text = Moment$format(moment, am_pm ? Text("%l:%M%P") : Text("%H:%M"), tz);
- return Text$trim(text, Pattern(" "), true, true);
-}
-
-public OptionalMoment_t Moment$parse(Text_t text, Text_t format)
-{
- struct tm info = {.tm_isdst=-1};
- const char *str = Text$as_c_string(text);
- const char *fmt = Text$as_c_string(format);
- if (strstr(fmt, "%Z"))
- fail("The %Z specifier is not supported for time parsing!");
-
- char *invalid = strptime(str, fmt, &info);
- if (!invalid || invalid[0] != '\0')
- return NONE_MOMENT;
-
- long offset = info.tm_gmtoff; // Need to cache this because mktime() mutates it to local tz >:(
- time_t t = mktime(&info);
- return (Moment_t){.tv_sec=t + offset - info.tm_gmtoff};
-}
-
-static INLINE Text_t num_format(long n, const char *unit)
-{
- if (n == 0)
- return Text("now");
- return Text$format((n == 1 || n == -1) ? "%ld %s %s" : "%ld %ss %s", n < 0 ? -n : n, unit, n < 0 ? "ago" : "later");
-}
-
-public Text_t Moment$relative(Moment_t moment, Moment_t relative_to, OptionalText_t tz)
-{
- struct tm info = {};
- struct tm relative_info = {};
- WITH_TIMEZONE(tz, {
- localtime_r(&moment.tv_sec, &info);
- localtime_r(&relative_to.tv_sec, &relative_info);
- });
-
- double second_diff = Moment$seconds_till(relative_to, moment);
- if (info.tm_year != relative_info.tm_year && fabs(second_diff) > 365.*24.*60.*60.)
- return num_format((long)info.tm_year - (long)relative_info.tm_year, "year");
- else if (info.tm_mon != relative_info.tm_mon && fabs(second_diff) > 31.*24.*60.*60.)
- return num_format(12*((long)info.tm_year - (long)relative_info.tm_year) + (long)info.tm_mon - (long)relative_info.tm_mon, "month");
- else if (info.tm_yday != relative_info.tm_yday && fabs(second_diff) > 24.*60.*60.)
- return num_format(round(second_diff/(24.*60.*60.)), "day");
- else if (info.tm_hour != relative_info.tm_hour && fabs(second_diff) > 60.*60.)
- return num_format(round(second_diff/(60.*60.)), "hour");
- else if (info.tm_min != relative_info.tm_min && fabs(second_diff) > 60.)
- return num_format(round(second_diff/(60.)), "minute");
- else {
- if (fabs(second_diff) < 1e-6)
- return num_format((long)(second_diff*1e9), "nanosecond");
- else if (fabs(second_diff) < 1e-3)
- return num_format((long)(second_diff*1e6), "microsecond");
- else if (fabs(second_diff) < 1.0)
- return num_format((long)(second_diff*1e3), "millisecond");
- else
- return num_format((long)(second_diff), "second");
- }
-}
-
-CONSTFUNC public Int64_t Moment$unix_timestamp(Moment_t moment)
-{
- return (Int64_t)moment.tv_sec;
-}
-
-CONSTFUNC public Moment_t Moment$from_unix_timestamp(Int64_t timestamp)
-{
- return (Moment_t){.tv_sec=(time_t)timestamp};
-}
-
-public void Moment$set_local_timezone(OptionalText_t tz)
-{
- if (tz.length >= 0) {
- setenv("TZ", Text$as_c_string(tz), 1);
- } else {
- unsetenv("TZ");
- }
- _local_timezone = tz;
- tzset();
-}
-
-public Text_t Moment$get_local_timezone(void)
-{
- if (_local_timezone.length < 0) {
- static char buf[PATH_MAX];
- ssize_t len = readlink("/etc/localtime", buf, sizeof(buf));
- if (len < 0)
- fail("Could not get local tz!");
-
- char *zoneinfo = strstr(buf, "/zoneinfo/");
- if (zoneinfo)
- _local_timezone = Text$from_str(zoneinfo + strlen("/zoneinfo/"));
- else
- fail("Could not resolve local tz!");
- }
- return _local_timezone;
-}
-
-public const TypeInfo_t Moment$info = {
- .size=sizeof(Moment_t),
- .align=__alignof__(Moment_t),
- .metamethods={
- .as_text=Moment$as_text,
- .compare=Moment$compare,
- .is_none=Moment$is_none,
- },
-};
-
-// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/moments.h b/src/stdlib/moments.h
deleted file mode 100644
index ff6d4119..00000000
--- a/src/stdlib/moments.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#pragma once
-
-// Moment objects
-
-#include <stdint.h>
-
-#include "datatypes.h"
-#include "integers.h"
-#include "optionals.h"
-#include "types.h"
-#include "util.h"
-
-Text_t Moment$as_text(const void *moment, bool colorize, const TypeInfo_t *type);
-PUREFUNC int32_t Moment$compare(const void *a, const void *b, const TypeInfo_t *type);
-CONSTFUNC public bool Moment$is_none(const void *m, const TypeInfo_t*);
-Moment_t Moment$now(void);
-Moment_t Moment$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second, OptionalText_t timezone);
-Moment_t Moment$after(Moment_t moment, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, OptionalText_t timezone);
-CONSTFUNC double Moment$seconds_till(Moment_t now, Moment_t then);
-CONSTFUNC double Moment$minutes_till(Moment_t now, Moment_t then);
-CONSTFUNC double Moment$hours_till(Moment_t now, Moment_t then);
-Int_t Moment$year(Moment_t moment, OptionalText_t timezone);
-Int_t Moment$month(Moment_t moment, OptionalText_t timezone);
-Int_t Moment$day_of_week(Moment_t moment, OptionalText_t timezone);
-Int_t Moment$day_of_month(Moment_t moment, OptionalText_t timezone);
-Int_t Moment$day_of_year(Moment_t moment, OptionalText_t timezone);
-Int_t Moment$hour(Moment_t moment, OptionalText_t timezone);
-Int_t Moment$minute(Moment_t moment, OptionalText_t timezone);
-Int_t Moment$second(Moment_t moment, OptionalText_t timezone);
-Int_t Moment$microsecond(Moment_t moment, OptionalText_t timezone);
-Text_t Moment$format(Moment_t moment, Text_t fmt, OptionalText_t timezone);
-Text_t Moment$date(Moment_t moment, OptionalText_t timezone);
-Text_t Moment$time(Moment_t moment, bool seconds, bool am_pm, OptionalText_t timezone);
-OptionalMoment_t Moment$parse(Text_t text, Text_t format);
-Text_t Moment$relative(Moment_t moment, Moment_t relative_to, OptionalText_t timezone);
-CONSTFUNC Int64_t Moment$unix_timestamp(Moment_t moment);
-CONSTFUNC Moment_t Moment$from_unix_timestamp(Int64_t timestamp);
-void Moment$set_local_timezone(OptionalText_t timezone);
-Text_t Moment$get_local_timezone(void);
-
-extern const TypeInfo_t Moment$info;
-
-// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
-
diff --git a/src/stdlib/optionals.c b/src/stdlib/optionals.c
index 462b2df2..db2c477f 100644
--- a/src/stdlib/optionals.c
+++ b/src/stdlib/optionals.c
@@ -7,7 +7,6 @@
#include "datatypes.h"
#include "integers.h"
#include "metamethods.h"
-#include "moments.h"
#include "nums.h"
#include "patterns.h"
#include "text.h"
diff --git a/src/stdlib/optionals.h b/src/stdlib/optionals.h
index 94e4d900..8d25c5f1 100644
--- a/src/stdlib/optionals.h
+++ b/src/stdlib/optionals.h
@@ -16,7 +16,6 @@
#define NONE_TABLE ((OptionalTable_t){.entries.length=-1})
#define NONE_CLOSURE ((OptionalClosure_t){.fn=NULL})
#define NONE_TEXT ((OptionalText_t){.length=-1})
-#define NONE_MOMENT ((OptionalMoment_t){.tv_usec=-1})
#define NONE_PATH ((Path_t){.type=PATH_NONE})
PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_type);
diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c
index c7b560b9..05575620 100644
--- a/src/stdlib/paths.c
+++ b/src/stdlib/paths.c
@@ -255,28 +255,28 @@ public bool Path$can_execute(Path_t path)
#endif
}
-public OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks)
+public OptionalInt64_t Path$modified(Path_t path, bool follow_symlinks)
{
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
- if (status != 0) return NONE_MOMENT;
- return (Moment_t){.tv_sec=sb.st_mtime};
+ if (status != 0) return NONE_INT64;
+ return (OptionalInt64_t){.value=(int64_t)sb.st_mtime};
}
-public OptionalMoment_t Path$accessed(Path_t path, bool follow_symlinks)
+public OptionalInt64_t Path$accessed(Path_t path, bool follow_symlinks)
{
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
- if (status != 0) return NONE_MOMENT;
- return (Moment_t){.tv_sec=sb.st_atime};
+ if (status != 0) return NONE_INT64;
+ return (OptionalInt64_t){.value=(int64_t)sb.st_atime};
}
-public OptionalMoment_t Path$changed(Path_t path, bool follow_symlinks)
+public OptionalInt64_t Path$changed(Path_t path, bool follow_symlinks)
{
struct stat sb;
int status = path_stat(path, follow_symlinks, &sb);
- if (status != 0) return NONE_MOMENT;
- return (Moment_t){.tv_sec=sb.st_ctime};
+ if (status != 0) return NONE_INT64;
+ return (OptionalInt64_t){.value=(int64_t)sb.st_ctime};
}
static void _write(Path_t path, Array_t bytes, int mode, int permissions)
diff --git a/src/stdlib/paths.h b/src/stdlib/paths.h
index 02afc494..9be81bdf 100644
--- a/src/stdlib/paths.h
+++ b/src/stdlib/paths.h
@@ -28,9 +28,9 @@ bool Path$is_symlink(Path_t path);
bool Path$can_read(Path_t path);
bool Path$can_write(Path_t path);
bool Path$can_execute(Path_t path);
-OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks);
-OptionalMoment_t Path$accessed(Path_t path, bool follow_symlinks);
-OptionalMoment_t Path$changed(Path_t path, bool follow_symlinks);
+OptionalInt64_t Path$modified(Path_t path, bool follow_symlinks);
+OptionalInt64_t Path$accessed(Path_t path, bool follow_symlinks);
+OptionalInt64_t Path$changed(Path_t path, bool follow_symlinks);
void Path$write(Path_t path, Text_t text, int permissions);
void Path$write_bytes(Path_t path, Array_t bytes, int permissions);
void Path$append(Path_t path, Text_t text, int permissions);
diff --git a/src/stdlib/tomo.h b/src/stdlib/tomo.h
index 567e5d14..16e5ec57 100644
--- a/src/stdlib/tomo.h
+++ b/src/stdlib/tomo.h
@@ -17,7 +17,6 @@
#include "integers.h"
#include "memory.h"
#include "metamethods.h"
-#include "moments.h"
#include "mutexeddata.h"
#include "nums.h"
#include "optionals.h"
diff --git a/src/typecheck.c b/src/typecheck.c
index ba03e968..5da84442 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -852,7 +852,7 @@ type_t *get_type(env_t *env, ast_t *ast)
if (constructor)
return t;
else if (t->tag == StructType || t->tag == IntType || t->tag == BigIntType || t->tag == NumType
- || t->tag == ByteType || t->tag == TextType || t->tag == CStringType || t->tag == MomentType)
+ || t->tag == ByteType || t->tag == TextType || t->tag == CStringType)
return t; // Constructor
code_err(call->fn, "This is not a type that has a constructor");
}
@@ -1408,7 +1408,6 @@ type_t *get_type(env_t *env, ast_t *ast)
type_ast_t *type_ast = inline_code->type_ast;
return type_ast ? parse_type_ast(env, type_ast) : Type(VoidType);
}
- case Moment: return Type(MomentType);
case Unknown: code_err(ast, "I can't figure out the type of: ", ast_to_str(ast));
case Deserialize: return parse_type_ast(env, Match(ast, Deserialize)->type);
}
diff --git a/src/types.c b/src/types.c
index 8b9289cb..07b6ced0 100644
--- a/src/types.c
+++ b/src/types.c
@@ -29,7 +29,6 @@ CORD type_to_cord(type_t *t) {
case BoolType: return "Bool";
case ByteType: return "Byte";
case CStringType: return "CString";
- case MomentType: return "Moment";
case TextType: return Match(t, TextType)->lang ? Match(t, TextType)->lang : "Text";
case BigIntType: return "Int";
case IntType: return CORD_asprintf("Int%d", Match(t, IntType)->bits);
@@ -497,7 +496,6 @@ PUREFUNC size_t type_size(type_t *t)
case BoolType: return sizeof(bool);
case ByteType: return sizeof(uint8_t);
case CStringType: return sizeof(char*);
- case MomentType: return sizeof(Moment_t);
case BigIntType: return sizeof(Int_t);
case IntType: {
switch (Match(t, IntType)->bits) {
@@ -590,7 +588,6 @@ PUREFUNC size_t type_align(type_t *t)
case BoolType: return __alignof__(bool);
case ByteType: return __alignof__(uint8_t);
case CStringType: return __alignof__(char*);
- case MomentType: return __alignof__(Moment_t);
case BigIntType: return __alignof__(Int_t);
case IntType: {
switch (Match(t, IntType)->bits) {
@@ -704,11 +701,6 @@ type_t *get_field_type(type_t *t, const char *field_name)
if (streq(field_name, "length")) return INT_TYPE;
return NULL;
}
- case MomentType: {
- if (streq(field_name, "seconds")) return Type(IntType, .bits=TYPE_IBITS64);
- else if (streq(field_name, "microseconds")) return Type(IntType, .bits=TYPE_IBITS64);
- return NULL;
- }
default: return NULL;
}
}
diff --git a/src/types.h b/src/types.h
index eec3fac2..ae34c217 100644
--- a/src/types.h
+++ b/src/types.h
@@ -46,7 +46,6 @@ struct type_s {
IntType,
NumType,
CStringType,
- MomentType,
TextType,
ArrayType,
SetType,
@@ -76,7 +75,7 @@ struct type_s {
struct {
enum { TYPE_NBITS32=32, TYPE_NBITS64=64 } bits;
} NumType;
- struct {} CStringType, MomentType;
+ struct {} CStringType;
struct {
const char *lang;
struct env_s *env;