<commit_before>#include "parser.h"

Parser::Parser()
{
    clear();
}

Parser::~Parser()
{
    clear();
}

void Parser::clear()
{
    m_index = -1;
    m_originalSpacesForIndent = 0;
    m_scope = 0;
    m_expectedScope = 0;
    m_indent = Unset;
    m_source = 0;
}

void Parser::parse(SourceBuffer* source)
{
    clear();
    m_source = source;

    while (m_index < m_source->tokenCount() - 1) {
        Token tok = advance(1);
        if (tok.type == Newline)
            continue;
        if (tok.type == Type)
            parseTypeDecl();
        else if (tok.type == Function)
            parseFuncDecl();
        else
            m_source->error(tok, "unexpected token when parsing translation unit");
    }
}

void Parser::newline()
{
}

Token Parser::advance(int i, bool skipComments)
{
    m_index += i;
    if (!skipComments)
        return current();

    while (current().type == Comment || (current().type == Whitespace && look(1).type == Comment))
        m_index++;

    return current();
}

Token Parser::current() const
{
    Q_ASSERT(m_index >= 0);
    Q_ASSERT(m_index < m_source->tokenCount());
    return look(0);
}

Token Parser::look(int i) const
{
    int index = m_index + i;
    Q_ASSERT(m_index >= 0);
    if (index >= m_source->tokenCount())
        return Token();
    return m_source->tokenAt(index);
}

bool Parser::expect(Token tok, TokenType type) const
{
    if (tok.type == type)
        return true;
    m_source->error(tok, "expecting " + typeToString(type) + " for " + m_context.top());
    return false;
}

bool Parser::checkLeadingWhitespace(const Token& tok)
{
    if (m_indent == Tabs) {
        m_source->error(tok, "unexpected ' ' when already using '\\t' for indentation");
        return false;
    }
    m_indent = Spaces;
    int spacesForIndent = tok.end.column - tok.start.column + 1;
    if (!m_originalSpacesForIndent) {
        m_originalSpacesForIndent = spacesForIndent;
    } else if (spacesForIndent % m_originalSpacesForIndent != 0) {
        m_source->error(tok, "number of spaces in indentation level is not divisable by " + QString::number(m_originalSpacesForIndent));
        return false;
    }
    m_scope = spacesForIndent / m_originalSpacesForIndent;
    return true;
}

bool Parser::checkLeadingTab(const Token& tok)
{
    if (m_indent == Spaces) {
        m_source->error(tok, "unexpected '\\t' when already using ' ' for indentation");
        return false;
    }
    m_indent = Tabs;
    m_scope = tok.end.column - tok.start.column + 1;
    return true;
}

// type foo : (b1:bar(, b2:baz)?)
void Parser::parseTypeDecl()
{
    ParserContext context(this, "type declaration");

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Identifier))
        return;

    Token name = tok;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Colon))
        return;

    QList<QSharedPointer<TypeObject> > objects;
    if (look(1).type == Whitespace && look(2).type == OpenParenthesis)
        objects = parseTypeObjects();

    tok = advance(1);
    if (!expect(tok, Newline))
        return;

    TypeDecl* decl = new TypeDecl;
    decl->name = name;
    decl->objects = objects;

    if (!m_source->symbols().addType(*decl))
        return;

    m_source->translationUnit().typeDecl.append(QSharedPointer<TypeDecl>(decl));
}

// function foo : (foo:Foo?, bar:Bar?, ...)? ->? Baz
void Parser::parseFuncDecl()
{
    ParserContext context(this, "function declaration");

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Identifier))
        return;

    Token name = tok;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Colon))
        return;

    QList<QSharedPointer<TypeObject> > objects;
    if (look(1).type == Whitespace && look(2).type == OpenParenthesis)
        objects = parseTypeObjects();

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Minus))
        return;

    tok = advance(1);
    if (!expect(tok, GreaterThan))
        return;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Identifier))
        return;

    Token returnType = tok;

    tok = advance(1);
    if (!expect(tok, Newline))
        return;

    FuncDef* funcDef = parseFuncDef();
    if (!funcDef)
        return;

    FuncDecl* decl = new FuncDecl;
    decl->name = name;
    decl->objects = objects;
    decl->funcDef = QSharedPointer<FuncDef>(funcDef);
    decl->returnType = returnType;

    if (!m_source->symbols().addFunction(*decl))
        return;

    m_source->translationUnit().funcDecl.append(QSharedPointer<FuncDecl>(decl));
}

QList<QSharedPointer<TypeObject> > Parser::parseTypeObjects()
{
    bool unnamedTypeObject = false;
    QList<QSharedPointer<TypeObject> > objects;
    Token tok = advance(3);
    Token first = tok;
    if (tok.type == Identifier) {
        while(TypeObject* object = parseTypeObject()) {
            if (object->name.type == Undefined)
                unnamedTypeObject = true;
            objects.append(QSharedPointer<TypeObject>(object));
        }
    }

    tok = current();
    if (!expect(tok, CloseParenthesis))
        return QList<QSharedPointer<TypeObject> >();

    if (unnamedTypeObject && objects.size() > 1) {
        m_source->error(first, "a type object list must consist of named objects or only one unnamed object");
        return QList<QSharedPointer<TypeObject> >();
    }

    return objects;
}

TypeObject* Parser::parseTypeObject()
{
    ParserContext context(this, "type object");

    Token tok = current();
    if (tok.type == Comma) {
        tok = advance(1);
        if (!expect(tok, Whitespace))
            return 0;
    } else if (tok.type == CloseParenthesis)
        return 0;

    if (!expect(tok, Identifier))
        return 0;

    Token identifier1 = tok;
    Token identifier2;

    if (look(1).type == Colon) {
        tok = advance(2);
        if (!expect(tok, Identifier))
            return 0;

        identifier2 = tok;
    }

    advance(1);

    TypeObject* arg = new TypeObject;
    arg->name = identifier2.type == Undefined ? Token() : identifier1;
    arg->type = identifier2.type == Identifier ? identifier2 : identifier1;
    return arg;
}

FuncDef* Parser::parseFuncDef()
{
    ParserContext context(this, "function definition");
    IndentLevel indent(this);

    QList<QSharedPointer<Stmt> > stmts;
    while (Stmt* stmt = parseStmt())
        stmts.append(QSharedPointer<Stmt>(stmt));

    if (stmts.isEmpty()) {
        m_source->error(current(), "function must define at least one statement");
        return 0;
    }

    FuncDef* funcDef = new FuncDef;
    funcDef->stmts = stmts;
    return funcDef;
}

bool Parser::parseIndent(unsigned expected)
{
    if (look(1).type != Whitespace && look(1).type != Tab)
        return false;

    Token tok = advance(1);
    if (tok.type == Whitespace && !checkLeadingWhitespace(tok))
        return false;
    else if (tok.type == Tab && !checkLeadingTab(tok))
        return false;

    if (m_scope != expected) {
        m_source->error(tok, "indentation level is incorrect");
        return false;
    }

    return true;
}

Expr* Parser::parseExpr()
{
    ParserContext context(this, "expression");

    Expr* lhs = parseBasicExpr();
    if (!lhs)
        return 0;

    Expr* rhs = parseBinaryOpExpr(0, lhs);
    if (!rhs)
        return 0;

    while (rhs && lhs != rhs) {
        lhs = rhs;
        rhs = parseBinaryOpExpr(0, lhs);
    }

    return rhs;
}

Expr* Parser::parseBasicExpr()
{
    ParserContext context(this, "basic expression");

    Token tok = advance(1);
    Expr* expr = 0;
    switch (tok.type) {
    case Identifier:
        if (look(1).type == OpenParenthesis)
            expr = parseFuncCallExpr();
        else
            expr = parseVarExpr();
        break;
    case Digits:
        expr = parseLiteralExpr();
        break;
    default:
        break;
    };

    if (expr)
        expr->start = tok;
    return expr;
}

Expr* Parser::parseBinaryOpExpr(int precedence, Expr* lhs)
{
    if (look(1).type != Whitespace)
        return lhs;

    Token tok = advance(2);

    BinaryExpr::BinaryOp op;
    bool foundBinaryOp = false;

    if (tok.type == Equals && look(1).type == Equals
        && precedence <= 1) {
        op = BinaryExpr::OpEquality;
        tok = advance(2);
        foundBinaryOp = true;
    } else if ((tok.type == LessThan || tok.type == GreaterThan)
        && look(1).type == Equals
        && precedence <= 1) {
        op = tok.type == LessThan ? BinaryExpr::OpLessThanOrEquality : BinaryExpr::OpGreaterThanOrEquality;
        tok = advance(2);
        foundBinaryOp = true;
    } else if ((tok.type == LessThan || tok.type == GreaterThan)
        && precedence <= 1) {
        op = tok.type == LessThan ? BinaryExpr::OpLessThan : BinaryExpr::OpGreaterThan;
        tok = advance(1);
        foundBinaryOp = true;
    } else if ((tok.type == Plus || tok.type == Minus)
        && precedence <= 2) {
        op = tok.type == Plus ? BinaryExpr::OpAddition : BinaryExpr::OpSubtraction;
        tok = advance(1);
        foundBinaryOp = true;
    } else if ((tok.type == Star || tok.type == Slash)
        && precedence <= 3) {
        op = tok.type == Star ? BinaryExpr::OpMultiplication : BinaryExpr::OpDivision;
        tok = advance(1);
        foundBinaryOp = true;
    }

    if (!foundBinaryOp)
        return lhs;

    if (!expect(tok, Whitespace))
        return 0;

    Expr* rhs = parseBasicExpr();
    if (!rhs)
        return 0;

    BinaryExpr* binaryExpr = new BinaryExpr;
    binaryExpr->op = op;
    binaryExpr->lhs = QSharedPointer<Expr>(lhs);
    binaryExpr->rhs = QSharedPointer<Expr>(rhs);
    return binaryExpr;
}

VarExpr* Parser::parseVarExpr()
{
    ParserContext context(this, "variable expression");

    Token var = current();

    VarExpr* varExpr = new VarExpr;
    varExpr->var = var;
    return varExpr;
}

LiteralExpr* Parser::parseLiteralExpr()
{
    ParserContext context(this, "literal expression");

    Token literal = current();

    LiteralExpr* literalExpr = new LiteralExpr;
    literalExpr->literal = literal;
    return literalExpr;
}

Stmt* Parser::parseStmt()
{
    ParserContext context(this, "statement");

    if (current().type == Newline && !parseIndent(m_expectedScope))
        return 0;

    if (m_index == m_source->tokenCount() - 1)
        return 0;

    Stmt* stmt = 0;
    Token tok = advance(1);
    switch (tok.type) {
    case If:
        stmt = parseIfStmt(); break;
    case Return:
        stmt = parseReturnStmt(); break;
    case Identifier:
        stmt = parseVarDeclStmt(); break;
    default:
        return 0;
    };

    return stmt;
}

