diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | builtins/nextline.c | 108 | ||||
| -rw-r--r-- | builtins/nextline.h | 31 | ||||
| -rw-r--r-- | builtins/path.c | 52 | ||||
| -rw-r--r-- | builtins/path.h | 1 | ||||
| -rw-r--r-- | builtins/siphash.h | 1 | ||||
| -rw-r--r-- | builtins/tomo.h | 1 | ||||
| -rw-r--r-- | environment.c | 12 |
8 files changed, 205 insertions, 3 deletions
@@ -30,7 +30,7 @@ CFLAGS_PLACEHOLDER="$$(echo -e '\033[2m<flags...>\033[m')" LDLIBS=-lgc -lcord -lm -lunistring -lgmp -ldl BUILTIN_OBJS=builtins/siphash.o builtins/array.o builtins/bool.o builtins/channel.o builtins/nums.o builtins/functions.o builtins/integers.o \ builtins/pointer.o builtins/memory.o builtins/text.o builtins/thread.o builtins/c_string.o builtins/table.o \ - builtins/types.o builtins/util.o builtins/files.o builtins/range.o builtins/shell.o builtins/path.o + builtins/types.o builtins/util.o builtins/files.o builtins/range.o builtins/shell.o builtins/path.o builtins/nextline.o TESTS=$(patsubst %.tm,%.tm.testresult,$(wildcard test/*.tm)) all: libtomo.so tomo diff --git a/builtins/nextline.c b/builtins/nextline.c new file mode 100644 index 00000000..3fa37412 --- /dev/null +++ b/builtins/nextline.c @@ -0,0 +1,108 @@ +// An enum used for iterating over lines in a file +// Most of the code here was generated by compiling: +// enum NextLine(Done, Next(line:Text)) + +#include <stdbool.h> +#include <stdint.h> + +#include "siphash.h" +#include "datatypes.h" +#include "nextline.h" +#include "text.h" +#include "util.h" + +static Text_t NextLine$Next$as_text(NextLine$Next_t *obj, bool use_color) +{ + if (!obj) + return Text("Next"); + return Text$concat(use_color ? Text("\x1b[0;1mNext\x1b[m(") : Text("Next("), Text("line="), + Text$as_text((Text_t[1]){obj->$line}, use_color, &Text$info), Text(")")); +} + +public inline NextLine_t NextLine$tagged$Next(Text_t $line) +{ + return (NextLine_t) { + .tag = NextLine$tag$Next,.$Next = { $line } + }; +} + +static Text_t NextLine$as_text(NextLine_t *obj, bool use_color) +{ + if (!obj) + return Text("NextLine"); + switch (obj->tag) { + case NextLine$tag$Done: + return use_color ? Text("\x1b[36;1mNextLine.Done\x1b[m") : Text("NextLine.Done"); + case NextLine$tag$Next: + return Text$concat(use_color ? Text("\x1b[36;1mNextLine.Next\x1b[m(") : + Text("NextLine.Next("), Text("line="), + Text$as_text((Text_t[1]){obj->$Next.$line}, use_color, &Text$info), Text(")")); + default: + return (Text_t) { + .length = 0}; + } +} + +static bool NextLine$equal(const NextLine_t *x, const NextLine_t *y, + const TypeInfo *info) +{ + (void) info; + if (x->tag != y->tag) + return false; + switch (x->tag) { + case NextLine$tag$Done: + return false; + case NextLine$tag$Next: + return generic_equal(&x->$Next, &y->$Next, (&NextLine$Next)); + default: + return 0; + } +} + +static int NextLine$compare(const NextLine_t *x, const NextLine_t *y, + const TypeInfo *info) +{ + (void) info; + int diff = (int)x->tag - (int)y->tag; + if (diff) + return diff; + switch (x->tag) { + case NextLine$tag$Done: + return 0; + case NextLine$tag$Next: + return generic_compare(&x->$Next, &y->$Next, (&NextLine$Next)); + default: + return 0; + } +} + +static uint64_t NextLine$hash(const NextLine_t *obj, const TypeInfo *info) +{ + (void) info; + uint64_t hashes[2] = { (uint64_t) obj->tag, 0 }; + switch (obj->tag) { + case NextLine$tag$Done: + break; + case NextLine$tag$Next: + hashes[1] = generic_hash(&obj->$Next, (&NextLine$Next)); + break; + default: break; + } + return siphash24((void *) &hashes, sizeof(hashes)); +} + +public const TypeInfo NextLine$Done = { 0, 0, {.tag = EmptyStruct,.EmptyStruct.name = + "NextLine$Done" } }; +public const TypeInfo NextLine$Next = { 24, 8, {.tag = CustomInfo,.CustomInfo = + {.as_text = + (void *) NextLine$Next$as_text,.hash = + (void *) Text$hash,.compare = + (void *) Text$compare,.equal = + (void *) Text$equal,} } }; +public const TypeInfo NextLine = { 32, 8, {.tag = CustomInfo,.CustomInfo = + {.as_text = (void *) NextLine$as_text,.equal = + (void *) NextLine$equal,.hash = + (void *) NextLine$hash,.compare = + (void *) NextLine$compare} } }; + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/nextline.h b/builtins/nextline.h new file mode 100644 index 00000000..ce4c9fab --- /dev/null +++ b/builtins/nextline.h @@ -0,0 +1,31 @@ +#pragma once + +#include "datatypes.h" +#include "types.h" + +// An enum used for iterating over lines in a file +// Most of the code here was generated by compiling: +// enum NextLine(Done, Next(line:Text)) + +typedef struct NextLine_s NextLine_t; +typedef struct NextLine$Done_s NextLine$Done_t; +#pragma GCC diagnostic ignored "-Wpedantic" +struct NextLine$Done_s { +}; +typedef struct NextLine$Next_s NextLine$Next_t; +struct NextLine$Next_s { + Text_t $line; +}; +struct NextLine_s { + enum { NextLine$tag$Done = 0, NextLine$tag$Next = 1 } tag; + union { + NextLine$Done_t $Done; + NextLine$Next_t $Next; + }; +}; +extern const TypeInfo NextLine; +extern const TypeInfo NextLine$Done; +extern const TypeInfo NextLine$Next; +NextLine_t NextLine$tagged$Next(Text_t $line); + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/path.c b/builtins/path.c index 7c2198cf..096cbdd0 100644 --- a/builtins/path.c +++ b/builtins/path.c @@ -1,10 +1,11 @@ // A lang for filesystem paths #include <dirent.h> -#include <fcntl.h> #include <errno.h> -#include <string.h> +#include <fcntl.h> +#include <gc.h> #include <stdbool.h> #include <stdint.h> +#include <string.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> @@ -15,6 +16,7 @@ #include "files.h" #include "functions.h" #include "integers.h" +#include "nextline.h" #include "path.h" #include "text.h" #include "types.h" @@ -423,6 +425,51 @@ public Text_t Path$extension(Path_t path, bool full) return Text(""); } +static void _line_reader_cleanup(FILE **f) +{ + if (f && *f) { + fclose(*f); + *f = NULL; + } +} + +static NextLine_t _next_line(FILE **f) +{ + if (!f || !*f) return (NextLine_t){NextLine$tag$Done}; + + char *line = NULL; + size_t size = 0; + ssize_t len = getline(&line, &size, *f); + if (len <= 0) { + _line_reader_cleanup(f); + return (NextLine_t){NextLine$tag$Done}; + } + + while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n')) + --len; + + if (u8_check((uint8_t*)line, (size_t)len) != NULL) + fail("Invalid UTF8!"); + + Text_t line_text = Text$format("%.*s", len, line); + free(line); + return NextLine$tagged$Next(line_text); +} + +public closure_t Path$by_line(Path_t path) +{ + path = Path$_expand_home(path); + + FILE *f = fopen(Text$as_c_string(path), "r"); + if (f == NULL) + fail("Could not read file: %k (%s)", &path, strerror(errno)); + + FILE **wrapper = GC_MALLOC(sizeof(FILE*)); + *wrapper = f; + GC_register_finalizer(wrapper, (void*)_line_reader_cleanup, NULL, NULL, NULL); + return (closure_t){.fn=(void*)_next_line, .userdata=wrapper}; +} + public const TypeInfo Path$info = { .size=sizeof(Path_t), .align=__alignof__(Path_t), @@ -430,4 +477,5 @@ public const TypeInfo Path$info = { .TextInfo={.lang="Path"}, }; + // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/path.h b/builtins/path.h index 6772f72d..dd42af85 100644 --- a/builtins/path.h +++ b/builtins/path.h @@ -39,6 +39,7 @@ Text_t Path$write_unique(Path_t path, Text_t text); Path_t Path$parent(Path_t path); Text_t Path$base_name(Path_t path); Text_t Path$extension(Path_t path, bool full); +closure_t Path$by_line(Path_t path); #define Path$hash Text$hash #define Path$compare Text$compare diff --git a/builtins/siphash.h b/builtins/siphash.h index a466200c..0fc7614c 100644 --- a/builtins/siphash.h +++ b/builtins/siphash.h @@ -3,6 +3,7 @@ // An implementation of the SipHash algorithm. #include <stdint.h> +#include <stddef.h> uint64_t siphash24(const uint8_t *src, size_t src_sz); diff --git a/builtins/tomo.h b/builtins/tomo.h index c7814376..29f71f71 100644 --- a/builtins/tomo.h +++ b/builtins/tomo.h @@ -17,6 +17,7 @@ #include "datatypes.h" #include "functions.h" #include "integers.h" +#include "nextline.h" #include "macros.h" #include "memory.h" #include "nums.h" diff --git a/environment.c b/environment.c index 45207da1..94401ec9 100644 --- a/environment.c +++ b/environment.c @@ -69,6 +69,16 @@ env_t *new_compilation_unit(CORD *libname) .next=new(arg_t, .name="step", .type=INT_TYPE, .default_val=FakeAST(Int, .str="1"))))); } + type_t *next_line_type; + { + next_line_type = Type( + EnumType, .name="NextLine", .env=namespace_env(env, "NextLine"), + .tags=new(tag_t, .name="Done", .tag_value=0, .type=Type(StructType, .name="NextLine$Done"), + .next=new(tag_t, .name="Next", .tag_value=1, .type=Type(StructType, .name="NextLine$Next", + .env=namespace_env(env, "NextLine$Next"), + .fields=new(arg_t, .name="line", .type=TEXT_TYPE))))); + } + { env_t *thread_env = namespace_env(env, "Thread"); THREAD_TYPE = Type(StructType, .name="Thread", .env=thread_env, .opaque=true); @@ -245,12 +255,14 @@ env_t *new_compilation_unit(CORD *libname) {"reversed", "Range$reversed", "func(range:Range)->Range"}, {"by", "Range$by", "func(range:Range, step:Int)->Range"}, )}, + {"NextLine", next_line_type, "NextLine_t", "NextLine", {}}, {"Pattern", Type(TextType, .lang="Pattern", .env=namespace_env(env, "Pattern")), "Pattern_t", "Pattern$info", TypedArray(ns_entry_t, {"escape_text", "Pattern$escape_text", "func(text:Text)->Pattern"}, )}, {"Path", Type(TextType, .lang="Path", .env=namespace_env(env, "Path")), "Text_t", "Text$info", TypedArray(ns_entry_t, {"append", "Path$append", "func(path:Path, text:Text, permissions=0o644_i32)"}, {"base_name", "Path$base_name", "func(path:Path)->Text"}, + {"by_line", "Path$by_line", "func(path:Path)->func()->NextLine"}, {"children", "Path$children", "func(path:Path, include_hidden=no)->[Path]"}, {"create_directory", "Path$create_directory", "func(path:Path, permissions=0o644_i32)"}, {"escape_path", "Path$escape_path", "func(path:Path)->Path"}, |
