mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Some refactoring of ranges. env::AUTHORS and env::AUTHOR_EMAILS
This commit is contained in:
@@ -198,6 +198,7 @@ macro bool os_is_posix() @const
|
||||
return false;
|
||||
$endswitch
|
||||
}
|
||||
|
||||
const String[] AUTHORS = $$AUTHORS;
|
||||
const String[] AUTHOR_EMAILS = $$AUTHOR_EMAILS;
|
||||
const BUILTIN_EXPECT_IS_DISABLED = $feature(DISABLE_BUILTIN_EXPECT);
|
||||
const BUILTIN_PREFETCH_IS_DISABLED = $feature(DISABLE_BUILTIN_PREFETCH);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
- `$is_const` is deprecated in favour of `@is_const` based on `$defined`.
|
||||
- Multiline contract comments #2113
|
||||
- Removed the use of temp allocator in backtrace printing.
|
||||
- `env::AUTHORS` and `env::AUTHOR_EMAILS` added.
|
||||
|
||||
### Fixes
|
||||
- mkdir/rmdir would not work properly with substring paths on non-windows platforms.
|
||||
|
||||
@@ -3,6 +3,8 @@ import std;
|
||||
import bar;
|
||||
import clib;
|
||||
import clib2;
|
||||
import std::core::env;
|
||||
|
||||
|
||||
fn int test_doubler(int x) @if(env::WIN32) => x * x;
|
||||
extern fn int test_doubler(int) @if(!env::WIN32);
|
||||
@@ -11,6 +13,11 @@ extern fn void printf(char *, ...);
|
||||
fn int main()
|
||||
{
|
||||
printf("Hello World!\n");
|
||||
printf("Authors:");
|
||||
io::printn(env::AUTHORS);
|
||||
printf("Author emails:");
|
||||
io::printn(env::AUTHOR_EMAILS);
|
||||
|
||||
bar::test();
|
||||
printf("Hello double: %d\n", test_doubler(11));
|
||||
if ($feature(ABCD)) io::printn("ABCD");
|
||||
|
||||
@@ -599,6 +599,12 @@ typedef struct BuildOptions_
|
||||
bool testing;
|
||||
} BuildOptions;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *author;
|
||||
const char *email;
|
||||
} AuthorEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct Library__ *parent;
|
||||
@@ -728,6 +734,7 @@ typedef struct
|
||||
const char **csources;
|
||||
const char **cinclude_dirs;
|
||||
const char **exec;
|
||||
AuthorEntry *authors;
|
||||
const char **feature_list;
|
||||
const char *custom_linker_path;
|
||||
struct
|
||||
|
||||
@@ -184,7 +184,29 @@ static void load_into_build_target(BuildParseContext context, JSONObject *json,
|
||||
error_exit("Error reading %s: output extension '%s' must start with a '.'", context.file, target->extension);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
const char **authors = get_optional_string_array(context, json, "authors");
|
||||
AuthorEntry *author_list = NULL;
|
||||
FOREACH(const char *, author, authors)
|
||||
{
|
||||
const char *email_start = strstr(author, "<");
|
||||
if (email_start)
|
||||
{
|
||||
const char *end = strstr(email_start + 1, ">");
|
||||
if (!end || end[1] != 0 || email_start + 1 == end) error_exit("Error reading %s: invalid author format '%s'", author);
|
||||
const char *email = str_trim(str_copy(email_start + 1, end - email_start - 1));
|
||||
AuthorEntry entry = { str_trim(str_copy(author, email_start - author)), email };
|
||||
vec_add(author_list, entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthorEntry entry = { str_trim(str_dup(author)), NULL };
|
||||
vec_add(author_list, entry);
|
||||
}
|
||||
}
|
||||
target->authors = author_list;
|
||||
}
|
||||
// "Before compilation" execution
|
||||
APPEND_STRING_LIST(&target->exec, "exec");
|
||||
|
||||
|
||||
@@ -1489,7 +1489,22 @@ void compile()
|
||||
setup_bool_define("THREAD_SANITIZER", compiler.build.feature.sanitize_thread);
|
||||
setup_string_define("BUILD_HASH", GIT_HASH);
|
||||
setup_string_define("BUILD_DATE", compiler_date_to_iso());
|
||||
|
||||
Expr *expr_names = expr_new(EXPR_CONST, INVALID_SPAN);
|
||||
Expr *expr_emails = expr_new(EXPR_CONST, INVALID_SPAN);
|
||||
expr_names->const_expr.const_kind = CONST_UNTYPED_LIST;
|
||||
expr_emails->const_expr.const_kind = CONST_UNTYPED_LIST;
|
||||
expr_names->type = type_untypedlist;
|
||||
expr_emails->type = type_untypedlist;
|
||||
expr_names->resolve_status = expr_names->resolve_status = RESOLVE_DONE;
|
||||
FOREACH(AuthorEntry, entry, compiler.build.authors)
|
||||
{
|
||||
Expr *const_name = expr_new_const_string(INVALID_SPAN, entry.author); // NOLINT
|
||||
Expr *const_email = expr_new_const_string(INVALID_SPAN, entry.email ? entry.email : ""); // NOLINT
|
||||
vec_add(expr_names->const_expr.untyped_list, const_name);
|
||||
vec_add(expr_emails->const_expr.untyped_list, const_email);
|
||||
}
|
||||
setup_define("AUTHORS", expr_names);
|
||||
setup_define("AUTHOR_EMAILS", expr_emails);
|
||||
type_init_cint();
|
||||
compiler_init_time = bench_mark();
|
||||
|
||||
|
||||
@@ -710,8 +710,10 @@ typedef enum RangeType
|
||||
RANGE_CONST_END,
|
||||
RANGE_CONST_LEN,
|
||||
RANGE_CONST_RANGE,
|
||||
RANGE_SINGLE_ELEMENT,
|
||||
} RangeType;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ResolveStatus status : 3;
|
||||
@@ -719,7 +721,6 @@ typedef struct
|
||||
bool start_from_end : 1;
|
||||
bool end_from_end : 1;
|
||||
bool is_len : 1;
|
||||
bool is_range : 1;
|
||||
bool is_optional : 1;
|
||||
union
|
||||
{
|
||||
|
||||
@@ -195,6 +195,8 @@ void copy_range(CopyStruct *c, Range *range)
|
||||
{
|
||||
switch (range->range_type)
|
||||
{
|
||||
case RANGE_SINGLE_ELEMENT:
|
||||
UNREACHABLE
|
||||
case RANGE_CONST_LEN:
|
||||
case RANGE_CONST_END:
|
||||
MACRO_COPY_EXPRID(range->start);
|
||||
|
||||
@@ -904,6 +904,8 @@ bool expr_is_pure(Expr *expr)
|
||||
if (!exprid_is_pure(expr->slice_expr.expr)) return false;
|
||||
switch (expr->slice_expr.range.range_type)
|
||||
{
|
||||
case RANGE_SINGLE_ELEMENT:
|
||||
UNREACHABLE
|
||||
case RANGE_CONST_RANGE:
|
||||
return true;
|
||||
case RANGE_CONST_END:
|
||||
|
||||
@@ -2611,6 +2611,8 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
BEValue start_index;
|
||||
switch (range.range_type)
|
||||
{
|
||||
case RANGE_SINGLE_ELEMENT:
|
||||
UNREACHABLE
|
||||
case RANGE_DYNAMIC:
|
||||
case RANGE_CONST_LEN:
|
||||
case RANGE_CONST_END:
|
||||
@@ -2680,6 +2682,8 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r
|
||||
// Get the index.
|
||||
switch (range.range_type)
|
||||
{
|
||||
case RANGE_SINGLE_ELEMENT:
|
||||
UNREACHABLE
|
||||
case RANGE_DYNAMIC:
|
||||
llvm_emit_exprid(c, &end_index, range.end);
|
||||
llvm_value_rvalue(c, &end_index);
|
||||
|
||||
@@ -50,12 +50,10 @@ bool parse_range(ParseContext *c, Range *range)
|
||||
bool is_len_range = range->is_len = try_consume(c, TOKEN_COLON);
|
||||
if (!is_len_range && !try_consume(c, TOKEN_DOTDOT))
|
||||
{
|
||||
// Otherwise this is not a range.
|
||||
range->is_range = false;
|
||||
// Otherwise this is a single element
|
||||
range->range_type = RANGE_SINGLE_ELEMENT;
|
||||
return true;
|
||||
}
|
||||
range->is_range = true;
|
||||
|
||||
// Is there an expression next?
|
||||
range->end_from_end = try_consume(c, TOKEN_BIT_XOR);
|
||||
if (range->end_from_end || parse_current_is_expr(c))
|
||||
@@ -443,6 +441,11 @@ Expr *parse_vasplat(ParseContext *c)
|
||||
if (try_consume(c, TOKEN_LBRACKET))
|
||||
{
|
||||
if (!parse_range(c, &expr->vasplat_expr)) return poisoned_expr;
|
||||
if (expr->vasplat_expr.range_type == RANGE_SINGLE_ELEMENT)
|
||||
{
|
||||
PRINT_ERROR_AT(expr, "$vasplat expected a range.");
|
||||
return poisoned_expr;
|
||||
}
|
||||
CONSUME_OR_RET(TOKEN_RBRACKET, poisoned_expr);
|
||||
}
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
@@ -1052,7 +1055,7 @@ static Expr *parse_subscript_expr(ParseContext *c, Expr *left, SourceSpan lhs_st
|
||||
Range range = { .range_type = RANGE_DYNAMIC };
|
||||
if (!parse_range(c, &range)) return poisoned_expr;
|
||||
CONSUME_OR_RET(TOKEN_RBRACKET, poisoned_expr);
|
||||
if (!range.is_range)
|
||||
if (range.range_type == RANGE_SINGLE_ELEMENT)
|
||||
{
|
||||
subs_expr->subscript_expr.index = (SubscriptIndex) {
|
||||
.expr = range.start,
|
||||
|
||||
@@ -1146,7 +1146,8 @@ static inline bool sema_identifier_find_possible_inferred(SemaContext *context,
|
||||
|
||||
static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr)
|
||||
{
|
||||
ASSERT_SPAN(expr, expr && expr->unresolved_ident_expr.ident);
|
||||
ASSERT(expr);
|
||||
ASSERT_SPAN(expr, expr->unresolved_ident_expr.ident);
|
||||
DEBUG_LOG("Resolving identifier '%s'", expr->unresolved_ident_expr.ident);
|
||||
|
||||
ASSERT_SPAN(expr, expr->resolve_status != RESOLVE_DONE);
|
||||
@@ -6212,11 +6213,6 @@ static Expr **sema_vasplat_insert(SemaContext *context, Expr **init_expressions,
|
||||
unsigned start_idx = 0;
|
||||
if (start)
|
||||
{
|
||||
if (!range->is_range)
|
||||
{
|
||||
SEMA_ERROR(expr, "$vasplat expected a range.");
|
||||
return NULL;
|
||||
}
|
||||
if (!sema_analyse_expr(context, start)) return NULL;
|
||||
if (!expr_is_const_int(start))
|
||||
{
|
||||
|
||||
@@ -190,6 +190,8 @@ static inline IndexDiff range_const_len(Range *range)
|
||||
{
|
||||
switch (range->range_type)
|
||||
{
|
||||
case RANGE_SINGLE_ELEMENT:
|
||||
UNREACHABLE;
|
||||
case RANGE_CONST_LEN:
|
||||
return range->const_end;
|
||||
case RANGE_CONST_END:
|
||||
|
||||
@@ -453,6 +453,8 @@ RETRY:
|
||||
sema_trace_expr_liveness(exprptr(expr->slice_expr.expr));
|
||||
switch (expr->slice_expr.range.range_type)
|
||||
{
|
||||
case RANGE_SINGLE_ELEMENT:
|
||||
UNREACHABLE
|
||||
case RANGE_CONST_RANGE:
|
||||
return;
|
||||
case RANGE_DYNAMIC:
|
||||
|
||||
@@ -157,6 +157,7 @@ bool str_is_integer(const char *string);
|
||||
bool str_has_no_uppercase(const char *string);
|
||||
bool str_is_valid_module_name(const char *name);
|
||||
char *str_copy(const char *start, size_t str_len);
|
||||
char *str_dup(const char *str);
|
||||
|
||||
StringSlice slice_next_token(StringSlice *slice, char separator);
|
||||
static inline bool slice_strcmp(StringSlice slice, const char *other);
|
||||
|
||||
@@ -332,6 +332,11 @@ char *str_cat(const char *a, const char *b)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char *str_dup(const char *str)
|
||||
{
|
||||
return str_copy(str, strlen(str));
|
||||
}
|
||||
|
||||
char *str_copy(const char *start, size_t str_len)
|
||||
{
|
||||
char *dst = calloc_string(str_len + 1);
|
||||
|
||||
Reference in New Issue
Block a user