IfStmt* Parser::parseIfStmt()
{
    ParserContext context(this, "if statement");

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    tok = advance(1);
    if (!expect(tok, OpenParenthesis))
        return 0;

    Expr* expr = parseExpr();
    if (!expr)
        return 0;

    tok = advance(1);
    if (!expect(tok, CloseParenthesis))
        return 0;

    tok = advance(1);

    IndentLevel indent(this);
    Stmt* stmt = parseStmt();
    if (!stmt) {
        m_source->error(tok, "no statement following condition");
        return 0;
    }

    IfStmt* ifStmt = new IfStmt;
    ifStmt->expr = QSharedPointer<Expr>(expr);
    ifStmt->stmt = QSharedPointer<Stmt>(stmt);
    return ifStmt;
}

ReturnStmt* Parser::parseReturnStmt()
{
    ParserContext context(this, "return statement");

    Token keyword = current();

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    Expr* expr = parseExpr();
    if (!expr)
        return 0;

    if (m_index < m_source->tokenCount() - 1) {
        tok = advance(1);
        if (!expect(tok, Newline))
            return 0;
    }

    ReturnStmt* returnStmt = new ReturnStmt;
    returnStmt->keyword = keyword;
    returnStmt->expr = QSharedPointer<Expr>(expr);
    return returnStmt;
}

FuncCallExpr* Parser::parseFuncCallExpr()
{
    ParserContext context(this, "function call expression");

    Token callee = current();

    Token tok = advance(1);
    if (!expect(tok, OpenParenthesis))
        return 0;

    QList<QSharedPointer<Expr> > args;
    while(Expr* expr = parseExpr())
        args.append(QSharedPointer<Expr>(expr));

    tok = current();
    if (!expect(tok, CloseParenthesis))
        return 0;

    FuncCallExpr* funcCallExpr = new FuncCallExpr;
    funcCallExpr->callee = callee;
    funcCallExpr->args = args;
    return funcCallExpr;
}

VarDeclStmt* Parser::parseVarDeclStmt()
{
    ParserContext context(this, "variable declaration statement");

    Token type = current();

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    tok = advance(1);
    if (!expect(tok, Identifier))
        return 0;

    Token name = tok;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    tok = advance(1);
    if (!expect(tok, Equals))
        return 0;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    tok = look(1);
    Expr* expr = parseExpr();
    if (!expr) {
        m_source->error(tok, "expected expression for variable initialization");
        return 0;
    }

    tok = advance(1);
    if (!expect(tok, Newline))
        return 0;

    VarDeclStmt* varDeclStmt = new VarDeclStmt;
    varDeclStmt->type = type;
    varDeclStmt->name = name;
    varDeclStmt->expr = QSharedPointer<Expr>(expr);
    return varDeclStmt;
}
<commit_msg>Fix bug for declarations with multiple type objects<commit_after>#include "parser.h"

Parser::Parser()
{
    clear();
}

Parser::~Parser()
{
    clear();
}

void Parser::clear()
{
    m_index = -1;
    m_originalSpacesForIndent = 0;
    m_scope = 0;
    m_expectedScope = 0;
    m_indent = Unset;
    m_source = 0;
}

void Parser::parse(SourceBuffer* source)
{
    clear();
    m_source = source;

    while (m_index < m_source->tokenCount() - 1) {
        Token tok = advance(1);
        if (tok.type == Newline)
            continue;
        if (tok.type == Type)
            parseTypeDecl();
        else if (tok.type == Function)
            parseFuncDecl();
        else
            m_source->error(tok, "unexpected token when parsing translation unit");
    }
}

void Parser::newline()
{
}

Token Parser::advance(int i, bool skipComments)
{
    m_index += i;
    if (!skipComments)
        return current();

    while (current().type == Comment || (current().type == Whitespace && look(1).type == Comment))
        m_index++;

    return current();
}

Token Parser::current() const
{
    Q_ASSERT(m_index >= 0);
    Q_ASSERT(m_index < m_source->tokenCount());
    return look(0);
}

Token Parser::look(int i) const
{
    int index = m_index + i;
    Q_ASSERT(m_index >= 0);
    if (index >= m_source->tokenCount())
        return Token();
    return m_source->tokenAt(index);
}

bool Parser::expect(Token tok, TokenType type) const
{
    if (tok.type == type)
        return true;
    m_source->error(tok, "expecting " + typeToString(type) + " for " + m_context.top());
    return false;
}

bool Parser::checkLeadingWhitespace(const Token& tok)
{
    if (m_indent == Tabs) {
        m_source->error(tok, "unexpected ' ' when already using '\\t' for indentation");
        return false;
    }
    m_indent = Spaces;
    int spacesForIndent = tok.end.column - tok.start.column + 1;
    if (!m_originalSpacesForIndent) {
        m_originalSpacesForIndent = spacesForIndent;
    } else if (spacesForIndent % m_originalSpacesForIndent != 0) {
        m_source->error(tok, "number of spaces in indentation level is not divisable by " + QString::number(m_originalSpacesForIndent));
        return false;
    }
    m_scope = spacesForIndent / m_originalSpacesForIndent;
    return true;
}

bool Parser::checkLeadingTab(const Token& tok)
{
    if (m_indent == Spaces) {
        m_source->error(tok, "unexpected '\\t' when already using ' ' for indentation");
        return false;
    }
    m_indent = Tabs;
    m_scope = tok.end.column - tok.start.column + 1;
    return true;
}

// type foo : (b1:bar(, b2:baz)?)
void Parser::parseTypeDecl()
{
    ParserContext context(this, "type declaration");

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Identifier))
        return;

    Token name = tok;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Colon))
        return;

    QList<QSharedPointer<TypeObject> > objects;
    if (look(1).type == Whitespace && look(2).type == OpenParenthesis)
        objects = parseTypeObjects();

    tok = advance(1);
    if (!expect(tok, Newline))
        return;

    TypeDecl* decl = new TypeDecl;
    decl->name = name;
    decl->objects = objects;

    if (!m_source->symbols().addType(*decl))
        return;

    m_source->translationUnit().typeDecl.append(QSharedPointer<TypeDecl>(decl));
}

// function foo : (foo:Foo?, bar:Bar?, ...)? ->? Baz
void Parser::parseFuncDecl()
{
    ParserContext context(this, "function declaration");

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Identifier))
        return;

    Token name = tok;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Colon))
        return;

    QList<QSharedPointer<TypeObject> > objects;
    if (look(1).type == Whitespace && look(2).type == OpenParenthesis)
        objects = parseTypeObjects();

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Minus))
        return;

    tok = advance(1);
    if (!expect(tok, GreaterThan))
        return;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return;

    tok = advance(1);
    if (!expect(tok, Identifier))
        return;

    Token returnType = tok;

    tok = advance(1);
    if (!expect(tok, Newline))
        return;

    FuncDef* funcDef = parseFuncDef();
    if (!funcDef)
        return;

    FuncDecl* decl = new FuncDecl;
    decl->name = name;
    decl->objects = objects;
    decl->funcDef = QSharedPointer<FuncDef>(funcDef);
    decl->returnType = returnType;

    if (!m_source->symbols().addFunction(*decl))
        return;

    m_source->translationUnit().funcDecl.append(QSharedPointer<FuncDecl>(decl));
}

QList<QSharedPointer<TypeObject> > Parser::parseTypeObjects()
{
    bool unnamedTypeObject = false;
    QList<QSharedPointer<TypeObject> > objects;
    Token tok = advance(3);
    Token first = tok;
    if (tok.type == Identifier) {
        while(TypeObject* object = parseTypeObject()) {
            if (object->name.type == Undefined)
                unnamedTypeObject = true;
            objects.append(QSharedPointer<TypeObject>(object));
        }
    }

    tok = current();
    if (!expect(tok, CloseParenthesis))
        return QList<QSharedPointer<TypeObject> >();

    if (unnamedTypeObject && objects.size() > 1) {
        m_source->error(first, "a type object list must consist of named objects or only one unnamed object");
        return QList<QSharedPointer<TypeObject> >();
    }

    return objects;
}

TypeObject* Parser::parseTypeObject()
{
    ParserContext context(this, "type object");

    Token tok = current();
    if (tok.type == Comma) {
        tok = advance(1);
        if (!expect(tok, Whitespace))
            return 0;
        tok = advance(1);
    } else if (tok.type == CloseParenthesis)
        return 0;

    if (!expect(tok, Identifier))
        return 0;

    Token identifier1 = tok;
    Token identifier2;

    if (look(1).type == Colon) {
        tok = advance(2);
        if (!expect(tok, Identifier))
            return 0;

        identifier2 = tok;
    }

    advance(1);

    TypeObject* arg = new TypeObject;
    arg->name = identifier2.type == Undefined ? Token() : identifier1;
    arg->type = identifier2.type == Identifier ? identifier2 : identifier1;
    return arg;
}

FuncDef* Parser::parseFuncDef()
{
    ParserContext context(this, "function definition");
    IndentLevel indent(this);

    QList<QSharedPointer<Stmt> > stmts;
    while (Stmt* stmt = parseStmt())
        stmts.append(QSharedPointer<Stmt>(stmt));

    if (stmts.isEmpty()) {
        m_source->error(current(), "function must define at least one statement");
        return 0;
    }

    FuncDef* funcDef = new FuncDef;
    funcDef->stmts = stmts;
    return funcDef;
}

bool Parser::parseIndent(unsigned expected)
{
    if (look(1).type != Whitespace && look(1).type != Tab)
        return false;

    Token tok = advance(1);
    if (tok.type == Whitespace && !checkLeadingWhitespace(tok))
        return false;
    else if (tok.type == Tab && !checkLeadingTab(tok))
        return false;

    if (m_scope != expected) {
        m_source->error(tok, "indentation level is incorrect");
        return false;
    }

    return true;
}

Expr* Parser::parseExpr()
{
    ParserContext context(this, "expression");

    Expr* lhs = parseBasicExpr();
    if (!lhs)
        return 0;

    Expr* rhs = parseBinaryOpExpr(0, lhs);
    if (!rhs)
        return 0;

    while (rhs && lhs != rhs) {
        lhs = rhs;
        rhs = parseBinaryOpExpr(0, lhs);
    }

    return rhs;
}

