Add DateTime
This commit is contained in:
parent
8f7f66d7c8
commit
05515d8645
2
Makefile
2
Makefile
@ -31,7 +31,7 @@ LDLIBS=-lgc -lcord -lm -lunistring -lgmp -ldl
|
||||
BUILTIN_OBJS=stdlib/siphash.o stdlib/arrays.o stdlib/bools.o stdlib/bytes.o stdlib/channels.o stdlib/nums.o stdlib/integers.o \
|
||||
stdlib/pointers.o stdlib/memory.o stdlib/text.o stdlib/threads.o stdlib/c_strings.o stdlib/tables.o \
|
||||
stdlib/types.o stdlib/util.o stdlib/files.o stdlib/ranges.o stdlib/shell.o stdlib/paths.o \
|
||||
stdlib/optionals.o stdlib/patterns.o stdlib/metamethods.o stdlib/functiontype.o stdlib/stdlib.o
|
||||
stdlib/optionals.o stdlib/patterns.o stdlib/metamethods.o stdlib/functiontype.o stdlib/stdlib.o stdlib/datetime.o
|
||||
TESTS=$(patsubst %.tm,%.tm.testresult,$(wildcard test/*.tm))
|
||||
|
||||
all: libtomo.so tomo
|
||||
|
@ -211,6 +211,7 @@ CORD compile_type(type_t *t)
|
||||
case BoolType: return "Bool_t";
|
||||
case ByteType: return "Byte_t";
|
||||
case CStringType: return "char*";
|
||||
case DateTimeType: return "DateTime_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);
|
||||
@ -257,7 +258,7 @@ CORD compile_type(type_t *t)
|
||||
case PointerType: case EnumType: case ChannelType:
|
||||
return compile_type(nonnull);
|
||||
case IntType: case BigIntType: case TextType: case NumType: case BoolType: case ByteType:
|
||||
case ArrayType: case TableType: case SetType:
|
||||
case ArrayType: case TableType: case SetType: case DateTimeType:
|
||||
return CORD_all("Optional", compile_type(nonnull));
|
||||
case StructType: {
|
||||
if (nonnull == THREAD_TYPE)
|
||||
@ -384,6 +385,8 @@ static CORD check_null(type_t *t, CORD value)
|
||||
return CORD_all("(", value, ").is_null");
|
||||
else if (t->tag == EnumType)
|
||||
return CORD_all("((", value, ").tag == 0)");
|
||||
else if (t->tag == DateTimeType)
|
||||
return CORD_all("((", value, ").tv_usec < 0)");
|
||||
errx(1, "Optional check not implemented for: %T", t);
|
||||
}
|
||||
|
||||
@ -1443,6 +1446,7 @@ CORD expr_as_text(env_t *env, 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 DateTimeType: return CORD_asprintf("DateTime$as_text(stack(%r), %r, &DateTime$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);
|
||||
@ -1808,6 +1812,7 @@ CORD compile_null(type_t *t)
|
||||
case ChannelType: return "NULL";
|
||||
case TextType: return "NULL_TEXT";
|
||||
case CStringType: return "NULL";
|
||||
case DateTimeType: return "NULL_DATETIME";
|
||||
case PointerType: return CORD_all("((", compile_type(t), ")NULL)");
|
||||
case ClosureType: return "NULL_CLOSURE";
|
||||
case NumType: return "nan(\"null\")";
|
||||
@ -3397,7 +3402,7 @@ CORD compile_type_info(env_t *env, type_t *t)
|
||||
else if (t == RANGE_TYPE) return "&Range$info";
|
||||
|
||||
switch (t->tag) {
|
||||
case BoolType: case ByteType: case IntType: case BigIntType: case NumType: case CStringType:
|
||||
case BoolType: case ByteType: case IntType: case BigIntType: case NumType: case CStringType: case DateTimeType:
|
||||
return CORD_all("&", type_to_cord(t), "$info");
|
||||
case TextType: {
|
||||
auto text = Match(t, TextType);
|
||||
|
435
docs/datetime.md
Normal file
435
docs/datetime.md
Normal file
@ -0,0 +1,435 @@
|
||||
# DateTime
|
||||
|
||||
Tomo has a builtin datatype for representing a specific single point in time:
|
||||
`DateTime`. A DateTime object is internally represented using a UNIX epoch in
|
||||
seconds and a number of nanoseconds to represent sub-second times (in C, the
|
||||
equivalent of `struct timeval`). DateTime values do not represent calendar
|
||||
dates or clock times, they represent an exact moment in time, such as the
|
||||
moment when a file was last modified on the filesystem or the current moment
|
||||
(`DateTime.now()`).
|
||||
|
||||
## Time Zones
|
||||
|
||||
Because humans are not able to easily understand UNIX timestamps, the default
|
||||
textual representation of `DateTime` objects uses the current locale's
|
||||
preferred representation of the DateTime in the current time zone:
|
||||
|
||||
```tomo
|
||||
>> DateTime.now()
|
||||
= Sun Sep 29 18:20:12 2024
|
||||
```
|
||||
|
||||
For various methods, it is assumed by default that users wish to perform
|
||||
calculations and specify datetimes using the local time zone and daylight
|
||||
savings time rules. For example, if a program is running in New York and it is
|
||||
currently 11pm on February 28th, 2023 (the last day of the month) in local
|
||||
time, it is assumed that "one month from now" refers to 11pm on March 28th,
|
||||
2024 in local time, rather than referring to one month from the current UTC
|
||||
time. In that example, the initial time would be 3am March 1, 2023 in UTC, so
|
||||
one month later would be 3am April 1, 2023 in UTC, which is which is 11am March
|
||||
31st in local time. Most users would be unpleasantly surprised to find out that
|
||||
when it's February 28th in local time, one month later is March 28th until 8pm,
|
||||
at which point it becomes March 31st! For functions where this matters, there
|
||||
is an extra `local_time` argument that is `yes` by default.
|
||||
|
||||
## DateTime Methods
|
||||
|
||||
### `after`
|
||||
|
||||
**Description:**
|
||||
Returns a DateTime that occurs after the specified time differences. Time
|
||||
differences may be either positive or negative.
|
||||
|
||||
**Note:** time offsets for days, months, weeks, and years do not refer to fixed
|
||||
time intervals, but are relative to which date they are applied to. For
|
||||
example, one year from January 1, 2024 is January 1, 2025, which is 366 days
|
||||
later because 2024 is a leap year. Similarly, adding one month may add anywhere
|
||||
from 28 to 31 days, depending on the starting month. Days and weeks are
|
||||
affected by leap seconds. For this reason, `after()` takes an argument,
|
||||
`local_time` which is used to determine whether time offsets should be
|
||||
calculated using the current local time or UTC.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:after(seconds : Num = 0.0, minutes : Num = 0.0, hours : Num = 0.0, days : Int = 0, weeks : Int = 0, months : Int = 0, years : Int = 0, local_time : Bool = yes) -> DateTime
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `seconds`: An amount of seconds to offset the datetime (default: 0).
|
||||
- `minutes`: An amount of minutes to offset the datetime (default: 0).
|
||||
- `hours`: An amount of hours to offset the datetime (default: 0).
|
||||
- `days`: An amount of days to offset the datetime (default: 0).
|
||||
- `weeks`: An amount of weeks to offset the datetime (default: 0).
|
||||
- `months`: An amount of months to offset the datetime (default: 0).
|
||||
- `years`: An amount of years to offset the datetime (default: 0).
|
||||
- `local_time`: Whether to perform the calculations in local time (default: `yes`) or, if not, in UTC time.
|
||||
|
||||
**Returns:**
|
||||
A new `DateTime` offset by the given amount.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
>> DateTime.new(2024, 9, 29, hour=19):after(days=1, minutes=30)
|
||||
= Mon Sep 30 19:30:00 2024
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `date`
|
||||
|
||||
**Description:**
|
||||
Return a text representation of the datetime using the `"%F"` format
|
||||
specifier, which gives the date in `YYYY-MM-DD` form.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:date(local_time : Bool = yes) -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `local_time`: Whether to use local time (default: `yes`) or UTC.
|
||||
|
||||
**Returns:**
|
||||
The date in `YYYY-MM-DD` format.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
>> DateTime.new(2024, 9, 29):format("%A")
|
||||
= "2024-09-29"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `format`
|
||||
|
||||
**Description:**
|
||||
Using the C-style [`strftime`](https://linux.die.net/man/3/strftime) format
|
||||
options, return a text representation of the given date in the given format. If
|
||||
`local_time` is `no`, then use UTC instead of the current locale's timezone.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:format(format: Text = "%c", local_time : Bool = yes) -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `path`: The path of the file to append to.
|
||||
- `bytes`: The bytes to append to the file.
|
||||
- `permissions` (optional): The permissions to set on the file if it is being created (default is `0o644`).
|
||||
|
||||
**Returns:**
|
||||
Nothing.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
>> DateTime.new(2024, 9, 29):format("%A")
|
||||
= "Sunday"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `from_unix_timestamp`
|
||||
|
||||
**Description:**
|
||||
Return a datetime object that represents the same moment in time as
|
||||
the given UNIX epoch timestamp (seconds since January 1, 1970 UTC).
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
DateTime.from_unix_timestamp(timestamp: Int64) -> DateTime
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `timestamp`: The UNIX timestamp.
|
||||
|
||||
**Returns:**
|
||||
A `DateTime` object representing the same moment as the given UNIX timestamp.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
# In the New York timezone:
|
||||
>> DateTime.from_unix_timestamp(0)
|
||||
= Wed Dec 31 19:00:00 1969
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `get`
|
||||
|
||||
**Description:**
|
||||
Get various components of the given datetime object and store them in the
|
||||
provided optional fields.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:get(year : &Int? = !&Int, month : &Int? = !&Int, day : &Int? = !&Int, hour : &Int? = !&Int, minute : &Int? = !&Int, second : &Int? = !&Int, nanosecond : &Int? = !&Int, weekday : &Int? = !&Int, local_time=yes) -> Void
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `year`: If non-null, store the year here.
|
||||
- `month`: If non-null, store the month here (1-12).
|
||||
- `day`: If non-null, store the day of the month here (1-31).
|
||||
- `hour`: If non-null, store the hour of the day here (0-23).
|
||||
- `minute`: If non-null, store the minute of the hour here (0-59).
|
||||
- `second`: If non-null, store the second of the minute here (0-59).
|
||||
- `nanosecond`: If non-null, store the nanosecond of the second here (0-1,000,000,000).
|
||||
- `weekday`: If non-null, store the day of the week here (sunday=1, saturday=7)
|
||||
- `local_time`: Whether to use the local timezone (default: `yes`) or UTC.
|
||||
|
||||
**Returns:**
|
||||
Nothing.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
dt := DateTime.new(2024, 9, 29)
|
||||
month := 0
|
||||
dt:get(month=&month)
|
||||
>> month
|
||||
= 9
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `hours_till`
|
||||
|
||||
**Description:**
|
||||
Return the number of hours until a given datetime.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:hours_till(then:DateTime) -> Num
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `then`: Another datetime that we want to calculate the time offset from (in hours).
|
||||
|
||||
**Returns:**
|
||||
The number of hours (possibly fractional, possibly negative) until the given time.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
the_future := now():after(hours=1, minutes=30)
|
||||
>> now():hours_till(the_future)
|
||||
= 1.5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `minutes_till`
|
||||
|
||||
**Description:**
|
||||
Return the number of minutes until a given datetime.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:minutes_till(then:DateTime) -> Num
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `then`: Another datetime that we want to calculate the time offset from (in minutes).
|
||||
|
||||
**Returns:**
|
||||
The number of minutes (possibly fractional, possibly negative) until the given time.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
the_future := now():after(minutes=1, seconds=30)
|
||||
>> now():minutes_till(the_future)
|
||||
= 1.5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `new`
|
||||
|
||||
**Description:**
|
||||
Return a new `DateTime` object representing the given time parameters expressed
|
||||
in local time.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
DateTime.new(year : Int, month : Int, day : Int, hour : Int = 0, minute : Int = 0, second : Num = 0.0) -> DateTime
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `year`: The year.
|
||||
- `month`: The month of the year (1-12).
|
||||
- `day`: The day of the month (1-31).
|
||||
- `hour`: The hour of the day (0-23) (default: 0).
|
||||
- `minute`: The minute of the hour (0-59) (default: 0).
|
||||
- `second`: The second of the minute (0-59) (default: 0.0).
|
||||
|
||||
**Returns:**
|
||||
A `DateTime` representing the given information in local time. If the given
|
||||
parameters exceed reasonable bounds, the time values will wrap around. For
|
||||
example, `DateTime.new(..., hour=3, minute=65)` is the same as
|
||||
`DateTime.new(..., hour=4, minute=5)`. If any arguments cannot fit in a 32-bit
|
||||
integer, an error will be raised.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
>> DateTime.new(2024, 9, 29)
|
||||
= Mon Sep 30 00:00:00 2024
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `parse`
|
||||
|
||||
**Description:**
|
||||
Return a new `DateTime` object parsed from the given string in the given format,
|
||||
or a null value if the value could not be successfully parsed.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
DateTime.parse(text: Text, format: Text = "%c") -> DateTime?
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `text`: The text to parse.
|
||||
- `format`: The date format of the text being parsed (see:
|
||||
[strptime](https://linux.die.net/man/3/strptime) for more info on this format) (default: `"%c"`).
|
||||
|
||||
**Returns:**
|
||||
If the text was successfully parsed according to the given format, return a
|
||||
`DateTime` representing that information. Otherwise, return a null value.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
>> DateTime.parse("2024-09-29", "%Y-%m-%d")!
|
||||
= Sun Sep 29 00:00:00 2024
|
||||
|
||||
>> DateTime.parse("???", "%Y-%m-%d")
|
||||
= !DateTime
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `relative`
|
||||
|
||||
**Description:**
|
||||
Return a plain English textual representation of the approximate time difference
|
||||
between two `DateTime`s. For example: `5 minutes ago` or `1 day later`
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:relative(relative_to : DateTime = DateTime.now(), local_time : Bool = yes) -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `relative_to` (optional): The time against which the relative time is calculated (default: `DateTime.now()`).
|
||||
- `local_time` (optional): Whether or not to perform calculations in local time (default: `yes`).
|
||||
|
||||
**Returns:**
|
||||
Return a plain English textual representation of the approximate time
|
||||
difference between two `DateTime`s. For example: `5 minutes ago` or `1 day
|
||||
later`. Return values are approximate and use only one significant unit of
|
||||
measure with one significant digit, so a difference of 1.6 days will be
|
||||
represented as `2 days later`. Datetimes in the past will have the suffix `"
|
||||
ago"`, while datetimes in the future will have the suffix `" later"`.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
>> now():after(days=2):relative()
|
||||
= "2 days later"
|
||||
|
||||
>> now():after(minutes=-65):relative()
|
||||
= "1 hour ago"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `seconds_till`
|
||||
|
||||
**Description:**
|
||||
Return the number of seconds until a given datetime.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:seconds_till(then:DateTime) -> Num
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `then`: Another datetime that we want to calculate the time offset from (in seconds).
|
||||
|
||||
**Returns:**
|
||||
The number of seconds (possibly fractional, possibly negative) until the given time.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
the_future := now():after(seconds=1)
|
||||
>> now():seconds_till(the_future)
|
||||
= 1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `time`
|
||||
|
||||
**Description:**
|
||||
Return a text representation of the time component of the given datetime.
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:time(seconds : Bool = no, am_pm : Bool = yes, local_time : Bool = yes) -> Text
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `seconds`: Whether to include seconds in the time (default: `no`).
|
||||
- `am_pm`: Whether to use am/pm in the representation or use a 24-hour clock (default: `yes`).
|
||||
- `local_time`: Whether to use local time (default: `yes`) or UTC.
|
||||
|
||||
**Returns:**
|
||||
A text representation of the time component of the datetime.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
dt := DateTime.new(2024, 9, 29, hours=13, minutes=59, seconds=30)
|
||||
|
||||
>> dt:time()
|
||||
= "1:59pm"
|
||||
|
||||
>> dt:time(am_pm=no)
|
||||
= "13:59"
|
||||
|
||||
>> dt:time(seconds=yes)
|
||||
= "1:59:30pm"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `unix_timestamp`
|
||||
|
||||
**Description:**
|
||||
Get the UNIX timestamp of the given datetime (seconds since the UNIX epoch:
|
||||
January 1, 1970 UTC).
|
||||
|
||||
**Usage:**
|
||||
```markdown
|
||||
datetime:unix_timestamp() -> Int64
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
None.
|
||||
|
||||
**Returns:**
|
||||
A 64-bit integer representation of the UNIX timestamp.
|
||||
|
||||
**Example:**
|
||||
```markdown
|
||||
>> now():unix_timestamp()
|
||||
= 1727654730[64]
|
||||
```
|
@ -50,6 +50,7 @@ env_t *new_compilation_unit(CORD libname)
|
||||
.default_val=FakeAST(Int, .bits=IBITS32, .str="1"))), .ret=Type(AbortType))}},
|
||||
{"fail", {.code="fail", .type=Type(FunctionType, .args=new(arg_t, .name="message", .type=Type(CStringType)), .ret=Type(AbortType))}},
|
||||
{"sleep", {.code="sleep_num", .type=Type(FunctionType, .args=new(arg_t, .name="seconds", .type=Type(NumType, .bits=TYPE_NBITS64)), .ret=Type(VoidType))}},
|
||||
{"now", {.code="DateTime$now", .type=Type(FunctionType, .args=NULL, .ret=Type(DateTimeType))}},
|
||||
{"USE_COLOR", {.code="USE_COLOR", .type=Type(BoolType)}},
|
||||
};
|
||||
|
||||
@ -77,7 +78,6 @@ env_t *new_compilation_unit(CORD libname)
|
||||
THREAD_TYPE = Type(StructType, .name="Thread", .env=thread_env, .opaque=true);
|
||||
}
|
||||
|
||||
|
||||
struct {
|
||||
const char *name;
|
||||
type_t *type;
|
||||
@ -261,6 +261,24 @@ env_t *new_compilation_unit(CORD libname)
|
||||
{"escape_int", "Int$value_as_text", "func(i:Int)->Pattern"},
|
||||
{"escape_text", "Pattern$escape_text", "func(text:Text)->Pattern"},
|
||||
)},
|
||||
{"DateTime", Type(DateTimeType), "DateTime_t", "DateTime", TypedArray(ns_entry_t,
|
||||
// Used as a default for functions below:
|
||||
{"now", "DateTime$now", "func()->DateTime"},
|
||||
|
||||
{"after", "DateTime$after", "func(dt:DateTime,seconds=0.0,minutes=0.0,hours=0.0,days=0,weeks=0,months=0,years=0,local_time=yes)->DateTime"},
|
||||
{"date", "DateTime$date", "func(dt:DateTime,local_time=yes)->Text"},
|
||||
{"format", "DateTime$format", "func(dt:DateTime,format=\"%c\",local_time=yes)->Text"},
|
||||
{"from_unix_timestamp", "DateTime$from_unix_timestamp", "func(timestamp:Int64)->DateTime"},
|
||||
{"get", "DateTime$get", "func(dt:DateTime,year=!&Int,month=!&Int,day=!&Int,hour=!&Int,minute=!&Int,second=!&Int,nanosecond=!&Int,weekday=!&Int, local_time=yes)"},
|
||||
{"hours_till", "DateTime$hours_till", "func(now:DateTime,then:DateTime)->Num"},
|
||||
{"minutes_till", "DateTime$minutes_till", "func(now:DateTime,then:DateTime)->Num"},
|
||||
{"new", "DateTime$new", "func(year:Int,month:Int,day:Int,hour=0,minute=0,second=0.0)->DateTime"},
|
||||
{"parse", "DateTime$parse", "func(text:Text, format=\"%c\")->DateTime?"},
|
||||
{"relative", "DateTime$relative", "func(dt:DateTime,relative_to=DateTime.now(),local_time=yes)->Text"},
|
||||
{"seconds_till", "DateTime$seconds_till", "func(now:DateTime,then:DateTime)->Num"},
|
||||
{"time", "DateTime$time", "func(dt:DateTime,seconds=no,am_pm=yes,local_time=yes)->Text"},
|
||||
{"unix_timestamp", "DateTime$unix_timestamp", "func(dt:DateTime)->Int64"},
|
||||
)},
|
||||
{"Path", Type(TextType, .lang="Path", .env=namespace_env(env, "Path")), "Text_t", "Text$info", TypedArray(ns_entry_t,
|
||||
{"append", "Path$append", "func(path:Path, text:Text, permissions=0o644[32])"},
|
||||
{"append_bytes", "Path$append_bytes", "func(path:Path, bytes:[Byte], permissions=0o644[32])"},
|
||||
@ -292,6 +310,10 @@ env_t *new_compilation_unit(CORD libname)
|
||||
{"write_unique", "Path$write_unique", "func(path:Path, text:Text)->Path"},
|
||||
{"write_unique_bytes", "Path$write_unique_bytes", "func(path:Path, bytes:[Byte])->Path"},
|
||||
|
||||
{"modified", "Path$modified", "func(path:Path, follow_symlinks=yes)->DateTime?"},
|
||||
{"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes)->DateTime?"},
|
||||
{"changed", "Path$changed", "func(path:Path, follow_symlinks=yes)->DateTime?"},
|
||||
|
||||
// Text methods:
|
||||
{"ends_with", "Text$ends_with", "func(path:Path, suffix:Text)->Bool"},
|
||||
{"has", "Text$has", "func(path:Path, pattern:Pattern)->Bool"},
|
||||
@ -380,7 +402,6 @@ env_t *new_compilation_unit(CORD libname)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
set_binding(namespace_env(env, "Shell"), "without_escaping",
|
||||
new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE),
|
||||
.ret=Type(TextType, .lang="Shell", .env=namespace_env(env, "Shell"))),
|
||||
@ -579,7 +600,7 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name)
|
||||
switch (cls_type->tag) {
|
||||
case ArrayType: return NULL;
|
||||
case TableType: return NULL;
|
||||
case CStringType:
|
||||
case CStringType: case DateTimeType:
|
||||
case BoolType: case IntType: case BigIntType: case NumType: {
|
||||
binding_t *b = get_binding(env, CORD_to_const_char_star(type_to_cord(cls_type)));
|
||||
assert(b);
|
||||
|
@ -3,9 +3,10 @@
|
||||
// Common datastructures (arrays, tables, closures)
|
||||
|
||||
#include <gmp.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#define ARRAY_LENGTH_BITS 42
|
||||
#define ARRAY_FREE_BITS 6
|
||||
@ -89,4 +90,7 @@ typedef struct Text_s {
|
||||
#define Pattern_t Text_t
|
||||
#define OptionalPattern_t Text_t
|
||||
|
||||
typedef struct timeval DateTime_t;
|
||||
#define OptionalDateTime_t DateTime_t
|
||||
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||
|
216
stdlib/datetime.c
Normal file
216
stdlib/datetime.c
Normal file
@ -0,0 +1,216 @@
|
||||
// DateTime methods/type info
|
||||
#include <ctype.h>
|
||||
#include <gc.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "optionals.h"
|
||||
#include "patterns.h"
|
||||
#include "stdlib.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
|
||||
public Text_t DateTime$as_text(const DateTime_t *dt, bool colorize, const TypeInfo *type)
|
||||
{
|
||||
(void)type;
|
||||
if (!dt)
|
||||
return Text("DateTime");
|
||||
|
||||
struct tm info;
|
||||
struct tm *final_info = localtime_r(&dt->tv_sec, &info);
|
||||
static char buf[256];
|
||||
size_t len = strftime(buf, sizeof(buf), "%c", 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 DateTime$compare(const DateTime_t *a, const DateTime_t *b, const TypeInfo *type)
|
||||
{
|
||||
(void)type;
|
||||
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);
|
||||
}
|
||||
|
||||
public DateTime_t DateTime$now(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
|
||||
fail("Couldn't get the time!");
|
||||
return (DateTime_t){.tv_sec=ts.tv_sec, .tv_usec=ts.tv_nsec};
|
||||
}
|
||||
|
||||
public DateTime_t DateTime$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second)
|
||||
{
|
||||
struct tm info = {
|
||||
.tm_min=Int_to_Int32(minute, false),
|
||||
.tm_hour=Int_to_Int32(hour, false),
|
||||
.tm_mday=Int_to_Int32(day, false),
|
||||
.tm_mon=Int_to_Int32(month, false) - 1,
|
||||
.tm_year=Int_to_Int32(year, false) - 1900,
|
||||
.tm_isdst=-1,
|
||||
};
|
||||
time_t t = mktime(&info);
|
||||
return (DateTime_t){.tv_sec=t + (time_t)second, .tv_usec=(suseconds_t)(fmod(second, 1.0) * 1e9)};
|
||||
}
|
||||
|
||||
public DateTime_t DateTime$after(DateTime_t dt, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, bool local_time)
|
||||
{
|
||||
double offset = seconds + 60.*minutes + 3600.*hours;
|
||||
dt.tv_sec += (time_t)offset;
|
||||
|
||||
struct tm info = {};
|
||||
if (local_time)
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
else
|
||||
gmtime_r(&dt.tv_sec, &info);
|
||||
info.tm_mday += Int_to_Int32(days, false) + 7*Int_to_Int32(weeks, false);
|
||||
info.tm_mon += Int_to_Int32(months, false);
|
||||
info.tm_year += Int_to_Int32(years, false);
|
||||
|
||||
time_t t = mktime(&info);
|
||||
return (DateTime_t){
|
||||
.tv_sec=t,
|
||||
.tv_usec=dt.tv_usec + (suseconds_t)(fmod(offset, 1.0) * 1e9),
|
||||
};
|
||||
}
|
||||
|
||||
CONSTFUNC public double DateTime$seconds_till(DateTime_t now, DateTime_t then)
|
||||
{
|
||||
return (double)(then.tv_sec - now.tv_sec) + 1e-9*(double)(then.tv_usec - now.tv_usec);
|
||||
}
|
||||
|
||||
CONSTFUNC public double DateTime$minutes_till(DateTime_t now, DateTime_t then)
|
||||
{
|
||||
return DateTime$seconds_till(now, then)/60.;
|
||||
}
|
||||
|
||||
CONSTFUNC public double DateTime$hours_till(DateTime_t now, DateTime_t then)
|
||||
{
|
||||
return DateTime$seconds_till(now, then)/3600.;
|
||||
}
|
||||
|
||||
public void DateTime$get(
|
||||
DateTime_t dt, Int_t *year, Int_t *month, Int_t *day, Int_t *hour, Int_t *minute, Int_t *second,
|
||||
Int_t *nanosecond, Int_t *weekday, bool local_time)
|
||||
{
|
||||
struct tm info = {};
|
||||
if (local_time)
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
else
|
||||
gmtime_r(&dt.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(dt.tv_usec);
|
||||
if (weekday) *weekday = I(info.tm_wday + 1);
|
||||
}
|
||||
|
||||
public Text_t DateTime$format(DateTime_t dt, Text_t fmt, bool local_time)
|
||||
{
|
||||
struct tm info;
|
||||
struct tm *final_info = local_time ? localtime_r(&dt.tv_sec, &info) : gmtime_r(&dt.tv_sec, &info);
|
||||
static char buf[256];
|
||||
size_t len = strftime(buf, sizeof(buf), Text$as_c_string(fmt), final_info);
|
||||
return Text$format("%.*s", (int)len, buf);
|
||||
}
|
||||
|
||||
public Text_t DateTime$date(DateTime_t dt, bool local_time)
|
||||
{
|
||||
return DateTime$format(dt, Text("%F"), local_time);
|
||||
}
|
||||
|
||||
public Text_t DateTime$time(DateTime_t dt, bool seconds, bool am_pm, bool local_time)
|
||||
{
|
||||
Text_t text;
|
||||
if (seconds)
|
||||
text = DateTime$format(dt, am_pm ? Text("%l:%M:%S%P") : Text("%T"), local_time);
|
||||
else
|
||||
text = DateTime$format(dt, am_pm ? Text("%l:%M%P") : Text("%H:%M"), local_time);
|
||||
return Text$trim(text, Pattern(" "), true, true);
|
||||
}
|
||||
|
||||
public OptionalDateTime_t DateTime$parse(Text_t text, Text_t format)
|
||||
{
|
||||
struct tm info = {.tm_isdst=-1};
|
||||
char *invalid = strptime(Text$as_c_string(text), Text$as_c_string(format), &info);
|
||||
if (!invalid || invalid[0] != '\0')
|
||||
return NULL_DATETIME;
|
||||
|
||||
time_t t = mktime(&info);
|
||||
return (DateTime_t){.tv_sec=t};
|
||||
}
|
||||
|
||||
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 DateTime$relative(DateTime_t dt, DateTime_t relative_to, bool local_time)
|
||||
{
|
||||
struct tm info = {};
|
||||
if (local_time)
|
||||
localtime_r(&dt.tv_sec, &info);
|
||||
else
|
||||
gmtime_r(&dt.tv_sec, &info);
|
||||
|
||||
struct tm relative_info = {};
|
||||
if (local_time)
|
||||
localtime_r(&relative_to.tv_sec, &relative_info);
|
||||
else
|
||||
gmtime_r(&relative_to.tv_sec, &relative_info);
|
||||
|
||||
double second_diff = DateTime$seconds_till(relative_to, dt);
|
||||
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 DateTime$unix_timestamp(DateTime_t dt)
|
||||
{
|
||||
return (Int64_t)(dt.tv_sec);
|
||||
}
|
||||
|
||||
CONSTFUNC public DateTime_t DateTime$from_unix_timestamp(Int64_t timestamp)
|
||||
{
|
||||
return (DateTime_t){.tv_sec=(time_t)timestamp};
|
||||
}
|
||||
|
||||
public const TypeInfo DateTime$info = {
|
||||
.size=sizeof(DateTime_t),
|
||||
.align=__alignof__(DateTime_t),
|
||||
.tag=CustomInfo,
|
||||
.CustomInfo={
|
||||
.as_text=(void*)DateTime$as_text,
|
||||
.compare=(void*)DateTime$compare,
|
||||
},
|
||||
};
|
||||
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
32
stdlib/datetime.h
Normal file
32
stdlib/datetime.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
// DateTime objects
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "integers.h"
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
|
||||
Text_t DateTime$as_text(const DateTime_t *dt, bool colorize, const TypeInfo *type);
|
||||
PUREFUNC int32_t DateTime$compare(const DateTime_t *a, const DateTime_t *b, const TypeInfo *type);
|
||||
DateTime_t DateTime$now(void);
|
||||
DateTime_t DateTime$new(Int_t year, Int_t month, Int_t day, Int_t hour, Int_t minute, double second);
|
||||
DateTime_t DateTime$after(DateTime_t dt, double seconds, double minutes, double hours, Int_t days, Int_t weeks, Int_t months, Int_t years, bool local_time);
|
||||
CONSTFUNC double DateTime$seconds_till(DateTime_t now, DateTime_t then);
|
||||
CONSTFUNC double DateTime$minutes_till(DateTime_t now, DateTime_t then);
|
||||
CONSTFUNC double DateTime$hours_till(DateTime_t now, DateTime_t then);
|
||||
void DateTime$get(DateTime_t dt, Int_t *year, Int_t *month, Int_t *day, Int_t *hour, Int_t *minute, Int_t *second, Int_t *nanosecond, Int_t *weekday, bool local_time);
|
||||
Text_t DateTime$format(DateTime_t dt, Text_t fmt, bool local_time);
|
||||
Text_t DateTime$date(DateTime_t dt, bool local_time);
|
||||
Text_t DateTime$time(DateTime_t dt, bool seconds, bool am_pm, bool local_time);
|
||||
OptionalDateTime_t DateTime$parse(Text_t text, Text_t format);
|
||||
Text_t DateTime$relative(DateTime_t dt, DateTime_t relative_to, bool local_time);
|
||||
CONSTFUNC Int64_t DateTime$unix_timestamp(DateTime_t dt);
|
||||
CONSTFUNC DateTime_t DateTime$from_unix_timestamp(Int64_t timestamp);
|
||||
|
||||
extern const TypeInfo DateTime$info;
|
||||
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||
|
@ -5,10 +5,11 @@
|
||||
#include "bools.h"
|
||||
#include "bytes.h"
|
||||
#include "datatypes.h"
|
||||
#include "datetime.h"
|
||||
#include "integers.h"
|
||||
#include "metamethods.h"
|
||||
#include "threads.h"
|
||||
#include "text.h"
|
||||
#include "threads.h"
|
||||
#include "util.h"
|
||||
|
||||
public PUREFUNC bool is_null(const void *obj, const TypeInfo *non_optional_type)
|
||||
@ -31,6 +32,8 @@ public PUREFUNC bool is_null(const void *obj, const TypeInfo *non_optional_type)
|
||||
return ((OptionalByte_t*)obj)->is_null;
|
||||
else if (non_optional_type == &Thread$info)
|
||||
return *(pthread_t**)obj == NULL;
|
||||
else if (non_optional_type == &DateTime$info)
|
||||
return ((OptionalDateTime_t*)obj)->tv_usec < 0;
|
||||
|
||||
switch (non_optional_type->tag) {
|
||||
case ChannelInfo: return *(Channel_t**)obj == NULL;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define NULL_TABLE ((OptionalTable_t){.entries.length=-1})
|
||||
#define NULL_CLOSURE ((OptionalClosure_t){.fn=NULL})
|
||||
#define NULL_TEXT ((OptionalText_t){.length=-1})
|
||||
#define NULL_DATETIME ((OptionalDateTime_t){.tv_usec=-1})
|
||||
|
||||
PUREFUNC bool is_null(const void *obj, const TypeInfo *non_optional_type);
|
||||
Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo *type);
|
||||
|
@ -157,56 +157,77 @@ public bool Path$exists(Path_t path)
|
||||
return (stat(Text$as_c_string(path), &sb) == 0);
|
||||
}
|
||||
|
||||
public bool Path$is_file(Path_t path, bool follow_symlinks)
|
||||
static inline int path_stat(Path_t path, bool follow_symlinks, struct stat *sb)
|
||||
{
|
||||
path = Path$_expand_home(path);
|
||||
struct stat sb;
|
||||
const char *path_str = Text$as_c_string(path);
|
||||
int status = follow_symlinks ? stat(path_str, &sb) : lstat(path_str, &sb);
|
||||
return follow_symlinks ? stat(path_str, sb) : lstat(path_str, sb);
|
||||
}
|
||||
|
||||
public bool Path$is_file(Path_t path, bool follow_symlinks)
|
||||
{
|
||||
struct stat sb;
|
||||
int status = path_stat(path, follow_symlinks, &sb);
|
||||
if (status != 0) return false;
|
||||
return (sb.st_mode & S_IFMT) == S_IFREG;
|
||||
}
|
||||
|
||||
public bool Path$is_directory(Path_t path, bool follow_symlinks)
|
||||
{
|
||||
path = Path$_expand_home(path);
|
||||
struct stat sb;
|
||||
const char *path_str = Text$as_c_string(path);
|
||||
int status = follow_symlinks ? stat(path_str, &sb) : lstat(path_str, &sb);
|
||||
int status = path_stat(path, follow_symlinks, &sb);
|
||||
if (status != 0) return false;
|
||||
return (sb.st_mode & S_IFMT) == S_IFDIR;
|
||||
}
|
||||
|
||||
public bool Path$is_pipe(Path_t path, bool follow_symlinks)
|
||||
{
|
||||
path = Path$_expand_home(path);
|
||||
struct stat sb;
|
||||
const char *path_str = Text$as_c_string(path);
|
||||
int status = follow_symlinks ? stat(path_str, &sb) : lstat(path_str, &sb);
|
||||
int status = path_stat(path, follow_symlinks, &sb);
|
||||
if (status != 0) return false;
|
||||
return (sb.st_mode & S_IFMT) == S_IFIFO;
|
||||
}
|
||||
|
||||
public bool Path$is_socket(Path_t path, bool follow_symlinks)
|
||||
{
|
||||
path = Path$_expand_home(path);
|
||||
struct stat sb;
|
||||
const char *path_str = Text$as_c_string(path);
|
||||
int status = follow_symlinks ? stat(path_str, &sb) : lstat(path_str, &sb);
|
||||
int status = path_stat(path, follow_symlinks, &sb);
|
||||
if (status != 0) return false;
|
||||
return (sb.st_mode & S_IFMT) == S_IFSOCK;
|
||||
}
|
||||
|
||||
public bool Path$is_symlink(Path_t path)
|
||||
{
|
||||
path = Path$_expand_home(path);
|
||||
struct stat sb;
|
||||
const char *path_str = Text$as_c_string(path);
|
||||
int status = stat(path_str, &sb);
|
||||
int status = path_stat(path, false, &sb);
|
||||
if (status != 0) return false;
|
||||
return (sb.st_mode & S_IFMT) == S_IFLNK;
|
||||
}
|
||||
|
||||
public OptionalDateTime_t Path$modified(Path_t path, bool follow_symlinks)
|
||||
{
|
||||
struct stat sb;
|
||||
int status = path_stat(path, follow_symlinks, &sb);
|
||||
if (status != 0) return NULL_DATETIME;
|
||||
return (DateTime_t){.tv_sec=sb.st_mtime};
|
||||
}
|
||||
|
||||
public OptionalDateTime_t Path$accessed(Path_t path, bool follow_symlinks)
|
||||
{
|
||||
struct stat sb;
|
||||
int status = path_stat(path, follow_symlinks, &sb);
|
||||
if (status != 0) return NULL_DATETIME;
|
||||
return (DateTime_t){.tv_sec=sb.st_atime};
|
||||
}
|
||||
|
||||
public OptionalDateTime_t Path$changed(Path_t path, bool follow_symlinks)
|
||||
{
|
||||
struct stat sb;
|
||||
int status = path_stat(path, follow_symlinks, &sb);
|
||||
if (status != 0) return NULL_DATETIME;
|
||||
return (DateTime_t){.tv_sec=sb.st_ctime};
|
||||
}
|
||||
|
||||
static void _write(Path_t path, Array_t bytes, int mode, int permissions)
|
||||
{
|
||||
path = Path$_expand_home(path);
|
||||
|
@ -26,6 +26,9 @@ bool Path$is_directory(Path_t path, bool follow_symlinks);
|
||||
bool Path$is_pipe(Path_t path, bool follow_symlinks);
|
||||
bool Path$is_socket(Path_t path, bool follow_symlinks);
|
||||
bool Path$is_symlink(Path_t path);
|
||||
OptionalDateTime_t Path$modified(Path_t path, bool follow_symlinks);
|
||||
OptionalDateTime_t Path$accessed(Path_t path, bool follow_symlinks);
|
||||
OptionalDateTime_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);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "c_strings.h"
|
||||
#include "channels.h"
|
||||
#include "datatypes.h"
|
||||
#include "datetime.h"
|
||||
#include "functiontype.h"
|
||||
#include "integers.h"
|
||||
#include "memory.h"
|
||||
|
3
types.c
3
types.c
@ -25,6 +25,7 @@ CORD type_to_cord(type_t *t) {
|
||||
case BoolType: return "Bool";
|
||||
case ByteType: return "Byte";
|
||||
case CStringType: return "CString";
|
||||
case DateTimeType: return "DateTime";
|
||||
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);
|
||||
@ -405,6 +406,7 @@ 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 DateTimeType: return sizeof(DateTime_t);
|
||||
case BigIntType: return sizeof(Int_t);
|
||||
case IntType: {
|
||||
switch (Match(t, IntType)->bits) {
|
||||
@ -484,6 +486,7 @@ 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 DateTimeType: return __alignof__(DateTime_t);
|
||||
case BigIntType: return __alignof__(Int_t);
|
||||
case IntType: {
|
||||
switch (Match(t, IntType)->bits) {
|
||||
|
3
types.h
3
types.h
@ -48,6 +48,7 @@ struct type_s {
|
||||
IntType,
|
||||
NumType,
|
||||
CStringType,
|
||||
DateTimeType,
|
||||
TextType,
|
||||
ArrayType,
|
||||
ChannelType,
|
||||
@ -77,7 +78,7 @@ struct type_s {
|
||||
struct {
|
||||
enum { TYPE_NBITS32=32, TYPE_NBITS64=64 } bits;
|
||||
} NumType;
|
||||
struct {} CStringType;
|
||||
struct {} CStringType, DateTimeType;
|
||||
struct {
|
||||
const char *lang;
|
||||
struct env_s *env;
|
||||
|
Loading…
Reference in New Issue
Block a user