aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/import.ct1
-rw-r--r--src/compiler.c150
-rw-r--r--src/path.c3
3 files changed, 148 insertions, 6 deletions
diff --git a/examples/import.ct b/examples/import.ct
new file mode 100644
index 0000000..36e7300
--- /dev/null
+++ b/examples/import.ct
@@ -0,0 +1 @@
+import vec.ct;
diff --git a/src/compiler.c b/src/compiler.c
index b8f5823..b222c2e 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -2,6 +2,8 @@
#include <string.h>
#include <unistd.h>
#include <ctype.h>
+#include <stdlib.h>
+#include <regex.h>
#include <errno.h>
#include <ct/compiler.h>
@@ -10,6 +12,34 @@
#include <ct/path.h>
#include <ct/res.h>
+const char *import_regex =
+"^[[:space:]]*(pub[[:space:]]+)?"
+"import[[:space:]]+"
+"([[:alnum:]/.]+)"
+"[[:space:]]*;"
+"[[:space:]]*$";
+
+const char *define_regex =
+"^[[:space:]]*(pub[[:space:]]+)?"
+"define[[:space:]]+"
+"([[:alnum:]]+)[[:space:]]*"
+"\\((.*)\\)"
+"[[:space:]]*"
+"\\{(.*)\\}"
+"[[:space:]]*$";
+
+regex_t import_re;
+regex_t define_re;
+
+/* this could maybe be moved to a utility file or something */
+static char *get_regerror(int errcode, regex_t *compiled)
+{
+ size_t len = regerror(errcode, compiled, NULL, 0);
+ char *buf = malloc(len);
+ regerror(errcode, compiled, buf, len);
+ return buf;
+}
+
static int read_element(FILE *f, struct string *element)
{
if (feof(f))
@@ -85,7 +115,69 @@ static struct string *read_block(FILE *f, size_t *lines)
return block;
}
-static int process(struct res *r, const char *file)
+static bool detect_pub(struct string *block, regmatch_t rm)
+{
+ const char *start = block->buf + rm.rm_so;
+ const size_t len = rm.rm_eo - rm.rm_so;
+ const size_t min = len < 3 ? len : 3;
+ return strncmp(start, "pub", min);
+}
+
+static char *extract_match(struct string *block, regmatch_t rm)
+{
+ const char *start = block->buf + rm.rm_so;
+ const size_t len = rm.rm_eo - rm.rm_so;
+ char *match = strndup(start, len);
+ if (!match)
+ error("couldn't extract match: %s\n", strerror(errno));
+
+ return match;
+}
+
+static bool detect_import(struct string *block, bool *pub, char **file)
+{
+ int ret = 0;
+ const size_t captures = 3;
+ regmatch_t rm[captures];
+ ret = regexec(&import_re, block->buf, captures, rm, 0);
+
+ switch (ret) {
+ case REG_ESPACE: error("import regex ran out of memory: %s\n",
+ strerror(errno));
+ /* fallthrough */
+ case REG_NOMATCH: return false;
+ }
+
+ *pub = detect_pub(block, rm[1]);
+ *file = extract_match(block, rm[2]);
+ return true;
+}
+
+static bool detect_define(struct string *block, bool *pub,
+ char **name, char **args, char **content)
+{
+ int ret = 0;
+ const size_t captures = 5;
+ regmatch_t rm[captures];
+ ret = regexec(&define_re, block->buf, captures, rm, 0);
+
+ switch (ret) {
+ case REG_ESPACE: error("define regex ran out of memory: %s\n",
+ strerror(errno));
+ /* fallthrough */
+ case REG_NOMATCH: return false;
+ }
+
+ *pub = detect_pub(block, rm[1]);
+ *name = extract_match(block, rm[2]);
+ *args = extract_match(block, rm[3]);
+ *content = extract_match(block, rm[4]);
+ return true;
+}
+
+static void process_file(const char *file);
+
+static int process(const char *file)
{
FILE *f = fopen(file, "r");
if (!f) {
@@ -100,6 +192,28 @@ static int process(struct res *r, const char *file)
lines - prev_lines, block->buf);
prev_lines = lines + 1;
+ bool pub = false;
+ char *file = NULL;
+ if (detect_import(block, &pub, &file)) {
+ debug("detected %s import block for file (%s)\n",
+ pub ? "public" : "private",
+ file);
+ process_file(file);
+ free(file);
+ goto next;
+ }
+
+ char *name = NULL, *args = NULL, *content = NULL;
+ if (detect_define(block, &pub, &name, &args, &content)) {
+ debug("detected %s define block %s (%s) {%s}\n",
+ pub ? "public" : "private",
+ name, args, content);
+ free(name);
+ free(args);
+ free(content);
+ goto next;
+ }
+
/* with each block,
* A) Detect if it is an import block and what kind,
* in which case process the file that it refers to.
@@ -132,6 +246,7 @@ static int process(struct res *r, const char *file)
* processing upwards. And probably detecting a main block as
* well?
*/
+next:
destroy_string(block);
}
@@ -139,9 +254,9 @@ static int process(struct res *r, const char *file)
return 0;
}
-void compile(const char *file) {
+void process_file(const char *file)
+{
struct res *r = res_create();
- res_add(r, (void *)(file = strdup(file)));
const char *base = ct_basename(file);
res_add(r, (void *)base);
@@ -160,12 +275,12 @@ void compile(const char *file) {
debug("(cwd:%s)(dir:%s)(base:%s)\n", cwd, dir, base);
- if (chdir(dir)) {
+ if (*dir != 0 && chdir(dir)) {
error("couldn't change to directory %s: %s\n", dir, strerror(errno));
goto out;
}
- if (process(r, base))
+ if (process(base))
goto out;
if (chdir(cwd)) {
@@ -173,7 +288,30 @@ void compile(const char *file) {
goto out;
}
-
out:
res_destroy(r);
}
+
+void compile(const char *file) {
+ int err = 0;
+ if ((err = regcomp(&import_re, import_regex, REG_EXTENDED)) != 0) {
+ char *err_str = get_regerror(err, &import_re);
+ error("failed compiling import regex: %s\n", err_str);
+ free(err_str);
+ goto out;
+ }
+
+ if ((err = regcomp(&define_re, define_regex, REG_EXTENDED)) != 0) {
+ char *err_str = get_regerror(err, &define_re);
+ error("failed compiling define regex: %s\n", err_str);
+ free(err_str);
+ goto define_out;
+ }
+
+ process_file(file);
+
+ regfree(&define_re);
+define_out:
+ regfree(&import_re);
+out:
+}
diff --git a/src/path.c b/src/path.c
index c9160bb..090727d 100644
--- a/src/path.c
+++ b/src/path.c
@@ -16,6 +16,9 @@ char *ct_basename(const char *file)
break;
}
+ if (n == 0)
+ return strdup(file);
+
return strndup(file + n + 1, l - n);
}