@str_hash, @str_upper, @str_lower, @str_find compile time macros.

This commit is contained in:
Christoffer Lerno
2024-06-16 21:16:03 +02:00
parent 147dee6ec7
commit 819049d596
7 changed files with 105 additions and 1 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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:

View File

@@ -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");

View 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;
}