Expr* Parser::parseBasicExpr()
{
    ParserContext context(this, "basic expression");

    Token tok = advance(1);
    Expr* expr = 0;
    switch (tok.type) {
    case Identifier:
        if (look(1).type == OpenParenthesis)
            expr = parseFuncCallExpr();
        else
            expr = parseVarExpr();
        break;
    case Digits:
        expr = parseLiteralExpr();
        break;
    default:
        break;
    };

    if (expr)
        expr->start = tok;
    return expr;
}

Expr* Parser::parseBinaryOpExpr(int precedence, Expr* lhs)
{
    if (look(1).type != Whitespace)
        return lhs;

    Token tok = advance(2);

    BinaryExpr::BinaryOp op;
    bool foundBinaryOp = false;

    if (tok.type == Equals && look(1).type == Equals
        && precedence <= 1) {
        op = BinaryExpr::OpEquality;
        tok = advance(2);
        foundBinaryOp = true;
    } else if ((tok.type == LessThan || tok.type == GreaterThan)
        && look(1).type == Equals
        && precedence <= 1) {
        op = tok.type == LessThan ? BinaryExpr::OpLessThanOrEquality : BinaryExpr::OpGreaterThanOrEquality;
        tok = advance(2);
        foundBinaryOp = true;
    } else if ((tok.type == LessThan || tok.type == GreaterThan)
        && precedence <= 1) {
        op = tok.type == LessThan ? BinaryExpr::OpLessThan : BinaryExpr::OpGreaterThan;
        tok = advance(1);
        foundBinaryOp = true;
    } else if ((tok.type == Plus || tok.type == Minus)
        && precedence <= 2) {
        op = tok.type == Plus ? BinaryExpr::OpAddition : BinaryExpr::OpSubtraction;
        tok = advance(1);
        foundBinaryOp = true;
    } else if ((tok.type == Star || tok.type == Slash)
        && precedence <= 3) {
        op = tok.type == Star ? BinaryExpr::OpMultiplication : BinaryExpr::OpDivision;
        tok = advance(1);
        foundBinaryOp = true;
    }

    if (!foundBinaryOp)
        return lhs;

    if (!expect(tok, Whitespace))
        return 0;

    Expr* rhs = parseBasicExpr();
    if (!rhs)
        return 0;

    BinaryExpr* binaryExpr = new BinaryExpr;
    binaryExpr->op = op;
    binaryExpr->lhs = QSharedPointer<Expr>(lhs);
    binaryExpr->rhs = QSharedPointer<Expr>(rhs);
    return binaryExpr;
}

VarExpr* Parser::parseVarExpr()
{
    ParserContext context(this, "variable expression");

    Token var = current();

    VarExpr* varExpr = new VarExpr;
    varExpr->var = var;
    return varExpr;
}

LiteralExpr* Parser::parseLiteralExpr()
{
    ParserContext context(this, "literal expression");

    Token literal = current();

    LiteralExpr* literalExpr = new LiteralExpr;
    literalExpr->literal = literal;
    return literalExpr;
}

Stmt* Parser::parseStmt()
{
    ParserContext context(this, "statement");

    if (current().type == Newline && !parseIndent(m_expectedScope))
        return 0;

    if (m_index == m_source->tokenCount() - 1)
        return 0;

    Stmt* stmt = 0;
    Token tok = advance(1);
    switch (tok.type) {
    case If:
        stmt = parseIfStmt(); break;
    case Return:
        stmt = parseReturnStmt(); break;
    case Identifier:
        stmt = parseVarDeclStmt(); break;
    default:
        return 0;
    };

    return stmt;
}

IfStmt* Parser::parseIfStmt()
{
    ParserContext context(this, "if statement");

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    tok = advance(1);
    if (!expect(tok, OpenParenthesis))
        return 0;

    Expr* expr = parseExpr();
    if (!expr)
        return 0;

    tok = advance(1);
    if (!expect(tok, CloseParenthesis))
        return 0;

    tok = advance(1);

    IndentLevel indent(this);
    Stmt* stmt = parseStmt();
    if (!stmt) {
        m_source->error(tok, "no statement following condition");
        return 0;
    }

    IfStmt* ifStmt = new IfStmt;
    ifStmt->expr = QSharedPointer<Expr>(expr);
    ifStmt->stmt = QSharedPointer<Stmt>(stmt);
    return ifStmt;
}

ReturnStmt* Parser::parseReturnStmt()
{
    ParserContext context(this, "return statement");

    Token keyword = current();

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    Expr* expr = parseExpr();
    if (!expr)
        return 0;

    if (m_index < m_source->tokenCount() - 1) {
        tok = advance(1);
        if (!expect(tok, Newline))
            return 0;
    }

    ReturnStmt* returnStmt = new ReturnStmt;
    returnStmt->keyword = keyword;
    returnStmt->expr = QSharedPointer<Expr>(expr);
    return returnStmt;
}

FuncCallExpr* Parser::parseFuncCallExpr()
{
    ParserContext context(this, "function call expression");

    Token callee = current();

    Token tok = advance(1);
    if (!expect(tok, OpenParenthesis))
        return 0;

    QList<QSharedPointer<Expr> > args;
    while(Expr* expr = parseExpr())
        args.append(QSharedPointer<Expr>(expr));

    tok = current();
    if (!expect(tok, CloseParenthesis))
        return 0;

    FuncCallExpr* funcCallExpr = new FuncCallExpr;
    funcCallExpr->callee = callee;
    funcCallExpr->args = args;
    return funcCallExpr;
}

VarDeclStmt* Parser::parseVarDeclStmt()
{
    ParserContext context(this, "variable declaration statement");

    Token type = current();

    Token tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    tok = advance(1);
    if (!expect(tok, Identifier))
        return 0;

    Token name = tok;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    tok = advance(1);
    if (!expect(tok, Equals))
        return 0;

    tok = advance(1);
    if (!expect(tok, Whitespace))
        return 0;

    tok = look(1);
    Expr* expr = parseExpr();
    if (!expr) {
        m_source->error(tok, "expected expression for variable initialization");
        return 0;
    }

    tok = advance(1);
    if (!expect(tok, Newline))
        return 0;

    VarDeclStmt* varDeclStmt = new VarDeclStmt;
    varDeclStmt->type = type;
    varDeclStmt->name = name;
    varDeclStmt->expr = QSharedPointer<Expr>(expr);
    return varDeclStmt;
}
<|endoftext|>


<commit_before>#include <sge/mainloop.hpp>

using namespace std;

namespace sge
{
    template<typename T, typename... U>
    static bool functions_equal(function<T(U...)> a, function<T(U...)> b)
    {
        typedef T(*fptr)(U...);
        fptr **pa = a.template target<fptr*>();
        fptr **pb = b.template target<fptr*>();

        return (*pa) == (*pb);
    }

    SGEMainLoop::SGEMainLoop(int fps) : running(false), fps(fps)
    {}

    void SGEMainLoop::add_event_watcher(EventHandler handler)
    {
        evtwatchers.push_back(std::move(handler));
    }

    void SGEMainLoop::remove_event_watcher(EventHandler handler)
    {
        for (auto it = evtwatchers.begin(); it != evtwatchers.end(); it++)
        {
            if (functions_equal(get<0>(*it), handler))
            {
                evtwatchers.erase(it);
                break;
            }
        }
    }

    void SGEMainLoop::queue_event_handler(Uint32 evtype, EventHandler handler)
    {
        events[evtype].push_back(std::move(handler));
    }

    void SGEMainLoop::dequeue_event_handler(Uint32 evtype, EventHandler handler)
    {
        if (events.find(evtype) != events.end())
        {
            auto handlers = events[evtype];

            for (auto it = handlers.begin(); it != handlers.end(); it++)
            {
                if (functions_equal(get<0>(*it), handler))
                {
                    handlers.erase(it);
                    break;
                }
            }
        }
    }

    void SGEMainLoop::queue_process_handler(ProcessHandler handler)
    {
        SGETimer timer;
        timer.start();

        processing.push_back(std::make_tuple(std::move(handler), std::move(timer)));
    }

    void SGEMainLoop::dequeue_process_handler(ProcessHandler handler)
    {
        for (auto it = processing.begin(); it != processing.end(); it++)
        {
            if (functions_equal(get<0>(*it), handler))
            {
                processing.erase(it);
                break;
            }
        }
    }

    void SGEMainLoop::queue_draw_handler(DrawHandler handler)
    {
        drawing.push_back(DrawEntry(handler));
    }

    void SGEMainLoop::dequeue_draw_handler(DrawHandler handler)
    {
        for (auto it = drawing.begin(); it != drawing.end(); it++)
        {
            if (functions_equal(get<0>(*it), handler))
            {
                drawing.erase(it);
                break;
            }
        }
    }

    void SGEMainLoop::run()
    {
        running = true;

        while (running)
        {
            fps_timer.start();

            SDL_Event event;
            while (SDL_PollEvent(&event))
            {
                bool accepted = true;

                for (auto it = evtwatchers.begin(); it != evtwatchers.end(); it++)
                {
                    auto handler = get<0>(*it);

                    if(!handler(this, &event))
                    {
                        accepted = false;
                        break;
                    }
                }

                if (accepted && events.find(event.type) != events.end())
                {
                    auto handlers = events[event.type];

                    for (auto it = handlers.begin(); it != handlers.end(); it++)
                    {
                        auto handler = get<0>(*it);

                        if (!handler(this, &event))
                        {
                            break;
                        }
                    }
                }
            }

            for (auto it = processing.begin(); it != processing.end(); it++)
            {
                auto handler = get<0>(*it);
                auto timer = get<1>(*it);

                handler(this, timer.get_ticks());
                timer.start();
            }

            for (auto it = drawing.begin(); it != drawing.end(); it++)
            {
                auto handler = get<0>(*it);

                handler(this);
            }

            Uint32 ticks = fps_timer.get_ticks();
            if (fps > 0 && ticks < 1000.0 / fps)
            {
                SDL_Delay((1000.0 / fps) - ticks);
            }
        }
    }

    void SGEMainLoop::quit()
    {
        running = false;
    }
}
<commit_msg>Use for-range<commit_after>#include <sge/mainloop.hpp>

using namespace std;

namespace sge
{
    template<typename T, typename... U>
    static bool functions_equal(function<T(U...)> a, function<T(U...)> b)
    {
        typedef T(*fptr)(U...);
        fptr **pa = a.template target<fptr*>();
        fptr **pb = b.template target<fptr*>();

        return (*pa) == (*pb);
    }

    SGEMainLoop::SGEMainLoop(int fps) : running(false), fps(fps)
    {}

    void SGEMainLoop::add_event_watcher(EventHandler handler)
    {
        evtwatchers.push_back(std::move(handler));
    }

