From b326a01228e48c8a7c948203d50ca2095efa38a4 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Thu, 1 Dec 2022 23:48:15 -0500 Subject: [PATCH] started implementing module imports --- cerise/inc/cerise.h | 6 ++ cerise/src/fs.c | 127 ++++++++++++++++++++++++++++++++++++++++++ cerise/src/grammar.c | 119 +++++++++++++++++---------------------- cerise/src/main.c | 2 +- cerise/tests/A.m | 2 + cerise/tests/Module.m | 3 + 6 files changed, 189 insertions(+), 70 deletions(-) create mode 100644 cerise/src/fs.c create mode 100644 cerise/tests/A.m diff --git a/cerise/inc/cerise.h b/cerise/inc/cerise.h index a6b6acc..f132ae4 100644 --- a/cerise/inc/cerise.h +++ b/cerise/inc/cerise.h @@ -237,6 +237,12 @@ typedef struct { void fatal(char* estr); void* emalloc(size_t size); +// src/fs.c +void fs_init(void); +char* fs_read(char* path); +char* fs_modname(char* path); +char* fs_modfind(Parser* p, char* path); + // src/lex.c void lexfile(Parser* ctx, char* path); void lex(Parser* ctx); diff --git a/cerise/src/fs.c b/cerise/src/fs.c new file mode 100644 index 0000000..1c1d944 --- /dev/null +++ b/cerise/src/fs.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include + +#define DEFAULT_MPATH "/usr/share/cerise/modules" +size_t Num_Paths = 0; +char** Paths = NULL; + +static char* strmcat(char* first, ...) { + va_list args; + /* calculate the length of the final string */ + size_t len = strlen(first); + va_start(args, first); + for (char* s = NULL; (s = va_arg(args, char*));) + len += strlen(s); + va_end(args); + /* allocate the final string and copy the args into it */ + char *str = malloc(len+1), *curr = str; + while (first && *first) *(curr++) = *(first++); + va_start(args, first); + for (char* s = NULL; (s = va_arg(args, char*));) + while (s && *s) *(curr++) = *(s++); + va_end(args); + /* null terminate and return */ + *curr = '\0'; + return str; +} + +void fs_init(void) +{ + /* get path variable */ + char* paths = getenv("CERISE_MPATH"); + if (!paths) + { + paths = DEFAULT_MPATH; + } + paths = strdup(paths); + + /* now let's process it */ + char* path = strtok(paths, ":"); + while (path) + { + Num_Paths++; + Paths = realloc(Paths, sizeof(char*) * Num_Paths); + Paths[Num_Paths-1] = path; + path = strtok(NULL, ":"); + } +} + +char* fs_read(char* path) +{ + int fd = -1, nread = 0, length = 0; + struct stat sb = {0}; + char* contents = NULL; + if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) + { + contents = calloc(sb.st_size + 1u, 1u); + while (sb.st_size && (nread = read(fd, contents+length, sb.st_size)) > 0) + { + length += nread, sb.st_size -= nread; + } + } + if (fd > 0) + { + close(fd); + } + return contents; + +} + +char* fs_modname(char* path) +{ + char* name = NULL; + char* last_slash = strrchr(path, '/'); + if (last_slash) + { + char* last_dot = strrchr(last_slash, '.'); + if (last_dot) + { + name = strndup(last_slash+1, last_dot-last_slash-1); + if (*name == '\0') + { + name = NULL; + } + } + } + return name; +} + +static char* dirname(char* path) +{ + char* last_slash = strrchr(path, '/'); + if (last_slash) + { + char* new_path = strdup(path); + new_path[last_slash - path] = '\0'; + path = new_path; + } + return path; +} + +static char* check_modpath(char* path, char* name) +{ + char* retpath = NULL; + char* full_path = strmcat(path, "/", name, ".m", 0); + if (access(full_path, F_OK) == 0) + { + retpath = full_path; + } + else + { + free(full_path); + } + return retpath; +} + +char* fs_modfind(Parser* p, char* name) +{ + char* curr_dir = dirname(p->file->path); + char* path = check_modpath(curr_dir, name); + for(size_t i = 0; !path && i < Num_Paths; i++) + { + path = check_modpath(Paths[i], name); + } + return path; +} diff --git a/cerise/src/grammar.c b/cerise/src/grammar.c index 96f6bd9..56870ab 100644 --- a/cerise/src/grammar.c +++ b/cerise/src/grammar.c @@ -1,8 +1,5 @@ #include "cerise.h" #include -#include -#include -#include //#define TRACE #ifdef TRACE @@ -17,6 +14,7 @@ #define EXIT_RULE() ((void)0) #endif +static void import(Parser* curr, char* modname, char* alias); /* Item Handling *****************************************************************************/ @@ -613,8 +611,7 @@ static void import_list(Parser* p) alias = name; name = expect_text(p, IDENT); } - (void)name, (void)alias; -// symbol_import(p, name, alias); + import(p, name, alias); } while (matches(p, IDENT)); @@ -624,7 +621,7 @@ static void import_list(Parser* p) static void module(Parser* p) { ENTER_RULE(); - size_t scope = symbol_openscope(p); + symbol_openscope(p); if (matches(p, IMPORT)) { @@ -686,80 +683,64 @@ static void module(Parser* p) { error(p, "expected end of file"); } - - symbol_closescope(p, scope); EXIT_RULE(); } -static inline char* file_load(char* path) +static void init_parser(Parser* p, char* path) { - int fd = -1, nread = 0, length = 0; - struct stat sb = {0}; - char* contents = NULL; - if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) - { - contents = calloc(sb.st_size + 1u, 1u); - while (sb.st_size && (nread = read(fd, contents+length, sb.st_size)) > 0) - { - length += nread, sb.st_size -= nread; - } - } - if (fd > 0) - { - close(fd); - } - return contents; + char* fcontents = fs_read(path); + p->name = fs_modname(path); + p->file = calloc(1, sizeof(LexFile)); + p->file->path = path; + p->file->fbeg = fcontents; + p->file->fpos = fcontents; + p->curr_reg = 0; + if (p->name == NULL) + { + fatal("could not determine module name from path"); + } + p->mtypes = 8; + p->types = calloc(p->mtypes, sizeof(Type*)); + symbol_new(p, 0, "$", SYM_VAR, 0); + symbol_new(p, 0, "Bool", SYM_TYPE, 0)->type = &BoolType; + p->types[p->ntypes++] = &BoolType; + symbol_new(p, 0, "Int", SYM_TYPE, 0)->type = &IntType; + p->types[p->ntypes++] = &IntType; + symbol_new(p, 0, "Real", SYM_TYPE, 0)->type = &RealType; + p->types[p->ntypes++] = &RealType; + symbol_new(p, 0, "String", SYM_TYPE, 0)->type = &StringType; + p->types[p->ntypes++] = &StringType; } -static char* get_module_name(char* path) +static void import(Parser* curr, char* modname, char* alias) { - char* name = NULL; - char* last_slash = strrchr(path, '/'); - if (last_slash) + Parser p = {0}; + char* path = fs_modfind(curr, modname); + if (!path) { - char* last_dot = strrchr(last_slash, '.'); - if (last_dot) - { - name = strndup(last_slash+1, last_dot-last_slash-1); - if (*name == '\0') - { - name = NULL; - } - } + error(curr, "unable to find module '%s'", modname); } - return name; + init_parser(&p, path); + module(&p); + (void)alias; + +// Symbol* sym = symbol_new(p, 0, modname, SYM_MODULE, 0); +// size_t modid = sym - &p->syms[0]; +// +// for (size_t i = 0; i < p.nsyms; i++) +// { +// if (p.syms[i].export) +// { +//// printf("sym: %s\n", p.syms[i].name); +//// (void)alias; +// } +// } } -void compile(char* fname) +void compile(char* path) { - char* fcontents = file_load(fname); - Parser p = { - .name = get_module_name(fname), - .file = &(LexFile){ - .path = fname, - .fbeg = fcontents, - .fpos = fcontents, - }, - .curr_reg = 0 - }; - - if (p.name == NULL) - { - error(&p, "could not determine module name from path"); - } - - p.mtypes = 8; - p.types = calloc(p.mtypes, sizeof(Type*)); - symbol_new(&p, 0, "$", SYM_VAR, 0); - symbol_new(&p, 0, "Bool", SYM_TYPE, 0)->type = &BoolType; - p.types[p.ntypes++] = &BoolType; - symbol_new(&p, 0, "Int", SYM_TYPE, 0)->type = &IntType; - p.types[p.ntypes++] = &IntType; - symbol_new(&p, 0, "Real", SYM_TYPE, 0)->type = &RealType; - p.types[p.ntypes++] = &RealType; - symbol_new(&p, 0, "String", SYM_TYPE, 0)->type = &StringType; - p.types[p.ntypes++] = &StringType; - - codegen_init(&p); + Parser p = {0}; + init_parser(&p, path); +// codegen_init(&p); module(&p); } diff --git a/cerise/src/main.c b/cerise/src/main.c index 22e0052..e170891 100644 --- a/cerise/src/main.c +++ b/cerise/src/main.c @@ -6,9 +6,9 @@ int main(int argc, char **argv) { if (argc >= 2) { + fs_init(); compile( argv[1] ); } - return 0; } diff --git a/cerise/tests/A.m b/cerise/tests/A.m new file mode 100644 index 0000000..d57ca9c --- /dev/null +++ b/cerise/tests/A.m @@ -0,0 +1,2 @@ +const + FOO* = 42 \ No newline at end of file diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m index c961300..a24ea43 100644 --- a/cerise/tests/Module.m +++ b/cerise/tests/Module.m @@ -1,5 +1,8 @@ +import A + const FOO* = 42 + type FooRec* = record a : Int -- 2.49.0