From 5a5d1fb8087ed1cfaa5a44d738b587dcb2bf9e27 Mon Sep 17 00:00:00 2001 From: Igor Parfenov Date: Mon, 30 Dec 2024 21:38:30 +0300 Subject: [PATCH] Alloc cyclic import --- altlib/memory.al | 4 ++ altlib/posix.al | 1 + altlib/stdlib.al | 6 +- altlib/string.al | 8 +++ compiler/include/settings.h | 1 + compiler/src/main.c | 30 ++++------ compiler/src/syntax.c | 56 +++++++++++++------ docs/altlibref.html | 23 ++++++-- stdlib/asm/memory.asm | 26 +++++++++ stdlib/asm/posix.asm | 6 ++ stdlib/include/memory.h | 1 + stdlib/include/posix.h | 1 + stdlib/include/string.h | 3 + stdlib/src/stdlib.c | 5 +- stdlib/src/string.c | 28 ++++++++++ .../integration/{string.al => test_string.al} | 13 +++-- .../{string.out => test_string.out} | 1 + ...st_allocator.al => test_test_allocator.al} | 0 ..._allocator.out => test_test_allocator.out} | 0 .../integration/{vector.al => test_vector.al} | 0 .../{vector.out => test_vector.out} | 0 21 files changed, 164 insertions(+), 49 deletions(-) rename test/integration/{string.al => test_string.al} (85%) rename test/integration/{string.out => test_string.out} (95%) rename test/integration/{test_allocator.al => test_test_allocator.al} (100%) rename test/integration/{test_allocator.out => test_test_allocator.out} (100%) rename test/integration/{vector.al => test_vector.al} (100%) rename test/integration/{vector.out => test_vector.out} (100%) diff --git a/altlib/memory.al b/altlib/memory.al index 245cf89..9b0acc4 100644 --- a/altlib/memory.al +++ b/altlib/memory.al @@ -4,6 +4,10 @@ //* Copies the data of length `sz` bytes from `src` pointer to `dest` pointer. proto ._memcpy(dest #1I, src #1I, sz #I) -> #1I +//* _memmove +//* Copies the data of length `sz` bytes from `src` pointer to `dest` pointer. Handles possible overlapping +proto ._memmove(dest #1I, src #1I, sz #I) -> #1I + //* _memset //* Sets the data of length `count` bytes to `dest` pointer with value `ch`. Important: only the lowest byte in `ch` argument is used. proto ._memset(dest #1I, ch #I, count #I) -> #1I diff --git a/altlib/posix.al b/altlib/posix.al index 8d8d71b..2222db3 100644 --- a/altlib/posix.al +++ b/altlib/posix.al @@ -12,3 +12,4 @@ proto .posix_execve(filename #1I, argv #2C, envp #2C) -> #I proto .posix_exit(error_code #I) -> #I proto .posix_wait4(pid #I, stat_addr #1I, options #I, rusage #1I) -> #I proto .posix_unlink(pathname #1I) -> #I +proto .posix_getcwd(buf #1C, size #I) -> #1C diff --git a/altlib/stdlib.al b/altlib/stdlib.al index 7d0bd10..a08deb9 100644 --- a/altlib/stdlib.al +++ b/altlib/stdlib.al @@ -1,3 +1,5 @@ +include altlib."string.al" + //* stdlib //* todo @@ -44,7 +46,7 @@ func ^.itoa_(n #I) -> #1C { } } -/* func ^.atoi_(str #1C) -> #I { +func ^.atoi_(str #1C) -> #I { def i := strlen_(str) - 1 def x := 0 eval while (i >= 0) { @@ -53,7 +55,7 @@ func ^.itoa_(n #I) -> #1C { i := i - 1 } return x -} */ +} func ^.rand_(seed #I) -> #I { seed := seed * 1103515245 + 12345 diff --git a/altlib/string.al b/altlib/string.al index 38da900..c6dd58c 100644 --- a/altlib/string.al +++ b/altlib/string.al @@ -48,6 +48,14 @@ func ^.strlen_(a #1C) -> #I { } else 0 } +func ^.strnlen_(a #1C, n #I) -> #I { + def i := 0 + return while (i < n) { + eval if (a[i] = '\0') { break i } + i := i + 1 + } else n +} + func ^.concat_(a #1C, b #1C) -> #1C { def s_a := strlen_(a) def s_b := strlen_(b) diff --git a/compiler/include/settings.h b/compiler/include/settings.h index e482824..bb5ea9e 100644 --- a/compiler/include/settings.h +++ b/compiler/include/settings.h @@ -16,4 +16,5 @@ struct Settings { const char *filename_output; const char *filename_compile_output; const char *calias_directory; + struct Vector included_files; }; diff --git a/compiler/src/main.c b/compiler/src/main.c index bb41654..4f40e6e 100644 --- a/compiler/src/main.c +++ b/compiler/src/main.c @@ -18,7 +18,7 @@ void help() { _puts(" -o Set output file name."); } -struct Settings *build_settings(int argc, char **argv, char **envp) { +struct Settings *build_settings(int argc, char **argv) { struct Settings *settings = (struct Settings*)_malloc(sizeof(struct Settings)); settings->language_server = false; settings->validate = false; @@ -31,7 +31,7 @@ struct Settings *build_settings(int argc, char **argv, char **envp) { settings->filename_input = NULL; settings->filename_output = NULL; settings->filename_compile_output = NULL; - settings->calias_directory = "/"; + settings->calias_directory = _strdup(argv[0]); for (int i = 1; i < argc; i++) { const char *arg = argv[i]; @@ -75,22 +75,6 @@ struct Settings *build_settings(int argc, char **argv, char **envp) { settings->filename_input = _strdup(arg); } } - for (int x = 0; envp[x]; x++) { - const char *str = envp[x]; - int delim = -1; - int n = _strlen(str); - for (int i = 0; i < n; i++) { - if (str[i] == '=') { - delim = i; - break; - } - } - if (delim == -1) continue; - if (_strncmp(str, "CALIAS_DIR", delim) == 0) { - settings->calias_directory = _strdup(str + delim + 1); - break; - } - } if (settings->language_server) { language_server(settings); @@ -99,16 +83,22 @@ struct Settings *build_settings(int argc, char **argv, char **envp) { if (!settings->filename_input) { return NULL; } + + settings->included_files = vnew(); + const char *filename = _strrchr(settings->filename_input, '/'); + if (!filename) filename = settings->filename_input; + else filename++; + vpush(&settings->included_files, _strdup(filename)); return settings; } -int main(int argc, char *argv[], char *envp[]) { +int main(int argc, char *argv[]) { if (argc < 2) { help(); return 0; } else { - struct Settings *settings = build_settings(argc, argv, envp); + struct Settings *settings = build_settings(argc, argv); if (!settings) { help(); return 1; diff --git a/compiler/src/syntax.c b/compiler/src/syntax.c index b9726e0..23ba2f3 100644 --- a/compiler/src/syntax.c +++ b/compiler/src/syntax.c @@ -68,11 +68,10 @@ struct Node *syntax_process_block(struct TokenStream *ts, struct Settings *st, b } while (tokenstream_get(ts).type != TokenEof && tokenstream_get(ts).type != TokenBraceClose) { - if (tokenstream_get(ts).type == TokenSemicolon) { - tokenstream_next(ts); - continue; + struct Node *node = syntax_process_statement(ts, st); + if (node) { + vpush(&this->statement_list, node); } - vpush(&this->statement_list, syntax_process_statement(ts, st)); if (one_statement) break; } if (braces && !one_statement) { @@ -737,6 +736,10 @@ struct FunctionSignature *syntax_process_function_signature(struct TokenStream * } struct Node *syntax_process_statement(struct TokenStream *ts, struct Settings *st) { + if (tokenstream_get(ts).type == TokenSemicolon) { + tokenstream_next(ts); + return NULL; + } if (tokenstream_get(ts).type == TokenEval) { tokenstream_next(ts); return syntax_process_expression(ts, st); @@ -764,22 +767,41 @@ struct Node *syntax_process_statement(struct TokenStream *ts, struct Settings *s } pass_next(ts, TokenDot, ". expected in include"); check_next(ts, TokenString, "String literal expected in include"); - char *filename = _concat(include_path, tokenstream_get(ts).value_string); + char *path = _concat(include_path, tokenstream_get(ts).value_string); tokenstream_next(ts); - int fd = posix_open(filename, 0, 0); - if (fd <= 0) { - const char *buffer = _concat("Could not open file ", filename); - error_syntax(buffer, tokenstream_get(ts)); + bool good = true; + + const char *filename = _strrchr(path, '/'); + if (!filename) filename = path; + else filename++; + + int sz = vsize(&st->included_files); + for (int i = 0; i < sz; i++) { + if (_strcmp(filename, st->included_files.ptr[i]) == 0) { + good = false; + break; + } + } + if (good) { + vpush(&st->included_files, (char*)filename); + int fd = posix_open(path, 0, 0); + if (fd <= 0) { + const char *buffer = _concat("Could not open file ", path); + error_syntax(buffer, tokenstream_get(ts)); + } + else { + posix_close(fd); + } + struct Node *_node = process_parse(path, st); + struct Block *inc_block = (struct Block*)_node->node_ptr; + this->statement_list = inc_block->statement_list; + _free(inc_block); + _free(_node); } else { - posix_close(fd); - } - struct Node *_node = process_parse(filename, st); - struct Block *inc_block = (struct Block*)_node->node_ptr; - this->statement_list = inc_block->statement_list; - _free(filename); - _free(inc_block); - _free(_node); + _free(node); + return NULL; + } } else if (tokenstream_get(ts).type == TokenTest) { struct Test *this = (struct Test*)_malloc(sizeof(struct Test)); diff --git a/docs/altlibref.html b/docs/altlibref.html index aafa0e6..c26a8ab 100644 --- a/docs/altlibref.html +++ b/docs/altlibref.html @@ -84,7 +84,8 @@