    void SGEMainLoop::remove_event_watcher(EventHandler handler)
    {
        for (auto it = evtwatchers.begin(); it != evtwatchers.end(); it++)
        {
            if (functions_equal(get<0>(*it), handler))
            {
                evtwatchers.erase(it);
                break;
            }
        }
    }

    void SGEMainLoop::queue_event_handler(Uint32 evtype, EventHandler handler)
    {
        events[evtype].push_back(std::move(handler));
    }

    void SGEMainLoop::dequeue_event_handler(Uint32 evtype, EventHandler handler)
    {
        if (events.find(evtype) != events.end())
        {
            auto handlers = events[evtype];

            for (auto it = handlers.begin(); it != handlers.end(); it++)
            {
                if (functions_equal(get<0>(*it), handler))
                {
                    handlers.erase(it);
                    break;
                }
            }
        }
    }

    void SGEMainLoop::queue_process_handler(ProcessHandler handler)
    {
        SGETimer timer;
        timer.start();

        processing.push_back(std::make_tuple(std::move(handler), std::move(timer)));
    }

    void SGEMainLoop::dequeue_process_handler(ProcessHandler handler)
    {
        for (auto it = processing.begin(); it != processing.end(); it++)
        {
            if (functions_equal(get<0>(*it), handler))
            {
                processing.erase(it);
                break;
            }
        }
    }

    void SGEMainLoop::queue_draw_handler(DrawHandler handler)
    {
        drawing.push_back(DrawEntry(handler));
    }

    void SGEMainLoop::dequeue_draw_handler(DrawHandler handler)
    {
        for (auto it = drawing.begin(); it != drawing.end(); it++)
        {
            if (functions_equal(get<0>(*it), handler))
            {
                drawing.erase(it);
                break;
            }
        }
    }

    void SGEMainLoop::run()
    {
        running = true;

        while (running)
        {
            fps_timer.start();

            SDL_Event event;
            while (SDL_PollEvent(&event))
            {
                bool accepted = true;

                for (auto &it : evtwatchers)
                {
                    auto handler = get<0>(it);

                    if(!handler(this, &event))
                    {
                        accepted = false;
                        break;
                    }
                }

                if (accepted && events.find(event.type) != events.end())
                {
                    auto handlers = events[event.type];

                    for (auto &it : handlers)
                    {
                        auto handler = get<0>(it);

                        if (!handler(this, &event))
                        {
                            break;
                        }
                    }
                }
            }

            for (auto &it : processing)
            {
                auto handler = get<0>(it);
                auto timer = get<1>(it);

                handler(this, timer.get_ticks());
                timer.start();
            }

            for (auto &it : drawing)
            {
                auto handler = get<0>(it);

                handler(this);
            }

            Uint32 ticks = fps_timer.get_ticks();
            if (fps > 0 && ticks < 1000.0 / fps)
            {
                SDL_Delay((1000.0 / fps) - ticks);
            }
        }
    }

    void SGEMainLoop::quit()
    {
        running = false;
    }
}
<|endoftext|>


