diff --git a/SLS_C/include/sls/string.h b/SLS_C/include/sls/string.h index e1f293d..70fbaa6 100644 --- a/SLS_C/include/sls/string.h +++ b/SLS_C/include/sls/string.h @@ -7,26 +7,27 @@ #define SLS_STRING_H #include +#include #include #include "bool.h" typedef struct { - size_t len; - const char *str; + size_t len; // Number of useable characters (does not include trailing null character) + char *str; Boolean allocated; } SlsStr; #define SLS_STR(s) (SlsStr){ sizeof(s) - 1, (s), FALSE } +#define SLS_STR_NULL (SlsStr){0, NULL, FALSE} -int isascii(unsigned char c); -size_t strnlen(const char *s, size_t maxlen); - -SlsStr malloc_str(const char *s, size_t maxlen); -SlsStr new_str(size_t length); -SlsStr copy_str(SlsStr s); -int32_t compare_str(SlsStr a, SlsStr b); -void free_str(SlsStr *s); -SlsStr format(const SlsStr s, ...); +int sls_isascii(unsigned char c); +size_t sls_str_nlen(const char *s, size_t maxlen); +SlsStr sls_str_malloc(const char *s, size_t maxlen); +SlsStr sls_str_new(size_t length); +SlsStr sls_str_cpy(SlsStr s); +int32_t sls_str_cmp(SlsStr a, SlsStr b); +void sls_str_free(SlsStr *s); +SlsStr sls_format(const SlsStr s, ...); #endif // SLS_STRING_H diff --git a/SLS_C/include/tests/lexer_test_helpers.h b/SLS_C/include/tests/lexer_test_helpers.h index 5bc46b3..6c678d2 100644 --- a/SLS_C/include/tests/lexer_test_helpers.h +++ b/SLS_C/include/tests/lexer_test_helpers.h @@ -99,6 +99,7 @@ typedef struct { LexerTest start_up_test(SlsStr test_name, SlsStr test_code); void clean_up_test(LexerResult result); +TestResult error_test_out_of_mem(LexerTest *test); TestResult error_test(LexerTest *test, LexerResult result, SlsError error); TestResult logic_fail_test(LexerTest *test, LexerResult result, SlsStr message); TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error); diff --git a/SLS_C/src/lexer.c b/SLS_C/src/lexer.c index 4502219..eec1782 100644 --- a/SLS_C/src/lexer.c +++ b/SLS_C/src/lexer.c @@ -454,7 +454,9 @@ static LexerResult parse_numeric_type(LexerInfo *lexer_info, char c, size_t star } return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Numeric Literal Not Implemented Error."), 1}}; } - return lexer_error(lexer_info, format(SLS_STR("Invalid numeric literal: unexpected '%c' in numeric type."), c), start, start_line); + SlsStr error_msg = sls_format(SLS_STR("Invalid numeric literal: unexpected '%c' in numeric type."), c); + if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}}; + return lexer_error(lexer_info, error_msg, start, start_line); } static LexerResult parse_binary_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) { @@ -464,7 +466,9 @@ static LexerResult parse_binary_integer(LexerInfo *lexer_info, char c, size_t st uint64_t value = create_binary_integer(lexer_info, start); return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line); } - return lexer_error(lexer_info, format(SLS_STR("Invalid binary literal: unexpected '%c' in binary integer."), c), start, start_line); + SlsStr error_msg = sls_format(SLS_STR("Invalid binary literal: unexpected '%c' in binary integer."), c); + if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}}; + return lexer_error(lexer_info, error_msg, start, start_line); } static LexerResult parse_octal_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) { @@ -474,7 +478,9 @@ static LexerResult parse_octal_integer(LexerInfo *lexer_info, char c, size_t sta uint64_t value = create_octal_integer(lexer_info, start); return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line); } - return lexer_error(lexer_info, format(SLS_STR("Invalid octal literal: unexpected '%c' in octal integer."), c), start, start_line); + SlsStr error_msg = sls_format(SLS_STR("Invalid octal literal: unexpected '%c' in octal integer."), c); + if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}}; + return lexer_error(lexer_info, error_msg, start, start_line); } static LexerResult parse_exponential(LexerInfo *lexer_info, char c, size_t start, size_t start_line) { @@ -496,7 +502,9 @@ static LexerResult parse_decimal_integer(LexerInfo *lexer_info, char c, size_t s uint64_t value = create_decimal_integer(lexer_info, start); return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line); } - return lexer_error(lexer_info, format(SLS_STR("Invalid decimal literal: unexpected '%c' in decimal integer."), c), start, start_line); + SlsStr error_msg = sls_format(SLS_STR("Invalid decimal literal: unexpected '%c' in decimal integer."), c); + if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}}; + return lexer_error(lexer_info, error_msg, start, start_line); } static LexerResult parse_hexadecimal_integer(LexerInfo *lexer_info, char c, size_t start, size_t start_line) { @@ -506,7 +514,9 @@ static LexerResult parse_hexadecimal_integer(LexerInfo *lexer_info, char c, size uint64_t value = create_hexadecimal_integer(lexer_info, start); return create_integer_token(lexer_info, INTEGER_I64, value, start, start_line); } - return lexer_error(lexer_info, format(SLS_STR("Invalid hexadecimal literal: unexpected '%c' in hexadecimal integer."), c), start, start_line); + SlsStr error_msg = sls_format(SLS_STR("Invalid hexadecimal literal: unexpected '%c' in hexadecimal integer."), c); + if (error_msg.str == NULL) return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Out Of Memory Error."), 1}}; + return lexer_error(lexer_info, error_msg, start, start_line); } static LexerResult parse_numeric_literal(LexerInfo *lexer_info, char c, size_t start, size_t start_line) { @@ -588,7 +598,7 @@ static LexerResult lexer_next(LexerInfo *lexer_info) { // Type Tuples if (c == '(') return parse_type_tuples(lexer_info, c, start, start_line); // Identifiers and Booleans - if (isascii(c)) return parse_identifiers_and_booleans(lexer_info, c, start, start_line); + if (sls_isascii(c)) return parse_identifiers_and_booleans(lexer_info, c, start, start_line); // Lexing Error return (LexerResult){SLS_ERROR, .error = (SlsError){SLS_STR("Lexer: Unknown Character Error."), 1}}; } @@ -598,9 +608,9 @@ void clean_token_result(LexerTokenResult *head) { LexerTokenResult *next; while (head) { next = head->next; - if (head->type == SLS_ERROR) free_str(&head->error.message); + if (head->type == SLS_ERROR) sls_str_free(&head->error.message); else { - if (head->result.type == TOKEN_STRING) free_str(&head->error.message); + if (head->result.type == TOKEN_STRING) sls_str_free(&head->error.message); } if (head) free(head); head = next; diff --git a/SLS_C/src/string.c b/SLS_C/src/string.c index 61138ce..2e2cffc 100644 --- a/SLS_C/src/string.c +++ b/SLS_C/src/string.c @@ -14,48 +14,53 @@ #include "sls/string.h" #include "sls/lexer.h" -int isascii(unsigned char c) { +int sls_isascii(unsigned char c) { return c < 128; } -size_t strnlen(const char *s, size_t maxlen) { +size_t sls_str_nlen(const char *s, size_t maxlen) { size_t i; for (i = 0; i < maxlen; i++) if (s[i] == '\0') break; return i; } -SlsStr malloc_str(const char *s, size_t maxlen) { - size_t length = strnlen(s, maxlen); +SlsStr sls_str_malloc(const char *s, size_t maxlen) { + size_t length = sls_str_nlen(s, maxlen); char *new_str = (char *)malloc(sizeof(char) * (length + 1)); - strncpy(new_str, s, length + 1); + if (new_str == NULL) return SLS_STR_NULL; + memcpy(new_str, s, length); + new_str[length] = '\0'; return (SlsStr){length, new_str, TRUE}; } -SlsStr new_str(size_t length) { - char *new_str = (char *)malloc(sizeof(char) * length); - for (size_t i = 0; i < length; i++) new_str[i] = '\0'; +SlsStr sls_str_new(size_t length) { + char *new_str = (char *)calloc(length + 1, sizeof(char)); + if (new_str == NULL) return SLS_STR_NULL; return (SlsStr){length, new_str, TRUE}; } -SlsStr copy_str(SlsStr s) { - return malloc_str(s.str, s.len); +SlsStr sls_str_cpy(const SlsStr s) { + return sls_str_malloc(s.str, s.len); } -int32_t compare_str(SlsStr a, SlsStr b) { - return strcmp(a.str, b.str); +int32_t sls_str_cmp(const SlsStr a, const SlsStr b) { + int cmp = strncmp(a.str, b.str, (a.len < b.len) ? a.len : b.len); + if (cmp != 0) return cmp; + return (a.len > b.len) - (a.len < b.len); } -void free_str(SlsStr *s) { +void sls_str_free(SlsStr *s) { if (s->allocated) { free((void *)s->str); s->len = 0; - s->str = 0; + s->str = NULL; s->allocated = FALSE; } } typedef enum { + FORMAT_PERCENT_ESCAPE, FORMAT_C_STRINGS, FORMAT_CHARACTER, FORMAT_INTEGER_32, @@ -88,27 +93,34 @@ typedef struct { SlsError error; Boolean boolean; }; - size_t str_index; + ptrdiff_t str_index; size_t self_length; } FormatStringItem; static size_t number_length(int64_t i) { if (i == 0) return 1; - else return (i < 0 ? 1 : 0) + (int)log10(llabs(i) + 1); + size_t len = (i < 0 ? 1 : 0); + while (i) { len++; i /= 10; } + return len; } static size_t unsigned_number_length(uint64_t i) { if (i == 0) return 1; - else return (int)log10(i + 1); + size_t len = 0; + while (i) { len++; i /= 10; } + return len; } -SlsStr format(const SlsStr s, ...) { +SlsStr sls_format(const SlsStr s, ...) { va_list args; va_start(args, s); size_t count = 0; const char *current = strchr(s.str, '%'); do { + if (!current) break; + if (!current[1]) break; switch (current[1]) { + case '%': case 'y': case 'c': case 'd': @@ -129,121 +141,119 @@ SlsStr format(const SlsStr s, ...) { } while (current); FormatStringItem *items = (FormatStringItem *)malloc(sizeof(FormatStringItem) * count); + if (items == NULL) return SLS_STR_NULL; size_t i = 0; - size_t last_index = (size_t)s.str; + const char *last_index = s.str; + size_t length = s.len; current = strchr(s.str, '%'); do { switch (current[1]) { + case '%': + items[i].type = FORMAT_PERCENT_ESCAPE; + length += items[i].self_length = 1; + length -= 2; + break; case 'y': items[i].type = FORMAT_C_STRINGS; items[i].c_string = va_arg(args, const char *); + length += items[i].self_length = strlen(items[i].c_string); + length -= 2; break; case 'c': items[i].type = FORMAT_CHARACTER; items[i].character = va_arg(args, int); + length += items[i].self_length = 1; + length -= 2; break; case 'd': items[i].type = FORMAT_INTEGER_32; items[i].integer_32 = va_arg(args, int32_t); + length += items[i].self_length = number_length(items[i].integer_32); + length -= 2; break; case 'l': items[i].type = FORMAT_INTEGER_64; items[i].integer_64 = va_arg(args, int64_t); + length += items[i].self_length = number_length(items[i].integer_64); + length -= 2; break; case 'u': items[i].type = FORMAT_UNSIGNED_INTEGER_64; items[i].unsigned_integer_64 = va_arg(args, uint64_t); + length += items[i].self_length = unsigned_number_length(items[i].unsigned_integer_64); + length -= 2; break; case 'z': items[i].type = FORMAT_SIZE_INTEGER; items[i].size_integer = va_arg(args, size_t); + length += items[i].self_length = unsigned_number_length(items[i].size_integer); + length -= 2; break; case 'f': items[i].type = FORMAT_FLOAT; items[i].ffloat = va_arg(args, double); + length += items[i].self_length = snprintf(NULL, 0, "%.2f", items[i].ffloat); + length -= 2; break; case 's': items[i].type = FORMAT_SLS_STR; items[i].sls_str = va_arg(args, SlsStr); + length += items[i].self_length = items[i].sls_str.len; + length -= 2; break; case 't': items[i].type = FORMAT_SLS_TOKEN_TYPE; items[i].token_type = va_arg(args, TokenType); + length += items[i].self_length = sls_str_nlen(TOKEN_TYPES_NAMES[items[i].token_type], TYPE_NAMES_SAFE_LENGTH); + length -= 2; break; case 'a': items[i].type = FORMAT_SLS_ARRAY_TYPE; items[i].array_type = va_arg(args, ArrayType); + length += items[i].self_length = sls_str_nlen(ARRAY_TYPES_NAMES[items[i].array_type], TYPE_NAMES_SAFE_LENGTH); + length -= 2; break; case 'i': items[i].type = FORMAT_SLS_BUILTIN_INTEGER; items[i].builtin_integer = va_arg(args, IntegerBuiltInType); + length += items[i].self_length = sls_str_nlen(INTEGER_TYPES_NAMES[items[i].builtin_integer], TYPE_NAMES_SAFE_LENGTH); + length -= 2; break; case 'e': items[i].type = FORMAT_SLS_ERROR; items[i].error = va_arg(args, SlsError); + length += items[i].self_length = items[i].error.message.len; + length -= 2; break; case 'b': items[i].type = FORMAT_SLS_BOOLEAN; items[i].boolean = va_arg(args, Boolean); + length += items[i].self_length = (items[i].boolean ? 4 : 5); + length -= 2; break; } - items[i].str_index = (size_t)current - last_index; - last_index = (size_t)current + 2; + items[i].str_index = (ptrdiff_t)(current - last_index); + last_index = current + 2; i++; current = strchr(current + 2, '%'); } while (current); - - size_t length = s.len - (count * 2); - for (size_t i = 0; i < count; i++) { - switch (items[i].type) { - case FORMAT_C_STRINGS: - length += items[i].self_length = strlen(items[i].c_string); - break; - case FORMAT_CHARACTER: - length += items[i].self_length = 1; - break; - case FORMAT_INTEGER_32: - length += items[i].self_length = number_length(items[i].integer_32); - break; - case FORMAT_INTEGER_64: - length += items[i].self_length = number_length(items[i].integer_64); - break; - case FORMAT_UNSIGNED_INTEGER_64: - length += items[i].self_length = unsigned_number_length(items[i].unsigned_integer_64); - break; - case FORMAT_SIZE_INTEGER: - length += items[i].self_length = unsigned_number_length(items[i].size_integer); - break; - case FORMAT_FLOAT: - length += items[i].self_length = number_length(items[i].ffloat) + 3; - break; - case FORMAT_SLS_STR: - length += items[i].self_length = items[i].sls_str.len - 1; - break; - case FORMAT_SLS_TOKEN_TYPE: - length += items[i].self_length = strnlen(TOKEN_TYPES_NAMES[items[i].token_type], TYPE_NAMES_SAFE_LENGTH); - break; - case FORMAT_SLS_ARRAY_TYPE: - length += items[i].self_length = strnlen(ARRAY_TYPES_NAMES[items[i].array_type], TYPE_NAMES_SAFE_LENGTH); - break; - case FORMAT_SLS_BUILTIN_INTEGER: - length += items[i].self_length = strnlen(INTEGER_TYPES_NAMES[items[i].builtin_integer], TYPE_NAMES_SAFE_LENGTH); - break; - case FORMAT_SLS_ERROR: - length += items[i].self_length = items[i].error.message.len - 1; - break; - case FORMAT_SLS_BOOLEAN: - length += items[i].self_length = (items[i].boolean ? 4 : 5); - break; - } - } + va_end(args); char *temp = (char *)malloc(sizeof(char) * length); - SlsStr str_new = new_str(length); + if (temp == NULL) { + free(items); + return SLS_STR_NULL; + } + SlsStr str_new = sls_str_new(length); + if (str_new.str == NULL) { + free(items); + free(temp); + return SLS_STR_NULL; + } char *str = (char *)str_new.str; size_t item_i = 0; - size_t target_i = 0; - size_t source_i = 0; + ptrdiff_t target_i = 0; + ptrdiff_t source_i = 0; while (item_i < count) { memcpy(str + target_i, s.str + source_i, items[item_i].str_index); @@ -251,6 +261,9 @@ SlsStr format(const SlsStr s, ...) { source_i += items[item_i].str_index + 2; switch (items[item_i].type) { + case FORMAT_PERCENT_ESCAPE: + memcpy(temp, "%", items[item_i].self_length + 1); + break; case FORMAT_C_STRINGS: snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].c_string); break; @@ -270,7 +283,7 @@ SlsStr format(const SlsStr s, ...) { snprintf(temp, items[item_i].self_length + 1, "%zu", items[item_i].size_integer); break; case FORMAT_FLOAT: - snprintf(temp, items[item_i].self_length + 1, "%.2f", items[item_i].ffloat); + snprintf(temp, items[item_i].self_length + 1, "%.2f", items[item_i].ffloat); // Fixed-point decimal display break; case FORMAT_SLS_STR: snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].sls_str.str); @@ -288,8 +301,7 @@ SlsStr format(const SlsStr s, ...) { snprintf(temp, items[item_i].self_length + 1, "%s", items[item_i].error.message.str); break; case FORMAT_SLS_BOOLEAN: - if (items[item_i].boolean) memcpy(temp, "TRUE", 5); - else memcpy(temp, "FALSE", 6); + memcpy(temp, (items[item_i].boolean ? "TRUE" : "FALSE"), items[item_i].self_length + 1); break; } @@ -297,7 +309,9 @@ SlsStr format(const SlsStr s, ...) { target_i += items[item_i].self_length; item_i++; } - memcpy(str + target_i, s.str + source_i, s.len - source_i); + if (s.len > source_i) + memcpy(str + target_i, s.str + source_i, s.len - source_i); + str[str_new.len] = '\0'; free(items); free(temp); diff --git a/SLS_C/tests/lexer_test_helpers.c b/SLS_C/tests/lexer_test_helpers.c index 98808d3..133a8e6 100644 --- a/SLS_C/tests/lexer_test_helpers.c +++ b/SLS_C/tests/lexer_test_helpers.c @@ -16,7 +16,7 @@ #include "tests/lexer_test_helpers.h" #include "tests/tests.h" -static const double FLOAT_TEST_PRECISION = 0.01; +static const double FLOAT_TEST_PRECISION = 0.0078125; // Test start and end helpers @@ -33,43 +33,63 @@ void clean_up_test(LexerResult result) { clean_token_result(result.result); } +TestResult error_test_out_of_mem(LexerTest *test) { + test->result.status = TEST_ERROR; + test->result.error = (SlsError){SLS_STR("Out Of Memory Error."), 1}; + return test->result; +} + TestResult error_test(LexerTest *test, LexerResult result, SlsError error) { + clean_up_test(result); + + if (error.message.str == NULL) return error_test_out_of_mem(test); + test->result.status = TEST_ERROR; test->result.error = error; - test->result.error.message = copy_str(error.message); + test->result.error.message = sls_str_cpy(error.message); - clean_up_test(result); + if (test->result.error.message.str == NULL) return error_test_out_of_mem(test); return test->result; } TestResult logic_fail_test(LexerTest *test, LexerResult result, SlsStr message) { + clean_up_test(result); + test->result.status = TEST_LOGIC_FAIL; test->result.message = message; - clean_up_test(result); return test->result; } TestResult logic_error_fail_test(LexerTest *test, LexerResult result, SlsError error) { + clean_up_test(result); + + if (error.message.str == NULL) return error_test_out_of_mem(test); + test->result.status = TEST_LOGIC_ERROR_FAIL; test->result.error = error; - test->result.error.message = copy_str(error.message); + test->result.error.message = sls_str_cpy(error.message); - clean_up_test(result); + if (test->result.error.message.str == NULL) return error_test_out_of_mem(test); return test->result; } TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error) { + clean_up_test(result); + + if (error.message.str == NULL) return error_test_out_of_mem(test); + test->result.status = TEST_ERROR_FAIL; test->result.error = error; - test->result.error.message = copy_str(error.message); + test->result.error.message = sls_str_cpy(error.message); - clean_up_test(result); + if (test->result.error.message.str == NULL) return error_test_out_of_mem(test); return test->result; } TestResult skip_test(LexerTest *test, LexerResult result) { - test->result.status = TEST_NOT_IMPLEMENTED; clean_up_test(result); + + test->result.status = TEST_NOT_IMPLEMENTED; return test->result; } @@ -79,106 +99,107 @@ TestResult skip_test_no_result(LexerTest *test) { } TestResult pass_test(LexerTest *test, LexerResult result) { - test->result.status = TEST_PASS; clean_up_test(result); + + test->result.status = TEST_PASS; return test->result; } // Test messages static SlsStr unexpected_end_of_token_stream(size_t i) { - return format(SLS_STR("Unexpected end of token stream (%z tokens found)"), i - 1); + return sls_format(SLS_STR("Unexpected end of token stream (%z tokens found)"), i - 1); } static SlsStr expected_end_of_token_stream(size_t i) { - return format(SLS_STR("Expected end of token stream (more than %z tokens found)"), i - 1); + return sls_format(SLS_STR("Expected end of token stream (more than %z tokens found)"), i - 1); } static SlsStr token_should_be(size_t i, TokenType should, TokenType found) { - return format(SLS_STR("Token #%z should be a %t, but found a %t"), i, should, found); + return sls_format(SLS_STR("Token #%z should be a %t, but found a %t"), i, should, found); } static SlsStr integer_type_should_be(size_t i, IntegerBuiltInType should, IntegerBuiltInType found) { - return format(SLS_STR("Token #%z integer type should be a %i, but found a %i"), i, should, found); + return sls_format(SLS_STR("Token #%z integer type should be a %i, but found a %i"), i, should, found); } static SlsStr integer_value_should_be(size_t i, uint64_t should, uint64_t found) { - return format(SLS_STR("Token #%z integer value should be %i, but found %i"), i, should, found); + return sls_format(SLS_STR("Token #%z integer value should be %i, but found %i"), i, should, found); } static SlsStr float_value_should_be(size_t i, double should, double found) { - return format(SLS_STR("Token #%z float value should be %f, but found %f"), i, should, found); + return sls_format(SLS_STR("Token #%z float value should be %f, but found %f"), i, should, found); } static SlsStr identifier_should_be_literal(size_t i) { - return format(SLS_STR("Token #%z identifier should be an identifier literal"), i); + return sls_format(SLS_STR("Token #%z identifier should be an identifier literal"), i); } static SlsStr identifier_should_not_be_literal(size_t i) { - return format(SLS_STR("Token #%z identifier should not be an identifier literal"), i); + return sls_format(SLS_STR("Token #%z identifier should not be an identifier literal"), i); } static SlsStr token_length_should_be(size_t i, TokenType type, uint64_t should, uint64_t found) { - return format(SLS_STR("Token #%z of type %t length should be %u, but found %u"), i, type, should, found); + return sls_format(SLS_STR("Token #%z of type %t length should be %u, but found %u"), i, type, should, found); } static SlsStr token_value_string_should_be(size_t i, TokenType type, SlsStr should, SlsStr found) { - return format(SLS_STR("Token #%z of type %t string value should be %s, but found %s"), i, type, should, found); + return sls_format(SLS_STR("Token #%z of type %t string value should be %s, but found %s"), i, type, should, found); } static SlsStr boolean_should_be(size_t i, Boolean value) { - if (value) return format(SLS_STR("Token #%z boolean should be true, but is false"), i); - else return format(SLS_STR("Token #%z boolean should be false, but is true"), i); + if (value) return sls_format(SLS_STR("Token #%z boolean should be true, but is false"), i); + else return sls_format(SLS_STR("Token #%z boolean should be false, but is true"), i); } static SlsStr array_type_should_be(size_t i, ArrayType should, ArrayType found) { - return format(SLS_STR("Token #%z should be a %a, but found a %a"), i, should, found); + return sls_format(SLS_STR("Token #%z should be a %a, but found a %a"), i, should, found); } static SlsStr array_dimensions_should_be(size_t i, size_t should, size_t found) { - return format(SLS_STR("Token #%z array dimensions should be %z, but found %z"), i, should, found); + return sls_format(SLS_STR("Token #%z array dimensions should be %z, but found %z"), i, should, found); } static SlsStr array_dimension_shape_should_be(size_t i, size_t j, ArrayType type, uint64_t should, uint64_t found) { - return format(SLS_STR("Token #%z dimension %z of array type %a should be shape %u, but found %u"), i, j, type, should, found); + return sls_format(SLS_STR("Token #%z dimension %z of array type %a should be shape %u, but found %u"), i, j, type, should, found); } static SlsStr array_element_integer_should_be(size_t i, size_t j, ArrayType type, uint64_t should, uint64_t found) { - return format(SLS_STR("Token #%z element %z of array type %a should be %u, but found %u"), i, j, type, should, found); + return sls_format(SLS_STR("Token #%z element %z of array type %a should be %u, but found %u"), i, j, type, should, found); } static SlsStr array_element_float_should_be(size_t i, size_t j, ArrayType type, double should, double found) { - return format(SLS_STR("Token #%z element %z of array type %a should be %f, but found %f"), i, j, type, should, found); + return sls_format(SLS_STR("Token #%z element %z of array type %a should be %f, but found %f"), i, j, type, should, found); } static SlsStr array_element_string_should_be(size_t i, size_t j, ArrayType type, SlsStr should, SlsStr found) { - return format(SLS_STR("Token #%z element %z of array type %a should be %s, but found %s"), i, j, type, should, found); + return sls_format(SLS_STR("Token #%z element %z of array type %a should be %s, but found %s"), i, j, type, should, found); } static SlsStr array_element_boolean_should_be(size_t i, size_t j, ArrayType type, Boolean value) { - if (value) return format(SLS_STR("Token #%z element %z of array type %a should be true, but is false"), i, j, type); - else return format(SLS_STR("Token #%z element %z of array type %a should be false, but is true"), i, j, type); + if (value) return sls_format(SLS_STR("Token #%z element %z of array type %a should be true, but is false"), i, j, type); + else return sls_format(SLS_STR("Token #%z element %z of array type %a should be false, but is true"), i, j, type); } static SlsStr type_tuple_element_integer_should_be(size_t i, size_t j, uint64_t should, uint64_t found) { - return format(SLS_STR("Token #%z element %u of type tuple should be %u, but found %u"), i, j, should, found); + return sls_format(SLS_STR("Token #%z element %u of type tuple should be %u, but found %u"), i, j, should, found); } static SlsStr type_tuple_element_string_should_be(size_t i, size_t j, SlsStr should, SlsStr found) { - return format(SLS_STR("Token #%z element %z of type tuple should be %s, but found %s"), i, j, should, found); + return sls_format(SLS_STR("Token #%z element %z of type tuple should be %s, but found %s"), i, j, should, found); } static SlsStr type_tuple_element_boolean_should_be(size_t i, size_t j, Boolean value) { - if (value) return format(SLS_STR("Token #%z element %z of type tuple should be true, but is false"), i, j); - else return format(SLS_STR("Token #%z element %z of type tuple should be false, but is true"), i, j); + if (value) return sls_format(SLS_STR("Token #%z element %z of type tuple should be true, but is false"), i, j); + else return sls_format(SLS_STR("Token #%z element %z of type tuple should be false, but is true"), i, j); } static SlsStr token_should_be_error(size_t i, SlsStr should, TokenType found) { - return format(SLS_STR("Token #%z should be an error with a message of \"%s\", but found token of type %t"), i, should, found); + return sls_format(SLS_STR("Token #%z should be an error with a message of \"%s\", but found token of type %t"), i, should, found); } static SlsStr error_should_be(size_t i, SlsStr should, SlsError found) { - return format(SLS_STR("Token #%z should be an error with a message of \"%s\", but found error with message \"%e\""), i, should, found); + return sls_format(SLS_STR("Token #%z should be an error with a message of \"%s\", but found error with message \"%e\""), i, should, found); } // Test parts @@ -242,7 +263,7 @@ Boolean test_identifier_value(LexerTest *test, LexerResult result, size_t i, Tes } if (head->result.identifier.name.len == value->name.len) { logic_fail_test(test, result, token_length_should_be(i + 1, token_type, value->name.len, head->result.identifier.name.len)); return TRUE; - } if (compare_str(head->result.identifier.name, value->name) != 0) { + } if (sls_str_cmp(head->result.identifier.name, value->name) != 0) { logic_fail_test(test, result, token_value_string_should_be(i + 1, token_type, head->result.identifier.name, value->name)); return TRUE; } @@ -296,7 +317,7 @@ Boolean test_string_value(LexerTest *test, LexerResult result, size_t i, SlsStr } if (head->result.string_literal.len == value.len) { logic_fail_test(test, result, token_length_should_be(i + 1, token_type, value.len, head->result.string_literal.len)); return TRUE; - } if (compare_str(head->result.string_literal, value) != 0) { + } if (sls_str_cmp(head->result.string_literal, value) != 0) { logic_fail_test(test, result, token_value_string_should_be(i + 1, token_type, value, head->result.string_literal)); return TRUE; } @@ -327,7 +348,7 @@ Boolean test_array_identifier_value(LexerTest *test, LexerResult result, size_t if (head->result.array_literal.identifiers[j].name.len == values->values[j].name.len) { logic_fail_test(test, result, array_element_integer_should_be(i + 1, j, array_type, values->values[j].name.len, head->result.array_literal.identifiers[j].name.len)); return TRUE; - } if (compare_str(head->result.array_literal.identifiers[j].name, values->values[j].name)) { + } if (sls_str_cmp(head->result.array_literal.identifiers[j].name, values->values[j].name)) { logic_fail_test(test, result, array_element_string_should_be(i + 1, j, array_type, values->values[j].name, head->result.array_literal.identifiers[j].name)); return TRUE; } if (head->result.array_literal.identifiers[j].is_literal) { @@ -401,7 +422,7 @@ Boolean test_array_string_value(LexerTest *test, LexerResult result, size_t i, T if (head->result.array_literal.string_literals[j].len == values->values[j].len) { logic_fail_test(test, result, array_element_integer_should_be(i + 1, j, array_type, values->values[j].len, head->result.array_literal.string_literals[j].len)); return TRUE; - } if (compare_str(head->result.array_literal.string_literals[j], values->values[j])) { + } if (sls_str_cmp(head->result.array_literal.string_literals[j], values->values[j])) { logic_fail_test(test, result, array_element_string_should_be(i + 1, j, array_type, values->values[j], head->result.array_literal.string_literals[j])); return TRUE; } @@ -431,7 +452,7 @@ Boolean test_array_struct_inline_value(LexerTest *test, LexerResult result, size LexerTokenResult *head = get_token(result.result, i); if (test_array_type(test, result, i, array_type, values->shape, values->dimensions)) { return TRUE; - } if (compare_str(head->result.array_literal.struct_inline.name, values->struct_name)) { + } if (sls_str_cmp(head->result.array_literal.struct_inline.name, values->struct_name)) { logic_fail_test(test, result, token_value_string_should_be(i + 1, TOKEN_IDENTIFIER, values->struct_name, head->result.array_literal.struct_inline.name)); return TRUE; } @@ -491,7 +512,7 @@ Boolean test_type_tuple_value(LexerTest *test, LexerResult result, size_t i, Tes if (head->result.type_tuple.input_identifiers[j].name.len == values->input_values[j].name.len) { logic_fail_test(test, result, type_tuple_element_integer_should_be(i + 1, j, values->input_values[j].name.len, head->result.type_tuple.input_identifiers[j].name.len)); return TRUE; - } if (compare_str(head->result.type_tuple.input_identifiers[j].name, values->input_values[j].name)) { + } if (sls_str_cmp(head->result.type_tuple.input_identifiers[j].name, values->input_values[j].name)) { logic_fail_test(test, result, type_tuple_element_string_should_be(i + 1, j, values->input_values[j].name, head->result.type_tuple.input_identifiers[j].name)); return TRUE; } if (head->result.type_tuple.input_identifiers[j].is_literal) { @@ -502,7 +523,7 @@ Boolean test_type_tuple_value(LexerTest *test, LexerResult result, size_t i, Tes if (head->result.type_tuple.output_identifiers[j].name.len == values->output_values[j].name.len) { logic_fail_test(test, result, type_tuple_element_integer_should_be(i + 1, j, values->output_values[j].name.len, head->result.type_tuple.output_identifiers[j].name.len)); return TRUE; - } if (compare_str(head->result.type_tuple.output_identifiers[j].name, values->output_values[j].name)) { + } if (sls_str_cmp(head->result.type_tuple.output_identifiers[j].name, values->output_values[j].name)) { logic_fail_test(test, result, type_tuple_element_string_should_be(i + 1, j, values->output_values[j].name, head->result.type_tuple.output_identifiers[j].name)); return TRUE; } if (head->result.type_tuple.output_identifiers[j].is_literal) { @@ -518,7 +539,7 @@ Boolean test_for_error(LexerTest *test, LexerResult result, size_t i, SlsStr err if (head->type != SLS_ERROR) { logic_fail_test(test, result, token_should_be_error(i + 1, error, head->result.type)); return TRUE; - } if (compare_str(head->error.message, error) != 0) { + } if (sls_str_cmp(head->error.message, error) != 0) { logic_fail_test(test, result, error_should_be(i + 1, error, head->error)); return TRUE; } diff --git a/SLS_C/tests/tests.c b/SLS_C/tests/tests.c index 9e03a2e..ace6cb0 100644 --- a/SLS_C/tests/tests.c +++ b/SLS_C/tests/tests.c @@ -40,13 +40,13 @@ static void lexer_test_report(TestsReport reports, TestCounts *counts) { // Red printf("\x1b[31mTest failed with lexical error: %s\n\t%s\n\x1b[0m", reports.tests[i].name.str, reports.tests[i].error.message.str); counts->logic_error_failed += 1; - free_str(&reports.tests[i].message); + sls_str_free(&reports.tests[i].message); break; case TEST_LOGIC_FAIL: // Red printf("\x1b[31mTest failed: %s\n\t%s\n\x1b[0m", reports.tests[i].name.str, reports.tests[i].message.str); counts->logic_failed += 1; - free_str(&reports.tests[i].message); + sls_str_free(&reports.tests[i].message); break; case TEST_PASS: // Green