diff options
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/baseref.hpp | 23 | ||||
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/common.hpp | 9 | ||||
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/concepts.hpp | 26 | ||||
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/funcs.cpp | 69 | ||||
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/funcs.hpp | 14 | ||||
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/meaning.hpp | 42 | ||||
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/ref.hpp (renamed from starts/meaning-vm/level-2/ref.hpp) | 0 | ||||
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/statementref.cpp | 68 | ||||
-rw-r--r-- | starts/meaning-vm/level-2-wip-stmtexprs/statementref.hpp | 31 | ||||
-rw-r--r-- | starts/meaning-vm/level-2/common.hpp | 0 |
10 files changed, 282 insertions, 0 deletions
diff --git a/starts/meaning-vm/level-2-wip-stmtexprs/baseref.hpp b/starts/meaning-vm/level-2-wip-stmtexprs/baseref.hpp new file mode 100644 index 0000000..84c9c13 --- /dev/null +++ b/starts/meaning-vm/level-2-wip-stmtexprs/baseref.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "common.hpp" +#include "../level-1/ref.hpp" +#include "statementref.hpp" + +namespace intellect { +namespace level2 { + +template <typename ref> +struct baseref : public level1::baseref<ref> +{ + using level1::baseref<ref>::baseref; + baseref(level1::ref other) : level1::baseref<ref>(other.ptr()) { } + operator level1::ref() { return ptr(); } + + statementref operator=(ref other) { return assignop(self, other); } + statementref operator,(ref other) { return commaop(self, other); } + ref operator[](ref other) { return subop(self, other); } +} + +} +} diff --git a/starts/meaning-vm/level-2-wip-stmtexprs/common.hpp b/starts/meaning-vm/level-2-wip-stmtexprs/common.hpp new file mode 100644 index 0000000..25c8026 --- /dev/null +++ b/starts/meaning-vm/level-2-wip-stmtexprs/common.hpp @@ -0,0 +1,9 @@ +#pragma once + +namespace intellect { +namespace level2 { + +struct ref; + +} +} diff --git a/starts/meaning-vm/level-2-wip-stmtexprs/concepts.hpp b/starts/meaning-vm/level-2-wip-stmtexprs/concepts.hpp new file mode 100644 index 0000000..20c5ad4 --- /dev/null +++ b/starts/meaning-vm/level-2-wip-stmtexprs/concepts.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "../level-1/concepts.hpp" + +namespace intellect { +namespace level2 { + +namespace concepts { + +using namespace level1::concepts; + +static decl(variable), + decl(expression), + decl(assign), + decl(comma), + decl(subscript), + decl(action), + decl(statement), + decl(left), + decl(right), + decl(operand); + +} + +} +} diff --git a/starts/meaning-vm/level-2-wip-stmtexprs/funcs.cpp b/starts/meaning-vm/level-2-wip-stmtexprs/funcs.cpp new file mode 100644 index 0000000..d746f13 --- /dev/null +++ b/starts/meaning-vm/level-2-wip-stmtexprs/funcs.cpp @@ -0,0 +1,69 @@ +#include "funcs.hpp" + +using namespace intellect; +using namespace level2; +using namespace concepts; + +static ref refassigned(ref expr) +{ + ref lhs = ref.get(left-operand); + ref rhs = ref.get(right-operand); + if (lhs.isa(link) && lhs.get(link-target) == unknown) { + // completes the target of a link, for a[b] = c + lhs.unlink(link-target, unknown); + lhs.set(link-target, rhs); + ref.unlink(right-operand, rhs); + ref src = lhs.get(link-source); + if (lhs.get(link-type) != unknown && src != unknown) { + src.set(lhs.get(link-type), rhs); + return src; + } else { + throw std::logic_error("not sure what to do with incomplete link assignment"); + } + } else if (isanonymous(rhs) && !isanonymous(lhs)) { + // assignment of anonymous content to empty named concept + ref.unlink(left-operand, lhs); + return level1::movetoname(rhs, lhs); + } else { + throw std::logic_error("unexpected bare assignment"); + } +} +// maybe later we can have ref class itself do operators completely based on its own +// ref content. + +statementref assignop(ref self, ref other) +{ + return statementref::makebinary( + self, concepts::assign, other, + refassigned, refassigned + ); +} +statementref commaop(ref self, ref other) +{ + if (self.isa(comma-expression)) { + if (other.isa(comma-expression)) { + for (auto & l : other.links()) { self.insert(l.first, l.second); } + dealloc(other); + } else { + self.link(topic, other); + } + return self; + } else if (other.isa(comma-expression)) { + other.link(topic, self); + return other; + } else { + return statementcallref::makebinary( + self, comma, other, + [](ref)->ref { return ref; }, + // um when we pass the comma-expression to + // the [] operator that takes a ref + // the destructor of statementref will deallocate it. + [](ref) { throw std::logic_error("bare comma-expression"); } + // something is wrong here. some approach is wrong. + // would it be better to have ref itself do it all? + ); + } +} +ref subop(ref self, ref other) +{ +} diff --git a/starts/meaning-vm/level-2-wip-stmtexprs/funcs.hpp b/starts/meaning-vm/level-2-wip-stmtexprs/funcs.hpp new file mode 100644 index 0000000..6af6ce1 --- /dev/null +++ b/starts/meaning-vm/level-2-wip-stmtexprs/funcs.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "common.hpp" +#include "../level-1/ref.hpp" + +namespace intellect { +namespace level2 { + +statementref commaop(ref self, ref other); +statementref assignop(ref self, ref other); +ref subop(ref self, ref other); + +} +} diff --git a/starts/meaning-vm/level-2-wip-stmtexprs/meaning.hpp b/starts/meaning-vm/level-2-wip-stmtexprs/meaning.hpp new file mode 100644 index 0000000..049e7f9 --- /dev/null +++ b/starts/meaning-vm/level-2-wip-stmtexprs/meaning.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "ref.hpp" +#include "../level-1/helpers.hpp" + +namespace intellect { +namespace level2 { + +// get a named variable +ref avariable(ref name); + +template <typename... T> +ref and(T... refs) +{ + std::initializer_list<ref> rs = { refs... }; + decl(and, topic); + ref ret = a(and); + ref name; int count = 0; + for (auto r : rs) { + ret.link(topic, r); + if (count == 0) { + name.ptr() = r.ptr(); + } else { + name.ptr() = (name-and-r).ptr(); + } + ++ count; + } + if (count == 1) { + throw std::invalid_argument("and needs at least two subjects"); + } + // in level-1, we'll want to name anonymous objects after defining them + return name = ret; +} + +// make a reference to a link +ref link(ref sourceref, ref typeref, ref targetref); + +// invert a meaning +ref not(ref whatref); + +} +} diff --git a/starts/meaning-vm/level-2/ref.hpp b/starts/meaning-vm/level-2-wip-stmtexprs/ref.hpp index 5b7dc4f..5b7dc4f 100644 --- a/starts/meaning-vm/level-2/ref.hpp +++ b/starts/meaning-vm/level-2-wip-stmtexprs/ref.hpp diff --git a/starts/meaning-vm/level-2-wip-stmtexprs/statementref.cpp b/starts/meaning-vm/level-2-wip-stmtexprs/statementref.cpp new file mode 100644 index 0000000..2f23dc8 --- /dev/null +++ b/starts/meaning-vm/level-2-wip-stmtexprs/statementref.cpp @@ -0,0 +1,68 @@ +#include "statementref.hpp" + +#include "concepts.hpp" +#include "ref.hpp" + +using namespace intellect; +using namespace level2; +using namespace concepts; + +// so, anonymous-assignment is both a statement and an expression. +// multiple-member-assignment is only an expression: it is an error to evaluate it +// the submember operator will be both a statement and an expression, but doesn't need to be held as a ref +// single-member-assignment is mostly a statement: using it as an expression should be an error. + +static statementref makebinary( + ref lhs, ref kind, ref rhs, + std::function<ref(ref)> expraction, + std::function<void(ref)> stmtaction +) +{ + a(statement-expresion, kind-expression); + ref r = a(kind-expression); + r.set(left-operand, lhs); + r.set(right-operand, rhs); + r.vset(expression-action, expraction); + r.vset(statement-action, stmtaction); + return r; +} + +statementref::statementref(ref r) +: r(r.ptr()) +{ + if (!r.isa(statement-expression)) { + throw std::logic_error("that is not a statement expression"); + } +} + +static void de(ref & r) +{ + ref lhs, rhs, expraction, stmtaction; + + try { lhs = r.get(left-operand); } catch(level0::no_such_link_type&) {} + try { rhs = r.get(right-operand); } catch(level0::no_such_link_type&) {} + + expraction = r.get(expression-action); + stmtaction = r.get(statement-action); + dealloc(r); + if (lhs != nothing) { dealloc(lhs); } + if (rhs != nothing) { dealloc(rhs); } + dealloc(expraction); + dealloc(stmtaction); + r = 0; +} + +statementref::~statementref() +{ + if (r == 0) { return; } + r.vget<std::function<void(ref)>>(statement-action)(r); + de(r); +} + +statementref::operator ref() +{ + if (r == 0) { throw std::logic_error("doubly evaluated expression"); } + auto ret = r.vget<std::function<void(ref)>>(expression-action)(r); + de(r); + return ret; +} diff --git a/starts/meaning-vm/level-2-wip-stmtexprs/statementref.hpp b/starts/meaning-vm/level-2-wip-stmtexprs/statementref.hpp new file mode 100644 index 0000000..502ecf4 --- /dev/null +++ b/starts/meaning-vm/level-2-wip-stmtexprs/statementref.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "common.hpp" +#include "../level-0/concept.hpp" + +namespace intellect { +namespace level2 { + +// this class is returned by some of the baseref operators. +// its purpose is to evaluate code when it goes out of +// scope, so as to facilitate syntactic behavior. +struct statementref +{ + statementref(ref r); + statementref(statementref const &) = delete; + ~statementref(); + + operator ref(); + + static statementref makebinary( + ref lhs, ref kind, ref rhs, + std::function<ref(ref)> expraction = {}, + std::function<void(ref)> stmtaction = {} + ); + +private: + level0::concept * r; +}; + +} +} diff --git a/starts/meaning-vm/level-2/common.hpp b/starts/meaning-vm/level-2/common.hpp deleted file mode 100644 index e69de29..0000000 --- a/starts/meaning-vm/level-2/common.hpp +++ /dev/null |