<commit_before>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read galaxies
	Gals G;
    if(F.Ascii){
        G=read_galaxies_ascii(F);}
    else{
        G = read_galaxies(F);
    }
	F.Ngal = G.size();
	printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.galFile.c_str());
    std::vector<int> count;
    count=count_galaxies(G);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    // make MTL
    //MTL Min=make_MTL(G,F);
    //write_MTLfile(Min);
    MTL M=read_MTLfile(F);
    assign_priority_class(M);
    //find available SS and SF galaxies on each petal

    std::vector <int> count_class(M.priority_list.size(),0);

    printf("Number in each priority class.  The last two are SF and SS.\n");
    for(int i;i<M.size();++i){
        count_class[M[i].priority_class]+=1;
    }
    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

    printf(" number of MTL galaxies  %d\n",M.size());

	PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);
	Plates P = read_plate_centers(F);
    F.Nplate=P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel  P[plate j].av_gal[k]=[g1,g2,..]
	collect_galaxies_for_all(M,T,P,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
	Assignment A(M,F);
	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
	//new_assign_fibers(G,P,pp,F,A); // Plans whole survey without sky fibers, standard stars
                                   // assumes maximum number of observations needed for QSOs, LRGs
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);

    simple_assign(M,P,pp,F,A);
     if(F.diagnose)diagnostic(M,G,F,A);
    //diagnostic 11/7/15
    for(int j=0;j<F.Nplate;++j{
        int count_assiged=0;
        for (int k=0;k<F.Nfiber;++k){
            if(TF[j][k]!=-1)count_assiged++;
        }
        printf(" j = %d  number assigned = %d \n",j count_assiged);
    }

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs
                                    // Want to have even distribution of unused fibers
                                    // so we can put in sky fibers and standard stars

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<3; i++) {                           // more iterations will improve performance slightly
		improve(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
	}
	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.Nplate;++j){
        A.next_plate=j;
        assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF just before an observation
        assign_unused(j,M,P,pp,F,A);
    }

    init_time_at(time,"# Begin real time assignment",t);

	// Still not updated, so all QSO targets have multiple observations etc
	// Apply and update the plan --------------------------------------

    for(int i=0;i<F.pass_intervals.size();++i){
        printf(" before pass = %d  at %d  tiles\n",i,F.pass_intervals[i]);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //execute this phase (i) of survey
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.Nplate&&jj<F.Nplate; jj++) {
            int j = A.next_plate;
            ///printf(" - Plate %d :\n",j);
            //printf(" %s not assigned - ",format(5,f(A.unused_f(j,F))).c_str()); fl();
            assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF just before an observation

            assign_unused(j,M,P,pp,F,A);

            A.next_plate++;
        }
        //update target information for this interval
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.pass_intervals[i+1]&&jj<F.Nplate; jj++) {
            int j = A.next_plate;

            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=j-F.Analysis) update_plan_from_one_obs(G,M,P,pp,F,A,F.Nplate-1); else printf("\n");
            A.next_plate++;
        }
        if(A.next_plate<F.Nplate){
        redistribute_tf(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        improve(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        }
        diagnostic(M,G,F,A);
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.Nplate; j++){
        write_FAtile_ascii(j,F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.Nplate; j++){
        fa_write(j,F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",G,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<commit_msg>diagnostic<commit_after>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read galaxies
	Gals G;
    if(F.Ascii){
        G=read_galaxies_ascii(F);}
    else{
        G = read_galaxies(F);
    }
	F.Ngal = G.size();
	printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.galFile.c_str());
    std::vector<int> count;
    count=count_galaxies(G);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    // make MTL
    //MTL Min=make_MTL(G,F);
    //write_MTLfile(Min);
    MTL M=read_MTLfile(F);
    assign_priority_class(M);
    //find available SS and SF galaxies on each petal

    std::vector <int> count_class(M.priority_list.size(),0);

    printf("Number in each priority class.  The last two are SF and SS.\n");
    for(int i;i<M.size();++i){
        count_class[M[i].priority_class]+=1;
    }
    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

    printf(" number of MTL galaxies  %d\n",M.size());

	PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);
	Plates P = read_plate_centers(F);
    F.Nplate=P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel  P[plate j].av_gal[k]=[g1,g2,..]
	collect_galaxies_for_all(M,T,P,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
	Assignment A(M,F);
	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
	//new_assign_fibers(G,P,pp,F,A); // Plans whole survey without sky fibers, standard stars
                                   // assumes maximum number of observations needed for QSOs, LRGs
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);

    simple_assign(M,P,pp,F,A);
     if(F.diagnose)diagnostic(M,G,F,A);
    //diagnostic 11/7/15
    for(int j=0;j<F.Nplate;++j{
        int count_assiged=0;
        for (int k=0;k<F.Nfiber;++k){
            if(A.TF[j][k]!=-1)count_assiged++;
        }
        printf(" j = %d  number assigned = %d \n",j, count_assiged);
    }

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs
                                    // Want to have even distribution of unused fibers
                                    // so we can put in sky fibers and standard stars

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<3; i++) {                           // more iterations will improve performance slightly
		improve(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
	}
	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.Nplate;++j){
        A.next_plate=j;
        assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF just before an observation
        assign_unused(j,M,P,pp,F,A);
    }

    init_time_at(time,"# Begin real time assignment",t);

	// Still not updated, so all QSO targets have multiple observations etc
	// Apply and update the plan --------------------------------------

    for(int i=0;i<F.pass_intervals.size();++i){
        printf(" before pass = %d  at %d  tiles\n",i,F.pass_intervals[i]);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //execute this phase (i) of survey
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.Nplate&&jj<F.Nplate; jj++) {
            int j = A.next_plate;
            ///printf(" - Plate %d :\n",j);
            //printf(" %s not assigned - ",format(5,f(A.unused_f(j,F))).c_str()); fl();
            assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF just before an observation

            assign_unused(j,M,P,pp,F,A);

            A.next_plate++;
        }
        //update target information for this interval
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.pass_intervals[i+1]&&jj<F.Nplate; jj++) {
            int j = A.next_plate;

            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=j-F.Analysis) update_plan_from_one_obs(G,M,P,pp,F,A,F.Nplate-1); else printf("\n");
            A.next_plate++;
        }
        if(A.next_plate<F.Nplate){
        redistribute_tf(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        improve(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        }
        diagnostic(M,G,F,A);
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.Nplate; j++){
        write_FAtile_ascii(j,F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.Nplate; j++){
        fa_write(j,F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",G,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<|endoftext|>


<commit_before>#include "webcam.hpp"

using namespace cv;
using namespace std;

int main (int argc, char** argv) {

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
  imshow("webcam", image);

// thresholds on dark regions

  Mat black, blurred;
  split(image, channel);
  merge(channel, 3, black);
  blur(black, blurred, Size(width/4.5,height/9));
  split(blurred, channel);
  black = (channel[0] + channel[1] + channel[2])/3.0;
  equalizeHist(black, black);
  bitwise_not(black,black);

  adaptiveThreshold(black, image, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 19, 0);
  imshow("ha", image);

  threshold(black, black, 220, 255, THRESH_BINARY);
  imshow("black", black);

/*
  split(image, channel);
  channel[0] = channel[0].mul(black);
  channel[1] = channel[1].mul(black);
  channel[2] = channel[2].mul(black);
  merge(channel, 3, image);
*/
//  imshow("yox", image);

//do some weird morphological closing thing
//  Mat channel[3];

/*
  Mat canny;
  Canny(image, canny, 0, 50);
  imshow("canny", canny);
*/

/*
  Mat fill = image.clone();
  Point seed(rand()%width, rand()%height);
  floodFill(fill, seed, Scalar(200,0,0), 0, Scalar(0,0,0), Scalar(25,25,25));
  imshow("fill", fill);
*/

  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<commit_msg>hacking<commit_after>#include "webcam.hpp"

using namespace cv;
using namespace std;

int main (int argc, char** argv) {

 CvCapture* capture = 0;
 int width, height, fps;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream configFile (".config");

 if (configFile.is_open()) {

  //probably want to support corrupted .config
  string line;
  getline(configFile, line);
  istringstream(line)>>width;
  getline(configFile, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  configFile.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream configFileOut(".config");
  configFileOut << width;
  configFileOut << "\n";
  configFileOut << height;
  configFileOut << "\n";
  configFileOut.close();
 }

 bool keepGoing = true;

// srand(890);//not interested in good randomness

 Mat image;
 Mat channel[3];

 while (keepGoing) {

  image = cvQueryFrame(capture);
  imshow("webcam", image);

// thresholds on dark regions

  Mat black, blurred;
  split(image, channel);
//  merge(channel, 3, black);
//  blur(black, blurred, Size(width/4.5,height/9));
//  split(blurred, channel);
  black = (channel[0] + channel[1] + channel[2])/3.0;
  equalizeHist(black, black);
  bitwise_not(black,black);

  adaptiveThreshold(black, black, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 19, 0);
  imshow("ha", black);

  threshold(black, black, 220, 255, THRESH_BINARY);
  imshow("black", black);

/*
  split(image, channel);
  channel[0] = channel[0].mul(black);
  channel[1] = channel[1].mul(black);
  channel[2] = channel[2].mul(black);
  merge(channel, 3, image);
*/
//  imshow("yox", image);

//do some weird morphological closing thing
//  Mat channel[3];

/*
  Mat canny;
  Canny(image, canny, 0, 50);
  imshow("canny", canny);
*/

/*
  Mat fill = image.clone();
  Point seed(rand()%width, rand()%height);
  floodFill(fill, seed, Scalar(200,0,0), 0, Scalar(0,0,0), Scalar(25,25,25));
  imshow("fill", fill);
*/

  keepGoing = (waitKey(25)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2017 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_OS_OBJECT_ACCESSOR_IMPL_HPP
#define REALM_OS_OBJECT_ACCESSOR_IMPL_HPP

#include "object_accessor.hpp"

#include "util/any.hpp"

namespace realm {
using AnyDict = std::map<std::string, util::Any>;
using AnyVector = std::vector<util::Any>;

// An object accessor context which can be used to create and access objects
// using util::Any as the type-erased value type. In addition, this serves as
// the reference implementation of an accessor context that must be implemented
// by each binding.
class CppContext {
public:
    // This constructor is the only one used by the object accessor code, and is
    // used when recurring into a link or array property during object creation
    // (i.e. prop.type will always be Object or Array).
    CppContext(CppContext& c, Property const& prop)
    : realm(c.realm)
    , object_schema(&*realm->schema().find(prop.object_type))
    { }

    CppContext() = default;
    CppContext(std::shared_ptr<Realm> realm, const ObjectSchema* os=nullptr)
    : realm(std::move(realm)), object_schema(os) { }

    // The use of util::Optional for the following two functions is not a hard
    // requirement; only that it be some type which can be evaluated in a
    // boolean context to determine if it contains a value, and if it does
    // contain a value it must be dereferencable to obtain that value.

    // Get the value for a property in an input object, or `util::none` if no
    // value present. The property is identified both by the name of the
    // property and its index within the ObjectScehma's persisted_properties
    // array.
    util::Optional<util::Any> value_for_property(util::Any& dict,
                                                 std::string const& prop_name,
                                                 size_t /* property_index */) const
    {
        auto const& v = any_cast<AnyDict&>(dict);
        auto it = v.find(prop_name);
        return it == v.end() ? util::none : util::make_optional(it->second);
    }

    // Get the default value for the given property in the given object schema,
    // or `util::none` if there is none (which is distinct from the default
    // being `null`).
    //
    // This implementation does not support default values; see the default
    // value tests for an example of one which does.
    util::Optional<util::Any>
    default_value_for_property(ObjectSchema const&, std::string const&) const
    {
        return util::none;
    }

    // Invoke `fn` with each of the values from an enumerable type
    template<typename Func>
    void enumerate_list(util::Any& value, Func&& fn) {
        for (auto&& v : any_cast<AnyVector&>(value))
            fn(v);
    }

    // Convert from core types to the boxed type
    util::Any box(BinaryData v) const { return std::string(v); }
    util::Any box(List v) const { return v; }
    util::Any box(Object v) const { return v; }
    util::Any box(Results v) const { return v; }
    util::Any box(StringData v) const { return std::string(v); }
    util::Any box(Timestamp v) const { return v; }
    util::Any box(bool v) const { return v; }
    util::Any box(double v) const { return v; }
    util::Any box(float v) const { return v; }
    util::Any box(long long v) const { return v; }
    util::Any box(RowExpr) const;

    // Any properties are only supported by the Cocoa binding to enable reading
    // old Realm files that may have used them. Other bindings can safely not
    // implement this.
    util::Any box(Mixed) const { REALM_TERMINATE("not supported"); }

    // Convert from the boxed type to core types. This needs to be implemented
    // for all of the types which `box()` can take, plus `RowExpr` and optional
    // versions of the numeric types, minus `List` and `Results`.
    //
    // `create` and `update` are only applicable to `unbox<RowExpr>`. If
    // `create` is false then when given something which is not a managed Realm
    // object `unbox()` should simply return a detached row expr, while if it's
    // true then `unbox()` should create a new object in the context's Realm
    // using the provided value. If `update` is true then upsert semantics
    // should be used for this.
    template<typename T>
    T unbox(util::Any& v, bool /*create*/= false, bool /*update*/= false) const { return any_cast<T>(v); }

    bool is_null(util::Any const& v) const noexcept { return !v.has_value(); }
    util::Any null_value() const noexcept { return {}; }
    util::Optional<util::Any> no_value() const noexcept { return {}; }

    // KVO hooks which will be called before and after modying a property from
    // within Object::create().
    void will_change(Object const&, Property const&) {}
    void did_change() {}

    // Get a string representation of the given value for use in error messages.
    std::string print(util::Any const&) const { return "not implemented"; }

    // Cocoa allows supplying fewer values than there are properties when
    // creating objects using an array of values. Other bindings should not
    // mimick this behavior so just return false here.
    bool allow_missing(util::Any const&) const { return false; }

private:
    std::shared_ptr<Realm> realm;
    const ObjectSchema* object_schema = nullptr;

};

inline util::Any CppContext::box(RowExpr row) const
{
    return Object(realm, *object_schema, row);
}

template<>
inline StringData CppContext::unbox(util::Any& v, bool, bool) const
{
    if (!v.has_value())
        return StringData();
    auto value = any_cast<std::string&>(v);
    return StringData(value.c_str(), value.size());
}

template<>
inline BinaryData CppContext::unbox(util::Any& v, bool, bool) const
{
    if (!v.has_value())
        return BinaryData();
    auto value = any_cast<std::string&>(v);
    return BinaryData(value.c_str(), value.size());
}

template<>
inline RowExpr CppContext::unbox(util::Any& v, bool create, bool update) const
{
    if (auto object = any_cast<Object>(&v))
        return object->row();
    if (auto row = any_cast<RowExpr>(&v))
        return *row;
    if (!create)
        return RowExpr();

    REALM_ASSERT(object_schema);
    return Object::create(const_cast<CppContext&>(*this), realm, *object_schema, v, update).row();
}

template<>
inline util::Optional<bool> CppContext::unbox(util::Any& v, bool, bool) const
{
    return v.has_value() ? util::make_optional(unbox<bool>(v)) : util::none;
}

template<>
inline util::Optional<int64_t> CppContext::unbox(util::Any& v, bool, bool) const
{
    return v.has_value() ? util::make_optional(unbox<int64_t>(v)) : util::none;
}

template<>
inline util::Optional<double> CppContext::unbox(util::Any& v, bool, bool) const
{
    return v.has_value() ? util::make_optional(unbox<double>(v)) : util::none;
}

template<>
inline util::Optional<float> CppContext::unbox(util::Any& v, bool, bool) const
{
    return v.has_value() ? util::make_optional(unbox<float>(v)) : util::none;
}

template<>
inline Mixed CppContext::unbox(util::Any&, bool, bool) const
{
    throw std::logic_error("'Any' type is unsupported");
}
}

#endif // REALM_OS_OBJECT_ACCESSOR_IMPL_HPP
<commit_msg>Fix unboxing string and binary values in CppContext<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2017 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_OS_OBJECT_ACCESSOR_IMPL_HPP
#define REALM_OS_OBJECT_ACCESSOR_IMPL_HPP

#include "object_accessor.hpp"

#include "util/any.hpp"

namespace realm {
using AnyDict = std::map<std::string, util::Any>;
using AnyVector = std::vector<util::Any>;

// An object accessor context which can be used to create and access objects
// using util::Any as the type-erased value type. In addition, this serves as
// the reference implementation of an accessor context that must be implemented
// by each binding.
class CppContext {
public:
    // This constructor is the only one used by the object accessor code, and is
    // used when recurring into a link or array property during object creation
    // (i.e. prop.type will always be Object or Array).
    CppContext(CppContext& c, Property const& prop)
    : realm(c.realm)
    , object_schema(&*realm->schema().find(prop.object_type))
    { }

    CppContext() = default;
    CppContext(std::shared_ptr<Realm> realm, const ObjectSchema* os=nullptr)
    : realm(std::move(realm)), object_schema(os) { }

    // The use of util::Optional for the following two functions is not a hard
    // requirement; only that it be some type which can be evaluated in a
    // boolean context to determine if it contains a value, and if it does
    // contain a value it must be dereferencable to obtain that value.

    // Get the value for a property in an input object, or `util::none` if no
    // value present. The property is identified both by the name of the
    // property and its index within the ObjectScehma's persisted_properties
    // array.
    util::Optional<util::Any> value_for_property(util::Any& dict,
                                                 std::string const& prop_name,
                                                 size_t /* property_index */) const
    {
        auto const& v = any_cast<AnyDict&>(dict);
        auto it = v.find(prop_name);
        return it == v.end() ? util::none : util::make_optional(it->second);
    }

    // Get the default value for the given property in the given object schema,
    // or `util::none` if there is none (which is distinct from the default
    // being `null`).
    //
    // This implementation does not support default values; see the default
    // value tests for an example of one which does.
    util::Optional<util::Any>
    default_value_for_property(ObjectSchema const&, std::string const&) const
    {
        return util::none;
    }

    // Invoke `fn` with each of the values from an enumerable type
    template<typename Func>
    void enumerate_list(util::Any& value, Func&& fn) {
        for (auto&& v : any_cast<AnyVector&>(value))
            fn(v);
    }

    // Convert from core types to the boxed type
    util::Any box(BinaryData v) const { return std::string(v); }
    util::Any box(List v) const { return v; }
    util::Any box(Object v) const { return v; }
    util::Any box(Results v) const { return v; }
    util::Any box(StringData v) const { return std::string(v); }
    util::Any box(Timestamp v) const { return v; }
    util::Any box(bool v) const { return v; }
    util::Any box(double v) const { return v; }
    util::Any box(float v) const { return v; }
    util::Any box(long long v) const { return v; }
    util::Any box(RowExpr) const;

    // Any properties are only supported by the Cocoa binding to enable reading
    // old Realm files that may have used them. Other bindings can safely not
    // implement this.
    util::Any box(Mixed) const { REALM_TERMINATE("not supported"); }

    // Convert from the boxed type to core types. This needs to be implemented
    // for all of the types which `box()` can take, plus `RowExpr` and optional
    // versions of the numeric types, minus `List` and `Results`.
    //
    // `create` and `update` are only applicable to `unbox<RowExpr>`. If
    // `create` is false then when given something which is not a managed Realm
    // object `unbox()` should simply return a detached row expr, while if it's
    // true then `unbox()` should create a new object in the context's Realm
    // using the provided value. If `update` is true then upsert semantics
    // should be used for this.
    template<typename T>
    T unbox(util::Any& v, bool /*create*/= false, bool /*update*/= false) const { return any_cast<T>(v); }

    bool is_null(util::Any const& v) const noexcept { return !v.has_value(); }
    util::Any null_value() const noexcept { return {}; }
    util::Optional<util::Any> no_value() const noexcept { return {}; }

    // KVO hooks which will be called before and after modying a property from
    // within Object::create().
    void will_change(Object const&, Property const&) {}
    void did_change() {}

    // Get a string representation of the given value for use in error messages.
    std::string print(util::Any const&) const { return "not implemented"; }

    // Cocoa allows supplying fewer values than there are properties when
    // creating objects using an array of values. Other bindings should not
    // mimick this behavior so just return false here.
    bool allow_missing(util::Any const&) const { return false; }

private:
    std::shared_ptr<Realm> realm;
    const ObjectSchema* object_schema = nullptr;

};

inline util::Any CppContext::box(RowExpr row) const
{
    return Object(realm, *object_schema, row);
}

template<>
inline StringData CppContext::unbox(util::Any& v, bool, bool) const
{
    if (!v.has_value())
        return StringData();
    auto& value = any_cast<std::string&>(v);
    return StringData(value.c_str(), value.size());
}

template<>
inline BinaryData CppContext::unbox(util::Any& v, bool, bool) const
{
    if (!v.has_value())
        return BinaryData();
    auto& value = any_cast<std::string&>(v);
    return BinaryData(value.c_str(), value.size());
}

template<>
inline RowExpr CppContext::unbox(util::Any& v, bool create, bool update) const
{
    if (auto object = any_cast<Object>(&v))
        return object->row();
    if (auto row = any_cast<RowExpr>(&v))
        return *row;
    if (!create)
        return RowExpr();

    REALM_ASSERT(object_schema);
    return Object::create(const_cast<CppContext&>(*this), realm, *object_schema, v, update).row();
}

template<>
inline util::Optional<bool> CppContext::unbox(util::Any& v, bool, bool) const
{
    return v.has_value() ? util::make_optional(unbox<bool>(v)) : util::none;
}

template<>
inline util::Optional<int64_t> CppContext::unbox(util::Any& v, bool, bool) const
{
    return v.has_value() ? util::make_optional(unbox<int64_t>(v)) : util::none;
}

template<>
inline util::Optional<double> CppContext::unbox(util::Any& v, bool, bool) const
{
    return v.has_value() ? util::make_optional(unbox<double>(v)) : util::none;
}

template<>
inline util::Optional<float> CppContext::unbox(util::Any& v, bool, bool) const
{
    return v.has_value() ? util::make_optional(unbox<float>(v)) : util::none;
}

template<>
inline Mixed CppContext::unbox(util::Any&, bool, bool) const
{
    throw std::logic_error("'Any' type is unsupported");
}
}

#endif // REALM_OS_OBJECT_ACCESSOR_IMPL_HPP
<|endoftext|>


<commit_before>/*
* @Author: Alejandro Bordallo
* @Date:   2015-04-22 18:12:31
* @Last Modified by:   Alejandro Bordallo
* @Last Modified time: 2015-04-22 17:29:47
*/

#include "joint_control.h"

Joint_Control::Joint_Control()
{
  nh_ = new ros::NodeHandle();
  mProxy_ = new AL::ALMotionProxy("127.0.0.1", 9559);

  // INFO("Setting up Joint Control publishers" << std::endl);

  // INFO("Setting up Joint Control subscribers" << std::endl);

  INFO("Setting up Joint Control services" << std::endl);

  srv_angle_interp_ = nh_->advertiseService(
                  "motion/angleInterp", &Joint_Control::angleInterp, this);
  srv_angle_interp_speed_ = nh_->advertiseService(
                  "motion/angleInterpSpeed", &Joint_Control::angleInterpSpeed, this);
  srv_set_angles_ = nh_->advertiseService(
                  "motion/setAngles", &Joint_Control::setAngles, this);
  srv_change_angles_ = nh_->advertiseService(
                  "motion/changeAngles", &Joint_Control::changeAngles, this);
  srv_get_angles_ = nh_->advertiseService(
                  "motion/getAngles", &Joint_Control::getAngles, this);
  srv_close_hand_ = nh_->advertiseService(
                  "motion/closeHand", &Joint_Control::closeHand, this);
  srv_open_hand_ = nh_->advertiseService(
                  "motion/openHand", &Joint_Control::openHand, this);
}

Joint_Control::~Joint_Control()
{
  ros::shutdown();
  delete nh_;
}

bool Joint_Control::angleInterp(motion::angleInterp::Request &req,
                                motion::angleInterp::Response &res)
{
  int s = req.names.size();
  AL::ALValue names = req.names;

  AL::ALValue angleLists;
  angleLists.arraySetSize(s);
  AL::ALValue timeLists;
  timeLists.arraySetSize(s);

  for(unsigned i = 0; i < s; ++i) {
    angleLists[i] = req.angleLists[i].floatList;
    timeLists[i] = req.timeLists[i].floatList;
  }

  try{
    mProxy_->angleInterpolation(names, angleLists,
                                timeLists, req.isAbsolute);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}
bool Joint_Control::angleInterpSpeed(motion::angleInterpSpeed::Request &req,
                                     motion::angleInterpSpeed::Response &res)
{
  return true;
}

bool Joint_Control::setAngles(motion::setAngles::Request &req,
                              motion::setAngles::Response &res)
{
  try{
    mProxy_->setAngles(req.names, req.angles, req.fractionMaxSpeed);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}

bool Joint_Control::changeAngles(motion::changeAngles::Request &req,
                                 motion::changeAngles::Response &res)
{
  try{
    mProxy_->changeAngles(req.names, req.changes, req.fractionMaxSpeed);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}

bool Joint_Control::getAngles(motion::getAngles::Request &req,
                              motion::getAngles::Response &res)
{
  try{
    res.jointAngles = mProxy_->getAngles(req.names, req.useSensors);
  }
  catch (const std::exception& e){
    return false;
  }
  return true;
}

bool Joint_Control::closeHand(motion::useHand::Request &req,
                              motion::useHand::Response &res)
{
  try{
    mProxy_->closeHand(req.handName);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}
bool Joint_Control::openHand(motion::useHand::Request &req,
                             motion::useHand::Response &res)
{
  try{
    mProxy_->openHand(req.handName);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}<commit_msg>Implements angleInterpolationWithSpeed service, easy to use<commit_after>/*
* @Author: Alejandro Bordallo
* @Date:   2015-04-22 18:12:31
* @Last Modified by:   Alejandro Bordallo
* @Last Modified time: 2015-04-22 17:29:47
*/

#include "joint_control.h"

Joint_Control::Joint_Control()
{
  nh_ = new ros::NodeHandle();
  mProxy_ = new AL::ALMotionProxy("127.0.0.1", 9559);

  // INFO("Setting up Joint Control publishers" << std::endl);

  // INFO("Setting up Joint Control subscribers" << std::endl);

  INFO("Setting up Joint Control services" << std::endl);

  srv_angle_interp_ = nh_->advertiseService(
                  "motion/angleInterp", &Joint_Control::angleInterp, this);
  srv_angle_interp_speed_ = nh_->advertiseService(
                  "motion/angleInterpSpeed", &Joint_Control::angleInterpSpeed, this);
  srv_set_angles_ = nh_->advertiseService(
                  "motion/setAngles", &Joint_Control::setAngles, this);
  srv_change_angles_ = nh_->advertiseService(
                  "motion/changeAngles", &Joint_Control::changeAngles, this);
  srv_get_angles_ = nh_->advertiseService(
                  "motion/getAngles", &Joint_Control::getAngles, this);
  srv_close_hand_ = nh_->advertiseService(
                  "motion/closeHand", &Joint_Control::closeHand, this);
  srv_open_hand_ = nh_->advertiseService(
                  "motion/openHand", &Joint_Control::openHand, this);
}

Joint_Control::~Joint_Control()
{
  ros::shutdown();
  delete nh_;
}

bool Joint_Control::angleInterp(motion::angleInterp::Request &req,
                                motion::angleInterp::Response &res)
{
  int s = req.names.size();
  AL::ALValue names = req.names;

  AL::ALValue angleLists;
  angleLists.arraySetSize(s);
  AL::ALValue timeLists;
  timeLists.arraySetSize(s);

  for(unsigned i = 0; i < s; ++i) {
    angleLists[i] = req.angleLists[i].floatList;
    timeLists[i] = req.timeLists[i].floatList;
  }

  try{
    mProxy_->angleInterpolation(names, angleLists,
                                timeLists, req.isAbsolute);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}
bool Joint_Control::angleInterpSpeed(motion::angleInterpSpeed::Request &req,
                                     motion::angleInterpSpeed::Response &res)
{
  try{
    mProxy_->angleInterpolationWithSpeed(req.names, req.targetAngles,
                                         req.maxSpeedFraction);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}

bool Joint_Control::setAngles(motion::setAngles::Request &req,
                              motion::setAngles::Response &res)
{
  try{
    mProxy_->setAngles(req.names, req.angles, req.fractionMaxSpeed);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}

bool Joint_Control::changeAngles(motion::changeAngles::Request &req,
                                 motion::changeAngles::Response &res)
{
  try{
    mProxy_->changeAngles(req.names, req.changes, req.fractionMaxSpeed);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}

bool Joint_Control::getAngles(motion::getAngles::Request &req,
                              motion::getAngles::Response &res)
{
  try{
    res.jointAngles = mProxy_->getAngles(req.names, req.useSensors);
  }
  catch (const std::exception& e){
    return false;
  }
  return true;
}

bool Joint_Control::closeHand(motion::useHand::Request &req,
                              motion::useHand::Response &res)
{
  try{
    mProxy_->closeHand(req.handName);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}
bool Joint_Control::openHand(motion::useHand::Request &req,
                             motion::useHand::Response &res)
{
  try{
    mProxy_->openHand(req.handName);
    res.res = true;
  }
  catch (const std::exception& e){
    res.res = false;
  }
  return true;
}<|endoftext|>


<commit_before>#include <algorithm>
#include <fstream>
#include <sstream>
#include <streambuf>

#include "parser.h"

using namespace std;

namespace gpr {

  //ostream& operator<<(ostream& stream, const token& ic) {
  //ic.print(stream);
    //return stream;
  //  }

  ostream& operator<<(ostream& stream, const block& block) {
    //for (auto i : block) { stream << i << " "; }
    return stream;
  }

  ostream& operator<<(ostream& stream, const vector<block>& blocks) {
    //for (auto b : blocks) { stream << b << endl; }
    return stream;
  }

  // int parse_i(parse_state& s) {
  //   string digits = "";
  //   while (s.chars_left() && isdigit(s.next())) {
  //     digits += s.next();
  //     s++;
  //   }
  //   return stoi(digits);
  // }

  // double parse_dbl(parse_state& s) {
  //   string text = "";
  //   if (s.next() == '-') { text += s.next(); s++; }
  //   while (s.chars_left() && isdigit(s.next())) { text += s.next(); s++; }
  //   if (s.next() == '.') { text += s.next(); s++; }
  //   while (s.chars_left() && isdigit(s.next())) { text += s.next(); s++; }
  //   return atof(text.c_str());
  // }

  // value parse_c_val(char c, parse_state& s) {
  //   switch(c) {
  //   case 'X':
  //   case 'Y':
  //   case 'Z':
  //   case 'I':
  //   case 'J':
  //   case 'K':
  //   case 'F':
  //   case 'R':
  //   case 'Q':
  //   case 'S':
  //   case 'x':
  //   case 'y':
  //   case 'z':
  //   case 'i':
  //   case 'j':
  //   case 'k':
  //   case 'f':
  //   case 'r':
  //   case 's':
  //   case 'q':
  //     return lit::make(parse_dbl(s));
  //   case 'G':
  //   case 'H':
  //   case 'M':
  //   case 'N':
  //   case 'O':
  //   case 'T':
  //   case 'P':
  //   case 'D':
  //   case 'L':
  //   case 'g':
  //   case 'h':
  //   case 'm':
  //   case 'n':
  //   case 'o':
  //   case 't':
  //   case 'p':
  //   case 'd':
  //   case 'l':
  //     return ilit::make(parse_i(s));
  //   default:
  //     cout << "Invalid c = " << c << endl;
  //     cout << "Inavlid c as int = " << ((int) c) << endl;
  //     cout << "Is EOF? " << (((int) c) == EOF) << endl;
  //     DBG_ASSERT(false);
  //   }
  // }

  // token parse_token(parse_state& s) {
  //   if (s.next() == '[') {
  //     string cs = parse_comment_with_delimiters('[', ']', s);
  //     return token(cs);
  //   } else if (s.next() == '(') {
  //     string cs = parse_comment_with_delimiters('(', ')', s);
  //     return token(cs);
  //   } else {
  //     char c = s.next();
  //     s++;
  //     value* v = parse_c_val(c, s);
  //     return token(c, v);
  //   }
  // }

  block lex_gprog_line(const string& str, int line_no) {
    return block();
  //   block ts;
  //   parse_state s(str);
  //   int i = 0;
  //   while (s.chars_left()) {
  //     ignore_whitespace(s);
  //     if (!s.chars_left()) { break; }
  //     token t = parse_token(s);
  //     t.line_no = line_no;
  //     ts.push_back(t);
  //     i++;
  //   }
  //   return ts;
  }

  vector<block> lex_gprog(const string& str) {
    vector<block> blocks;
    string::const_iterator line_start = str.begin();
    string::const_iterator line_end;
    int line_no = 1;
    while (line_start < str.end()) {
      line_end = find(line_start, str.end(), '\n');
      string line(line_start, line_end);
      if (line.size() > 0) {
	block b = lex_gprog_line(line, line_no);
	if (b.size() > 0) {
	  blocks.push_back(b);
	}
      }
      line_start += line.size() + 1;
      line_no++;
    }
    return blocks;
  }

  gcode_program parse_gcode(const std::string& program_text) {
    auto blocks = lex_gprog(program_text);
    return gcode_program(blocks);
  }

}
<commit_msg>Now need to add blocks parsing<commit_after>#include <algorithm>
#include <fstream>
#include <sstream>
#include <streambuf>

#include "parser.h"

using namespace std;

namespace gpr {

  //ostream& operator<<(ostream& stream, const token& ic) {
  //ic.print(stream);
    //return stream;
  //  }

  ostream& operator<<(ostream& stream, const block& block) {
    //for (auto i : block) { stream << i << " "; }
    return stream;
  }

  ostream& operator<<(ostream& stream, const vector<block>& blocks) {
    //for (auto b : blocks) { stream << b << endl; }
    return stream;
  }

  // int parse_i(parse_state& s) {
  //   string digits = "";
  //   while (s.chars_left() && isdigit(s.next())) {
  //     digits += s.next();
  //     s++;
  //   }
  //   return stoi(digits);
  // }

  // double parse_dbl(parse_state& s) {
  //   string text = "";
  //   if (s.next() == '-') { text += s.next(); s++; }
  //   while (s.chars_left() && isdigit(s.next())) { text += s.next(); s++; }
  //   if (s.next() == '.') { text += s.next(); s++; }
  //   while (s.chars_left() && isdigit(s.next())) { text += s.next(); s++; }
  //   return atof(text.c_str());
  // }

  // value parse_c_val(char c, parse_state& s) {
  //   switch(c) {
  //   case 'X':
  //   case 'Y':
  //   case 'Z':
  //   case 'I':
  //   case 'J':
  //   case 'K':
  //   case 'F':
  //   case 'R':
  //   case 'Q':
  //   case 'S':
  //   case 'x':
  //   case 'y':
  //   case 'z':
  //   case 'i':
  //   case 'j':
  //   case 'k':
  //   case 'f':
  //   case 'r':
  //   case 's':
  //   case 'q':
  //     return lit::make(parse_dbl(s));
  //   case 'G':
  //   case 'H':
  //   case 'M':
  //   case 'N':
  //   case 'O':
  //   case 'T':
  //   case 'P':
  //   case 'D':
  //   case 'L':
  //   case 'g':
  //   case 'h':
  //   case 'm':
  //   case 'n':
  //   case 'o':
  //   case 't':
  //   case 'p':
  //   case 'd':
  //   case 'l':
  //     return ilit::make(parse_i(s));
  //   default:
  //     cout << "Invalid c = " << c << endl;
  //     cout << "Inavlid c as int = " << ((int) c) << endl;
  //     cout << "Is EOF? " << (((int) c) == EOF) << endl;
  //     DBG_ASSERT(false);
  //   }
  // }

  // token parse_token(parse_state& s) {
  //   if (s.next() == '[') {
  //     string cs = parse_comment_with_delimiters('[', ']', s);
  //     return token(cs);
  //   } else if (s.next() == '(') {
  //     string cs = parse_comment_with_delimiters('(', ')', s);
  //     return token(cs);
  //   } else {
  //     char c = s.next();
  //     s++;
  //     value* v = parse_c_val(c, s);
  //     return token(c, v);
  //   }
  // }

  block lex_gprog_line(const string& str, int line_no) {
    block ts;

    // while (s.chars_left()) {
    //   ignore_whitespace(s);
    //   if (!s.chars_left()) { break; }
    //   token t = parse_token(s);
    //   t.line_no = line_no;
    //   ts.push_back(t);

    // }

    return ts;
  }

  vector<block> lex_gprog(const string& str) {
    vector<block> blocks;
    string::const_iterator line_start = str.begin();
    string::const_iterator line_end;
    int line_no = 1;
    while (line_start < str.end()) {
      line_end = find(line_start, str.end(), '\n');
      string line(line_start, line_end);
      if (line.size() > 0) {
	block b = lex_gprog_line(line, line_no);
	if (b.size() > 0) {
	  blocks.push_back(b);
	}
      }
      line_start += line.size() + 1;
      line_no++;
    }
    return blocks;
  }

  gcode_program parse_gcode(const std::string& program_text) {
    auto blocks = lex_gprog(program_text);
    return gcode_program(blocks);
  }

}
<|endoftext|>


<commit_before>#include "db_single.h"

namespace LeviDB {
    DBSingle::DBSingle(std::string name, Options options, SeqGenerator * seq_gen)
            : DB(std::move(name), options), _seq_gen(seq_gen) {
        std::string prefix = _name + '/' + _name;
        _file_lock.build(prefix + ".lock");

        if (IOEnv::fileExists(_name)) {
            if (_options.error_if_exists) {
                throw Exception::invalidArgumentException("DB already exists");
            }
            // 打开现有数据库
            std::string data_fname = prefix + ".data";
            if (!IOEnv::fileExists(data_fname)) {
                throw Exception::notFoundException("data file missing", data_fname);
            }
            std::string index_fname = prefix + ".index";
            std::string keeper_fname = prefix + ".keeper";
            if (!IOEnv::fileExists(index_fname) || !IOEnv::fileExists(keeper_fname)) {
                simpleRepair();
                return;
            }
            _meta.build(std::move(prefix));
            _af.build(data_fname);
            _rf.build(std::move(data_fname));
            _index.build(std::move(index_fname), _meta->immut_value()._offset, _seq_gen, _rf.get());
            _writer.build(_af.get());
        } else {
            if (!_options.create_if_missing) {
                throw Exception::notFoundException("DB not found");
            }
            // 新建数据库
            IOEnv::createDir(_name);
            _af.build(prefix + ".data");
            _rf.build(prefix + ".data");
            _index.build(prefix + ".index", _seq_gen, _rf.get());
            _writer.build(_af.get());
            _meta.build(std::move(prefix), DBSingleWeakMeta{}, ""); // WeakKeeper will add ".keeper" automatically
        }
    }

    void DBSingle::put(const WriteOptions & options,
                       const Slice & key,
                       const Slice & value) {
        RWLockWriteGuard write_guard(_rwlock);

        uint32_t pos = _writer->calcWritePos();
        std::vector<uint8_t> bin = LogWriter::makeRecord(key, value);
        _writer->addRecord({bin.data(), bin.size()});
        _index->insert(key, OffsetToData{pos});

        if (options.sync) _af->sync();
    };

    void DBSingle::remove(const WriteOptions & options,
                          const Slice & key) {
        RWLockWriteGuard write_guard(_rwlock);

        std::vector<uint8_t> bin = LogWriter::makeRecord(key, {});
        _writer->addDelRecord({bin.data(), bin.size()});
        _index->remove(key);

        if (options.sync) _af->sync();
    };

    void DBSingle::write(const WriteOptions & options,
                         const std::vector<std::pair<Slice, Slice>> & kvs) {
        RWLockWriteGuard write_guard(_rwlock);

        if (options.compress) {
            assert(options.uncompress_size != 0);
            uint32_t pos = _writer->calcWritePos();
            std::vector<uint8_t> bin = LogWriter::makeCompressRecord(kvs);
            if (bin.size() <= options.uncompress_size / 8 * 7) { // worth
                _writer->addCompressRecord({bin.data(), bin.size()});
                for (const auto & kv:kvs) {
                    _index->insert(kv.first, OffsetToData{pos});
                }

                if (options.sync) _af->sync();
                return;
            }
        }

        std::vector<std::vector<uint8_t>> group;
        group.reserve(kvs.size());
        std::transform(kvs.cbegin(), kvs.cend(), group.begin(), [](const std::pair<Slice, Slice> & kv) {
            return LogWriter::makeRecord(kv.first, kv.second);
        });

        std::vector<Slice> bkvs;
        bkvs.reserve(group.size());
        std::transform(group.cbegin(), group.cend(), bkvs.begin(), [](const std::vector<uint8_t> & bkv) -> Slice {
            return {bkv.data(), bkv.size()};
        });

        std::vector<uint32_t> addrs = _writer->addRecords(bkvs);
        assert(kvs.size() == addrs.size());
        for (int i = 0; i < kvs.size(); ++i) {
            _index->insert(kvs[i].first, OffsetToData{addrs[i]});
        }

        if (options.sync) _af->sync();
    };

    std::pair<std::string, bool>
    DBSingle::get(const ReadOptions & options, const Slice & key) const {
        RWLockReadGuard read_guard(_rwlock);

        return _index->find(key, options.sequence_number);
    };

    std::unique_ptr<Snapshot>
    DBSingle::makeSnapshot() {
        RWLockWriteGuard write_guard(_rwlock);

        return _seq_gen->makeSnapshot();
    };

    std::unique_ptr<Iterator<Slice, std::string>>
    DBSingle::makeIterator(std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);

        return _index->makeIterator(std::move(snapshot));
    };

    std::unique_ptr<SimpleIterator<std::pair<Slice, std::string>>>
    DBSingle::makeRegexIterator(std::shared_ptr<Regex::R> regex,
                                std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);

        return _index->makeRegexIterator(std::move(regex), std::move(snapshot));
    };

    std::unique_ptr<SimpleIterator<std::pair<Slice, std::string>>>
    DBSingle::makeRegexReversedIterator(std::shared_ptr<Regex::R> regex,
                                        std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);

        return _index->makeRegexReversedIterator(std::move(regex), std::move(snapshot));
    };

    uint64_t DBSingle::indexFileSize() const noexcept {
        return _index->immut_dst().immut_length();
    };

    uint64_t DBSingle::dataFileSize() const noexcept {
        return _af->immut_length();
    };

    void DBSingle::explicitRemove(const WriteOptions & options, const Slice & key) {
        RWLockWriteGuard write_guard(_rwlock);

        uint32_t pos = _writer->calcWritePos();
        std::vector<uint8_t> bin = LogWriter::makeRecord(key, {});
        _writer->addDelRecord({bin.data(), bin.size()});
        _index->insert(key, OffsetToData{pos});

        if (options.sync) _af->sync();
    }

    void DBSingle::simpleRepair() noexcept {

    }

    Slice DBSingle::largestKey() const noexcept {

    };

    Slice DBSingle::smallestKey() const noexcept {

    };

    void DBSingle::updateKeyRange(const Slice & key) noexcept {

    };

    bool repairDBSingle(const std::string & db_single_name) noexcept {

    };
}
<commit_msg>mark lamdba noexcept<commit_after>#include "db_single.h"

namespace LeviDB {
    DBSingle::DBSingle(std::string name, Options options, SeqGenerator * seq_gen)
            : DB(std::move(name), options), _seq_gen(seq_gen) {
        std::string prefix = _name + '/' + _name;
        _file_lock.build(prefix + ".lock");

        if (IOEnv::fileExists(_name)) {
            if (_options.error_if_exists) {
                throw Exception::invalidArgumentException("DB already exists");
            }
            // 打开现有数据库
            std::string data_fname = prefix + ".data";
            if (!IOEnv::fileExists(data_fname)) {
                throw Exception::notFoundException("data file missing", data_fname);
            }
            std::string index_fname = prefix + ".index";
            std::string keeper_fname = prefix + ".keeper";
            if (!IOEnv::fileExists(index_fname) || !IOEnv::fileExists(keeper_fname)) {
                simpleRepair();
                return;
            }
            _meta.build(std::move(prefix));
            _af.build(data_fname);
            _rf.build(std::move(data_fname));
            _index.build(std::move(index_fname), _meta->immut_value()._offset, _seq_gen, _rf.get());
            _writer.build(_af.get());
        } else {
            if (!_options.create_if_missing) {
                throw Exception::notFoundException("DB not found");
            }
            // 新建数据库
            IOEnv::createDir(_name);
            _af.build(prefix + ".data");
            _rf.build(prefix + ".data");
            _index.build(prefix + ".index", _seq_gen, _rf.get());
            _writer.build(_af.get());
            _meta.build(std::move(prefix), DBSingleWeakMeta{}, ""); // WeakKeeper will add ".keeper" automatically
        }
    }

    void DBSingle::put(const WriteOptions & options,
                       const Slice & key,
                       const Slice & value) {
        RWLockWriteGuard write_guard(_rwlock);

        uint32_t pos = _writer->calcWritePos();
        std::vector<uint8_t> bin = LogWriter::makeRecord(key, value);
        _writer->addRecord({bin.data(), bin.size()});
        _index->insert(key, OffsetToData{pos});

        if (options.sync) _af->sync();
    };

    void DBSingle::remove(const WriteOptions & options,
                          const Slice & key) {
        RWLockWriteGuard write_guard(_rwlock);

        std::vector<uint8_t> bin = LogWriter::makeRecord(key, {});
        _writer->addDelRecord({bin.data(), bin.size()});
        _index->remove(key);

        if (options.sync) _af->sync();
    };

    void DBSingle::write(const WriteOptions & options,
                         const std::vector<std::pair<Slice, Slice>> & kvs) {
        RWLockWriteGuard write_guard(_rwlock);

        if (options.compress) {
            assert(options.uncompress_size != 0);
            uint32_t pos = _writer->calcWritePos();
            std::vector<uint8_t> bin = LogWriter::makeCompressRecord(kvs);
            if (bin.size() <= options.uncompress_size / 8 * 7) { // worth
                _writer->addCompressRecord({bin.data(), bin.size()});
                for (const auto & kv:kvs) {
                    _index->insert(kv.first, OffsetToData{pos});
                }

                if (options.sync) _af->sync();
                return;
            }
        }

        std::vector<std::vector<uint8_t>> group;
        group.reserve(kvs.size());
        std::transform(kvs.cbegin(), kvs.cend(), group.begin(), [](const std::pair<Slice, Slice> & kv) noexcept {
            return LogWriter::makeRecord(kv.first, kv.second);
        });

        std::vector<Slice> bkvs;
        bkvs.reserve(group.size());
        std::transform(group.cbegin(), group.cend(), bkvs.begin(),
                       [](const std::vector<uint8_t> & bkv) noexcept -> Slice {
                           return {bkv.data(), bkv.size()};
                       });

        std::vector<uint32_t> addrs = _writer->addRecords(bkvs);
        assert(kvs.size() == addrs.size());
        for (int i = 0; i < kvs.size(); ++i) {
            _index->insert(kvs[i].first, OffsetToData{addrs[i]});
        }

        if (options.sync) _af->sync();
    };

    std::pair<std::string, bool>
    DBSingle::get(const ReadOptions & options, const Slice & key) const {
        RWLockReadGuard read_guard(_rwlock);

        return _index->find(key, options.sequence_number);
    };

    std::unique_ptr<Snapshot>
    DBSingle::makeSnapshot() {
        RWLockWriteGuard write_guard(_rwlock);

        return _seq_gen->makeSnapshot();
    };

    std::unique_ptr<Iterator<Slice, std::string>>
    DBSingle::makeIterator(std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);

        return _index->makeIterator(std::move(snapshot));
    };

    std::unique_ptr<SimpleIterator<std::pair<Slice, std::string>>>
    DBSingle::makeRegexIterator(std::shared_ptr<Regex::R> regex,
                                std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);

        return _index->makeRegexIterator(std::move(regex), std::move(snapshot));
    };

    std::unique_ptr<SimpleIterator<std::pair<Slice, std::string>>>
    DBSingle::makeRegexReversedIterator(std::shared_ptr<Regex::R> regex,
                                        std::unique_ptr<Snapshot> && snapshot) const {
        RWLockReadGuard read_guard(_rwlock);

        return _index->makeRegexReversedIterator(std::move(regex), std::move(snapshot));
    };

    uint64_t DBSingle::indexFileSize() const noexcept {
        return _index->immut_dst().immut_length();
    };

    uint64_t DBSingle::dataFileSize() const noexcept {
        return _af->immut_length();
    };

    void DBSingle::explicitRemove(const WriteOptions & options, const Slice & key) {
        RWLockWriteGuard write_guard(_rwlock);

        uint32_t pos = _writer->calcWritePos();
        std::vector<uint8_t> bin = LogWriter::makeRecord(key, {});
        _writer->addDelRecord({bin.data(), bin.size()});
        _index->insert(key, OffsetToData{pos});

        if (options.sync) _af->sync();
    }

    void DBSingle::simpleRepair() noexcept {

    }

    Slice DBSingle::largestKey() const noexcept {

    };

    Slice DBSingle::smallestKey() const noexcept {

    };

    void DBSingle::updateKeyRange(const Slice & key) noexcept {

    };

    bool repairDBSingle(const std::string & db_single_name) noexcept {

    };
}
<|endoftext|>