Skip to content

Commit

Permalink
Re-implemented the 'other' literal types: (#91)
Browse files Browse the repository at this point in the history
Datetime
Time
Date
Size
Duration

URLs are done not as a separate type, but as a literal modifier that
calls CURL's URL validation (loose as it is).

Added an option to turn on / off static binding of calls exposed via
the FFI. If not set, it's on if glibc is off on linux, and off by
default on mac.

Also, for simple assignment ONLY, if the assignment is to a variable
with an explicitly declared type (and that type is a simple literal),
then we will infer the litmod type, picking the first one added
associated with the type.w

Some issue with the dynamic binding test in meson; just always leave static on for now.
  • Loading branch information
viega authored Jul 25, 2024
1 parent 1da1ac5 commit de5b659
Show file tree
Hide file tree
Showing 56 changed files with 3,007 additions and 267 deletions.
53 changes: 5 additions & 48 deletions doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -533,74 +533,31 @@ BITYPE ::= "void" | "bool" | "i8" | "byte" | "i32" | "char" | "u32" | "int" |
EOS ::= '\n' | ';' <<or, if followed by a '}' or line comment, then ''>>
```

# Builtin methods used by the language
- $repr

# Features to re-add from old con4m
- VM save restore
- Arg parsing
- Libraries
- Doc API.
- Checkpointing
- Hot loading
- Finish data types (date, ip, and extra hatrack stuff)
- Change $result back to result (or alias?)
- Libraries (but only the ones Chalk needs)
- Final mile: specs
- Final mile: params
- Auto-import standard library.
- Doc API.
- Callbacks
- Len, etc.
- Make litmods optional when types are declared.

# Items for afterward
- Objects
- Folding
- Casting
- Mixed
- Varargs functions
- Clean up unused instructions in VM
- Remove the two-words-per-stack-slot thing; it's not needed anymore.
- automatic logfd + optional server for log messages
- REPL
- Keyword arguments
- 'maybe' types / nil
- Aspects (before / after / around pattern(sig) when x)
- Casting
- (Possibly) re-add := literals
- Threading
- Mixed
- Pretty printing w/ type annotations
- Language server
- Checks based on PDG
- Full-program info on unused fields & fns.

# Features removed (considered for adding back in)
Also, the language accepts ":=", which has the special syntax of
generating a "=" operator, then tries to automatically determine the
(non-numeric) literal type automatically by running through a
prioritized list of literal parsers (currently intended for the
config-focused literals).

For instance:

```
now := 11 Jan 2024
```

Is equal to:

```
now = "11 Jan 2024"'date
```

Note that currently, without a literal modifier, "" always assume
'string', so the following does NOT work:

```
var now: date
now = "11 Jan 2024"
```

This gives a string vs. date type error. `:=` is the thing that says,
"try to be smart!"

The lexer actually does the conversion, adding an assignment token and the
`OTHERLIT` token (which maybe we should change to be more descriptive?)

14 changes: 14 additions & 0 deletions include/adts/datetime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once
#include "con4m.h"

typedef struct c4m_date_time_t {
struct tm dt;
int64_t fracsec;
unsigned int have_time : 1;
unsigned int have_sec : 1;
unsigned int have_frac_sec : 1;
unsigned int have_month : 1;
unsigned int have_year : 1;
unsigned int have_day : 1;
unsigned int have_offset : 1;
} c4m_date_time_t;
12 changes: 12 additions & 0 deletions include/adts/duration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once
#include "con4m.h"

extern c4m_duration_t *c4m_now(void);
extern c4m_duration_t *c4m_timestamp(void);
extern c4m_duration_t *c4m_process_cpu(void);
extern c4m_duration_t *c4m_thread_cpu(void);
extern c4m_duration_t *c4m_uptime(void);
extern c4m_duration_t *c4m_program_clock(void);
extern void c4m_init_program_timestamp(void);
extern c4m_duration_t *c4m_duration_diff(c4m_duration_t *,
c4m_duration_t *);
12 changes: 12 additions & 0 deletions include/adts/ipaddr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once
#include "con4m.h"

// I realize some of this is redundant, but it's just easier.
typedef struct {
char addr[sizeof(struct sockaddr_in6)];
uint16_t port;
int32_t af;
} c4m_ipaddr_t;

extern void
c4m_ipaddr_set_address(c4m_ipaddr_t *obj, c4m_str_t *s, uint16_t port);
1 change: 1 addition & 0 deletions include/adts/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ extern bool c4m_list_contains(c4m_list_t *, c4m_obj_t);
extern c4m_list_t *c4m_list_copy(c4m_list_t *);
extern c4m_list_t *c4m_list_shallow_copy(c4m_list_t *);
extern void c4m_list_sort(c4m_list_t *, c4m_sort_fn);
extern void c4m_list_resize(c4m_list_t *, size_t);
3 changes: 1 addition & 2 deletions include/adts/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extern c4m_utf8_t *c4m_rich(c4m_utf8_t *, c4m_utf8_t *style);
extern c4m_codepoint_t c4m_index(const c4m_str_t *, int64_t);
extern bool c4m_str_can_coerce_to(c4m_type_t *, c4m_type_t *);
extern c4m_obj_t c4m_str_coerce_to(const c4m_str_t *, c4m_type_t *);
extern c4m_list_t *c4m_str_xsplit(c4m_str_t *, c4m_str_t *);
extern c4m_list_t *c4m_str_split(c4m_str_t *, c4m_str_t *);
extern struct flexarray_t *c4m_str_fsplit(c4m_str_t *, c4m_str_t *);
extern bool c4m_str_starts_with(const c4m_str_t *,
const c4m_str_t *);
Expand All @@ -37,7 +37,6 @@ extern c4m_utf32_t *c4m_title_case(c4m_str_t *);
extern c4m_str_t *c4m_str_pad(c4m_str_t *, int64_t);
extern c4m_utf8_t *c4m_str_to_hex(c4m_str_t *, bool);

#define c4m_str_split(x, y) c4m_str_xsplit(x, y)
// This is in richlit.c
extern c4m_utf8_t *c4m_rich_lit(char *);

Expand Down
6 changes: 6 additions & 0 deletions include/compiler/dt_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ typedef enum {
c4m_internal_type_error,
c4m_err_concrete_index,
c4m_err_non_dict_index_type,
c4m_err_invalid_ip,
c4m_err_invalid_dt_spec,
c4m_err_invalid_date_spec,
c4m_err_invalid_time_spec,
c4m_err_invalid_size_lit,
c4m_err_invalid_duration_lit,
#ifdef C4M_DEV
c4m_err_void_print,
#endif
Expand Down
4 changes: 3 additions & 1 deletion include/con4m.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#pragma once

#include "con4m/config.h"
// Useful options (mainly for dev) are commented out here.
// The logic below (and into the relevent header files) sets up defaults.
Expand Down Expand Up @@ -115,6 +114,9 @@

#include "adts/dict.h"
#include "adts/set.h"
#include "adts/ipaddr.h"
#include "adts/datetime.h"
#include "adts/duration.h"

#include "core/ffi.h"
#include "util/watch.h"
Expand Down
1 change: 1 addition & 0 deletions include/con4m/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <dlfcn.h>
#include <pwd.h>
#include <dirent.h>
#include <ctype.h>

#include <sys/select.h>
#include <sys/types.h>
Expand Down
3 changes: 3 additions & 0 deletions include/con4m/datatypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ typedef struct hatrack_set_st c4m_set_t;
#include "compiler/dt_module.h"
#include "compiler/dt_compile.h"

typedef uint64_t c4m_size_t;
typedef struct timespec c4m_duration_t;

typedef c4m_str_t *(*c4m_repr_fn)(c4m_obj_t);
typedef void (*c4m_marshal_fn)(c4m_obj_t,
c4m_stream_t *,
Expand Down
1 change: 1 addition & 0 deletions include/core/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ extern void c4m_get_heap_bounds(uint64_t *, uint64_t *, uint64_t *);
extern void c4m_gc_register_collect_fns(c4m_gc_hook, c4m_gc_hook);
extern c4m_alloc_hdr *c4m_find_alloc(void *);
extern bool c4m_in_heap(void *);
extern void c4m_header_gc_bits(uint64_t *, c4m_base_obj_t *);

#ifdef C4M_GC_STATS
uint64_t c4m_get_alloc_counter();
Expand Down
20 changes: 10 additions & 10 deletions include/core/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,36 @@ extern char **c4m_stashed_argv;
extern char **c4m_stashed_envp;

static inline char **
c4m_raw_argv()
c4m_raw_argv(void)
{
return c4m_stashed_argv;
}

static inline char **
c4m_raw_envp()
c4m_raw_envp(void)
{
return c4m_stashed_envp;
}

extern c4m_list_t *c4m_get_program_arguments();
extern c4m_utf8_t *c4m_get_argv0();
extern c4m_list_t *c4m_get_program_arguments(void);
extern c4m_utf8_t *c4m_get_argv0(void);
extern c4m_utf8_t *c4m_get_env(c4m_utf8_t *);
extern c4m_dict_t *c4m_environment();
extern c4m_dict_t *c4m_environment(void);
extern c4m_utf8_t *c4m_path_search(c4m_utf8_t *, c4m_utf8_t *);
extern c4m_utf8_t *c4m_con4m_root();
c4m_utf8_t *c4m_system_module_path();

extern c4m_utf8_t *c4m_con4m_root(void);
extern c4m_utf8_t *c4m_system_module_path(void);
extern void c4m_add_static_symbols(void);
extern c4m_list_t *con4m_path;
extern c4m_set_t *con4m_extensions;

static inline c4m_list_t *
c4m_get_module_search_path()
c4m_get_module_search_path(void)
{
return con4m_path;
}

static inline c4m_set_t *
c4m_get_allowed_file_extensions()
c4m_get_allowed_file_extensions(void)
{
return con4m_extensions;
}
3 changes: 2 additions & 1 deletion include/core/literal.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once
#include "con4m.h"

extern __uint128_t c4m_raw_int_parse(char *,
extern __uint128_t c4m_raw_int_parse(c4m_utf8_t *,
c4m_compile_error_t *,
bool *);
extern __uint128_t c4m_raw_hex_parse(char *,
Expand All @@ -15,3 +15,4 @@ extern c4m_compile_error_t c4m_parse_simple_lit(c4m_token_t *,
c4m_utf8_t **);
extern c4m_builtin_t c4m_base_type_from_litmod(c4m_lit_syntax_t,
c4m_utf8_t *);
extern bool c4m_fix_litmod(c4m_token_t *, c4m_pnode_t *);
5 changes: 5 additions & 0 deletions include/core/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,8 @@ extern const c4m_vtable_t c4m_callback_vtable;
extern const c4m_vtable_t c4m_flags_vtable;
extern const c4m_vtable_t c4m_box_vtable;
extern const c4m_vtable_t c4m_basic_http_vtable;
extern const c4m_vtable_t c4m_datetime_vtable;
extern const c4m_vtable_t c4m_date_vtable;
extern const c4m_vtable_t c4m_time_vtable;
extern const c4m_vtable_t c4m_size_vtable;
extern const c4m_vtable_t c4m_duration_vtable;
6 changes: 3 additions & 3 deletions include/core/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,15 +315,15 @@ c4m_type_typespec()
}

static inline c4m_type_t *
c4m_type_ipv4()
c4m_type_ip()
{
return c4m_bi_types[C4M_T_IPV4];
}

static inline c4m_type_t *
c4m_type_ipv6()
c4m_type_ipv4()
{
return c4m_bi_types[C4M_T_IPV6];
return c4m_bi_types[C4M_T_IPV4];
}

static inline c4m_type_t *
Expand Down
8 changes: 8 additions & 0 deletions include/io/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ extern c4m_basic_http_response_t *_c4m_http_upload(c4m_str_t *,
c4m_buf_t *,
...);

static inline bool
c4m_validate_url(c4m_utf8_t *candidate)
{
CURLU *handle = curl_url();

return curl_url_set(handle, CURLUPART_URL, candidate->data, 0) == CURLUE_OK;
}

static inline bool
c4m_http_op_succeded(c4m_basic_http_response_t *op)
{
Expand Down
6 changes: 3 additions & 3 deletions include/util/wrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#include "con4m.h"

extern c4m_utf32_t *c4m_wrapper_join(c4m_list_t *, const c4m_str_t *);
extern c4m_str_t *c4m_wrapper_hostname();
extern c4m_str_t *c4m_wrapper_os();
extern c4m_str_t *c4m_wrapper_arch();
extern c4m_str_t *c4m_wrapper_hostname(void);
extern c4m_str_t *c4m_wrapper_os(void);
extern c4m_str_t *c4m_wrapper_arch(void);
extern c4m_str_t *c4m_wrapper_repr(c4m_obj_t);
extern c4m_str_t *c4m_wrapper_to_str(c4m_obj_t);
extern void c4m_snap_column(c4m_grid_t *, int64_t);
11 changes: 10 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ project(
license: 'MIT',
)


cc = meson.get_compiler('c')
incdir = include_directories('include')
using_osx = false
Expand Down Expand Up @@ -65,6 +64,12 @@ if get_option('forkless_tests').enabled()
c_args = c_args + ['-DC4M_TEST_WITHOUT_FORK']
endif



if not get_option('static_ffi_binding').disabled()
c_args = c_args + ['-DC4M_STATIC_FFI_BINDING']
endif

backtrace = cc.find_library('backtrace', required: false)

if backtrace.found()
Expand Down Expand Up @@ -208,6 +213,9 @@ c4m_adts = [
'src/adts/mixed.c',
'src/adts/tuple.c',
'src/adts/ipaddr.c',
'src/adts/datetime.c',
'src/adts/size.c',
'src/adts/duration.c',
'src/adts/callback.c',
'src/adts/streams.c',
'src/adts/flags.c',
Expand Down Expand Up @@ -328,6 +336,7 @@ test_src = [

threads = dependency('threads')
math = cc.find_library('m', required: false)

ffi = cc.find_library(
'ffi',
required: true
Expand Down
7 changes: 7 additions & 0 deletions meson.options
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,11 @@ option(
type: 'feature',
value: 'auto',
description: 'Run test suite without forking',
)

option(
'static_ffi_binding',
type: 'feature',
value: 'auto',
description: 'Whether to statically bind native builtins in std library',
)
Loading

0 comments on commit de5b659

Please sign in to comment.