diff options
author | olpc user <olpc@xo-5d-f7-86.localdomain> | 2019-12-09 06:51:41 -0800 |
---|---|---|
committer | olpc user <olpc@xo-5d-f7-86.localdomain> | 2019-12-09 06:51:41 -0800 |
commit | e6f2b95fb543b535b1914bd4954e240dbd724275 (patch) | |
tree | dcd081c1098489bc5c2172e5e535abb56094e763 /starts/meaning-vm | |
parent | 8ceeb5f83f22ed3db06fc02bb23710ccc1dbbb90 (diff) | |
download | standingwithresilience-e6f2b95fb543b535b1914bd4954e240dbd724275.tar.gz standingwithresilience-e6f2b95fb543b535b1914bd4954e240dbd724275.zip |
positional argument sugar for habits
Diffstat (limited to 'starts/meaning-vm')
-rw-r--r-- | starts/meaning-vm/.gitignore | 1 | ||||
-rw-r--r-- | starts/meaning-vm/habit-starts/rhythm.cpp | 19 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/common.hpp | 46 | ||||
-rw-r--r-- | starts/meaning-vm/level-2/baseref.hpp | 2 | ||||
-rw-r--r-- | starts/meaning-vm/level-2/common.hpp | 3 | ||||
-rw-r--r-- | starts/meaning-vm/level-2/concepts.hpp | 4 | ||||
-rw-r--r-- | starts/meaning-vm/level-2/funcs.cpp | 43 | ||||
-rw-r--r-- | starts/meaning-vm/level-2/funcs.hpp | 5 | ||||
-rw-r--r-- | starts/meaning-vm/level-2/sugar.hpp | 73 | ||||
-rw-r--r-- | starts/meaning-vm/makefile | 10 |
10 files changed, 145 insertions, 61 deletions
diff --git a/starts/meaning-vm/.gitignore b/starts/meaning-vm/.gitignore index 1859903..285fc08 100644 --- a/starts/meaning-vm/.gitignore +++ b/starts/meaning-vm/.gitignore @@ -1,3 +1,4 @@ +*.ii *.o *.a level? diff --git a/starts/meaning-vm/habit-starts/rhythm.cpp b/starts/meaning-vm/habit-starts/rhythm.cpp index 7afb8ed..0877250 100644 --- a/starts/meaning-vm/habit-starts/rhythm.cpp +++ b/starts/meaning-vm/habit-starts/rhythm.cpp @@ -32,35 +32,34 @@ int main() // next -> habit that follows #undef self - ahabit(next-habit, + ahabit(next-habit, (), { ref n = ctx[active-habit].get(next); ctx.set(active-habit, n); return n(); }); - ahabit(start-habit, + ahabit(start-habit, ((start,s)), { - ref s = ctx[start]; ctx.set(active-habit, s); return s(); }); - ahabit(keep-doing-habit, + ahabit(keep-doing-habit, ((start,s)), { - (start-habit)(); + (start-habit)(s); while (true) { (next-habit)(); } }); - ahabit(start-beat, + ahabit(start-beat, (), { ctx.vset(beat, int(0)); self.set(next, wait-habit); (beat-habit).set(next, wait-habit); (wait-habit).set(next, beat-habit); }); - ahabit(beat-habit, + ahabit(beat-habit, (), { int & b = ctx.vget<int>(beat); char const * beats[] = { @@ -118,12 +117,10 @@ int main() std::cout << beats[b] << std::endl; b = (b + 1) % (sizeof(beats) / sizeof(*beats)); }); - ahabit(wait-habit, + ahabit(wait-habit, (), { usleep(micros); }); - - ref::context().set(start, start-beat); - (keep-doing-habit)(); + (keep-doing-habit)(start-beat); } diff --git a/starts/meaning-vm/level-0/common.hpp b/starts/meaning-vm/level-0/common.hpp index e06e478..d75229d 100644 --- a/starts/meaning-vm/level-0/common.hpp +++ b/starts/meaning-vm/level-0/common.hpp @@ -2,24 +2,48 @@ #define self (*this) +// macro tools +#define _macro_expand_to_args(...) __VA_ARGS__ +#define _macro_expand_to_comma_args(...) ,##__VA_ARGS__ +#define _macro_call(funcormacro, ...) funcormacro(__VA_ARGS__) +#define _macro_remove_parens(args) _macro_expand_to_args args +#define _macro_comma_remove_parens(args) _macro_expand_to_comma_args args + +#define _macro_expand_to_arg1(arg, ...) arg +#define _macro_expand_to_arg2(_1, arg, ...) arg + // macro argument iteration, from stackoverflow.com/questions/1872220 #define _macro_for_each(funcormacro,...) \ - _macro_fe_get(__VA_ARGS__, \ + _macro_fe_get(_0,##__VA_ARGS__, \ _macro_fe_9,_macro_fe_8,_macro_fe_7,_macro_fe_6,_macro_fe_5,_macro_fe_4,_macro_fe_3,_macro_fe_2,_macro_fe_1,_macro_fe_0 \ )(funcormacro,__VA_ARGS__) - #define _macro_fe_0(what, x, ...) what(x) - #define _macro_fe_1(what, x, ...) what(x)fe_0(what, __VA_ARGS__) - #define _macro_fe_2(what, x, ...) what(x)fe_1(what, __VA_ARGS__) - #define _macro_fe_3(what, x, ...) what(x)fe_2(what, __VA_ARGS__) - #define _macro_fe_4(what, x, ...) what(x)fe_3(what, __VA_ARGS__) - #define _macro_fe_5(what, x, ...) what(x)fe_4(what, __VA_ARGS__) - #define _macro_fe_6(what, x, ...) what(x)fe_5(what, __VA_ARGS__) - #define _macro_fe_7(what, x, ...) what(x)fe_6(what, __VA_ARGS__) - #define _macro_fe_8(what, x, ...) what(x)fe_7(what, __VA_ARGS__) - #define _macro_fe_9(what, x, ...) what(x)fe_8(what, __VA_ARGS__) + #define _macro_fe_0(what, ...) + #define _macro_fe_1(what, x, ...) what(x)_macro_fe_0(what, __VA_ARGS__) + #define _macro_fe_2(what, x, ...) what(x)_macro_fe_1(what, __VA_ARGS__) + #define _macro_fe_3(what, x, ...) what(x)_macro_fe_2(what, __VA_ARGS__) + #define _macro_fe_4(what, x, ...) what(x)_macro_fe_3(what, __VA_ARGS__) + #define _macro_fe_5(what, x, ...) what(x)_macro_fe_4(what, __VA_ARGS__) + #define _macro_fe_6(what, x, ...) what(x)_macro_fe_5(what, __VA_ARGS__) + #define _macro_fe_7(what, x, ...) what(x)_macro_fe_6(what, __VA_ARGS__) + #define _macro_fe_8(what, x, ...) what(x)_macro_fe_7(what, __VA_ARGS__) + #define _macro_fe_9(what, x, ...) what(x)_macro_fe_8(what, __VA_ARGS__) #define _macro_fe_get( \ _0,_1,_2,_3,_4,_5,_6,_7,_8,_9, \ name,...) name +#define _macro_for_each_parens(funcormacro,...) \ + _macro_fe_get(_0,##__VA_ARGS__, \ + _macro_fep9,_macro_fep8,_macro_fep7,_macro_fe_6,_macro_fep5,_macro_fep4,_macro_fep3,_macro_fep2,_macro_fep1,_macro_fep0 \ + )(funcormacro,__VA_ARGS__) + #define _macro_fep0(what, ...) + #define _macro_fep1(what, x, ...) what x _macro_fep0(what, __VA_ARGS__) + #define _macro_fep2(what, x, ...) what x _macro_fep1(what, __VA_ARGS__) + #define _macro_fep3(what, x, ...) what x _macro_fep2(what, __VA_ARGS__) + #define _macro_fep4(what, x, ...) what x _macro_fep3(what, __VA_ARGS__) + #define _macro_fep5(what, x, ...) what x _macro_fep4(what, __VA_ARGS__) + #define _macro_fep6(what, x, ...) what x _macro_fep5(what, __VA_ARGS__) + #define _macro_fep7(what, x, ...) what x _macro_fep6(what, __VA_ARGS__) + #define _macro_fep8(what, x, ...) what x _macro_fep7(what, __VA_ARGS__) + #define _macro_fep9(what, x, ...) what x _macro_fep8(what, __VA_ARGS__) namespace intellect { namespace level0 { diff --git a/starts/meaning-vm/level-2/baseref.hpp b/starts/meaning-vm/level-2/baseref.hpp index c2bc0d1..921d1d3 100644 --- a/starts/meaning-vm/level-2/baseref.hpp +++ b/starts/meaning-vm/level-2/baseref.hpp @@ -19,6 +19,8 @@ struct baseref : public level1::baseref<ref> // thread-local context static ref context() { return level2::context(); } + template <typename... Refs> + ref operator()(Refs... args) { return level2::dohabit(self, {args.ptr()...}); } }; } diff --git a/starts/meaning-vm/level-2/common.hpp b/starts/meaning-vm/level-2/common.hpp index aac072e..3d38155 100644 --- a/starts/meaning-vm/level-2/common.hpp +++ b/starts/meaning-vm/level-2/common.hpp @@ -6,5 +6,8 @@ namespace level2 { template <typename T> struct baseref; struct ref; +namespace concepts { +} + } } diff --git a/starts/meaning-vm/level-2/concepts.hpp b/starts/meaning-vm/level-2/concepts.hpp index a8cfb0d..3a6ac6b 100644 --- a/starts/meaning-vm/level-2/concepts.hpp +++ b/starts/meaning-vm/level-2/concepts.hpp @@ -8,6 +8,10 @@ namespace level2 { namespace concepts { static ref context("context"); +static ref habit("habit"); +static ref next("next"); +static ref positional("positional"); +static ref argument("argument"); } diff --git a/starts/meaning-vm/level-2/funcs.cpp b/starts/meaning-vm/level-2/funcs.cpp index c25ead2..b17d221 100644 --- a/starts/meaning-vm/level-2/funcs.cpp +++ b/starts/meaning-vm/level-2/funcs.cpp @@ -2,17 +2,58 @@ #include "../level-1/sugar.hpp" #include "ref.hpp" +#include "concepts.hpp" namespace intellect { using namespace level1; namespace level2 { +using namespace concepts; + ref context() { - static thread_local auto ctx = a("context"); + static thread_local auto ctx = a(concepts::context); return ctx; } +ref makehabit(ref name, std::initializer_list<ref> argnames, std::function<void()> code) +{ + ref habit = level1::a(habit, name); + ref posarg = habit; + for (auto argname : argnames) { + ref nextarg = a(positional-argument); + nextarg.set(argument, argname); + posarg.set(next-positional-argument, nextarg); + posarg = nextarg; + } + habit.fun(code); + return habit; +} + +ref dohabit(ref habit, std::initializer_list<ref> args) +{ + using namespace concepts; + ref posarg = habit; + for (ref const & arg : args) { + if (!posarg.linked(next-positional-argument)) { + throw std::invalid_argument("wrong number of arguments to habit"); + } + posarg = posarg[next-positional-argument]; + // TODO: subcontexts + ref::context().set(posarg[argument], arg); + } + if (posarg.linked(next-positional-argument)) { + throw std::invalid_argument("wrong number of arguments to habit"); + } + ref ret = habit.fun<>()(); + posarg = habit; + while (posarg.linked(next-positional-argument)) { + posarg = posarg[next-positional-argument]; + ref::context().unlink(posarg[argument]); + } + return ret; +} + } } diff --git a/starts/meaning-vm/level-2/funcs.hpp b/starts/meaning-vm/level-2/funcs.hpp index 52c041d..770ff0a 100644 --- a/starts/meaning-vm/level-2/funcs.hpp +++ b/starts/meaning-vm/level-2/funcs.hpp @@ -2,10 +2,15 @@ #include "common.hpp" +#include <functional> +#include <initializer_list> + namespace intellect { namespace level2 { ref context(); +ref makehabit(ref name, std::initializer_list<ref> argnames, std::function<void()> code); +ref dohabit(ref habit, std::initializer_list<ref> args); } } diff --git a/starts/meaning-vm/level-2/sugar.hpp b/starts/meaning-vm/level-2/sugar.hpp index 6734eae..3b0e2c0 100644 --- a/starts/meaning-vm/level-2/sugar.hpp +++ b/starts/meaning-vm/level-2/sugar.hpp @@ -4,45 +4,46 @@ #include <time.h> // int time(0); int clock_gettime(CLOCK_REALTIME, struct timespec *tp{tv_sec,tv_nsec}) #include <unistd.h> // usleep(unsigned int usecs) -#define habitdelay \ - static int thisdelay = (double(rand()) / RAND_MAX * 400000 + 200000); \ - usleep(thisdelay) - #undef self -#define ahabit(name, ...) \ - a(habit, name); \ - (name).fun((std::function<void()>) \ - [=]() -> ref\ + +// habits have a structure such that they contain information about their positional +// arguments. they are made with a macro that turns the args into local variables. +// the function to call them takes any number of arguments, and these are placed in the +// thread context according to the information in the habit. + +// idea: preprocessor for level3 runs with habits +// runs after C preprocessor and responds to output produced by macros e.g. +// SET SYMBOL: <any string> +// UNSET SYMBOL: <any string> +// between the two <any string> is converted to valid c symbol when not double quoted. +// removes much of the need for individual word declarations, +// and starts to pave way towards user/intellect participation +// here, could remove the 'tok' for local refnames. + +#define ahabit(name, argnametoklist, ...) \ + intellect::level2::makehabit( \ + name, \ + {_macro_call(_macro_for_each_parens, _macro_habit_argnameref _macro_comma_remove_parens(argnametoklist))}, \ + (std::function<void()>) \ + [=]() \ { \ - habitdelay; \ + { \ + static int delay = (double(rand()) / RAND_MAX * 400000 + 200000); \ + usleep(delay); \ + } \ ref self = name; (void)self; \ ref ctx = intellect::level2::ref::context(); (void) ctx;\ + _macro_call(_macro_for_each_parens, _macro_habit_set_posarg _macro_comma_remove_parens(argnametoklist)); \ __VA_ARGS__ \ - return intellect::level1::concepts::nothing; \ }); - -// thinking on handling arguments with less boilerplate, more positional sugar -// transfer argslist to a context for calling? -// possibly transfer argslist to a function signature for the call -// transfer context to the argslist for handling call -// for each item of argslist, make a local variable, and set it to its value -/* -#define _positionalhabitarg(local, arg) \ - ref local = ctx.get(arg); -#define _ph - -#define apositionalhabit(name, argslist, ...) \ - a(habit, name); \ - (name).fun((std::function<ref(ref)>) \ - [=](ref ctx) \ - { \ - \ - }); -*/ - -// seed random number generator statically, for habitdelay -namespace __internal { -static struct timespec __tp; -static int __timeres = clock_gettime(CLOCK_REALTIME, &__tp); -static int __seed = (srand(__tp.tv_nsec), __tp.tv_nsec); -} + #define _macro_habit_argnameref(name, tok) \ + ref(#name) + #define _macro_habit_set_posarg(name, tok) \ + ref tok = ctx[ref(#name)]; + + // seed random number generator statically, for habit delay + namespace _macro_habit { + static struct timespec tp; + static int timeres = clock_gettime(CLOCK_REALTIME, &tp); + static int seed = (srand(tp.tv_nsec), tp.tv_nsec); + } diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile index fbb8a57..bd0d2bd 100644 --- a/starts/meaning-vm/makefile +++ b/starts/meaning-vm/makefile @@ -1,4 +1,4 @@ -CXXFLAGS=-Wall -Werror -std=c++17 -fno-operator-names -ggdb -O0 +CXXFLAGS=-Wall -Werror -std=gnu++17 -fno-operator-names -ggdb -O0 LINK.o=$(LINK.cc) all: level0 level1 habit-starts/rhythm @@ -11,10 +11,16 @@ liblevel2.a: $(patsubst %.cpp,%.o,$(wildcard level-0/*.cpp)) $(patsubst %.cpp,%. habit-starts/rhythm: habit-starts/rhythm.o liblevel2.a +%.o: %.ii + $(CXX) $(CXXFLAGS) -c $^ -o $@ +%.ii: %.cpp + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -E $^ -o $@ +.INTERMEDIATE: $(patsubst %.cpp,%.ii,$(wildcard */*.cpp *.cpp)) + liblevel%.a: level-%/*.hpp %.a: ar ru $@ $^ ranlib $@ clean: - -rm *.o level? *.a */*.o + -rm *.ii *.o level? *.a */*.o */*.ii |