mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-25 08:41:01 +01:00
Initial import
This commit is contained in:
12
Makefile
Normal file
12
Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
OBJS = tree_pool.o tree_reference.o test.o
|
||||
CXXFLAGS = -std=c++11 -g -O0
|
||||
|
||||
test: $(OBJS)
|
||||
clang++ $(CXXFLAGS) $^ -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS)
|
||||
|
||||
%.o: %.cpp
|
||||
clang++ $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
46
addition_node.h
Normal file
46
addition_node.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef ADDITION_NODE_H
|
||||
#define ADDITION_NODE_H
|
||||
|
||||
#include "expression_reference.h"
|
||||
#include "expression_node.h"
|
||||
|
||||
class AdditionNode : public ExpressionNode {
|
||||
public:
|
||||
AdditionNode(int identifier) : ExpressionNode(identifier) {
|
||||
printf("Create Addition\n");
|
||||
}
|
||||
#if TREE_LOGGING
|
||||
const char * description() const override {
|
||||
return "Addition";
|
||||
}
|
||||
#endif
|
||||
float approximate() override {
|
||||
float result = 0.0f;
|
||||
for (int i=0; i<numberOfOperands(); i++) {
|
||||
result += operand(i)->approximate();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
Expression simplify() override {
|
||||
// Scan operands, merge constants
|
||||
Addition a = wrapped(this);
|
||||
if (operand(0)->type() == Integer && operand(1)->type() == Integer) {
|
||||
}
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
class Addition : public ExpressionReference<AdditionNode> {
|
||||
public:
|
||||
Addition(Expression e1, Expression e2) :
|
||||
ExpressionReference<AdditionNode>()
|
||||
{
|
||||
// Ok, here I want to take e1 and e2 as operands
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//typedef ExpressionReference<AdditionNode> Addition;
|
||||
|
||||
#endif
|
||||
22
expression_node.h
Normal file
22
expression_node.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef EXPRESSION_NODE_H
|
||||
#define EXPRESSION_NODE_H
|
||||
|
||||
#include "tree_node.h"
|
||||
|
||||
class TreePool;
|
||||
|
||||
class ExpressionNode : public TreeNode {
|
||||
public:
|
||||
ExpressionNode(int identifier) : TreeNode(identifier) {}
|
||||
|
||||
static TreePool * Pool() {
|
||||
static TreePool pool;
|
||||
return &pool;
|
||||
}
|
||||
|
||||
virtual float approximate() = 0;
|
||||
int numberOfOperands() { return numberOfChildren(); }
|
||||
ExpressionNode * operand(int i) { return static_cast<ExpressionNode *>(childAtIndex(i)); }
|
||||
};
|
||||
|
||||
#endif
|
||||
38
expression_reference.h
Normal file
38
expression_reference.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef EXPRESSION_REFERENCE_H
|
||||
#define EXPRESSION_REFERENCE_H
|
||||
|
||||
#include "tree_reference.h"
|
||||
#include "expression_node.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
template <class T>
|
||||
class ExpressionReference : public TreeReference<T> {
|
||||
public:
|
||||
ExpressionReference() : TreeReference<T>(ExpressionNode::Pool()) { }
|
||||
|
||||
/*ExpressionReference(const ExpressionReference & er) {
|
||||
}*/
|
||||
|
||||
// Allow every ExpressionReference<T> to be transformed into an ExpressionReference<ExpressionNode>, i.e. Expression
|
||||
operator ExpressionReference<ExpressionNode>() const {
|
||||
printf("ExpressionReference cast\n");
|
||||
// TODO: make sure this is kosher
|
||||
// static_assert(sizeof(ExpressionReference<T>) == sizeof(ExpressionReference<ExpressionNode>), "All ExpressionReference are supposed to have the same size");
|
||||
return *(reinterpret_cast<const ExpressionReference<ExpressionNode> *>(this));
|
||||
}
|
||||
|
||||
float approximate() const {
|
||||
return this->node()->approximate();
|
||||
}
|
||||
|
||||
/*
|
||||
ExpressionReference<ExpressionNode> simplify() {
|
||||
return node()->simplify();
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
typedef ExpressionReference<ExpressionNode> Expression;
|
||||
|
||||
#endif
|
||||
41
float_node.h
Normal file
41
float_node.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef FLOAT_NODE_H
|
||||
#define FLOAT_NODE_H
|
||||
|
||||
#include "expression_reference.h"
|
||||
#include "expression_node.h"
|
||||
|
||||
class FloatNode : public ExpressionNode {
|
||||
public:
|
||||
FloatNode(int identifier) : ExpressionNode(identifier) {
|
||||
printf("Create float\n");
|
||||
}
|
||||
size_t size() const override {
|
||||
return sizeof(FloatNode);
|
||||
}
|
||||
float approximate() override {
|
||||
return m_value;
|
||||
}
|
||||
#if TREE_LOGGING
|
||||
const char * description() const override {
|
||||
if (m_value > 1) {
|
||||
return "BigFloat";
|
||||
} else {
|
||||
return "SmallFloat";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void setFloat(float f) { m_value = f; }
|
||||
private:
|
||||
float m_value;
|
||||
};
|
||||
|
||||
class Float : public ExpressionReference<FloatNode> {
|
||||
public:
|
||||
Float(float f) : ExpressionReference<FloatNode>() {
|
||||
this->node()->setFloat(f);
|
||||
}
|
||||
};
|
||||
|
||||
//typedef ExpressionReference<FloatNode> Float;
|
||||
|
||||
#endif
|
||||
107
test.cpp
Normal file
107
test.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "float_node.h"
|
||||
#include "addition_node.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
int main() {
|
||||
printf("Hello\n");
|
||||
|
||||
ExpressionNode::Pool()->log();
|
||||
|
||||
Float e(0.2f);
|
||||
|
||||
ExpressionNode::Pool()->log();
|
||||
|
||||
if (true) {
|
||||
Expression j = e;
|
||||
|
||||
ExpressionNode::Pool()->log();
|
||||
|
||||
Float m(3.4f);
|
||||
|
||||
ExpressionNode::Pool()->log();
|
||||
}
|
||||
|
||||
ExpressionNode::Pool()->log();
|
||||
|
||||
Addition a(e, e);
|
||||
|
||||
ExpressionNode::Pool()->log();
|
||||
|
||||
/*
|
||||
Expression e = Parse("1+1");
|
||||
Expression j = e;
|
||||
Expression f = Addition(e, Parse("5"));
|
||||
f.removeChildAtIndex(0);
|
||||
*/
|
||||
#if 0
|
||||
TreeNodePool pool;
|
||||
TreeNodePool * p = &pool;
|
||||
|
||||
pool.log();
|
||||
|
||||
TreeNode * t1 = new (pool) AdditionNode();
|
||||
|
||||
TreeNode * t1 = TreeNode::Create(p, 11);
|
||||
TreeNode * t2 = TreeNode::Create(p, 12);
|
||||
TreeNode * t3 = TreeNode::Create(p, 13);
|
||||
|
||||
TreeNode * t4 = AddNode::Create(t1, t3);
|
||||
//TreeNode * t4 = new(p) IntNode(4);
|
||||
//
|
||||
t4->createChild(Addition()
|
||||
|
||||
pool.log();
|
||||
|
||||
pool.move(t1, t3);
|
||||
|
||||
pool.log();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
static inline swap(uint32_t * a, uint32_t * b) {
|
||||
uint32_t tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
void insert(char * source, char * destination, size_t length) {
|
||||
assert(length % 4 == 0);
|
||||
assert(source % 4 == 0);
|
||||
assert(destination % 4 == 0);
|
||||
uint32_t * src = reinterpret_cast<uint32_t *>(source);
|
||||
uint32_t * dst = reinterpret_cast<uint32_t *>(destination);
|
||||
size_t len = length/4;
|
||||
|
||||
if (dst < src) {
|
||||
if (src - dst <= len) {
|
||||
uint32_t * srcPointer = src;
|
||||
uint32_t * dstPointer = dst;
|
||||
while (dstPointer != src) {
|
||||
swap(srcPointer, dstPointer);
|
||||
srcPointer++;
|
||||
dstPointer++;
|
||||
if (srcPointer == src + len) {
|
||||
srcPointer = src;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeNodePool::move(TreeNode * source, TreeNode * destination) {
|
||||
if (source == destination) {
|
||||
return;
|
||||
}
|
||||
insert(source, destination, source->deepSize());
|
||||
}
|
||||
|
||||
bool TreeNode::hasVariableNumberOfChildren() const {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
178
tree_node.h
Normal file
178
tree_node.h
Normal file
@@ -0,0 +1,178 @@
|
||||
#ifndef TREE_NODE_H
|
||||
#define TREE_NODE_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <strings.h>
|
||||
|
||||
#define TREE_LOGGING 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class TreeNode {
|
||||
//friend class TreeReference;
|
||||
// friend class TreePool;
|
||||
public:
|
||||
virtual ~TreeNode() {
|
||||
}
|
||||
|
||||
|
||||
// Iterators
|
||||
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator(TreeNode * node) : m_node(node) {}
|
||||
TreeNode * operator*() { return m_node; }
|
||||
bool operator!=(const Iterator& it) const { return (m_node != it.m_node); }
|
||||
protected:
|
||||
TreeNode * m_node;
|
||||
};
|
||||
|
||||
class DepthFirst {
|
||||
public:
|
||||
DepthFirst(TreeNode * node) : m_node(node) {}
|
||||
class Iterator : public TreeNode::Iterator {
|
||||
public:
|
||||
using TreeNode::Iterator::Iterator;
|
||||
Iterator & operator++() {
|
||||
printf(" Iterating from %d(%p) to %d(%p)\n", m_node->m_identifier, m_node, m_node->next()->m_identifier, m_node->next());
|
||||
m_node = m_node->next();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
Iterator begin() const { return Iterator(m_node); }
|
||||
Iterator end() const { return Iterator(m_node->nextSibling()); }
|
||||
private:
|
||||
TreeNode * m_node;
|
||||
};
|
||||
|
||||
DepthFirst depthFirstChildren() { return DepthFirst(this); }
|
||||
|
||||
|
||||
int identifier() const { return m_identifier; }
|
||||
|
||||
#if TREE_LOGGING
|
||||
virtual const char * description() const {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual size_t size() const {
|
||||
return sizeof(TreeNode);
|
||||
}
|
||||
|
||||
void retain() {
|
||||
m_referenceCounter++;
|
||||
}
|
||||
void release() {
|
||||
m_referenceCounter--;
|
||||
}
|
||||
|
||||
int retainCount() {
|
||||
return m_referenceCounter;
|
||||
}
|
||||
|
||||
virtual bool hasVariableNumberOfChildren() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
int numberOfChildren() const {
|
||||
if (hasVariableNumberOfChildren()) {
|
||||
int numberOfChildren = 0;
|
||||
TreeNode * child = next();
|
||||
while (!child->isEndMarker()) {
|
||||
child = child->nextSibling();
|
||||
numberOfChildren++;
|
||||
}
|
||||
return numberOfChildren;
|
||||
} else {
|
||||
// TODO: Make this function virtual
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
TreeNode * childAtIndex(int i) const {
|
||||
assert(i >= 0);
|
||||
assert(i < numberOfChildren());
|
||||
TreeNode * child = next();
|
||||
while (i>0) {
|
||||
child = child->nextSibling();
|
||||
assert(child != nullptr);
|
||||
assert(!child->isEndMarker());
|
||||
i--;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
void addChild(TreeNode * node) {
|
||||
// This will move node in the pool so that it becomes
|
||||
// a children of this
|
||||
pool->move(node, this + size());
|
||||
}
|
||||
*/
|
||||
|
||||
//private:
|
||||
|
||||
// FIXME: Make this private
|
||||
TreeNode(int identifier) :
|
||||
m_identifier(identifier),
|
||||
m_referenceCounter(1)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr static int EmptyIdentifier = 0;
|
||||
constexpr static int EndMarkerIdentifier = 1;
|
||||
|
||||
bool isEndMarker() const {
|
||||
return (m_identifier == EndMarkerIdentifier);
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return (m_identifier == EmptyIdentifier);
|
||||
}
|
||||
|
||||
void markAsEmpty() {
|
||||
m_identifier = EmptyIdentifier;
|
||||
}
|
||||
|
||||
TreeNode * next() const {
|
||||
// Simple version would be "return this + 1;", with pointer arithmetics taken care of by the compiler.
|
||||
// Unfortunately, we want TreeNode to have a VARIABLE size
|
||||
return reinterpret_cast<TreeNode *>(reinterpret_cast<char *>(const_cast<TreeNode *>(this)) + size());
|
||||
}
|
||||
|
||||
TreeNode * nextSibling() const {
|
||||
TreeNode * n = const_cast<TreeNode *>(this);
|
||||
int depth = 0;
|
||||
do {
|
||||
if (n->hasVariableNumberOfChildren()) {
|
||||
depth++;
|
||||
}
|
||||
/*
|
||||
if (n->isEndMarker()) {
|
||||
depth--;
|
||||
}
|
||||
*/
|
||||
n = n->next();
|
||||
// TODO: Return nullptr if n overflows the pool!
|
||||
assert(depth >= 0);
|
||||
} while(depth != 0);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t deepSize() const {
|
||||
// TODO: Error handling
|
||||
return
|
||||
reinterpret_cast<char *>(nextSibling())
|
||||
-
|
||||
reinterpret_cast<const char *>(this);
|
||||
;
|
||||
}
|
||||
|
||||
//private:
|
||||
int m_identifier;
|
||||
int m_referenceCounter;
|
||||
};
|
||||
|
||||
#endif
|
||||
52
tree_pool.cpp
Normal file
52
tree_pool.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "tree_pool.h"
|
||||
#include <string.h>
|
||||
#include "tree_node.h"
|
||||
|
||||
void * TreePool::alloc(size_t size) {
|
||||
void * result = m_cursor;
|
||||
m_cursor += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
void TreePool::dealloc(void * ptr, size_t size) {
|
||||
// Step 1 - Compact the pool
|
||||
memmove(
|
||||
ptr,
|
||||
static_cast<char *>(ptr) - size,
|
||||
m_cursor - static_cast<char *>(ptr)
|
||||
);
|
||||
m_cursor -= size;
|
||||
}
|
||||
|
||||
TreeNode * TreePool::node(int identifier) const {
|
||||
for (TreeNode * node : *this) {
|
||||
if (node->identifier() == identifier) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
/*
|
||||
TreeNode * node = const_cast<TreeNode *>(reinterpret_cast<const TreeNode *>(m_buffer));
|
||||
TreeNode * endOfPool = reinterpret_cast<TreeNode *>(m_cursor);
|
||||
while (node < endOfPool) {
|
||||
if (node->identifier() == identifier) {
|
||||
return node;
|
||||
}
|
||||
node = node->next();
|
||||
}
|
||||
*/
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if TREE_LOGGING
|
||||
#include <stdio.h>
|
||||
|
||||
void TreePool::log() {
|
||||
printf("POOL:");
|
||||
for (TreeNode * node : *this) {
|
||||
printf("|%d", node->m_identifier);
|
||||
//printf("|(%03d|%s|%03d)", node->m_identifier, node->description(), node->retainCount());
|
||||
}
|
||||
printf("|\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
79
tree_pool.h
Normal file
79
tree_pool.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef TREE_POOL_H
|
||||
#define TREE_POOL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "tree_node.h"
|
||||
|
||||
class TreePool {
|
||||
public:
|
||||
TreePool() : m_lastIdentifier(0), m_cursor(m_buffer) {}
|
||||
|
||||
int generateIdentifier() {
|
||||
assert(node(m_lastIdentifier) == nullptr);
|
||||
return m_lastIdentifier++;
|
||||
}
|
||||
void reclaimIdentifier(int identifier) {
|
||||
}
|
||||
|
||||
void * alloc(size_t size);
|
||||
void dealloc(void * ptr, size_t size);
|
||||
|
||||
TreeNode * node(int identifier) const;
|
||||
#if TREE_LOGGING
|
||||
void log();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
TreeNode::DepthFirst::Iterator begin() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast<TreeNode *>(const_cast<char *>(m_buffer))); }
|
||||
TreeNode::DepthFirst::Iterator end() const { return TreeNode::DepthFirst::Iterator(reinterpret_cast<TreeNode *>(const_cast<char *>(m_cursor))); }
|
||||
|
||||
int m_lastIdentifier;
|
||||
char * m_cursor;
|
||||
char m_buffer[256];
|
||||
};
|
||||
|
||||
#if 0
|
||||
class TreePool {
|
||||
public:
|
||||
TreePool() :
|
||||
m_identifier(0),
|
||||
m_cursor(m_data)
|
||||
{
|
||||
}
|
||||
|
||||
class Slot {
|
||||
public:
|
||||
Slot(int identifier, void * area) :
|
||||
m_identifier(identifier), m_area(area) {}
|
||||
int identifier() const { return m_identifier; }
|
||||
void * area() const { return m_area; }
|
||||
private:
|
||||
int m_identifier;
|
||||
void * m_area;
|
||||
int m_size;
|
||||
};
|
||||
|
||||
Slot alloc(size_t size);
|
||||
void dealloc(Slot s, size_t size);
|
||||
|
||||
//TreeNode * node(int identifier) const;
|
||||
TreeNode * alloc(size_t size) {
|
||||
|
||||
}
|
||||
void dealloc(TreeNode * node);
|
||||
|
||||
void move(TreeNode * source, TreeNode * destination);
|
||||
//#define TREE_LOGGING 1
|
||||
#if TREE_LOGGING
|
||||
void log();
|
||||
#endif
|
||||
private:
|
||||
int m_identifier;
|
||||
char * m_cursor;
|
||||
char m_data[200];
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
14
tree_reference.cpp
Normal file
14
tree_reference.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "tree_reference.h"
|
||||
|
||||
#if 0
|
||||
void TreeReference::addOperand(TreeReference<TreeNode> t) {
|
||||
// At this point, e has been copied.
|
||||
// We can therefore pilfer its node!
|
||||
Node * n = node();
|
||||
pool->move(
|
||||
t->node(),
|
||||
t->next()
|
||||
);
|
||||
node->stealAsOperand(t->node());
|
||||
}
|
||||
#endif
|
||||
88
tree_reference.h
Normal file
88
tree_reference.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef TREE_REFERENCE_H
|
||||
#define TREE_REFERENCE_H
|
||||
|
||||
#include "tree_pool.h"
|
||||
#include <new>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
template <class T>
|
||||
class TreeReference {
|
||||
public:
|
||||
TreeReference(const TreeReference & tr) :
|
||||
m_pool(tr.m_pool),
|
||||
m_identifier(tr.m_identifier)
|
||||
{
|
||||
printf("TreeReference copy\n");
|
||||
node()->retain();
|
||||
}
|
||||
|
||||
~TreeReference() {
|
||||
TreeNode * node = this->node();
|
||||
node->release();
|
||||
if (node->retainCount() == 0) {
|
||||
printf("Discarding node %d(%p)\n", node->identifier(), node);
|
||||
// Here the static_cast should fail if T is not a subclass of TreeNode
|
||||
size_t deepNodeSize = node->deepSize();
|
||||
#if 0
|
||||
// Here, if needed, call reclaimIdentifier
|
||||
for (TreeNode * child : node->depthFirstChildren()) {
|
||||
m_pool->reclaimIdentifier(child->identifier());
|
||||
}
|
||||
m_pool->reclaimIdentifier(node->identifier());
|
||||
#endif
|
||||
static_cast<T*>(node)->~T();
|
||||
m_pool->dealloc(node, deepNodeSize);
|
||||
}
|
||||
}
|
||||
|
||||
int numberOfChildren() const {
|
||||
return node()->numberOfChildren();
|
||||
}
|
||||
|
||||
TreeReference<T> childAtIndex(int i) const {
|
||||
return TreeReference(node()->childAtIndex(i));
|
||||
}
|
||||
|
||||
void addOperand(TreeReference<TreeNode> t) {
|
||||
assert(t.m_pool == m_pool);
|
||||
/*
|
||||
m_pool->move(
|
||||
t->node(),
|
||||
t->next()
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
protected:
|
||||
TreeReference(TreePool * pool) :
|
||||
m_pool(pool)
|
||||
{
|
||||
int identifier = pool->generateIdentifier();
|
||||
void * area = pool->alloc(sizeof(T));
|
||||
TreeNode * n = new (area) T(identifier);
|
||||
m_identifier = n->identifier();
|
||||
assert(m_identifier == identifier);
|
||||
//m_cachedNode = n;
|
||||
}
|
||||
|
||||
T * node() const {
|
||||
// TODO: Here, assert that the node type is indeed T
|
||||
return static_cast<T*>(m_pool->node(m_identifier));
|
||||
}
|
||||
private:
|
||||
TreeReference(TreePool * pool, TreeNode * node) :
|
||||
m_pool(pool),
|
||||
m_identifier(node->identifier())
|
||||
//m_cachedNode(node)
|
||||
{
|
||||
node->retain();
|
||||
}
|
||||
|
||||
|
||||
TreePool * m_pool;
|
||||
int m_identifier;
|
||||
//TreeNode * m_cachedNode;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user