Table of Contents

  • memory
  • posix
      @@ -151,7 +152,12 @@

      _memcpy

      proto ._memcpy(dest #1I, src #1I, sz #I) -> #1I
       
       
      -

      _memset

      +

      _memmove

      +Copies the data of length sz bytes from src pointer to dest pointer. Handles possible overlapping +
      proto ._memmove(dest #1I, src #1I, sz #I) -> #1I
      +
      +
      +

      _memset

      Sets the data of length count bytes to dest pointer with value ch. Important: only the lowest byte in ch argument is used.
      proto ._memset(dest #1I, ch #I, count #I) -> #1I
       
      @@ -168,6 +174,7 @@

      todo

      proto .posix_exit(error_code #I) -> #I proto .posix_wait4(pid #I, stat_addr #1I, options #I, rusage #1I) -> #I proto .posix_unlink(pathname #1I) -> #I +proto .posix_getcwd(buf #1C, size #I) -> #1C

      stdio

      fputs_

      @@ -361,7 +368,7 @@

      todo

      } } -/* func ^.atoi_(str #1C) -> #I { +func ^.atoi_(str #1C) -> #I { def i := strlen_(str) - 1 def x := 0 eval while (i >= 0) { @@ -370,7 +377,7 @@

      todo

      i := i - 1 } return x -} */ +} func ^.rand_(seed #I) -> #I { seed := seed * 1103515245 + 12345 @@ -425,6 +432,14 @@

      todo

      } else 0 } +func ^.strnlen_(a #1C, n #I) -> #I { + def i := 0 + return while (i < n) { + eval if (a[i] = '\0') { break i } + i := i + 1 + } else n +} + func ^.concat_(a #1C, b #1C) -> #1C { def s_a := strlen_(a) def s_b := strlen_(b) diff --git a/stdlib/asm/memory.asm b/stdlib/asm/memory.asm index 1c3106e..b142be1 100644 --- a/stdlib/asm/memory.asm +++ b/stdlib/asm/memory.asm @@ -1,8 +1,34 @@ global _memcpy _memcpy: + call _cpy_dir + +global _memmove +_memmove: + mov rax, rdi + sub rax, rsi + jl _call_dir + call _cpy_rev + ret +_call_dir: + call _cpy_dir + ret + +_cpy_dir: + mov rcx, rdx + rep movsb + mov rax, rdi + ret + +_cpy_rev: mov rcx, rdx + add rdi, rcx + sub rdi, 1 + add rsi, rcx + sub rsi, 1 + std rep movsb mov rax, rdi + cld ret global _memset diff --git a/stdlib/asm/posix.asm b/stdlib/asm/posix.asm index d4e190d..d16a000 100644 --- a/stdlib/asm/posix.asm +++ b/stdlib/asm/posix.asm @@ -11,6 +11,7 @@ global posix_execve global posix_exit global posix_wait4 global posix_unlink +global posix_getcwd posix_read: mov rax, 0x0 @@ -77,3 +78,8 @@ posix_unlink: mov rax, 0x57 syscall ret + +posix_getcwd: + mov rax, 0xb7 + syscall + ret diff --git a/stdlib/include/memory.h b/stdlib/include/memory.h index ad10f44..4c85ab7 100644 --- a/stdlib/include/memory.h +++ b/stdlib/include/memory.h @@ -1,4 +1,5 @@ #pragma once void *_memcpy(void *dest, const void *src, int count); +void *_memmove(void *dest, const void *src, int count); void *_memset(void *dest, int ch, int count); diff --git a/stdlib/include/posix.h b/stdlib/include/posix.h index df49b14..0d4e5b3 100644 --- a/stdlib/include/posix.h +++ b/stdlib/include/posix.h @@ -27,3 +27,4 @@ int posix_execve(const char *filename, const char *const *argv, const char *cons void posix_exit(int error_code); int posix_wait4(int pid, int *stat_addr, int options, void *rusage); int posix_unlink(const char *pathname); +char *posix_getcwd(char *buf, unsigned long size); diff --git a/stdlib/include/string.h b/stdlib/include/string.h index 8d28c9b..9aa5749 100644 --- a/stdlib/include/string.h +++ b/stdlib/include/string.h @@ -11,6 +11,8 @@ bool _isalpha(char c); bool _isdigit(char c); +char *_strchr(const char *s, int c); +char *_strrchr(const char *s, int c); char *_strcpy(char *a, const char *b); char *_strncpy(char *a, const char *b, int n); @@ -19,6 +21,7 @@ char *_strndup(const char *a, int n); int _strcmp(const char *a, const char *b); int _strncmp(const char *a, const char *b, int num); int _strlen(const char *a); +int _strnlen(const char *a, int n); char *_concat(const char *a, const char *b); char *_concat3(const char *a, const char *b, const char *c); const char *_substr(const char *a, int n); diff --git a/stdlib/src/stdlib.c b/stdlib/src/stdlib.c index 25b648f..0cd6a51 100644 --- a/stdlib/src/stdlib.c +++ b/stdlib/src/stdlib.c @@ -1,5 +1,8 @@ -#include #include +#include +#include +#include +#include char *_itoa(int n) { if (n == 0) { diff --git a/stdlib/src/string.c b/stdlib/src/string.c index 6fde156..e77dad0 100644 --- a/stdlib/src/string.c +++ b/stdlib/src/string.c @@ -11,6 +11,26 @@ bool _isdigit(char c) { return (c >= '0' && c <= '9'); } +char *_strchr(const char *s, int c) { + int n = _strlen(s); + for (int i = 0; i < n; i++) { + if (s[i] == c) { + return (char*)&s[i]; + } + } + return NULL; +} + +char *_strrchr(const char *s, int c) { + int n = _strlen(s); + for (int i = n - 1; i >= 0; i--) { + if (s[i] == c) { + return (char*)&s[i]; + } + } + return NULL; +} + char *_strcpy(char *a, const char *b) { for (int i = 0; ; i++) { a[i] = b[i]; @@ -89,6 +109,14 @@ int _strlen(const char *a) { } } +int _strnlen(const char *a, int n) { + for (int i = 0; i < n; i++) { + if (a[i] == '\0') { + return i; + } + } +} + char *_concat(const char *a, const char *b) { int s_a = _strlen(a); int s_b = _strlen(b); diff --git a/test/integration/string.al b/test/integration/test_string.al similarity index 85% rename from test/integration/string.al rename to test/integration/test_string.al index ffa7e8b..306c9a0 100644 --- a/test/integration/string.al +++ b/test/integration/test_string.al @@ -35,17 +35,20 @@ func ^._start() -> #V { def n6 := strlen_(str1) eval puti_(n6) - def n7 := strlen_(str3) + def n7 := strnlen_(str1, 4) eval puti_(n7) + def n8 := strlen_(str3) + eval puti_(n8) + def str4 := concat_(str1, str2) def str5 := "abac" - def n8 := strncmp_(str4, str5, 4) - eval puti_(n8) + def n9 := strncmp_(str4, str5, 4) + eval puti_(n9) def str6 := substr_(str1, 3) - def n9 := strcmp_(str6, str3) - eval puti_(n9) + def n10 := strcmp_(str6, str3) + eval puti_(n10) eval posix_exit(0) } diff --git a/test/integration/string.out b/test/integration/test_string.out similarity index 95% rename from test/integration/string.out rename to test/integration/test_string.out index dff900d..ac3a1e7 100644 --- a/test/integration/string.out +++ b/test/integration/test_string.out @@ -7,6 +7,7 @@ aba 0 -1 7 +4 3 0 0 diff --git a/test/integration/test_allocator.al b/test/integration/test_test_allocator.al similarity index 100% rename from test/integration/test_allocator.al rename to test/integration/test_test_allocator.al diff --git a/test/integration/test_allocator.out b/test/integration/test_test_allocator.out similarity index 100% rename from test/integration/test_allocator.out rename to test/integration/test_test_allocator.out diff --git a/test/integration/vector.al b/test/integration/test_vector.al similarity index 100% rename from test/integration/vector.al rename to test/integration/test_vector.al diff --git a/test/integration/vector.out b/test/integration/test_vector.out similarity index 100% rename from test/integration/vector.out rename to test/integration/test_vector.out