summaryrefslogtreecommitdiff
path: root/starts/meaning-vm/level-2
diff options
context:
space:
mode:
Diffstat (limited to 'starts/meaning-vm/level-2')
-rw-r--r--starts/meaning-vm/level-2/concepts.hpp8
-rw-r--r--starts/meaning-vm/level-2/funcs.cpp103
-rw-r--r--starts/meaning-vm/level-2/funcs.hpp4
-rw-r--r--starts/meaning-vm/level-2/sugar.hpp12
4 files changed, 98 insertions, 29 deletions
diff --git a/starts/meaning-vm/level-2/concepts.hpp b/starts/meaning-vm/level-2/concepts.hpp
index 8e9c145..57f5adb 100644
--- a/starts/meaning-vm/level-2/concepts.hpp
+++ b/starts/meaning-vm/level-2/concepts.hpp
@@ -8,13 +8,17 @@ namespace level2 {
namespace concepts {
using level1::concepts::nothing;
+using level1::concepts::name;
static ref context("context");
static ref habit("habit");
static ref next("next");
-static ref positional("positional");
-static ref argument("argument");
+static ref information("information");
+static ref needed("needed");
static ref result("result");
+static ref assume("assume");
+static ref unexpected("unexpected");
+static ref value("value");
}
diff --git a/starts/meaning-vm/level-2/funcs.cpp b/starts/meaning-vm/level-2/funcs.cpp
index 36f93ca..c13e973 100644
--- a/starts/meaning-vm/level-2/funcs.cpp
+++ b/starts/meaning-vm/level-2/funcs.cpp
@@ -4,7 +4,6 @@
#include "ref.hpp"
#include "concepts.hpp"
-
namespace intellect {
using namespace level1;
namespace level2 {
@@ -17,40 +16,65 @@ ref & context()
return ctx;
}
-ref makehabit(ref name, std::initializer_list<ref> argnames, std::initializer_list<ref> defaults, std::function<void(ref)> code)
+ref makehabit(ref name, std::initializer_list<ref> argnames, std::function<void(ref)> code)
{
ref habit = level1::a(concepts::habit, name);
- ref posarg = habit;
+ ref infn = a(habit-information-needed);
+ habit.set(information-needed, infn);
+ ref posinf = infn;
for (auto argname : argnames) {
- ref nextarg = a(positional-argument);
- nextarg.set(argument, argname);
- posarg.set(next-positional-argument, nextarg);
- posarg = nextarg;
+ ref nextinf = a(habit-information);
+ nextinf.set(information, argname);
+ posinf.set(next-information, nextinf);
+ posinf = nextinf;
+ if (!infn.linked(argname)) {
+ infn.set(argname, nextinf);
+ } else {
+ if (!infn.get(argname).isa(habit-information)) {
+ throw a(bad-concepts::habit-information-concepts::name)
+ .link(concepts::name, argname)
+ .link(concepts::habit, habit);
+ }
+ }
}
habit.fun(code);
return habit;
}
+void habitassume(ref habit, ref information, ref assumption)
+{
+ ref infn = habit.get(concepts::information-needed);
+ infn.get(information).set(assume, assumption);
+}
+
ref dohabit(ref habit, std::initializer_list<ref> args)
{
using namespace concepts;
- ref posarg = habit;
+ ref posinf = habit.get(information-needed);
for (ref const & arg : args) {
- if (!posarg.linked(next-positional-argument)) {
- throw std::invalid_argument("wrong number of arguments to habit");
+ if (!posinf.linked(next-information)) {
+ throw an(unexpected-information).link
+ (concepts::habit, habit,
+ information-value, arg);
}
- posarg = posarg[next-positional-argument];
+ posinf = posinf[next-information];
// TODO: subcontexts or call instances
- ref::context().set(posarg[argument], arg);
+ ref::context().set(posinf[information], arg);
}
- if (posarg.linked(next-positional-argument)) {
- throw std::invalid_argument("wrong number of arguments to habit");
+ while (posinf.linked(next-information)) {
+ posinf = posinf[next-information];
+ if (!posinf.linked(assume)) {
+ throw a(information-needed).link
+ (concepts::habit, habit,
+ information, posinf);
+ }
+ ref::context().set(posinf[information], posinf[assume]);
}
habit.fun<ref>()(ref::context());
- posarg = habit;
- while (posarg.linked(next-positional-argument)) {
- posarg = posarg[next-positional-argument];
- ref::context().unlink(posarg[argument]);
+ posinf = habit.get(information-needed);
+ while (posinf.linked(next-information)) {
+ posinf = posinf[next-information];
+ ref::context().unlink(posinf[information]);
}
if (ref::context().linked(result)) {
ref ret = ref::context().get(result);
@@ -65,15 +89,50 @@ ref dohabit(ref habit, std::initializer_list<std::initializer_list<ref>> pairs)
using namespace concepts;
// TODO: subcontexts or call instances
ref ctx = ref::context();
+ ref infn = habit.get(information-needed);
+ std::map<ref, ref> provided;
for (auto pair : pairs) {
auto second = pair.begin(); ++ second;
- ctx.link(pair.begin(), second);
+ if (!infn.linked(*pair.begin())) {
+ throw an(unexpected-information).link
+ (concepts::habit, habit,
+ information, *pair.begin(),
+ information-value, *second);
+ }
+ if (provided.count(*pair.begin())) { throw "multiple instances same name not implemented here"; }
+ provided[*pair.begin()] = *second;
+ }
+ ref nextinf = infn;
+ while (nextinf.linked(next-information)) {
+ nextinf = nextinf.get(next-information);
+ ref inf = nextinf.get(information);
+ if (!provided.count(inf)) {
+ if (nextinf.get(assume)) {
+ ctx.link(inf, nextinf.get(assume));
+ } else {
+ throw a(information-needed).link
+ (concepts::habit, habit,
+ information, inf);
+ }
+ } else {
+ ctx.link(inf, provided[inf]);
+ }
}
habit.fun<ref>()(ctx);
- for (auto pair : pairs) {
- auto second = pair.begin(); ++ second;
- ctx.unlink(pair.begin(), second);
+ nextinf = infn;
+ while (nextinf.linked(next-information)) {
+ nextinf = nextinf.get(next-information);
+ ref inf = nextinf.get(information);
+ if (provided.count(inf)) {
+ ctx.unlink(inf, provided[inf]);
+ } else {
+ ctx.unlink(inf, nextinf.get(assume));
+ }
}
+ //for (auto pair : pairs) {
+ // auto second = pair.begin(); ++ second;
+ // ctx.unlink(pair.begin(), second);
+ //}
if (ctx.linked(result)) {
ref ret = ctx.get(result);
ctx.unlink(result, ret);
diff --git a/starts/meaning-vm/level-2/funcs.hpp b/starts/meaning-vm/level-2/funcs.hpp
index d1d1d7d..cd32fc4 100644
--- a/starts/meaning-vm/level-2/funcs.hpp
+++ b/starts/meaning-vm/level-2/funcs.hpp
@@ -9,8 +9,8 @@ namespace intellect {
namespace level2 {
ref & context();
-// TODO: pass default argument values to makehabit?
-ref makehabit(ref name, std::initializer_list<ref> argnames, std::function<void(ref)> code);
+ref makehabit(ref name, std::initializer_list<ref> infonames, std::function<void(ref)> code);
+void habitassume(ref habit, ref information, ref value);
ref dohabit(ref habit, std::initializer_list<ref> args = {});
ref dohabit(ref habit, std::initializer_list<std::initializer_list<ref>> args);
diff --git a/starts/meaning-vm/level-2/sugar.hpp b/starts/meaning-vm/level-2/sugar.hpp
index 9065a20..e6d9ea4 100644
--- a/starts/meaning-vm/level-2/sugar.hpp
+++ b/starts/meaning-vm/level-2/sugar.hpp
@@ -22,7 +22,7 @@
#define ahabit(name, argnametoklist, ...) \
intellect::level2::makehabit( \
- name, \
+ ref(#name), \
{_macro_call(_macro_for_each_parens, _macro_habit_argnameref, _macro_habit_commaargnameref _macro_comma_remove_parens(argnametoklist))}, \
(std::function<void(ref)>) \
[=](ref ctx) \
@@ -31,12 +31,16 @@
static int delay = (double(rand()) / RAND_MAX * 400000 + 200000); \
usleep(delay); \
} \
- ref self = name; (void)self; \
+ ref self = ref(#name); (void)self; \
ref result("nothing"); (void)result; \
_macro_call(_macro_for_each_parens, _macro_habit_set_posarg, _macro_habit_set_posarg _macro_comma_remove_parens(argnametoklist)); \
__VA_ARGS__ \
if (result != ref("nothing")) { ctx.link(ref("result"), result); } \
- });
+ }); \
+ { \
+ ref _macro_habit_name(#name); \
+ _macro_call(_macro_for_each_parens, _macro_habit_assume, _macro_habit_assume _macro_comma_remove_parens(argnametoklist)) \
+ }
#define _macro_habit_argnameref(name, tok, ...) \
ref(#name)
#define _macro_habit_commaargnameref(name, tok, ...) \
@@ -49,6 +53,8 @@
ref("missing-information"), ref(#name)); \
} \
ref tok = ctx.linked(ref(#name)) ? ctx[ref(#name)] : ref(#__VA_ARGS__);
+ #define _macro_habit_assume(info, tok, ...) \
+ if ((#__VA_ARGS__)[0] != 0) { intellect::level2::habitassume(_macro_habit_name, ref(#info), ref(#__VA_ARGS__)); }
// seed random number generator statically, for habit delay
namespace _macro_habit {