mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
@str_hash, @str_upper, @str_lower, @str_find compile time macros.
This commit is contained in:
@@ -315,6 +315,11 @@ macro char[] @as_char_view(&value) @builtin
|
||||
return ((char*)value)[:$sizeof(*value)];
|
||||
}
|
||||
|
||||
macro isz @str_find(String $string, String $needle) @builtin => $$str_find($string, $needle);
|
||||
macro String @str_upper(String $str) @builtin => $$str_upper($str);
|
||||
macro String @str_lower(String $str) @builtin => $$str_lower($str);
|
||||
macro uint @str_hash(String $str) @builtin => $$str_hash($str);
|
||||
|
||||
macro uint int.hash(int i) => i;
|
||||
macro uint uint.hash(uint i) => i;
|
||||
macro uint short.hash(short s) => s;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
### Changes / improvements
|
||||
- Addition of $append and $concat functions.
|
||||
- Added $$str_hash builtin.
|
||||
- Added $$str_hash, $$str_upper, $$str_lower, $$str_find builtins.
|
||||
|
||||
### Fixes
|
||||
- Error with unsigned compare in `@ensure` when early returning 0 #1207.
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
### Stdlib changes
|
||||
- Added `remove_first_item` `remove_last_item` and `remove_item` as aliases for the `match` functions.
|
||||
- Added @str_hash, @str_upper, @str_lower, @str_find compile time macros.
|
||||
|
||||
## 0.6.0 Change list
|
||||
|
||||
|
||||
@@ -947,6 +947,9 @@ typedef enum
|
||||
BUILTIN_SELECT,
|
||||
BUILTIN_SET_ROUNDING_MODE,
|
||||
BUILTIN_STR_HASH,
|
||||
BUILTIN_STR_UPPER,
|
||||
BUILTIN_STR_LOWER,
|
||||
BUILTIN_STR_FIND,
|
||||
BUILTIN_SWIZZLE,
|
||||
BUILTIN_SWIZZLE2,
|
||||
BUILTIN_SIN,
|
||||
|
||||
@@ -1076,6 +1076,9 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
case BUILTIN_LLROUND:
|
||||
TODO
|
||||
case BUILTIN_STR_HASH:
|
||||
case BUILTIN_STR_LOWER:
|
||||
case BUILTIN_STR_UPPER:
|
||||
case BUILTIN_STR_FIND:
|
||||
UNREACHABLE
|
||||
case BUILTIN_NONE:
|
||||
UNREACHABLE
|
||||
|
||||
@@ -305,6 +305,73 @@ bool sema_expr_analyse_str_hash(SemaContext *context, Expr *expr)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sema_expr_analyse_str_find(SemaContext *context, Expr *expr)
|
||||
{
|
||||
Expr *inner = expr->call_expr.arguments[0];
|
||||
Expr *inner_find = expr->call_expr.arguments[1];
|
||||
if (!sema_analyse_expr(context, inner) || !sema_analyse_expr(context, inner_find)) return true;
|
||||
if (!expr_is_const_string(inner))
|
||||
{
|
||||
RETURN_SEMA_ERROR(inner, "You need a compile time constant string to search.");
|
||||
}
|
||||
if (!expr_is_const_string(inner_find))
|
||||
{
|
||||
RETURN_SEMA_ERROR(inner_find, "You need a compile time constant string to search for.");
|
||||
}
|
||||
const char *inner_str = inner->const_expr.bytes.ptr;
|
||||
const char *find_str = inner_find->const_expr.bytes.ptr;
|
||||
char *ret = strstr(inner_str, find_str);
|
||||
expr_rewrite_const_int(expr, type_isz, (uint64_t)(ret == NULL ? -1 : ret - inner_str));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sema_expr_analyse_str_conv(SemaContext *context, Expr *expr, BuiltinFunction func)
|
||||
{
|
||||
Expr *inner = expr->call_expr.arguments[0];
|
||||
if (!sema_analyse_expr(context, inner)) return true;
|
||||
if (!expr_is_const_string(inner))
|
||||
{
|
||||
RETURN_SEMA_ERROR(inner, "You need a compile time constant string to take convert.");
|
||||
}
|
||||
const char *string = inner->const_expr.bytes.ptr;
|
||||
ArraySize len = inner->const_expr.bytes.len;
|
||||
// Empty string: no conversion
|
||||
if (!len)
|
||||
{
|
||||
expr_replace(expr, inner);
|
||||
return true;
|
||||
}
|
||||
char *new_string = malloc_string(len + 1);
|
||||
switch (func)
|
||||
{
|
||||
case BUILTIN_STR_LOWER:
|
||||
for (ArraySize i = 0; i < len; i++)
|
||||
{
|
||||
char c = string[i];
|
||||
new_string[i] = char_is_upper(c) ? (c | 0x20) : c;
|
||||
}
|
||||
break;
|
||||
case BUILTIN_STR_UPPER:
|
||||
for (ArraySize i = 0; i < len; i++)
|
||||
{
|
||||
char c = string[i];
|
||||
new_string[i] = char_is_lower(c) ? (c & ~0x20) : c;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.const_kind = CONST_STRING;
|
||||
new_string[len] = 0;
|
||||
expr->const_expr.bytes.ptr = new_string;
|
||||
expr->const_expr.bytes.len = len;
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
expr->type = type_string;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
{
|
||||
expr->call_expr.is_builtin = true;
|
||||
@@ -336,6 +403,11 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
{
|
||||
case BUILTIN_STR_HASH:
|
||||
return sema_expr_analyse_str_hash(context, expr);
|
||||
case BUILTIN_STR_UPPER:
|
||||
case BUILTIN_STR_LOWER:
|
||||
return sema_expr_analyse_str_conv(context, expr, func);
|
||||
case BUILTIN_STR_FIND:
|
||||
return sema_expr_analyse_str_find(context, expr);
|
||||
case BUILTIN_SWIZZLE2:
|
||||
case BUILTIN_SWIZZLE:
|
||||
return sema_expr_analyse_swizzle(context, expr, func == BUILTIN_SWIZZLE2);
|
||||
@@ -378,6 +450,9 @@ bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *expr)
|
||||
break;
|
||||
case BUILTIN_SYSCALL:
|
||||
case BUILTIN_STR_HASH:
|
||||
case BUILTIN_STR_UPPER:
|
||||
case BUILTIN_STR_LOWER:
|
||||
case BUILTIN_STR_FIND:
|
||||
UNREACHABLE
|
||||
case BUILTIN_VECCOMPGE:
|
||||
case BUILTIN_VECCOMPEQ:
|
||||
@@ -962,10 +1037,13 @@ static inline int builtin_expected_args(BuiltinFunction func)
|
||||
case BUILTIN_SIN:
|
||||
case BUILTIN_SQRT:
|
||||
case BUILTIN_STR_HASH:
|
||||
case BUILTIN_STR_UPPER:
|
||||
case BUILTIN_STR_LOWER:
|
||||
case BUILTIN_TRUNC:
|
||||
case BUILTIN_VOLATILE_LOAD:
|
||||
case BUILTIN_WASM_MEMORY_SIZE:
|
||||
return 1;
|
||||
case BUILTIN_STR_FIND:
|
||||
case BUILTIN_COPYSIGN:
|
||||
case BUILTIN_EXACT_ADD:
|
||||
case BUILTIN_EXACT_DIV:
|
||||
|
||||
@@ -278,6 +278,9 @@ void symtab_init(uint32_t capacity)
|
||||
builtin_list[BUILTIN_SET_ROUNDING_MODE] = KW_DEF("set_rounding_mode");
|
||||
builtin_list[BUILTIN_SIN] = KW_DEF("sin");
|
||||
builtin_list[BUILTIN_STR_HASH] = KW_DEF("str_hash");
|
||||
builtin_list[BUILTIN_STR_UPPER] = KW_DEF("str_upper");
|
||||
builtin_list[BUILTIN_STR_LOWER] = KW_DEF("str_lower");
|
||||
builtin_list[BUILTIN_STR_FIND] = KW_DEF("str_find");
|
||||
builtin_list[BUILTIN_SWIZZLE] = KW_DEF("swizzle");
|
||||
builtin_list[BUILTIN_SWIZZLE2] = KW_DEF("swizzle2");
|
||||
builtin_list[BUILTIN_SQRT] = KW_DEF("sqrt");
|
||||
|
||||
11
test/test_suite/compile_time/ct_string_functions.c3t
Normal file
11
test/test_suite/compile_time/ct_string_functions.c3t
Normal file
@@ -0,0 +1,11 @@
|
||||
import std;
|
||||
|
||||
fn int main()
|
||||
{
|
||||
$assert(@str_upper("Hello World") == "HELLO WORLD");
|
||||
$assert(@str_lower("Hello World") == "hello world");
|
||||
$assert(@str_find("Hello World", "o") == 4);
|
||||
$assert(@str_find("Hello World", "w") == -1);
|
||||
$assert(@str_hash("Hello C3") == 487972447);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user