aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/dependencies.tm65
-rw-r--r--examples/file.tm6
2 files changed, 70 insertions, 1 deletions
diff --git a/examples/dependencies.tm b/examples/dependencies.tm
new file mode 100644
index 00000000..e13e3621
--- /dev/null
+++ b/examples/dependencies.tm
@@ -0,0 +1,65 @@
+# Show dependency graph
+use file
+
+func build_dependency_graph(filename:Text, dependencies:&{Text:@{Text}}):
+ reader := when LineReader.from_file(filename) is Failure(msg):
+ return
+ is Open(reader): reader
+
+ while when reader:next_line() is Success(line):
+ if line:matches($/{start}use {..}.tm/):
+ import := line:replace($/{start}use {..}/, "\2")
+ resolved := relative_path(resolve_path(import, filename))
+ if resolved != "":
+ import = resolved
+
+ if not dependencies:has(filename):
+ dependencies:set(filename, @{:Text})
+
+ dependencies:get(filename):add(import)
+ if not dependencies:has(import):
+ build_dependency_graph(import, dependencies)
+
+func get_dependency_graph(file:Text)->{Text:{Text}}:
+ graph := {:Text:@{Text}}
+ resolved := relative_path(file)
+ build_dependency_graph(resolved, &graph)
+ return {f:deps[] for f,deps in graph}
+
+func draw_tree(file:Text, dependencies:{Text:{Text}}, already_printed:&{Text}, prefix="", is_last=yes):
+ color_file := if resolve_path(file): file else: "$\x1b[31;1m$file$\x1b[m"
+
+
+ if already_printed:has(file):
+ say(prefix ++ (if is_last: "└── " else: "├── ") ++ color_file ++ " $\x1b[2m(recursive)$\x1b[m")
+ return
+
+ say(prefix ++ (if is_last: "└── " else: "├── ") ++ color_file)
+ already_printed:add(file)
+
+ child_prefix := prefix ++ (if is_last: " " else: "│ ")
+
+ children := dependencies:get(file, {:Text})
+ for i,child in children.items:
+ is_child_last := (i == children.length)
+ draw_tree(child, dependencies, already_printed, child_prefix, is_child_last)
+
+func main(files:[Text]):
+ for f,file in files:
+ if not file:matches($/{..}.tm/):
+ say("$\x1b[2mSkipping $file$\x1b[m")
+ skip
+
+ printed := {:Text}
+ resolved := relative_path(file)
+ if resolved != "":
+ file = resolved
+
+ deps := get_dependency_graph(file)
+
+ say(file)
+ printed:add(file)
+ children := deps:get(file, {:Text})
+ for i,child in children.items:
+ is_child_last := (i == children.length)
+ draw_tree(child, deps, already_printed=&printed, is_last=is_child_last)
diff --git a/examples/file.tm b/examples/file.tm
index 4f4d8645..7def4187 100644
--- a/examples/file.tm
+++ b/examples/file.tm
@@ -6,6 +6,8 @@ use <stdio.h>
use <sys/mman.h>
use <sys/stat.h>
use <unistd.h>
+use <unistr.h>
+use libunistring.so
enum FileReadResult(Success(text:Text), Failure(reason:Text))
@@ -45,6 +47,8 @@ func read(path:Text)->FileReadResult:
do {
just_read = read(fd, buf, chunk_size);
if (just_read > 0) {
+ if (u8_check(buf, just_read) != NULL)
+ break;
contents = Texts(contents, Text$from_strn(buf, just_read));
buf = GC_MALLOC_ATOMIC(chunk_size);
}
@@ -132,7 +136,7 @@ struct LineReader(_file:@Memory):
memcpy(line, buf, len);
line[len] = '\0';
if (buf) free(buf);
- Text$from_strn(line, len);
+ u8_check(line, len) ? Text("") : Text$from_strn(line, len);
})
):Text
return Success(line)