diff --git a/src/collections/Array.h b/src/collections/Array.h index 24a4255..93394c3 100644 --- a/src/collections/Array.h +++ b/src/collections/Array.h @@ -12,9 +12,9 @@ }\ \ static inline Array_##T Array_##T##_alloc(u32 len){\ - return Array_##T##_construct(malloc(len * sizeof(T)), len);\ + return Array_##T##_construct((T*)malloc(len * sizeof(T)), len);\ }\ static inline void Array_##T##_realloc(Array_##T* ptr, u32 new_len){\ - ptr->data = realloc(ptr->data, new_len * sizeof(T));\ + ptr->data = (T*)realloc(ptr->data, new_len * sizeof(T));\ ptr->len = new_len;\ } diff --git a/src/collections/List.h b/src/collections/List.h index 5dc523a..b72cb8d 100644 --- a/src/collections/List.h +++ b/src/collections/List.h @@ -1,6 +1,9 @@ #pragma once #include "../std.h" +// minimal max_len after initial (0) +#define __List_min_size 16 + #define List_declare(T)\ typedef struct List_##T {\ T* data;\ @@ -14,35 +17,42 @@ \ List_##T List_##T##_alloc(u32 initial_len);\ \ - T* List_##T##_expand(List_##T* ptr);\ + T* List_##T##_expand(List_##T* ptr, u32 count);\ void List_##T##_push(List_##T* ptr, T value);\ + void List_##T##_pushMany(List_##T* ptr, T* values, u32 count);\ #define List_define(T)\ List_##T List_##T##_alloc(u32 initial_len){\ if(initial_len == 0)\ return List_##T##_construct((T*)NULL, 0, 0);\ - u32 max_Len = ALIGN_TO(initial_len, sizeof(void*)/sizeof(T));\ + u32 max_len = ALIGN_TO(initial_len, sizeof(void*)/sizeof(T));\ /* branchless version of max(max_len, __List_min_size) */\ max_len += (max_len < __List_min_size) * (__List_min_size - max_len);\ return List_##T##_construct((T*)malloc(initial_len * sizeof(T)), 0, max_len);\ }\ \ - T* List_##T##_expand(List_##T* ptr){\ - if(ptr->len == ptr->max_len){\ - ptr->max_len *= 2;\ - ptr->data = (T*)realloc(ptr->data, ptr->max_len * sizeof(T));\ - ptr->max_len = max_len;\ + T* List_##T##_expand(List_##T* ptr, u32 count){\ + u32 occupied_len = ptr->len;\ + u32 expanded_max_len = ptr->max_len;\ + ptr->len += count;\ + while(ptr->len > ptr->max_len){\ + expanded_max_len *= 2;\ }\ - return &ptr->data[ptr->len++];\ + ptr->data = (T*)realloc(ptr->data, expanded_max_len * sizeof(T));\ + return ptr->data + occupied_len;\ }\ \ void List_##T##_push(List_##T* ptr, T value){\ - T* empty_cell_ptr = List_##T##_expand(ptr);\ + T* empty_cell_ptr = List_##T##_expand(ptr, 1);\ *empty_cell_ptr = value;\ }\ + \ + void List_##T##_pushMany(List_##T* ptr, T* values, u32 count){\ + T* empty_cell_ptr = List_##T##_expand(ptr, count);\ + memcpy(empty_cell_ptr, values, count * sizeof(T));\ + }\ -#define __List_min_size 16 List_declare(cstr); List_declare(u32); diff --git a/src/compiler/AST.c b/src/compiler/AST.c index 76c1b1e..f5d4625 100644 --- a/src/compiler/AST.c +++ b/src/compiler/AST.c @@ -3,6 +3,7 @@ List_define(Argument); List_define(Operation); List_define(DataDefinition); +List_define(Section); static cstr _ArgumentType_str[] = { "Unset", diff --git a/src/compiler/Parser.c b/src/compiler/Parser.c index c0b591b..7af60a2 100644 --- a/src/compiler/Parser.c +++ b/src/compiler/Parser.c @@ -85,7 +85,7 @@ static void parseDataDefinition(Compiler* cmp, char* instr_name, DataDefinition* Token tok = cmp->tokens.data[++cmp->tok_i]; char* tok_str = Compiler_extractTokenStr(cmp, tok); u8* processed_str = NULL; - i32 len = 0; + u32 len = 0; ddf->name = tok_str; while(++cmp->tok_i < cmp->tokens.len){ @@ -114,7 +114,7 @@ static void parseDataDefinition(Compiler* cmp, char* instr_name, DataDefinition* tok_str = Compiler_extractTokenStr(cmp, tok); processed_str = resolveEscapeSequences(cmp, tok_str); free(tok_str); - len = strlen(processed_str); + len = strlen((char*)processed_str); if(len != ddf->element_size){ setError("can't fit char of size %i in %u bit variable", len, _element_size_bits); return; @@ -127,7 +127,7 @@ static void parseDataDefinition(Compiler* cmp, char* instr_name, DataDefinition* tok_str = Compiler_extractTokenStr(cmp, tok); processed_str = resolveEscapeSequences(cmp, tok_str); free(tok_str); - len = strlen(processed_str); + len = strlen((char*)processed_str); List_u8_pushBytes(&ddf->data, processed_str, 0, len); break; case TokenType_OperationEnd: @@ -161,7 +161,7 @@ bool Compiler_parse(Compiler* cmp){ break; case TokenType_Label: // create new section - sec = List_Section_expand(&cmp->ast.sections); + sec = List_Section_expand(&cmp->ast.sections, 1); Section_init(sec, Compiler_extractTokenStr(cmp, tok)); break; case TokenType_Instruction: @@ -170,11 +170,11 @@ bool Compiler_parse(Compiler* cmp){ char* instr_name = Compiler_extractTokenStr(cmp, tok); // data definition starts with const if(cstr_seek(instr_name, "const", 0, 1)){ - DataDefinition* dataDefPtr = List_DataDefinition_expand(&sec->data); + DataDefinition* dataDefPtr = List_DataDefinition_expand(&sec->data, 1); parseDataDefinition(cmp, instr_name, dataDefPtr); } else { - Operation* operPtr = List_Operation_expand(&sec->code); + Operation* operPtr = List_Operation_expand(&sec->code, 1); parseOperation(cmp, instr_name, operPtr); } break; diff --git a/src/string/StringBuilder.c b/src/string/StringBuilder.c new file mode 100644 index 0000000..8db4361 --- /dev/null +++ b/src/string/StringBuilder.c @@ -0,0 +1,43 @@ +#include "StringBuilder.h" + +void StringBuilder_free(StringBuilder* b){ + free(b->buffer.data); +} + +str StringBuilder_build(StringBuilder* b){ + List_u8_push(&b->buffer, '\0'); + str result = str_construct((char*)b->buffer.data, b->buffer.len - 1, true); + return result; +} + + +void StringBuilder_append_char(StringBuilder* b, char c){ + List_u8_push(&b->buffer, c); +} + + +void StringBuilder_append_string(StringBuilder* b, str s){ + List_u8_pushMany(&b->buffer, (u8*)s.data, s.len); +} + +void StringBuilder_append_cstr(StringBuilder* b, char* s){ + StringBuilder_append_string(b, str_construct(s, strlen(s), true)); +} + +void StringBuilder_append_i64(StringBuilder* b, i64 n){ + char buf[32]; + sprintf_s(buf, sizeof(buf), "%llu", n); + StringBuilder_append_cstr(b, buf); +} + +void StringBuilder_append_u64(StringBuilder* b, u64 n){ + char buf[32]; + sprintf_s(buf, sizeof(buf), "%llu", n); + StringBuilder_append_cstr(b, buf); +} + +void StringBuilder_append_f64(StringBuilder* b, f64 n){ + char buf[32]; + sprintf_s(buf, sizeof(buf), "%lf", n); + StringBuilder_append_cstr(b, buf); +} diff --git a/src/string/StringBuilder.h b/src/string/StringBuilder.h new file mode 100644 index 0000000..3d5d766 --- /dev/null +++ b/src/string/StringBuilder.h @@ -0,0 +1,32 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../collections/List.h" +#include "str.h" + +typedef struct StringBuilder { + List_u8 buffer; +} StringBuilder; + +static inline StringBuilder StringBuilder_construct(u32 initial_size) { + return (StringBuilder){ .buffer = List_u8_alloc(initial_size) }; +} +void StringBuilder_free(StringBuilder* b); + +void StringBuilder_removeFromEnd(StringBuilder* b, u32 count); +void StringBuilder_append_char(StringBuilder* b, char c); +void StringBuilder_append_cstr(StringBuilder* b, char* s); +void StringBuilder_append_string(StringBuilder* b, str s); +void StringBuilder_append_i64(StringBuilder* b, i64 a); +void StringBuilder_append_u64(StringBuilder* b, u64 a); +void StringBuilder_append_f64(StringBuilder* b, f64 a); + +// adds '\0' to the buffer and returns pointer to buffer content +str StringBuilder_getStr(StringBuilder* b); + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/string/str.c b/src/string/str.c new file mode 100644 index 0000000..52af538 --- /dev/null +++ b/src/string/str.c @@ -0,0 +1,29 @@ +#include "str.h" + +str str_copy(str src){ + if(src.data == NULL || src.len == 0) + return src; + str nstr = str_construct((char*)malloc(src.len + 1), src.len, true); + memcpy(nstr.data, src.data, src.len); + nstr.data[nstr.len] = '\0'; + return nstr; +} + +bool str_compare(str str0, str str1){ + if(str0.len!= str1.len) return false; + if(!str0.data) return str1.data ? false : true; + else if(!str1.data) return false; + while(str0.len-- > 0) + if(*str0.data++ != *str1.data++ ) + return false; + return true; +} + +str str_reverse(str s){ + if(s.data == NULL || s.len == 0) + return s; + str r = str_construct(malloc(s.len), s.len, s.isZeroTerminated); + for(u32 i = 0; i < s.len; i++ ) + r.data[i] = s.data[s.len - i - 1]; + return r; +} diff --git a/src/string/str.h b/src/string/str.h new file mode 100644 index 0000000..c53585a --- /dev/null +++ b/src/string/str.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../std.h" + +typedef struct str { + char* data; + u32 len; + bool isZeroTerminated; +} str; + +#define str_construct(DATA, LEN, ZERO_TERMINATED) ((str){ .data = DATA, .len = LEN, .isZeroTerminated = ZERO_TERMINATED }) + +static const str str_null = str_construct(NULL, 0, 0); + + +/// copies str content to new char pointer value (adding '\0' at the end) +char* str_extractcstr(str str); + +/// copies src content to new string and adds \0 at the end +str str_copy(str src); + +/// compares two strings, NullPtr-friendly +bool str_compare(str str0, str str1); + +/// allocates new string which is reversed variant of +str str_reverse(str s); + +#if __cplusplus +} +#endif \ No newline at end of file