diff options
Diffstat (limited to 'starts/meaning-vm')
-rw-r--r-- | starts/meaning-vm/DESIGN.txt | 10 | ||||
-rw-r--r-- | starts/meaning-vm/concept.hpp | 100 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/common.hpp | 14 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/concept.cpp (renamed from starts/meaning-vm/concept.cpp) | 91 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/concept.hpp | 38 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/errors.hpp | 77 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/level-0.hpp | 9 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/memorystore.cpp (renamed from starts/meaning-vm/memorystore.cpp) | 22 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/memorystore.hpp | 13 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/ref.cpp | 34 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/ref.hpp | 26 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/value.hpp | 25 | ||||
-rw-r--r-- | starts/meaning-vm/level-0/vref.hpp | 31 | ||||
-rw-r--r-- | starts/meaning-vm/level0.cpp | 25 | ||||
-rw-r--r-- | starts/meaning-vm/makefile | 10 | ||||
-rw-r--r-- | starts/meaning-vm/memorystore.hpp | 9 |
16 files changed, 377 insertions, 157 deletions
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.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 <map> -#include <stdexcept> -#include <string> -#include <vector> - -template <typename T> struct vref; -struct concept; -template <typename T> 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<std::string> 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 <typename T> -struct vref -{ - vref(value<T> *p) : ptr(p) { } - value<T>* operator->() { return ptr; } - operator T const &() const { return *ptr; } - - vref(T const & val); - - vref(ref const & that) : ptr(static_cast<value<T>*>(that.ptr)) { } - operator ref() { return ptr; } - - // for use by containers - //bool operator<(ref const & that) const { return ptr < that.ptr; } - - value<T> * ptr; -}; - -struct concept -{ - // a concept is made of concept-typed links to other concepts - std::multimap<concept*,concept*> links; - using array = std::vector<ref>; - - 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 <typename T> - vref<T> 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 <typename T> -struct value : public concept -{ - value(T const & val) : data(val) { } - value(value<T> const & val) = default; - static value<T>& of(ref c) - { - return *static_cast<value<T>*>(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 <typename T> struct value; +template <typename T> struct vref; + +} +} diff --git a/starts/meaning-vm/concept.cpp b/starts/meaning-vm/level-0/concept.cpp index 993ac62..579cca8 100644 --- a/starts/meaning-vm/concept.cpp +++ b/starts/meaning-vm/level-0/concept.cpp @@ -1,10 +1,46 @@ #include "concept.hpp" +#include "errors.hpp" + +using namespace intellect::level0; + +#define selfref const_cast<concept*>(&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; @@ -20,25 +56,11 @@ bool concept::linked(ref const & type, ref const & target) const 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); + auto range = links.equal_range(type); range.first != range.second; ++ range.first ) { @@ -47,33 +69,26 @@ concept::array concept::getAll(ref const & type) const return ret; } -void concept::link(ref const & type, ref const & target) +ref concept::get(ref const & type) const { - 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; - } + 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); } - throw std::out_of_range("no such concept link to erase"); + return result.first->second; } -void concept::unlink(ref const & type) +void concept::set(ref const & type, ref const & target) { - auto ls = links.equal_range(type.ptr); - if (ls.first == ls.second) { - throw std::out_of_range("no such concept link to erase"); + if (linked(type)) { + throw link_type_not_unique(selfref, type); } - 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); + 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 <map> +#include <vector> + +namespace intellect { +namespace level0 { + +struct concept +{ + // a concept is made of concept-typed links to other concepts + std::multimap<ref,ref> links; + using array = std::vector<ref>; + + 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 <typename T> + vref<T> 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 <stdexcept> + +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/memorystore.cpp b/starts/meaning-vm/level-0/memorystore.cpp index 9be7ba5..6cf71df 100644 --- a/starts/meaning-vm/memorystore.cpp +++ b/starts/meaning-vm/level-0/memorystore.cpp @@ -1,22 +1,25 @@ #include "memorystore.hpp" +#include "concept.hpp" +#include "errors.hpp" #include <unordered_set> -using namespace std; +namespace intellect { +namespace level0 { -auto & concepts() +static auto & concepts() { - static std::unordered_set<concept*> concepts; + static std::unordered_set<ref, std::hash<concept*>> concepts; return concepts; } ref alloc(concept * moved) { ref r = moved ? moved : new concept(); - concepts().insert(r.ptr); + concepts().insert(r); return r; } -concept* referenced(ref r) { +static concept* referenced(ref r) { for (ref r2 : concepts()) { if (r2 == r) { continue; @@ -34,9 +37,9 @@ concept* referenced(ref r) { } void dealloc(ref r) { - concept * referenced = ::referenced(r); + concept * referenced = intellect::level0::referenced(r); if (referenced) { - throw std::logic_error("concept '" + r.name()->data + "' is referenced by '" + ref(referenced).name()->data + '"'); + throw still_referenced_by(r, referenced); } for ( auto it = concepts().begin(); @@ -49,5 +52,8 @@ void dealloc(ref r) { return; } } - throw std::logic_error("concept not held"); + 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 <ostream> + +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 <string> + +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 <typename T> +struct value : public concept +{ + value(T const & val) : data(val) { } + + value(value<T> 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 <typename T> +struct vref +{ + vref(value<T> *p) : ptr(p) { } + value<T>* operator->() { return ptr; } + operator T const &() const { return *ptr; } + + vref(T const & val) : ptr(alloc(new value<T>(val))) { } + + vref(ref const & other) : ptr(static_cast<value<T>*>(other.ptr)) { } + operator ref() { return ptr; } + + // for use by containers + bool operator<(vref<T> const & other) const { return self.ptr < other.ptr; } + + value<T> * 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 <iostream> + +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.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 <typename T> -vref<T> valloc(T const & val) { return alloc(new value<T>(val)); } -void dealloc(ref); -void dealloc_all(ref); // todo? |