Initial import

This commit is contained in:
Romain Goyet
2018-06-12 13:56:20 +02:00
commit 3cd1015614
11 changed files with 677 additions and 0 deletions

12
Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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