From 5feecff9d93522002c74a1423d138c2aa8bc150d Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 3 Sep 2024 03:53:36 -0400 Subject: Deprecate `Where` and change channel API to use a boolean `front` value --- Makefile | 2 +- builtins/channel.c | 23 +++++++++++------------ builtins/channel.h | 19 +++++++++---------- builtins/text.h | 1 - builtins/where.c | 37 ------------------------------------- builtins/where.h | 37 ------------------------------------- compile.c | 14 ++++++-------- docs/channels.md | 20 ++++++++------------ docs/text.md | 27 +-------------------------- environment.c | 17 ----------------- environment.h | 1 - test/threads.tm | 4 ++-- 12 files changed, 38 insertions(+), 164 deletions(-) delete mode 100644 builtins/where.c delete mode 100644 builtins/where.h diff --git a/Makefile b/Makefile index eb085734..b636c8be 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ O=-Og CFLAGS=$(CCONFIG) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) LDLIBS=-lgc -lcord -lreadline -lm -lunistring -lgmp -ldl BUILTIN_OBJS=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/where.o builtins/c_string.o builtins/table.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 TESTS=$(patsubst %.tm,%.tm.testresult,$(wildcard test/*.tm)) diff --git a/builtins/channel.c b/builtins/channel.c index a0a0ddc5..08d6424f 100644 --- a/builtins/channel.c +++ b/builtins/channel.c @@ -18,11 +18,10 @@ #include "text.h" #include "types.h" #include "util.h" -#include "where.h" public channel_t *Channel$new(Int_t max_size) { - if (Int$compare_value(max_size, I(0)) <= 0) + if (Int$compare_value(max_size, I_small(0)) <= 0) fail("Cannot create a channel with a size less than one: %ld", max_size); channel_t *channel = new(channel_t); channel->items = (array_t){}; @@ -32,22 +31,22 @@ public channel_t *Channel$new(Int_t max_size) return channel; } -public void Channel$give(channel_t *channel, const void *item, Where_t where, int64_t padded_item_size) +public void Channel$give(channel_t *channel, const void *item, bool front, int64_t padded_item_size) { (void)pthread_mutex_lock(&channel->mutex); while (channel->items.length >= channel->max_size) pthread_cond_wait(&channel->cond, &channel->mutex); - Int_t index = (where.tag == $tag$Where$Start) ? I(1) : I(0); + Int_t index = front ? I_small(1) : I_small(0); Array$insert(&channel->items, item, index, padded_item_size); (void)pthread_mutex_unlock(&channel->mutex); (void)pthread_cond_signal(&channel->cond); } -public void Channel$give_all(channel_t *channel, array_t to_give, Where_t where, int64_t padded_item_size) +public void Channel$give_all(channel_t *channel, array_t to_give, bool front, int64_t padded_item_size) { if (to_give.length == 0) return; (void)pthread_mutex_lock(&channel->mutex); - Int_t index = (where.tag == $tag$Where$Start) ? I(1) : I(0); + Int_t index = front ? I_small(1) : I_small(0); if (channel->items.length + to_give.length >= channel->max_size) { for (int64_t i = 0; i < to_give.length; i++) { while (channel->items.length >= channel->max_size) @@ -61,24 +60,24 @@ public void Channel$give_all(channel_t *channel, array_t to_give, Where_t where, (void)pthread_cond_signal(&channel->cond); } -public void Channel$get(channel_t *channel, void *out, Where_t where, int64_t item_size, int64_t padded_item_size) +public void Channel$get(channel_t *channel, void *out, bool front, int64_t item_size, int64_t padded_item_size) { (void)pthread_mutex_lock(&channel->mutex); while (channel->items.length == 0) pthread_cond_wait(&channel->cond, &channel->mutex); - memcpy(out, channel->items.data, item_size); - Int_t index = (where.tag == $tag$Where$End) ? I(0) : I(1); - Array$remove_at(&channel->items, index, I(1), padded_item_size); + memcpy(out, channel->items.data + channel->items.stride * (front ? 0 : channel->items.length-1), item_size); + Int_t index = front ? I_small(1) : Int64_to_Int(channel->items.length); + Array$remove_at(&channel->items, index, I_small(1), padded_item_size); (void)pthread_mutex_unlock(&channel->mutex); (void)pthread_cond_signal(&channel->cond); } -public void Channel$peek(channel_t *channel, void *out, Where_t where, int64_t item_size) +public void Channel$peek(channel_t *channel, void *out, bool front, int64_t item_size) { (void)pthread_mutex_lock(&channel->mutex); while (channel->items.length == 0) pthread_cond_wait(&channel->cond, &channel->mutex); - int64_t index = (where.tag == $tag$Where$End) ? channel->items.length-1 : 0; + int64_t index = front ? 0 : channel->items.length-1; memcpy(out, channel->items.data + channel->items.stride*index, item_size); (void)pthread_mutex_unlock(&channel->mutex); (void)pthread_cond_signal(&channel->cond); diff --git a/builtins/channel.h b/builtins/channel.h index bf24f806..debbc457 100644 --- a/builtins/channel.h +++ b/builtins/channel.h @@ -8,18 +8,17 @@ #include "datatypes.h" #include "types.h" #include "util.h" -#include "where.h" channel_t *Channel$new(Int_t max_size); -void Channel$give(channel_t *channel, const void *item, Where_t where, int64_t padded_item_size); -#define Channel$give_value(channel, item, where, padded_item_size) \ - ({ __typeof(item) _item = item; Channel$give(channel, &_item, where, padded_item_size); }) -void Channel$give_all(channel_t *channel, array_t to_give, Where_t where, int64_t padded_item_size); -void Channel$get(channel_t *channel, void *out, Where_t where, int64_t item_size, int64_t padded_item_size); -#define Channel$get_value(channel, where, t, padded_item_size) \ - ({ t _val; Channel$get(channel, &_val, where, sizeof(t), padded_item_size); _val; }) -void Channel$peek(channel_t *channel, void *out, Where_t where, int64_t item_size); -#define Channel$peek_value(channel, where, t) ({ t _val; Channel$peek(channel, &_val, where, sizeof(t)); _val; }) +void Channel$give(channel_t *channel, const void *item, bool front, int64_t padded_item_size); +#define Channel$give_value(channel, item, front, padded_item_size) \ + ({ __typeof(item) _item = item; Channel$give(channel, &_item, front, padded_item_size); }) +void Channel$give_all(channel_t *channel, array_t to_give, bool front, int64_t padded_item_size); +void Channel$get(channel_t *channel, void *out, bool front, int64_t item_size, int64_t padded_item_size); +#define Channel$get_value(channel, front, t, padded_item_size) \ + ({ t _val; Channel$get(channel, &_val, front, sizeof(t), padded_item_size); _val; }) +void Channel$peek(channel_t *channel, void *out, bool front, int64_t item_size); +#define Channel$peek_value(channel, front, t) ({ t _val; Channel$peek(channel, &_val, front, sizeof(t)); _val; }) void Channel$clear(channel_t *channel); array_t Channel$view(channel_t *channel); uint64_t Channel$hash(const channel_t **channel, const TypeInfo *type); diff --git a/builtins/text.h b/builtins/text.h index 20ea9a25..b3cb6d79 100644 --- a/builtins/text.h +++ b/builtins/text.h @@ -10,7 +10,6 @@ #include "datatypes.h" #include "integers.h" #include "types.h" -#include "where.h" int printf_text(FILE *stream, const struct printf_info *info, const void *const args[]); int printf_text_size(const struct printf_info *info, size_t n, int argtypes[n], int sizes[n]); diff --git a/builtins/where.c b/builtins/where.c deleted file mode 100644 index d57f532e..00000000 --- a/builtins/where.c +++ /dev/null @@ -1,37 +0,0 @@ -// A type called "Where" that is an enum for "Anywhere", "Start", or "End" -// Mainly used for text methods - -#include -#include - -#include "text.h" -#include "types.h" -#include "util.h" -#include "where.h" - -static Text_t Where$as_text(Where_t *obj, bool use_color) -{ - if (!obj) - return Text$from_str("Where"); - switch (obj->tag) { - case $tag$Where$Anywhere: - return Text$from_str(use_color ? "\x1b[36;1mWhere.Anywhere\x1b[m" : "Where.Anywhere"); - case $tag$Where$Start: - return Text$from_str(use_color ? "\x1b[36;1mWhere.Start\x1b[m" : "Where.Start"); - case $tag$Where$End: - return Text$from_str(use_color ? "\x1b[36;1mWhere.End\x1b[m" : "Where.End"); - default: - return (Text_t){.length=0}; - } -} - -public const Where_t Where$tagged$Anywhere = {$tag$Where$Anywhere}; -public const Where_t Where$tagged$Start = {$tag$Where$Start}; -public const Where_t Where$tagged$End = {$tag$Where$End}; -public const TypeInfo Where$Anywhere = {0, 0, {.tag=EmptyStruct, .EmptyStruct.name="Anywhere"}}; -public const TypeInfo Where$Start = {0, 0, {.tag=EmptyStruct, .EmptyStruct.name="Start"}}; -public const TypeInfo Where$End = {0, 0, {.tag=EmptyStruct, .EmptyStruct.name="End"}}; -public const TypeInfo Where = {sizeof(Where_t), __alignof__(Where_t), - {.tag=CustomInfo, .CustomInfo={.as_text=(void*)Where$as_text}}}; - -// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/builtins/where.h b/builtins/where.h deleted file mode 100644 index cfb45c62..00000000 --- a/builtins/where.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -// Type info and methods for Where datatype (Anywhere, Start, or End enum) -// Mainly used for text methods. - -#include -#include -#include - -#include "types.h" - -typedef struct Where_s Where_t; -extern const TypeInfo Where; -typedef struct Where$Anywhere_s Where$Anywhere_t; -extern const TypeInfo Where$Anywhere; -typedef struct Where$Start_s Where$Start_t; -extern const TypeInfo Where$Start; -typedef struct Where$End_s Where$End_t; -extern const TypeInfo Where$End; - -struct Where$Anywhere_s {}; -struct Where$Start_s {}; -struct Where$End_s {}; -struct Where_s { - enum { $tag$Where$Anywhere = 0, $tag$Where$Start = 1, $tag$Where$End = 2 } tag; - union { - Where$Anywhere_t Anywhere; - Where$Start_t Start; - Where$End_t End; - }; -}; - -extern const Where_t Where$tagged$Anywhere; -extern const Where_t Where$tagged$Start; -extern const Where_t Where$tagged$End; - -// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/compile.c b/compile.c index 5c4cc592..69fa345c 100644 --- a/compile.c +++ b/compile.c @@ -2404,28 +2404,26 @@ CORD compile(env_t *env, ast_t *ast) case ChannelType: { type_t *item_t = Match(self_value_t, ChannelType)->item_type; CORD padded_item_size = CORD_asprintf("%ld", padded_type_size(item_t)); - arg_t *where_default_end = new(arg_t, .name="where", .type=WHERE_TYPE, - .default_val=FakeAST(FieldAccess, .fielded=FakeAST(Var, "Where"), .field="End")); - arg_t *where_default_start = new(arg_t, .name="where", .type=WHERE_TYPE, - .default_val=FakeAST(FieldAccess, .fielded=FakeAST(Var, "Where"), .field="Start")); + arg_t *front_default_end = new(arg_t, .name="front", .type=Type(BoolType), .default_val=FakeAST(Bool, false)); + arg_t *front_default_start = new(arg_t, .name="front", .type=Type(BoolType), .default_val=FakeAST(Bool, true)); if (streq(call->name, "give")) { CORD self = compile_to_pointer_depth(env, call->self, 0, false); - arg_t *arg_spec = new(arg_t, .name="item", .type=item_t, .next=where_default_end); + arg_t *arg_spec = new(arg_t, .name="item", .type=item_t, .next=front_default_end); return CORD_all("Channel$give_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "give_all")) { CORD self = compile_to_pointer_depth(env, call->self, 0, false); - arg_t *arg_spec = new(arg_t, .name="to_give", .type=Type(ArrayType, .item_type=item_t), .next=where_default_end); + arg_t *arg_spec = new(arg_t, .name="to_give", .type=Type(ArrayType, .item_type=item_t), .next=front_default_end); return CORD_all("Channel$give_all(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", padded_item_size, ")"); } else if (streq(call->name, "get")) { CORD self = compile_to_pointer_depth(env, call->self, 0, false); - arg_t *arg_spec = where_default_start; + arg_t *arg_spec = front_default_start; return CORD_all("Channel$get_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type(item_t), ", ", padded_item_size, ")"); } else if (streq(call->name, "peek")) { CORD self = compile_to_pointer_depth(env, call->self, 0, false); - arg_t *arg_spec = where_default_start; + arg_t *arg_spec = front_default_start; return CORD_all("Channel$peek_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", compile_type(item_t), ")"); } else if (streq(call->name, "clear")) { diff --git a/docs/channels.md b/docs/channels.md index 88cb46ff..8763f11d 100644 --- a/docs/channels.md +++ b/docs/channels.md @@ -31,15 +31,14 @@ Adds an item to the channel. **Usage:** ```markdown -give(channel:|T|, item: T, where: Where = Where.End) -> Void +give(channel:|T|, item: T, front: Bool = no) -> Void ``` **Parameters:** - `channel`: The channel to which the item will be added. - `item`: The item to add to the channel. -- `where`: Where to put the item (at the `Start` or `End` of the queue). - `Anywhere` defaults to `End`. +- `front`: Whether to put the item at the front of the channel (as opposed to the back). **Returns:** Nothing. @@ -58,15 +57,14 @@ Adds multiple items to the channel. **Usage:** ```markdown -give_all(channel:|T|, items: [T], where: Where = Where.End) -> Void +give_all(channel:|T|, items: [T], front: Bool = no) -> Void ``` **Parameters:** - `channel`: The channel to which the items will be added. - `items`: The array of items to add to the channel. -- `where`: Where to put the items (at the `Start` or `End` of the queue). - `Anywhere` defaults to `End`. +- `front`: Whether to put the item at the front of the channel (as opposed to the back). **Returns:** Nothing. @@ -85,14 +83,13 @@ Removes and returns an item from the channel. If the channel is empty, it waits **Usage:** ```markdown -get(channel:|T|, where: Where = Where.Start) -> T +get(channel:|T|, front: Bool = yes) -> T ``` **Parameters:** - `channel`: The channel from which to remove an item. -- `where`: Where to get the item from (from the `Start` or `End` of the queue). - `Anywhere` defaults to `Start`. +- `front`: Whether to put the item at the front of the channel (as opposed to the back). **Returns:** The item removed from the channel. @@ -113,14 +110,13 @@ it. If the channel is empty, it waits until an item is available. **Usage:** ```markdown -peek(channel:|T|, where: Where = Where.Start) -> T +peek(channel:|T|, front: Bool = yes) -> T ``` **Parameters:** - `channel`: The channel from which to remove an item. -- `where`: Which end of the channel to peek from (the `Start` or `End`). - `Anywhere` defaults to `Start`. +- `front`: Whether to put the item at the front of the channel (as opposed to the back). **Returns:** The item removed from the channel. diff --git a/docs/text.md b/docs/text.md index ca8c875d..5d399edd 100644 --- a/docs/text.md +++ b/docs/text.md @@ -270,7 +270,7 @@ Text.find(pattern:Text, start=1, length=!&Int64?)->Int Text.find_all(pattern:Text)->[Text] Text.split(pattern:Text)->[Text] Text.replace(pattern:Text, replacement:Text)->[Text] -Text.has(pattern:Text, where=Where.Anywhere)->Bool +Text.has(pattern:Text)->Bool ``` See [Text Functions](#Text-Functions) for the full API documentation. @@ -345,31 +345,6 @@ many repetitions you want by putting a number or range of numbers first using [..0-1 question mark] ``` -## Some Examples - -URL query string parameters: - -``` -text := "example.com/page?a=b&c=d" ->> text:find(before=$Pat`?`, $Pat`[..]`):split($Pat`&`) -= ["a=b", "c=d"] -``` - -Remove or get file extension: - -``` -filename := "foo.txt" ->> filename:without($Pat`.[:id:]`, where=End) -= "foo" - ->> filename:find(before=$Pat`.`, $Pat`[:id:][:end:]`) -= MatchResult.Success(match="txt") - ->> filename := "foo.tar.gz" ->> ".":join(filename:split($Pat`.`):from(2)) -= "tar.gz" -``` - # Text Functions ## `as_c_string` diff --git a/environment.c b/environment.c index dc897ae0..f960aaec 100644 --- a/environment.c +++ b/environment.c @@ -11,7 +11,6 @@ type_t *TEXT_TYPE = NULL; type_t *RANGE_TYPE = NULL; -type_t *WHERE_TYPE = NULL; public type_t *THREAD_TYPE = NULL; env_t *new_compilation_unit(CORD *libname) @@ -47,20 +46,6 @@ env_t *new_compilation_unit(CORD *libname) const char *name, *code, *type_str; } ns_entry_t; - { - env_t *where_env = namespace_env(env, "Where"); - type_t *anywhere = Type(StructType, .name="Anywhere"); - type_t *start = Type(StructType, .name="Start"); - type_t *end = Type(StructType, .name="End"); - WHERE_TYPE = Type(EnumType, .name="Where", .env=where_env, - .tags=new(tag_t, .name="Anywhere", .tag_value=0, .type=anywhere, - .next=new(tag_t, .name="Start", .tag_value=0, .type=start, - .next=new(tag_t, .name="End", .tag_value=0, .type=end)))); - set_binding(where_env, "Anywhere", new(binding_t, .type=WHERE_TYPE, .code="Where$tagged$Anywhere")); - set_binding(where_env, "Start", new(binding_t, .type=WHERE_TYPE, .code="Where$tagged$Start")); - set_binding(where_env, "End", new(binding_t, .type=WHERE_TYPE, .code="Where$tagged$End")); - } - { env_t *range_env = namespace_env(env, "Range"); RANGE_TYPE = Type( @@ -241,7 +226,6 @@ env_t *new_compilation_unit(CORD *libname) #undef F2 #undef F #undef C - {"Where", WHERE_TYPE, "Where_t", "Where", {}}, {"Range", RANGE_TYPE, "Range_t", "Range", TypedArray(ns_entry_t, {"reversed", "Range$reversed", "func(range:Range)->Range"}, {"by", "Range$by", "func(range:Range, step:Int)->Range"}, @@ -264,7 +248,6 @@ env_t *new_compilation_unit(CORD *libname) {"split", "Text$split", "func(text:Text, pattern='')->[Text]"}, {"slice", "Text$slice", "func(text:Text, from=1, to=-1)->Text"}, {"title", "Text$title", "func(text:Text)->Text"}, - {"trimmed", "Text$trimmed", "func(text:Text, trim=\" {\\n\\r\\t}\", where=Where.Anywhere)->Text"}, {"upper", "Text$upper", "func(text:Text)->Text"}, {"utf32_codepoints", "Text$utf32_codepoints", "func(text:Text)->[Int32]"}, {"utf8_bytes", "Text$utf8_bytes", "func(text:Text)->[Int8]"}, diff --git a/environment.h b/environment.h index 0fd67b4e..98d61d84 100644 --- a/environment.h +++ b/environment.h @@ -81,6 +81,5 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name); extern type_t *TEXT_TYPE; extern type_t *RANGE_TYPE; extern type_t *THREAD_TYPE; -extern type_t *WHERE_TYPE; // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/test/threads.tm b/test/threads.tm index 09ec7dc2..986ab864 100644 --- a/test/threads.tm +++ b/test/threads.tm @@ -11,10 +11,10 @@ func main(): = [10, 20, 30] >> channel:peek() = 10 - >> channel:peek(End) + >> channel:peek(front=no) = 30 - >> channel:give(-10, Start) + >> channel:give(-10, front=yes) >> channel:view() = [-10, 10, 20, 30] -- cgit v1.2.3