From 9a14918abec434d8463e07635daef380ad630649 Mon Sep 17 00:00:00 2001 From: olpc user Date: Sun, 24 Nov 2019 13:22:55 -0800 Subject: breaking into levels --- starts/meaning-vm/DESIGN.txt | 10 +++ starts/meaning-vm/concept.cpp | 79 ----------------------- starts/meaning-vm/concept.hpp | 100 ------------------------------ starts/meaning-vm/level-0/common.hpp | 14 +++++ starts/meaning-vm/level-0/concept.cpp | 94 ++++++++++++++++++++++++++++ starts/meaning-vm/level-0/concept.hpp | 38 ++++++++++++ starts/meaning-vm/level-0/errors.hpp | 77 +++++++++++++++++++++++ starts/meaning-vm/level-0/level-0.hpp | 9 +++ starts/meaning-vm/level-0/memorystore.cpp | 59 ++++++++++++++++++ starts/meaning-vm/level-0/memorystore.hpp | 13 ++++ starts/meaning-vm/level-0/ref.cpp | 34 ++++++++++ starts/meaning-vm/level-0/ref.hpp | 26 ++++++++ starts/meaning-vm/level-0/value.hpp | 25 ++++++++ starts/meaning-vm/level-0/vref.hpp | 31 +++++++++ starts/meaning-vm/level0.cpp | 25 ++++++++ starts/meaning-vm/makefile | 10 ++- starts/meaning-vm/memorystore.cpp | 53 ---------------- starts/meaning-vm/memorystore.hpp | 9 --- 18 files changed, 463 insertions(+), 243 deletions(-) create mode 100644 starts/meaning-vm/DESIGN.txt delete mode 100644 starts/meaning-vm/concept.cpp delete mode 100644 starts/meaning-vm/concept.hpp create mode 100644 starts/meaning-vm/level-0/common.hpp create mode 100644 starts/meaning-vm/level-0/concept.cpp create mode 100644 starts/meaning-vm/level-0/concept.hpp create mode 100644 starts/meaning-vm/level-0/errors.hpp create mode 100644 starts/meaning-vm/level-0/level-0.hpp create mode 100644 starts/meaning-vm/level-0/memorystore.cpp create mode 100644 starts/meaning-vm/level-0/memorystore.hpp create mode 100644 starts/meaning-vm/level-0/ref.cpp create mode 100644 starts/meaning-vm/level-0/ref.hpp create mode 100644 starts/meaning-vm/level-0/value.hpp create mode 100644 starts/meaning-vm/level-0/vref.hpp create mode 100644 starts/meaning-vm/level0.cpp delete mode 100644 starts/meaning-vm/memorystore.cpp delete mode 100644 starts/meaning-vm/memorystore.hpp diff --git a/starts/meaning-vm/DESIGN.txt b/starts/meaning-vm/DESIGN.txt new file mode 100644 index 0000000..299acb2 --- /dev/null +++ b/starts/meaning-vm/DESIGN.txt @@ -0,0 +1,10 @@ +The codebase is made in levels. +Ideally each level defines a complete API to the underworkings. +Higher levels include greater degrees of meaning. + +# LEVEL 0 +Level 0 defines an interconnected network of concept references in memory. +Each concept has a unique address, and a list of concept pairs it links to. +The first of the pair represents the type of the link, and the second the target. +Concepts may not be deallocated unless nothing links to them. +A special kind of concept is the value, which holds arbitrary data alongside itself. diff --git a/starts/meaning-vm/concept.cpp b/starts/meaning-vm/concept.cpp deleted file mode 100644 index 993ac62..0000000 --- a/starts/meaning-vm/concept.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "concept.hpp" - -ref concept::id() -{ - return this; -} - -bool concept::linked(ref const & type) const -{ - return links.count(type.ptr) > 0; -} - -bool concept::linked(ref const & type, ref const & target) const -{ - for (ref const & t : getAll(type)) { - if (t == target) { - return true; - } - } - return false; -} - -ref concept::get(ref const & type, bool quick) const -{ - // this is called by name(), so it passes quick=true - auto result = links.equal_range(type.ptr); - if (result.first == result.second) { - if (quick) { - throw std::out_of_range("no such concept link to get"); - } else { - throw std::out_of_range("no such concept link to get: " + (std::string)type.name()); - } - } - return result.first->second; -} - -concept::array concept::getAll(ref const & type) const -{ - array ret; - for ( - auto range = links.equal_range(type.ptr); - range.first != range.second; - ++ range.first - ) { - ret.emplace_back(range.first->second); - } - return ret; -} - -void concept::link(ref const & type, ref const & target) -{ - links.insert({type.ptr, target.ptr}); -} - -void concept::unlink(ref const & type, ref const & target) -{ - auto ls = links.equal_range(type.ptr); - for (auto l = ls.first; l != ls.second; ++ l) { - if (l->second == target.ptr) { - links.erase(l); - return; - } - } - throw std::out_of_range("no such concept link to erase"); -} - -void concept::unlink(ref const & type) -{ - auto ls = links.equal_range(type.ptr); - if (ls.first == ls.second) { - throw std::out_of_range("no such concept link to erase"); - } - auto mid = ls.first; - ++ mid; - if (mid != ls.second) { - throw std::out_of_range("more than one link of type to erase"); - } - links.erase(ls.first); -} diff --git a/starts/meaning-vm/concept.hpp b/starts/meaning-vm/concept.hpp deleted file mode 100644 index 3308e10..0000000 --- a/starts/meaning-vm/concept.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -template struct vref; -struct concept; -template struct value; -struct statementcallref; - -struct ref -{ - ref(concept *p) : ptr(p) { if (p == 0) throw std::logic_error("null reference"); } - concept* operator->() { return ptr; } - concept const * operator->() const { return ptr; } - bool operator==(ref const & that) const { return this->ptr == that.ptr; } - bool operator!=(ref const & that) const { return this->ptr != that.ptr; } - - bool operator<(ref const &) const { throw std::logic_error("ref has redefined syntax sugar: do not use in containers"); } - - // for helpers, mostly names - ref(std::string const &); - ref(char const * str) : ref(std::string(str)) { } - ref(bool b) : ref(b ? "true" : "false") { } - ref() : ref("nothing") { } - vref name() const; - operator const char *() const; - - // helper linking syntax sugar - statementcallref operator=(ref that); - //ref operator<<(ref target); - ref operator[](ref links); - - bool isa(ref what) const; - bool isan(ref what) const; - - concept * ptr; - - /* - // destructor handles evaluating refs as statements - ~ref() noexcept; - ref(ref & that); - ref(ref && that) noexcept; - void destatement(); - */ -}; - -template -struct vref -{ - vref(value *p) : ptr(p) { } - value* operator->() { return ptr; } - operator T const &() const { return *ptr; } - - vref(T const & val); - - vref(ref const & that) : ptr(static_cast*>(that.ptr)) { } - operator ref() { return ptr; } - - // for use by containers - //bool operator<(ref const & that) const { return ptr < that.ptr; } - - value * ptr; -}; - -struct concept -{ - // a concept is made of concept-typed links to other concepts - std::multimap links; - using array = std::vector; - - ref id(); - bool linked(ref const & type) const; - bool linked(ref const & type, ref const & target) const; - ref get(ref const & type, bool quick = false) const; // returns first - template - vref vget(ref const & type, bool quick = false) const { return get(type, quick); } - array getAll(ref const & type) const; - void link(ref const & type, ref const & target); - void unlink(ref const & type, ref const & target); - void unlink(ref const & type); -}; - -template -struct value : public concept -{ - value(T const & val) : data(val) { } - value(value const & val) = default; - static value& of(ref c) - { - return *static_cast*>(c.ptr); - } - - operator T&() { return data; } - operator T const &() const { return data; } - - T data; -}; diff --git a/starts/meaning-vm/level-0/common.hpp b/starts/meaning-vm/level-0/common.hpp new file mode 100644 index 0000000..4c36a04 --- /dev/null +++ b/starts/meaning-vm/level-0/common.hpp @@ -0,0 +1,14 @@ +#pragma once + +#define self (*this) + +namespace intellect { +namespace level0 { + +struct concept; +struct ref; +template struct value; +template struct vref; + +} +} diff --git a/starts/meaning-vm/level-0/concept.cpp b/starts/meaning-vm/level-0/concept.cpp new file mode 100644 index 0000000..579cca8 --- /dev/null +++ b/starts/meaning-vm/level-0/concept.cpp @@ -0,0 +1,94 @@ +#include "concept.hpp" +#include "errors.hpp" + +using namespace intellect::level0; + +#define selfref const_cast(&self) + +ref concept::id() +{ + return this; +} + +void concept::link(ref const & type, ref const & target) +{ + links.insert({type.ptr, target.ptr}); +} + +void concept::unlink(ref const & type, ref const & target) +{ + auto ls = links.equal_range(type); + for (auto l = ls.first; l != ls.second; ++ l) { + if (l->second == target) { + links.erase(l); + return; + } + } + throw no_such_link_type_target(selfref, type, target); +} + +void concept::unlink(ref const & type) +{ + auto ls = links.equal_range(type); + if (ls.first == ls.second) { + throw no_such_link_type(selfref, type); + } + auto mid = ls.first; + ++ mid; + if (mid != ls.second) { + throw link_type_not_unique(selfref, type); + } + links.erase(ls.first); +} + +bool concept::linked(ref const & type) const +{ + return links.count(type.ptr) > 0; +} + +bool concept::linked(ref const & type, ref const & target) const +{ + for (ref const & t : getAll(type)) { + if (t == target) { + return true; + } + } + return false; +} + +concept::array concept::getAll(ref const & type) const +{ + array ret; + for ( + auto range = links.equal_range(type); + range.first != range.second; + ++ range.first + ) { + ret.emplace_back(range.first->second); + } + return ret; +} + +ref concept::get(ref const & type) const +{ + auto result = links.equal_range(type.ptr); + if (result.first == result.second) { + throw no_such_link_type(selfref, type); + } + auto test = result.first; + ++ test; + if (test != result.second) { + throw link_type_not_unique(selfref, type); + } + return result.first->second; +} + +void concept::set(ref const & type, ref const & target) +{ + if (linked(type)) { + throw link_type_not_unique(selfref, type); + } + link(type, target); +} + + diff --git a/starts/meaning-vm/level-0/concept.hpp b/starts/meaning-vm/level-0/concept.hpp new file mode 100644 index 0000000..dc3221b --- /dev/null +++ b/starts/meaning-vm/level-0/concept.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "common.hpp" +#include "ref.hpp" + +#include +#include + +namespace intellect { +namespace level0 { + +struct concept +{ + // a concept is made of concept-typed links to other concepts + std::multimap links; + using array = std::vector; + + ref id(); + + void link(ref const & type, ref const & target); + void unlink(ref const & type, ref const & target); + void unlink(ref const & type); + + bool linked(ref const & type) const; + bool linked(ref const & type, ref const & target) const; + + array getAll(ref const & type) const; + + // get and set enforce that only 1 link of a given type is present + ref get(ref const & type) const; + void set(ref const & type, ref const & target); + + template + vref vget(ref const & type) const { return get(type); } +}; + +} +} diff --git a/starts/meaning-vm/level-0/errors.hpp b/starts/meaning-vm/level-0/errors.hpp new file mode 100644 index 0000000..c052c69 --- /dev/null +++ b/starts/meaning-vm/level-0/errors.hpp @@ -0,0 +1,77 @@ +#pragma once +#include "ref.hpp" + +#include + +namespace intellect { +namespace level0 { + +struct no_such_link_type : public std::out_of_range +{ + no_such_link_type(ref source, ref type) + : std::out_of_range("no such concept link type"), + source(source), + type(type) + { } + + ref const source; + ref const type; +}; + +struct no_such_link_type_target : public std::out_of_range +{ + no_such_link_type_target(ref source, ref type, ref target) + : std::out_of_range("no such concept link type and target"), + source(source), + type(type), + target(type) + { } + + ref const source; + ref const type; + ref const target; +}; + +struct link_type_not_unique : public std::invalid_argument +{ + link_type_not_unique(ref source, ref type) + : std::invalid_argument("more than one such concept link type"), + source(source), + type(type) + { } + + ref const source; + ref const type; +}; + +struct still_referenced_by : public std::invalid_argument +{ + still_referenced_by(ref topic, ref referrer) + : std::invalid_argument("concept is still referenced"), + topic(topic), + referrer(referrer) + { } + + ref const topic; + ref const referrer; +}; + +struct no_such_concept : public std::invalid_argument +{ + no_such_concept(ref topic) + : std::invalid_argument("no such concept reference"), + topic(topic) + { } + + ref const topic; +}; + +struct null_reference : public std::invalid_argument +{ + null_reference() + : std::invalid_argument("null reference") + { } +}; + +} +} diff --git a/starts/meaning-vm/level-0/level-0.hpp b/starts/meaning-vm/level-0/level-0.hpp new file mode 100644 index 0000000..b44b6e0 --- /dev/null +++ b/starts/meaning-vm/level-0/level-0.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "common.hpp" +#include "concept.hpp" +#include "errors.hpp" +#include "memorystore.hpp" +#include "ref.hpp" +#include "value.hpp" +#include "vref.hpp" diff --git a/starts/meaning-vm/level-0/memorystore.cpp b/starts/meaning-vm/level-0/memorystore.cpp new file mode 100644 index 0000000..6cf71df --- /dev/null +++ b/starts/meaning-vm/level-0/memorystore.cpp @@ -0,0 +1,59 @@ +#include "memorystore.hpp" +#include "concept.hpp" +#include "errors.hpp" + +#include + +namespace intellect { +namespace level0 { + +static auto & concepts() +{ + static std::unordered_set> concepts; + return concepts; +} + +ref alloc(concept * moved) { + ref r = moved ? moved : new concept(); + concepts().insert(r); + return r; +} + +static concept* referenced(ref r) { + for (ref r2 : concepts()) { + if (r2 == r) { + continue; + } + for (auto & l : r2->links) { + if (ref(l.first) == r) { + return r2.ptr; + } + if (ref(l.second) == r) { + return r2.ptr; + } + } + } + return 0; +} + +void dealloc(ref r) { + concept * referenced = intellect::level0::referenced(r); + if (referenced) { + throw still_referenced_by(r, referenced); + } + for ( + auto it = concepts().begin(); + it != concepts().end(); + ++ it) + { + if (ref(*it) == r) { + concepts().erase(it); + delete r.ptr; + return; + } + } + throw no_such_concept(r); +} + +} +} diff --git a/starts/meaning-vm/level-0/memorystore.hpp b/starts/meaning-vm/level-0/memorystore.hpp new file mode 100644 index 0000000..4e0a2bd --- /dev/null +++ b/starts/meaning-vm/level-0/memorystore.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "common.hpp" +#include "ref.hpp" + +namespace intellect { +namespace level0 { + +ref alloc(concept * moved = 0); +void dealloc(ref); + +} +} diff --git a/starts/meaning-vm/level-0/ref.cpp b/starts/meaning-vm/level-0/ref.cpp new file mode 100644 index 0000000..7e10528 --- /dev/null +++ b/starts/meaning-vm/level-0/ref.cpp @@ -0,0 +1,34 @@ +#include "ref.hpp" +#include "concept.hpp" +#include "errors.hpp" + +#include + +using namespace intellect::level0; + +ref::ref(concept *p) +: ptr(p) +{ + if (p == 0) { + throw null_reference(); + } +} + +std::string ref::dump(ref skipmarkertype, ref skipmarkertarget) const +{ + if (self->linked(skipmarkertype, skipmarkertarget)) { + return {}; + } + std::string ret = std::to_string((unsigned long)ptr) + ":\n"; + for (auto & link : self->links) { + ret += " " + std::to_string((unsigned long)link.first.ptr) + ": " + std::to_string((unsigned long)link.second.ptr) + "\n"; + } + self->link(skipmarkertype, skipmarkertarget); + for (auto & link : self->links) { + if (link.first == skipmarkertype && link.second == skipmarkertype) { + continue; + } + ret += link.second.dump(skipmarkertype, skipmarkertarget); + } + return ret; +} diff --git a/starts/meaning-vm/level-0/ref.hpp b/starts/meaning-vm/level-0/ref.hpp new file mode 100644 index 0000000..951676b --- /dev/null +++ b/starts/meaning-vm/level-0/ref.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "common.hpp" + +#include + +namespace intellect { +namespace level0 { + +struct ref +{ + ref(concept *p); + operator concept*() const { return ptr; } + concept* operator->() const { return ptr; } + bool operator==(ref const & other) const { return self.ptr == other.ptr; } + bool operator!=(ref const & other) const { return self.ptr != other.ptr; } + bool operator<(ref const & other) const { return self.ptr < other.ptr; } + concept & deref() { return *ptr; } + + std::string dump(ref skipmarkertype, ref skipmarkertarget) const; + + concept * const ptr; +}; + +} +} diff --git a/starts/meaning-vm/level-0/value.hpp b/starts/meaning-vm/level-0/value.hpp new file mode 100644 index 0000000..ff704bf --- /dev/null +++ b/starts/meaning-vm/level-0/value.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "common.hpp" + +#include "concept.hpp" + +namespace intellect { +namespace level0 { + +template +struct value : public concept +{ + value(T const & val) : data(val) { } + + value(value const & val) = default; + + operator T&() { return data; } + operator T const &() const { return data; } + + T data; +}; + + +} +} diff --git a/starts/meaning-vm/level-0/vref.hpp b/starts/meaning-vm/level-0/vref.hpp new file mode 100644 index 0000000..7fe2045 --- /dev/null +++ b/starts/meaning-vm/level-0/vref.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "common.hpp" +#include "memorystore.hpp" +#include "ref.hpp" +#include "value.hpp" + +namespace intellect { +namespace level0 { + +template +struct vref +{ + vref(value *p) : ptr(p) { } + value* operator->() { return ptr; } + operator T const &() const { return *ptr; } + + vref(T const & val) : ptr(alloc(new value(val))) { } + + vref(ref const & other) : ptr(static_cast*>(other.ptr)) { } + operator ref() { return ptr; } + + // for use by containers + bool operator<(vref const & other) const { return self.ptr < other.ptr; } + + value * const ptr; +}; + + +} +} diff --git a/starts/meaning-vm/level0.cpp b/starts/meaning-vm/level0.cpp new file mode 100644 index 0000000..71c18b7 --- /dev/null +++ b/starts/meaning-vm/level0.cpp @@ -0,0 +1,25 @@ +#include "level-0/level-0.hpp" + +#include + +using namespace intellect::level0; + +int main() +{ + ref a = alloc(); + ref b = alloc(); + ref c = alloc(); + ref d = alloc(); + ref e = alloc(); + + ref skip = alloc(); + + a->link(b, c); + a->link(d, e); + e->link(b, a); + c->link(b, e); + + std::cout << a.dump(skip, skip) << std::endl; + + return 0; +} diff --git a/starts/meaning-vm/makefile b/starts/meaning-vm/makefile index 7c39de3..748cca2 100644 --- a/starts/meaning-vm/makefile +++ b/starts/meaning-vm/makefile @@ -1,7 +1,13 @@ CXXFLAGS=-Wall -Werror -std=c++17 -fno-operator-names -ggdb -O0 LINK.o=$(LINK.cc) +level0: level0.o liblevel0.a +liblevel0.a: level-0/memorystore.o level-0/concept.o level-0/ref.o +%.a: + ar ru $@ $^ + ranlib $@ + main: main.o concept.o helpers.o memorystore.o meaning.o -*.o: *.hpp +*.o: *.hpp */*.hpp clean: - -rm *.o main + -rm *.o main level0 *.a */*.o diff --git a/starts/meaning-vm/memorystore.cpp b/starts/meaning-vm/memorystore.cpp deleted file mode 100644 index 9be7ba5..0000000 --- a/starts/meaning-vm/memorystore.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "memorystore.hpp" - -#include - -using namespace std; - -auto & concepts() -{ - static std::unordered_set concepts; - return concepts; -} - -ref alloc(concept * moved) { - ref r = moved ? moved : new concept(); - concepts().insert(r.ptr); - return r; -} - -concept* referenced(ref r) { - for (ref r2 : concepts()) { - if (r2 == r) { - continue; - } - for (auto & l : r2->links) { - if (ref(l.first) == r) { - return r2.ptr; - } - if (ref(l.second) == r) { - return r2.ptr; - } - } - } - return 0; -} - -void dealloc(ref r) { - concept * referenced = ::referenced(r); - if (referenced) { - throw std::logic_error("concept '" + r.name()->data + "' is referenced by '" + ref(referenced).name()->data + '"'); - } - for ( - auto it = concepts().begin(); - it != concepts().end(); - ++ it) - { - if (ref(*it) == r) { - concepts().erase(it); - delete r.ptr; - return; - } - } - throw std::logic_error("concept not held"); -} diff --git a/starts/meaning-vm/memorystore.hpp b/starts/meaning-vm/memorystore.hpp deleted file mode 100644 index d1ca98d..0000000 --- a/starts/meaning-vm/memorystore.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "concept.hpp" - -ref alloc(concept * moved = 0); -template -vref valloc(T const & val) { return alloc(new value(val)); } -void dealloc(ref); -void dealloc_all(ref); // todo? -- cgit v1.2.3