<commit_before>#include "sendcoinsentry.h"
#include "ui_sendcoinsentry.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h"

#include <QApplication>
#include <QClipboard>

SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::SendCoinsEntry),
    model(0)
{
    ui->setupUi(this);

#ifdef Q_WS_MAC
    ui->payToLayout->setSpacing(4);
#endif
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
    ui->payTo->setPlaceholderText(tr("Enter a nlocoin address (they start with an 'm')"));
#endif
    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(ui->payTo);

    GUIUtil::setupAddressWidget(ui->payTo, this);
}

SendCoinsEntry::~SendCoinsEntry()
{
    delete ui;
}

void SendCoinsEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void SendCoinsEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
    if(!model)
        return;
    // Fill in label from address book, if address has an associated label
    QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
    if(!associatedLabel.isEmpty())
        ui->addAsLabel->setText(associatedLabel);
}

void SendCoinsEntry::setModel(WalletModel *model)
{
    this->model = model;

    if(model && model->getOptionsModel())
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

    clear();
}

void SendCoinsEntry::setRemoveEnabled(bool enabled)
{
    ui->deleteButton->setEnabled(enabled);
}

void SendCoinsEntry::clear()
{
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
    ui->payTo->setFocus();
    // update the display unit, to not use the default ("BTC")
    updateDisplayUnit();
}

void SendCoinsEntry::on_deleteButton_clicked()
{
    emit removeEntry(this);
}

bool SendCoinsEntry::validate()
{
    // Check input validity
    bool retval = true;

    if(!ui->payAmount->validate())
    {
        retval = false;
    }
    else
    {
        if(ui->payAmount->value() <= 0)
        {
            // Cannot send 0 coins or less
            ui->payAmount->setValid(false);
            retval = false;
        }
    }

    if(!ui->payTo->hasAcceptableInput() ||
       (model && !model->validateAddress(ui->payTo->text())))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient SendCoinsEntry::getValue()
{
    SendCoinsRecipient rv;

    rv.address = ui->payTo->text();
    rv.label = ui->addAsLabel->text();
    rv.amount = ui->payAmount->value();

    return rv;
}

QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
    QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
    return ui->payAmount->setupTabChain(ui->addAsLabel);
}

void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
    ui->payTo->setText(value.address);
    ui->addAsLabel->setText(value.label);
    ui->payAmount->setValue(value.amount);
}

bool SendCoinsEntry::isClear()
{
    return ui->payTo->text().isEmpty();
}

void SendCoinsEntry::setFocus()
{
    ui->payTo->setFocus();
}

void SendCoinsEntry::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update payAmount with the current unit
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}
<commit_msg>Fixed typo address start 'm' to 'N' - "Enter a nlocoin address (they start with an 'm')"<commit_after>#include "sendcoinsentry.h"
#include "ui_sendcoinsentry.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h"

#include <QApplication>
#include <QClipboard>

SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::SendCoinsEntry),
    model(0)
{
    ui->setupUi(this);

#ifdef Q_WS_MAC
    ui->payToLayout->setSpacing(4);
#endif
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
    ui->payTo->setPlaceholderText(tr("Enter a nlocoin address (they start with an 'N')"));
#endif
    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(ui->payTo);

    GUIUtil::setupAddressWidget(ui->payTo, this);
}

SendCoinsEntry::~SendCoinsEntry()
{
    delete ui;
}

void SendCoinsEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void SendCoinsEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
    if(!model)
        return;
    // Fill in label from address book, if address has an associated label
    QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
    if(!associatedLabel.isEmpty())
        ui->addAsLabel->setText(associatedLabel);
}

void SendCoinsEntry::setModel(WalletModel *model)
{
    this->model = model;

    if(model && model->getOptionsModel())
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

    clear();
}

void SendCoinsEntry::setRemoveEnabled(bool enabled)
{
    ui->deleteButton->setEnabled(enabled);
}

void SendCoinsEntry::clear()
{
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
    ui->payTo->setFocus();
    // update the display unit, to not use the default ("BTC")
    updateDisplayUnit();
}

void SendCoinsEntry::on_deleteButton_clicked()
{
    emit removeEntry(this);
}

bool SendCoinsEntry::validate()
{
    // Check input validity
    bool retval = true;

    if(!ui->payAmount->validate())
    {
        retval = false;
    }
    else
    {
        if(ui->payAmount->value() <= 0)
        {
            // Cannot send 0 coins or less
            ui->payAmount->setValid(false);
            retval = false;
        }
    }

    if(!ui->payTo->hasAcceptableInput() ||
       (model && !model->validateAddress(ui->payTo->text())))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient SendCoinsEntry::getValue()
{
    SendCoinsRecipient rv;

    rv.address = ui->payTo->text();
    rv.label = ui->addAsLabel->text();
    rv.amount = ui->payAmount->value();

    return rv;
}

QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
    QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
    return ui->payAmount->setupTabChain(ui->addAsLabel);
}

void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
    ui->payTo->setText(value.address);
    ui->addAsLabel->setText(value.label);
    ui->payAmount->setValue(value.amount);
}

bool SendCoinsEntry::isClear()
{
    return ui->payTo->text().isEmpty();
}

void SendCoinsEntry::setFocus()
{
    ui->payTo->setFocus();
}

void SendCoinsEntry::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update payAmount with the current unit
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}
<|endoftext|>


<commit_before>#include "sendcoinsentry.h"
#include "ui_sendcoinsentry.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h"

#include <QApplication>
#include <QClipboard>

SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::SendCoinsEntry),
    model(0)
{
    ui->setupUi(this);

#ifdef Q_WS_MAC
    ui->payToLayout->setSpacing(4);
#endif
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
    ui->payTo->setPlaceholderText(tr("Enter a KAC address (they start with an S)"));
#endif
    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(ui->payTo);

    GUIUtil::setupAddressWidget(ui->payTo, this);
}

SendCoinsEntry::~SendCoinsEntry()
{
    delete ui;
}

void SendCoinsEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void SendCoinsEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
    if(!model)
        return;
    // Fill in label from address book, if address has an associated label
    QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
    if(!associatedLabel.isEmpty())
        ui->addAsLabel->setText(associatedLabel);
}

void SendCoinsEntry::setModel(WalletModel *model)
{
    this->model = model;

    if(model && model->getOptionsModel())
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

    clear();
}

void SendCoinsEntry::setRemoveEnabled(bool enabled)
{
    ui->deleteButton->setEnabled(enabled);
}

void SendCoinsEntry::clear()
{
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
    ui->payTo->setFocus();
    // update the display unit, to not use the default ("BTC")
    updateDisplayUnit();
}

void SendCoinsEntry::on_deleteButton_clicked()
{
    emit removeEntry(this);
}

bool SendCoinsEntry::validate()
{
    // Check input validity
    bool retval = true;

    if(!ui->payAmount->validate())
    {
        retval = false;
    }
    else
    {
        if(ui->payAmount->value() <= 0)
        {
            // Cannot send 0 coins or less
            ui->payAmount->setValid(false);
            retval = false;
        }
    }

    if(!ui->payTo->hasAcceptableInput() ||
       (model && !model->validateAddress(ui->payTo->text())))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient SendCoinsEntry::getValue()
{
    SendCoinsRecipient rv;

    rv.address = ui->payTo->text();
    rv.label = ui->addAsLabel->text();
    rv.amount = ui->payAmount->value();

    return rv;
}

QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
    QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
    return ui->payAmount->setupTabChain(ui->addAsLabel);
}

void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
    ui->payTo->setText(value.address);
    ui->addAsLabel->setText(value.label);
    ui->payAmount->setValue(value.amount);
}

bool SendCoinsEntry::isClear()
{
    return ui->payTo->text().isEmpty();
}

void SendCoinsEntry::setFocus()
{
    ui->payTo->setFocus();
}

void SendCoinsEntry::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update payAmount with the current unit
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}
<commit_msg>changes<commit_after>#include "sendcoinsentry.h"
#include "ui_sendcoinsentry.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h"

#include <QApplication>
#include <QClipboard>

SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::SendCoinsEntry),
    model(0)
{
    ui->setupUi(this);

#ifdef Q_WS_MAC
    ui->payToLayout->setSpacing(4);
#endif
#if QT_VERSION >= 0x040700
    /* Do not move this to the XML file, Qt before 4.7 will choke on it */
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
    ui->payTo->setPlaceholderText(tr("Enter a KAC address (they start with an 8)"));
#endif
    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(ui->payTo);

    GUIUtil::setupAddressWidget(ui->payTo, this);
}

SendCoinsEntry::~SendCoinsEntry()
{
    delete ui;
}

void SendCoinsEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void SendCoinsEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
    if(!model)
        return;
    // Fill in label from address book, if address has an associated label
    QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
    if(!associatedLabel.isEmpty())
        ui->addAsLabel->setText(associatedLabel);
}

void SendCoinsEntry::setModel(WalletModel *model)
{
    this->model = model;

    if(model && model->getOptionsModel())
        connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));

    clear();
}

void SendCoinsEntry::setRemoveEnabled(bool enabled)
{
    ui->deleteButton->setEnabled(enabled);
}

void SendCoinsEntry::clear()
{
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
    ui->payTo->setFocus();
    // update the display unit, to not use the default ("BTC")
    updateDisplayUnit();
}

void SendCoinsEntry::on_deleteButton_clicked()
{
    emit removeEntry(this);
}

bool SendCoinsEntry::validate()
{
    // Check input validity
    bool retval = true;

    if(!ui->payAmount->validate())
    {
        retval = false;
    }
    else
    {
        if(ui->payAmount->value() <= 0)
        {
            // Cannot send 0 coins or less
            ui->payAmount->setValid(false);
            retval = false;
        }
    }

    if(!ui->payTo->hasAcceptableInput() ||
       (model && !model->validateAddress(ui->payTo->text())))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient SendCoinsEntry::getValue()
{
    SendCoinsRecipient rv;

    rv.address = ui->payTo->text();
    rv.label = ui->addAsLabel->text();
    rv.amount = ui->payAmount->value();

    return rv;
}

QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
    QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
    return ui->payAmount->setupTabChain(ui->addAsLabel);
}

void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
    ui->payTo->setText(value.address);
    ui->addAsLabel->setText(value.label);
    ui->payAmount->setValue(value.amount);
}

bool SendCoinsEntry::isClear()
{
    return ui->payTo->text().isEmpty();
}

void SendCoinsEntry::setFocus()
{
    ui->payTo->setFocus();
}

void SendCoinsEntry::updateDisplayUnit()
{
    if(model && model->getOptionsModel())
    {
        // Update payAmount with the current unit
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2014-2017 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/energi-config.h"
#endif

#include "util.h"
#include "uritests.h"
#include "compattests.h"
#include "trafficgraphdatatests.h"

#ifdef ENABLE_WALLET
#include "paymentservertests.h"
#endif

#include <QCoreApplication>
#include <QObject>
#include <QTest>

#include <openssl/ssl.h>

#if defined(QT_STATICPLUGIN) && QT_VERSION < 0x050000
#include <QtPlugin>
Q_IMPORT_PLUGIN(qcncodecs)
Q_IMPORT_PLUGIN(qjpcodecs)
Q_IMPORT_PLUGIN(qtwcodecs)
Q_IMPORT_PLUGIN(qkrcodecs)
#endif

// This is all you need to run all the tests
int main(int argc, char *argv[])
{
    SetupEnvironment();
    bool fInvalid = false;

    // Don't remove this, it's needed to access
    // QCoreApplication:: in the tests
    QCoreApplication app(argc, argv);
    app.setApplicationName("Energi-Qt-test");

    SSL_library_init();

    URITests test1;
    if (QTest::qExec(&test1) != 0)
        fInvalid = true;
#ifdef ENABLE_WALLET
    PaymentServerTests test2;
    if (QTest::qExec(&test2) != 0)
        fInvalid = true;
#endif
    CompatTests test4;
    if (QTest::qExec(&test4) != 0)
        fInvalid = true;

    TrafficGraphDataTests test5;
    if (QTest::qExec(&test5) != 0)
        fInvalid = true;

    return fInvalid;
}
<commit_msg>pass arguments to qt tests for ability to generate test xml<commit_after>// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2014-2017 The Dash Core developers
// Copyright (c) 2017 The Energi Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/energi-config.h"
#endif

#include "util.h"
#include "uritests.h"
#include "compattests.h"
#include "trafficgraphdatatests.h"

#ifdef ENABLE_WALLET
#include "paymentservertests.h"
#endif

#include <QCoreApplication>
#include <QObject>
#include <QTest>

#include <openssl/ssl.h>

#if defined(QT_STATICPLUGIN) && QT_VERSION < 0x050000
#include <QtPlugin>
Q_IMPORT_PLUGIN(qcncodecs)
Q_IMPORT_PLUGIN(qjpcodecs)
Q_IMPORT_PLUGIN(qtwcodecs)
Q_IMPORT_PLUGIN(qkrcodecs)
#endif

// This is all you need to run all the tests
int main(int argc, char *argv[])
{
    SetupEnvironment();
    bool fInvalid = false;

    // Don't remove this, it's needed to access
    // QCoreApplication:: in the tests
    QCoreApplication app(argc, argv);
    app.setApplicationName("Energi-Qt-test");

    SSL_library_init();

    URITests test1;
    if (QTest::qExec(&test1, app.arguments()) != 0)
        fInvalid = true;
#ifdef ENABLE_WALLET
    PaymentServerTests test2;
    if (QTest::qExec(&test2, app.arguments()) != 0)
        fInvalid = true;
#endif
    CompatTests test4;
    if (QTest::qExec(&test4, app.arguments()) != 0)
        fInvalid = true;

    TrafficGraphDataTests test5;
    if (QTest::qExec(&test5, app.arguments()) != 0)
        fInvalid = true;

    return fInvalid;
}
<|endoftext|>


<commit_before>#ifndef RDB_PROTOCOL_FUNC_HPP_
#define RDB_PROTOCOL_FUNC_HPP_

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "utils.hpp"

#include "containers/ptr_bag.hpp"
#include "containers/scoped.hpp"
#include "protob/protob.hpp"
#include "rdb_protocol/js.hpp"
#include "rdb_protocol/term.hpp"
#include "rpc/serialize_macros.hpp"

namespace ql {

class func_t : public ptr_baggable_t, public pb_rcheckable_t {
public:
    func_t(env_t *env, js::id_t id, term_t *parent);
    func_t(env_t *env, const Term *_source);
    // Some queries, like filter, can take a shortcut object instead of a
    // function as their argument.
    static func_t *new_identity_func(env_t *env, const datum_t *obj,
                                     const pb_rcheckable_t *root);
    val_t *call(const std::vector<const datum_t *> &args);
    // Prefer these versions of call.
    val_t *call();
    val_t *call(const datum_t *arg);
    val_t *call(const datum_t *arg1, const datum_t *arg2);
    bool filter_call(const datum_t *arg);

    void dump_scope(std::map<int64_t, Datum> *out) const;
    bool is_deterministic() const;

private:
    // Pointers to this function's arguments.
    std::vector<const datum_t *> argptrs;
    term_t *body; // body to evaluate with functions bound

    // This is what's serialized over the wire.
    friend class wire_func_t;
    const Term *source;
    bool implicit_bound;

    // TODO: make this smarter (it's sort of slow and shitty as-is)
    std::map<int64_t, const datum_t **> scope;

    term_t *js_parent;
    env_t *js_env;
    js::id_t js_id;
};

class js_result_visitor_t : public boost::static_visitor<val_t *> {
public:
    typedef val_t *result_type;

    js_result_visitor_t(env_t *_env, term_t *_parent) : env(_env), parent(_parent) { }

    // This JS evaluation resulted in an error
    result_type operator()(const std::string err_val) const {
        rfail_target(parent, "%s", err_val.c_str());
        unreachable();
    }

    // This JS call resulted in a JSON value
    result_type operator()(const boost::shared_ptr<scoped_cJSON_t> json_val) const {
        return parent->new_val(new datum_t(json_val, env));
    }

    // This JS evaluation resulted in an id for a js function
    result_type operator()(const id_t id_val) const {
        return parent->new_val(new func_t(env, id_val, parent));
    }

private:
    env_t *env;
    term_t *parent;
};

RDB_MAKE_PROTOB_SERIALIZABLE(Term);
RDB_MAKE_PROTOB_SERIALIZABLE(Datum);

// Used to serialize a function (or gmr) over the wire.
class wire_func_t {
public:
    wire_func_t();
    wire_func_t(env_t *env, func_t *_func);
    wire_func_t(const Term &_source, std::map<int64_t, Datum> *_scope);

    func_t *compile(env_t *env);

    RDB_MAKE_ME_SERIALIZABLE_2(source, scope);

    const Backtrace *get_bt() const {
        return &source.GetExtension(ql2::extension::backtrace);
    }
private:
    // We cache a separate function for every environment.
    std::map<env_t *, func_t *> cached_funcs;

    Term source;
    std::map<int64_t, Datum> scope;
};

class map_wire_func_t : public wire_func_t {
public:
    template <class... Args>
    explicit map_wire_func_t(Args... args) : wire_func_t(args...) { }
};

class filter_wire_func_t : public wire_func_t {
public:
    template <class... Args>
    explicit filter_wire_func_t(Args... args) : wire_func_t(args...) { }
};

class reduce_wire_func_t : public wire_func_t {
public:
    template <class... Args>
    explicit reduce_wire_func_t(Args... args) : wire_func_t(args...) { }
};

class concatmap_wire_func_t : public wire_func_t {
public:
    template <class... Args>
    explicit concatmap_wire_func_t(Args... args) : wire_func_t(args...) { }
};

// Count is a fake function because we don't need to send anything.
class count_wire_func_t {
public:
    RDB_MAKE_ME_SERIALIZABLE_0()
    const Backtrace *get_bt() const {
        r_sanity_check(!"SERVER SHOULD NEVER CRASH HERE");
        unreachable();
    }
};

// Grouped Map Reduce
class gmr_wire_func_t {
public:
    gmr_wire_func_t() { }
    gmr_wire_func_t(env_t *env, func_t *_group, func_t *_map, func_t *_reduce)
        : group(env, _group), map(env, _map), reduce(env, _reduce) { }
    func_t *compile_group(env_t *env) { return group.compile(env); }
    func_t *compile_map(env_t *env) { return map.compile(env); }
    func_t *compile_reduce(env_t *env) { return reduce.compile(env); }

    const Backtrace *get_bt() const {
        // If this goes wrong at the toplevel, it goes wrong in reduce.
        return reduce.get_bt();
    }

private:
    map_wire_func_t group;
    map_wire_func_t map;
    reduce_wire_func_t reduce;
public:
    RDB_MAKE_ME_SERIALIZABLE_3(group, map, reduce);
};

// Evaluating this returns a `func_t` wrapped in a `val_t`.
class func_term_t : public term_t {
public:
    func_term_t(env_t *env, const Term *term);
private:
    virtual bool is_deterministic_impl() const;
    virtual val_t *eval_impl();
    virtual const char *name() const { return "func"; }
    func_t *func;
};

} // namespace ql
#endif // RDB_PROTOCOL_FUNC_HPP_
<commit_msg>fixed silly assert<commit_after>#ifndef RDB_PROTOCOL_FUNC_HPP_
#define RDB_PROTOCOL_FUNC_HPP_

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "utils.hpp"

#include "containers/ptr_bag.hpp"
#include "containers/scoped.hpp"
#include "protob/protob.hpp"
#include "rdb_protocol/js.hpp"
#include "rdb_protocol/term.hpp"
#include "rpc/serialize_macros.hpp"

namespace ql {

class func_t : public ptr_baggable_t, public pb_rcheckable_t {
public:
    func_t(env_t *env, js::id_t id, term_t *parent);
    func_t(env_t *env, const Term *_source);
    // Some queries, like filter, can take a shortcut object instead of a
    // function as their argument.
    static func_t *new_identity_func(env_t *env, const datum_t *obj,
                                     const pb_rcheckable_t *root);
    val_t *call(const std::vector<const datum_t *> &args);
    // Prefer these versions of call.
    val_t *call();
    val_t *call(const datum_t *arg);
    val_t *call(const datum_t *arg1, const datum_t *arg2);
    bool filter_call(const datum_t *arg);

    void dump_scope(std::map<int64_t, Datum> *out) const;
    bool is_deterministic() const;

private:
    // Pointers to this function's arguments.
    std::vector<const datum_t *> argptrs;
    term_t *body; // body to evaluate with functions bound

    // This is what's serialized over the wire.
    friend class wire_func_t;
    const Term *source;
    bool implicit_bound;

    // TODO: make this smarter (it's sort of slow and shitty as-is)
    std::map<int64_t, const datum_t **> scope;

    term_t *js_parent;
    env_t *js_env;
    js::id_t js_id;
};

class js_result_visitor_t : public boost::static_visitor<val_t *> {
public:
    typedef val_t *result_type;

    js_result_visitor_t(env_t *_env, term_t *_parent) : env(_env), parent(_parent) { }

    // This JS evaluation resulted in an error
    result_type operator()(const std::string err_val) const {
        rfail_target(parent, "%s", err_val.c_str());
        unreachable();
    }

    // This JS call resulted in a JSON value
    result_type operator()(const boost::shared_ptr<scoped_cJSON_t> json_val) const {
        return parent->new_val(new datum_t(json_val, env));
    }

    // This JS evaluation resulted in an id for a js function
    result_type operator()(const id_t id_val) const {
        return parent->new_val(new func_t(env, id_val, parent));
    }

private:
    env_t *env;
    term_t *parent;
};

RDB_MAKE_PROTOB_SERIALIZABLE(Term);
RDB_MAKE_PROTOB_SERIALIZABLE(Datum);

// Used to serialize a function (or gmr) over the wire.
class wire_func_t {
public:
    wire_func_t();
    wire_func_t(env_t *env, func_t *_func);
    wire_func_t(const Term &_source, std::map<int64_t, Datum> *_scope);

    func_t *compile(env_t *env);

    RDB_MAKE_ME_SERIALIZABLE_2(source, scope);

    const Backtrace *get_bt() const {
        return &source.GetExtension(ql2::extension::backtrace);
    }
private:
    // We cache a separate function for every environment.
    std::map<env_t *, func_t *> cached_funcs;

    Term source;
    std::map<int64_t, Datum> scope;
};

class map_wire_func_t : public wire_func_t {
public:
    template <class... Args>
    explicit map_wire_func_t(Args... args) : wire_func_t(args...) { }
};

class filter_wire_func_t : public wire_func_t {
public:
    template <class... Args>
    explicit filter_wire_func_t(Args... args) : wire_func_t(args...) { }
};

class reduce_wire_func_t : public wire_func_t {
public:
    template <class... Args>
    explicit reduce_wire_func_t(Args... args) : wire_func_t(args...) { }
};

class concatmap_wire_func_t : public wire_func_t {
public:
    template <class... Args>
    explicit concatmap_wire_func_t(Args... args) : wire_func_t(args...) { }
};

// Count is a fake function because we don't need to send anything.
class count_wire_func_t {
public:
    RDB_MAKE_ME_SERIALIZABLE_0()
    const Backtrace *get_bt() const {
        r_sanity_check(false); // Server should never crash here.
        unreachable();
    }
};

// Grouped Map Reduce
class gmr_wire_func_t {
public:
    gmr_wire_func_t() { }
    gmr_wire_func_t(env_t *env, func_t *_group, func_t *_map, func_t *_reduce)
        : group(env, _group), map(env, _map), reduce(env, _reduce) { }
    func_t *compile_group(env_t *env) { return group.compile(env); }
    func_t *compile_map(env_t *env) { return map.compile(env); }
    func_t *compile_reduce(env_t *env) { return reduce.compile(env); }

    const Backtrace *get_bt() const {
        // If this goes wrong at the toplevel, it goes wrong in reduce.
        return reduce.get_bt();
    }

private:
    map_wire_func_t group;
    map_wire_func_t map;
    reduce_wire_func_t reduce;
public:
    RDB_MAKE_ME_SERIALIZABLE_3(group, map, reduce);
};

// Evaluating this returns a `func_t` wrapped in a `val_t`.
class func_term_t : public term_t {
public:
    func_term_t(env_t *env, const Term *term);
private:
    virtual bool is_deterministic_impl() const;
    virtual val_t *eval_impl();
    virtual const char *name() const { return "func"; }
    func_t *func;
};

} // namespace ql
#endif // RDB_PROTOCOL_FUNC_HPP_
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "CppUTest/TestHarness.h"
#include "CppUTest/TestOutput.h"
#include "CppUTest/TestTestingFixture.h"

TEST_GROUP(Utest)
{
	TestTestingFixture* fixture;
	TEST_SETUP()
	{
		fixture = new TestTestingFixture();
	    UT_PTR_SET(PlatformSpecificExitCurrentTest, FakePlatformSpecificExitCurrentTest);
	}
	TEST_TEARDOWN()
	{
  		delete fixture;
  	}
};

static void _failMethod()
{
    FAIL("This test fails");
}

TEST(Utest, FailurePrintsSomething)
{
  fixture->setTestFunction(_failMethod);
  fixture->runAllTests();
  LONGS_EQUAL(1, fixture->getFailureCount());
  fixture->assertPrintContains("This test fails");
}

static void _LongsEqualFailMethod()
{
  LONGS_EQUAL(1, 0xff);
}

TEST(Utest, FailurePrintHexOutputForLongInts)
{
  fixture->setTestFunction(_LongsEqualFailMethod);
  fixture->runAllTests();
  fixture->assertPrintContains("expected <  1 0x01>");
  fixture->assertPrintContains("but was  <255 0xff>");
}

static void _passMethod()
{
	CHECK(true);
}

TEST(Utest, SuccessPrintsNothing)
{
  fixture->setTestFunction(_passMethod);
  fixture->runAllTests();
  LONGS_EQUAL(0, fixture->getFailureCount());
  fixture->assertPrintContains(".\nOK (1 tests");
}

TEST(Utest, allMacros)
{
  CHECK(0 == 0);
  LONGS_EQUAL(1,1);
  CHECK_EQUAL("THIS", "THIS");
  CHECK_EQUAL(100,100);
  STRCMP_EQUAL("THIS", "THIS");
  DOUBLES_EQUAL(1.0, 1.0, .01);
}

TEST(Utest, AssertsActLikeStatements)
{
  if (fixture != 0)
    CHECK(true)
  else
    CHECK(false)

  if (fixture != 0)
    CHECK_EQUAL(true, true)
  else
    CHECK_EQUAL(false, false)

  if (fixture != 0)
    STRCMP_EQUAL("", "")
    else
      STRCMP_EQUAL("", " ")

  if (fixture != 0)
    LONGS_EQUAL(1, 1)
    else
      LONGS_EQUAL(1, 0)

  if (fixture != 0)
    DOUBLES_EQUAL(1, 1, 0.01)
    else
      DOUBLES_EQUAL(1, 0, 0.01)

  if (false)
    FAIL("")
    else
      ;

  if (true)
    ;
  else
    FAIL("")

}

IGNORE_TEST(Utest, IgnoreTestSupportsAllMacros)
{
  CHECK(true);
  CHECK_EQUAL(true, true);
  STRCMP_EQUAL("", "");
  LONGS_EQUAL(1, 1);
  DOUBLES_EQUAL(1, 1, 0.01);
  FAIL("");
}

IGNORE_TEST(Utest, IgnoreTestAccessingFixture)
{
	CHECK(fixture != 0);
}

TEST(Utest, MacrosUsedInSetup)
{
	delete fixture->genTest;
	fixture->genTest = new ExecFunctionTest(_failMethod);
 	fixture->setTestFunction(_passMethod);
 	fixture->runAllTests();
	LONGS_EQUAL(1, fixture->getFailureCount());
}

TEST(Utest, MacrosUsedInTearDown)
{
	delete fixture->genTest;
	fixture->genTest = new ExecFunctionTest(0, _failMethod);
 	fixture->setTestFunction(_passMethod);
 	fixture->runAllTests();
	LONGS_EQUAL(1, fixture->getFailureCount());
}

TEST_BASE(MyOwnTest)
{
	MyOwnTest() : inTest(false) {}
	bool inTest;

	void setup()
	{
		CHECK(!inTest);
		inTest = true;
	}
	void teardown()
	{
		CHECK(inTest);
		inTest = false;
	}
};

TEST_GROUP_BASE(UtestMyOwn, MyOwnTest)
{
};

TEST(UtestMyOwn, test)
{
	CHECK(inTest);
}

class NullParameterTest : public Utest
{
};

TEST(UtestMyOwn, NullParameters)
{
	NullParameterTest nullTest; /* Bug fix tests for creating a test without a name, fix in SimpleString */
	TestRegistry* reg = TestRegistry::getCurrentRegistry();
	nullTest.shouldRun(reg->getGroupFilter(), reg->getNameFilter());
}

<commit_msg>added BYTES_EQUAL<commit_after>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "CppUTest/TestHarness.h"
#include "CppUTest/TestOutput.h"
#include "CppUTest/TestTestingFixture.h"

TEST_GROUP(Utest)
{
	TestTestingFixture* fixture;
	TEST_SETUP()
	{
		fixture = new TestTestingFixture();
	    UT_PTR_SET(PlatformSpecificExitCurrentTest, FakePlatformSpecificExitCurrentTest);
	}
	TEST_TEARDOWN()
	{
  		delete fixture;
  	}
};

static void _failMethod()
{
    FAIL("This test fails");
}

TEST(Utest, FailurePrintsSomething)
{
  fixture->setTestFunction(_failMethod);
  fixture->runAllTests();
  LONGS_EQUAL(1, fixture->getFailureCount());
  fixture->assertPrintContains("This test fails");
}

static void _LongsEqualFailMethod()
{
  LONGS_EQUAL(1, 0xff);
}

TEST(Utest, FailurePrintHexOutputForLongInts)
{
  fixture->setTestFunction(_LongsEqualFailMethod);
  fixture->runAllTests();
  fixture->assertPrintContains("expected <  1 0x01>");
  fixture->assertPrintContains("but was  <255 0xff>");
}

static void _passMethod()
{
	CHECK(true);
}

TEST(Utest, SuccessPrintsNothing)
{
  fixture->setTestFunction(_passMethod);
  fixture->runAllTests();
  LONGS_EQUAL(0, fixture->getFailureCount());
  fixture->assertPrintContains(".\nOK (1 tests");
}

TEST(Utest, allMacros)
{
  CHECK(0 == 0);
  LONGS_EQUAL(1,1);
  BYTES_EQUAL(0xab,0xab);
  CHECK_EQUAL("THIS", "THIS");
  CHECK_EQUAL(100,100);
  STRCMP_EQUAL("THIS", "THIS");
  DOUBLES_EQUAL(1.0, 1.0, .01);
}

TEST(Utest, AssertsActLikeStatements)
{
  if (fixture != 0)
    CHECK(true)
  else
    CHECK(false)

  if (fixture != 0)
    CHECK_EQUAL(true, true)
  else
    CHECK_EQUAL(false, false)

  if (fixture != 0)
    STRCMP_EQUAL("", "")
    else
      STRCMP_EQUAL("", " ")

  if (fixture != 0)
    LONGS_EQUAL(1, 1)
    else
      LONGS_EQUAL(1, 0)

  if (fixture != 0)
    DOUBLES_EQUAL(1, 1, 0.01)
    else
      DOUBLES_EQUAL(1, 0, 0.01)

  if (false)
    FAIL("")
    else
      ;

  if (true)
    ;
  else
    FAIL("")

}

IGNORE_TEST(Utest, IgnoreTestSupportsAllMacros)
{
  CHECK(true);
  CHECK_EQUAL(true, true);
  STRCMP_EQUAL("", "");
  LONGS_EQUAL(1, 1);
  DOUBLES_EQUAL(1, 1, 0.01);
  FAIL("");
}

IGNORE_TEST(Utest, IgnoreTestAccessingFixture)
{
	CHECK(fixture != 0);
}

TEST(Utest, MacrosUsedInSetup)
{
	delete fixture->genTest;
	fixture->genTest = new ExecFunctionTest(_failMethod);
 	fixture->setTestFunction(_passMethod);
 	fixture->runAllTests();
	LONGS_EQUAL(1, fixture->getFailureCount());
}

TEST(Utest, MacrosUsedInTearDown)
{
	delete fixture->genTest;
	fixture->genTest = new ExecFunctionTest(0, _failMethod);
 	fixture->setTestFunction(_passMethod);
 	fixture->runAllTests();
	LONGS_EQUAL(1, fixture->getFailureCount());
}

TEST_BASE(MyOwnTest)
{
	MyOwnTest() : inTest(false) {}
	bool inTest;

	void setup()
	{
		CHECK(!inTest);
		inTest = true;
	}
	void teardown()
	{
		CHECK(inTest);
		inTest = false;
	}
};

TEST_GROUP_BASE(UtestMyOwn, MyOwnTest)
{
};

TEST(UtestMyOwn, test)
{
	CHECK(inTest);
}

class NullParameterTest : public Utest
{
};

TEST(UtestMyOwn, NullParameters)
{
	NullParameterTest nullTest; /* Bug fix tests for creating a test without a name, fix in SimpleString */
	TestRegistry* reg = TestRegistry::getCurrentRegistry();
	nullTest.shouldRun(reg->getGroupFilter(), reg->getNameFilter());
}

<|endoftext|>


<commit_before>#include "master.hpp"

#include <boost/scoped_ptr.hpp>

#include "logger.hpp"
#include "replication/net_structs.hpp"
#include "replication/protocol.hpp"
#include "server/slice_dispatching_to_master.hpp"

namespace replication {

void master_t::register_dispatcher(btree_slice_dispatching_to_master_t *dispatcher) {
    dispatchers_.push_back(dispatcher);
}

void master_t::get_cas(const store_key_t& key, castime_t castime) {
    // There is something disgusting with this.  What if the thing
    // that the tmp_hold would prevent happens before we grap the
    // tmp_hold?  Right now, this can't happen because spawn_on_thread
    // won't block before we grab the tmp_hold, because we don't do
    // anything before.

    // TODO Is grabbing a tmp_hold really necessary?  I wish it wasn't.
    snag_ptr_t<master_t> tmp_hold(*this);

    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(castime.timestamp);

        size_t n = sizeof(net_get_cas_t) + key.size;
        scoped_malloc<net_get_cas_t> msg(n);
        msg->proposed_cas = castime.proposed_cas;
        msg->timestamp = castime.timestamp;
        msg->key_size = key.size;

        memcpy(msg->key, key.contents, key.size);

        stream_->send(msg.get());
    }
}

void master_t::sarc(const store_key_t& key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime, add_policy_t add_policy, replace_policy_t replace_policy, cas_t old_cas) {
    snag_ptr_t<master_t> tmp_hold(*this);

    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(castime.timestamp);

        net_sarc_t stru;
        stru.timestamp = castime.timestamp;
        stru.proposed_cas = castime.proposed_cas;
        stru.flags = flags;
        stru.exptime = exptime;
        stru.key_size = key.size;
        stru.value_size = data->get_size();
        stru.add_policy = add_policy;
        stru.replace_policy = replace_policy;
        stru.old_cas = old_cas;
        stream_->send(&stru, key.contents, data);
    }
    // TODO: do we delete data or does repli_stream_t delete it?
    delete data;
}

void master_t::incr_decr(incr_decr_kind_t kind, const store_key_t &key, uint64_t amount, castime_t castime) {
    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(castime.timestamp);

        if (kind == incr_decr_INCR) {
            incr_decr_like<net_incr_t>(INCR, key, amount, castime);
        } else {
            rassert(kind == incr_decr_DECR);
            incr_decr_like<net_decr_t>(DECR, key, amount, castime);
        }
    }
}

template <class net_struct_type>
void master_t::incr_decr_like(UNUSED uint8_t msgcode, UNUSED const store_key_t &key, uint64_t amount, castime_t castime) {
    // TODO: We aren't using the parameter key.  How did we do this?
    // TODO: We aren't using the parameter msgcode.  This is obviously broken!

    net_struct_type msg;
    msg.timestamp = castime.timestamp;
    msg.proposed_cas = castime.proposed_cas;
    msg.amount = amount;

    stream_->send(&msg);
}

void master_t::append_prepend(append_prepend_kind_t kind, const store_key_t &key, data_provider_t *data, castime_t castime) {
    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(castime.timestamp);

        if (kind == append_prepend_APPEND) {
            net_append_t appendstruct;
            appendstruct.timestamp = castime.timestamp;
            appendstruct.proposed_cas = castime.proposed_cas;
            appendstruct.key_size = key.size;
            appendstruct.value_size = data->get_size();

            stream_->send(&appendstruct, key.contents, data);
        } else {
            rassert(kind == append_prepend_PREPEND);

            net_prepend_t prependstruct;
            prependstruct.timestamp = castime.timestamp;
            prependstruct.proposed_cas = castime.proposed_cas;
            prependstruct.key_size = key.size;
            prependstruct.value_size = data->get_size();

            stream_->send(&prependstruct, key.contents, data);
        }
    }
    delete data;
}

void master_t::delete_key(const store_key_t &key, repli_timestamp timestamp) {
    size_t n = sizeof(net_delete_t) + key.size;
    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(timestamp);

        scoped_malloc<net_delete_t> msg(n);
        msg->timestamp = timestamp;
        msg->key_size = key.size;
        memcpy(msg->key, key.contents, key.size);

        stream_->send(msg.get());
    }
}

void nop_timer_trigger(void *master_) {
    master_t *master = reinterpret_cast<master_t *>(master_);

    master->consider_nop_dispatch_and_update_latest_timestamp(current_time());
}

void master_t::on_tcp_listener_accept(boost::scoped_ptr<linux_tcp_conn_t>& conn) {
    // TODO: Carefully handle case where a slave is already connected.

    // Right now we uncleanly close the slave connection.  What if
    // somebody has partially written a message to it (and writes the
    // rest of the message to conn?)  That will happen, the way the
    // code is, right now.
    {
        debugf("listener accept, destroying existing slave conn\n");
        destroy_existing_slave_conn_if_it_exists();
        debugf("making new repli_stream..\n");
        stream_ = new repli_stream_t(conn, this);
        next_timestamp_nop_timer_ = timer_handler_->add_timer_internal(1100, nop_timer_trigger, this, true);
        debugf("made repli_stream.\n");
    }
    // TODO when sending/receiving hello handshake, use database magic
    // to handle case where slave is already connected.

    // TODO receive hello handshake before sending other messages.
}

void master_t::destroy_existing_slave_conn_if_it_exists() {
    assert_thread();
    if (stream_) {
        stream_->co_shutdown();
        cancel_timer(next_timestamp_nop_timer_);
        next_timestamp_nop_timer_ = NULL;
    }

    stream_ = NULL;
}

void master_t::consider_nop_dispatch_and_update_latest_timestamp(repli_timestamp timestamp) {
    assert_thread();
    rassert(timestamp.time != repli_timestamp::invalid.time);

    if (timestamp.time > latest_timestamp_.time) {
        latest_timestamp_ = timestamp;
        coro_t::spawn(boost::bind(&master_t::do_nop_rebound, this, timestamp));
    }

    timer_handler_->cancel_timer(next_timestamp_nop_timer_);
    next_timestamp_nop_timer_ = timer_handler_->add_timer_internal(1100, nop_timer_trigger, this, true);
}

void master_t::do_nop_rebound(repli_timestamp t) {
    assert_thread();
    cond_t cond;
    int counter = dispatchers_.size();
    for (std::vector<btree_slice_dispatching_to_master_t *>::iterator p = dispatchers_.begin(), e = dispatchers_.end();
         p != e;
         ++p) {
        coro_t::spawn(boost::bind(&btree_slice_dispatching_to_master_t::nop_back_on_masters_thread, *p, t, &cond, &counter));
    }

    cond.wait();

    net_nop_t msg;
    msg.timestamp = t;
    stream_->send(msg);
}

struct do_backfill_cb : public backfill_callback_t {
    int count;
    master_t *master;
    cond_t *for_when_done;

    void on_keyvalue(backfill_atom_t atom) {
        coro_t::spawn_on_thread(master->home_thread, boost::bind(&master_t::send_backfill_atom_to_slave, master, atom));
    }
    void done() {
        coro_t::spawn_on_thread(master->home_thread, boost::bind(&do_backfill_cb::do_done, this));
    }

    void do_done() {
        rassert(get_thread_id() == master->home_thread);

        if (0 == --count) {
            for_when_done->pulse();
        }
    }
};

void master_t::do_backfill(repli_timestamp since_when) {
    assert_thread();
    debugf("Somebody called do_backfill(%u)\n", since_when.time);

    int n = dispatchers_.size();
    cond_t done_cond;

    do_backfill_cb cb;
    cb.count = n;
    cb.master = this;
    cb.for_when_done = &done_cond;

    for (int i = 0; i < n; ++i) {
        debugf("Spawning backfill %d of %d\n", i, n);
        dispatchers_[i]->spawn_backfill(since_when, &cb);
        debugf("Spawned... %d of %d\n", i, n);
    }

    debugf("Done spawning, now waiting for done_cond...\n");
    done_cond.wait();
    debugf("Done backfill.\n");
}

void master_t::send_backfill_atom_to_slave(backfill_atom_t atom) {
    const const_buffer_group_t *group = atom.value->get_data_as_buffers();
    debugf("Would have sent atom '%.*s': flags=%u exptime=%u recency=%u cas=%lu\n",
           atom.key.size, atom.key.contents, atom.flags, atom.exptime, atom.recency, atom.cas_or_zero);
    for (int i = 0, n = group->num_buffers(); i < n; ++i) {
        const_buffer_group_t::buffer_t buf = group->get_buffer(i);
        debugf("(Part): %.*s\n", buf.size, buf.data);
    }
    debugf("END\n");
}

}  // namespace replication

<commit_msg>Made send_backfill_atom_to_slave do more than just print debug message, actually use sarc.<commit_after>#include "master.hpp"

#include <boost/scoped_ptr.hpp>

#include "logger.hpp"
#include "replication/net_structs.hpp"
#include "replication/protocol.hpp"
#include "server/slice_dispatching_to_master.hpp"

namespace replication {

void master_t::register_dispatcher(btree_slice_dispatching_to_master_t *dispatcher) {
    dispatchers_.push_back(dispatcher);
}

void master_t::get_cas(const store_key_t& key, castime_t castime) {
    // There is something disgusting with this.  What if the thing
    // that the tmp_hold would prevent happens before we grap the
    // tmp_hold?  Right now, this can't happen because spawn_on_thread
    // won't block before we grab the tmp_hold, because we don't do
    // anything before.

    // TODO Is grabbing a tmp_hold really necessary?  I wish it wasn't.
    snag_ptr_t<master_t> tmp_hold(*this);

    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(castime.timestamp);

        size_t n = sizeof(net_get_cas_t) + key.size;
        scoped_malloc<net_get_cas_t> msg(n);
        msg->proposed_cas = castime.proposed_cas;
        msg->timestamp = castime.timestamp;
        msg->key_size = key.size;

        memcpy(msg->key, key.contents, key.size);

        stream_->send(msg.get());
    }
}

void master_t::sarc(const store_key_t& key, data_provider_t *data, mcflags_t flags, exptime_t exptime, castime_t castime, add_policy_t add_policy, replace_policy_t replace_policy, cas_t old_cas) {
    snag_ptr_t<master_t> tmp_hold(*this);

    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(castime.timestamp);

        net_sarc_t stru;
        stru.timestamp = castime.timestamp;
        stru.proposed_cas = castime.proposed_cas;
        stru.flags = flags;
        stru.exptime = exptime;
        stru.key_size = key.size;
        stru.value_size = data->get_size();
        stru.add_policy = add_policy;
        stru.replace_policy = replace_policy;
        stru.old_cas = old_cas;
        stream_->send(&stru, key.contents, data);
    }
    // TODO: do we delete data or does repli_stream_t delete it?
    delete data;
}

void master_t::incr_decr(incr_decr_kind_t kind, const store_key_t &key, uint64_t amount, castime_t castime) {
    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(castime.timestamp);

        if (kind == incr_decr_INCR) {
            incr_decr_like<net_incr_t>(INCR, key, amount, castime);
        } else {
            rassert(kind == incr_decr_DECR);
            incr_decr_like<net_decr_t>(DECR, key, amount, castime);
        }
    }
}

template <class net_struct_type>
void master_t::incr_decr_like(UNUSED uint8_t msgcode, UNUSED const store_key_t &key, uint64_t amount, castime_t castime) {
    // TODO: We aren't using the parameter key.  How did we do this?
    // TODO: We aren't using the parameter msgcode.  This is obviously broken!

    net_struct_type msg;
    msg.timestamp = castime.timestamp;
    msg.proposed_cas = castime.proposed_cas;
    msg.amount = amount;

    stream_->send(&msg);
}

void master_t::append_prepend(append_prepend_kind_t kind, const store_key_t &key, data_provider_t *data, castime_t castime) {
    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(castime.timestamp);

        if (kind == append_prepend_APPEND) {
            net_append_t appendstruct;
            appendstruct.timestamp = castime.timestamp;
            appendstruct.proposed_cas = castime.proposed_cas;
            appendstruct.key_size = key.size;
            appendstruct.value_size = data->get_size();

            stream_->send(&appendstruct, key.contents, data);
        } else {
            rassert(kind == append_prepend_PREPEND);

            net_prepend_t prependstruct;
            prependstruct.timestamp = castime.timestamp;
            prependstruct.proposed_cas = castime.proposed_cas;
            prependstruct.key_size = key.size;
            prependstruct.value_size = data->get_size();

            stream_->send(&prependstruct, key.contents, data);
        }
    }
    delete data;
}

void master_t::delete_key(const store_key_t &key, repli_timestamp timestamp) {
    size_t n = sizeof(net_delete_t) + key.size;
    if (stream_) {
        consider_nop_dispatch_and_update_latest_timestamp(timestamp);

        scoped_malloc<net_delete_t> msg(n);
        msg->timestamp = timestamp;
        msg->key_size = key.size;
        memcpy(msg->key, key.contents, key.size);

        stream_->send(msg.get());
    }
}

void nop_timer_trigger(void *master_) {
    master_t *master = reinterpret_cast<master_t *>(master_);

    master->consider_nop_dispatch_and_update_latest_timestamp(current_time());
}

void master_t::on_tcp_listener_accept(boost::scoped_ptr<linux_tcp_conn_t>& conn) {
    // TODO: Carefully handle case where a slave is already connected.

    // Right now we uncleanly close the slave connection.  What if
    // somebody has partially written a message to it (and writes the
    // rest of the message to conn?)  That will happen, the way the
    // code is, right now.
    {
        debugf("listener accept, destroying existing slave conn\n");
        destroy_existing_slave_conn_if_it_exists();
        debugf("making new repli_stream..\n");
        stream_ = new repli_stream_t(conn, this);
        next_timestamp_nop_timer_ = timer_handler_->add_timer_internal(1100, nop_timer_trigger, this, true);
        debugf("made repli_stream.\n");
    }
    // TODO when sending/receiving hello handshake, use database magic
    // to handle case where slave is already connected.

    // TODO receive hello handshake before sending other messages.
}

void master_t::destroy_existing_slave_conn_if_it_exists() {
    assert_thread();
    if (stream_) {
        stream_->co_shutdown();
        cancel_timer(next_timestamp_nop_timer_);
        next_timestamp_nop_timer_ = NULL;
    }

    stream_ = NULL;
}

void master_t::consider_nop_dispatch_and_update_latest_timestamp(repli_timestamp timestamp) {
    assert_thread();
    rassert(timestamp.time != repli_timestamp::invalid.time);

    if (timestamp.time > latest_timestamp_.time) {
        latest_timestamp_ = timestamp;
        coro_t::spawn(boost::bind(&master_t::do_nop_rebound, this, timestamp));
    }

    timer_handler_->cancel_timer(next_timestamp_nop_timer_);
    next_timestamp_nop_timer_ = timer_handler_->add_timer_internal(1100, nop_timer_trigger, this, true);
}

void master_t::do_nop_rebound(repli_timestamp t) {
    assert_thread();
    cond_t cond;
    int counter = dispatchers_.size();
    for (std::vector<btree_slice_dispatching_to_master_t *>::iterator p = dispatchers_.begin(), e = dispatchers_.end();
         p != e;
         ++p) {
        coro_t::spawn(boost::bind(&btree_slice_dispatching_to_master_t::nop_back_on_masters_thread, *p, t, &cond, &counter));
    }

    cond.wait();

    net_nop_t msg;
    msg.timestamp = t;
    stream_->send(msg);
}

struct do_backfill_cb : public backfill_callback_t {
    int count;
    master_t *master;
    cond_t *for_when_done;

    void on_keyvalue(backfill_atom_t atom) {
        coro_t::spawn_on_thread(master->home_thread, boost::bind(&master_t::send_backfill_atom_to_slave, master, atom));
    }
    void done() {
        coro_t::spawn_on_thread(master->home_thread, boost::bind(&do_backfill_cb::do_done, this));
    }

    void do_done() {
        rassert(get_thread_id() == master->home_thread);

        if (0 == --count) {
            for_when_done->pulse();
        }
    }
};

void master_t::do_backfill(repli_timestamp since_when) {
    assert_thread();
    debugf("Somebody called do_backfill(%u)\n", since_when.time);

    int n = dispatchers_.size();
    cond_t done_cond;

    do_backfill_cb cb;
    cb.count = n;
    cb.master = this;
    cb.for_when_done = &done_cond;

    for (int i = 0; i < n; ++i) {
        debugf("Spawning backfill %d of %d\n", i, n);
        dispatchers_[i]->spawn_backfill(since_when, &cb);
        debugf("Spawned... %d of %d\n", i, n);
    }

    debugf("Done spawning, now waiting for done_cond...\n");
    done_cond.wait();
    debugf("Done backfill.\n");
}

void master_t::send_backfill_atom_to_slave(backfill_atom_t atom) {
    // TODO: This is bad because (1) the slave can't sort out
    // backfilling messages from real ones.
    //
    // TODO: Make sure that we're sending things such that the slave
    // uses the latest cas value if it's not zero, and doesn't simply
    // discard it or do something stupid like that.

    debugf("We are about to send atom '%.*s': flags=%u exptime=%u recency=%u cas=%lu...\n",
           atom.key.size, atom.key.contents, atom.flags, atom.exptime, atom.recency, atom.cas_or_zero);

    sarc(atom.key, atom.value.release(), atom.flags, atom.exptime, castime_t(atom.cas_or_zero, atom.recency), add_policy_yes, replace_policy_yes, NO_CAS_SUPPLIED);

    debugf("Finished sending atom '%.*s'.\n", atom.key.size, atom.key.contents);
}

}  // namespace replication

<|endoftext|>


<commit_before>#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <vector>

#include "Shader.h"
#include "Program.h"
#include "Uniforms.h"
#include "Geometry.h"
#include "Model.h"
#include "Camera.h"
#include "CameraControls.h"
#include "Texture.h"
#include "TextureCube.h"

#include "DebugOpengl.h"

static std::string vertexShaderSource = "\
#version 150\n\
in vec3 iPosition;\
in vec3 iNormal;\
out vec3 normal;\
out vec3 position;\
uniform mat4 uModelView;\
void main() \
{ \
  gl_Position = uModelView * vec4(iPosition, 1); \
  normal = iNormal;\n\
  position = iPosition;\n\
}";

static std::string fragmentShaderSource = "\
#version 150\n\
struct Light \
{ \
  vec3 color; \
  vec3 position;\
  float intensity; \
}; \
uniform Light light;\
uniform sampler2D sampler;\
uniform samplerCube cube;\
in vec3 normal;\n\
in vec3 position; \n\
out vec4 oColor;\n\
void main(void)\n\
{\n\
  vec3 lightDir = light.position - position;\n\
  lightDir = normalize(lightDir);\n\
  float NdotL = max( dot(normal, lightDir), 0.0f );\n\
  oColor = vec4(vec3(0.3f, 0.3f, 0.3f) * light.color * NdotL, 1);\n\
  vec4 res = texture2D(sampler, position.xz/10);\n\
  oColor = vec4(res.xyz, 1);\n\
  oColor = texture(cube, normal);\n\
}";

int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if(!glfwInit())
      return -1;

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(2*640, 2*480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    glewExperimental = GL_TRUE;
    /* Initialize extension loader once context up*/
    if(GLEW_OK != glewInit())
      return -1;

    if (glewIsSupported("GL_ARB_debug_output")) {
        glDebugMessageCallback(DebugCallbackARB, stderr); // print debug output to stderr
        glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
    } else {
      std::cerr << "Error detection not supported" << std::endl;
      assert(0);
    }

    std::cout << "VENDOR: " << glGetString(GL_VENDOR) << std::endl;
    std::cout << "RENDERER: " << glGetString(GL_RENDERER) << std::endl;
    std::cout << "VERSION: " << glGetString(GL_VERSION) << std::endl;
    std::cout << "GLSL: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
    //Setup inputs
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    Shader::Ptr vertexShader = createShaderFromSource(Shader::Type::Vertex, vertexShaderSource);
    Shader::Ptr fragmentShader = createShaderFromSource(Shader::Type::Fragment, fragmentShaderSource);

    std::vector<Shader::Ptr> shaders{vertexShader, fragmentShader};
    Program::Ptr program = createProgramWithShaders(shaders);

    Geometry::Ptr geometry = createGeometryFromFile("./assets/perlin.geo");

    Model::Ptr model = createModel(geometry);
    Camera::Ptr camera = createCamera();
    camera->projection = glm::perspective(45.0f, 4.0f/3.0f, 0.1f, 500.0f);
    camera->view = glm::lookAt(
        glm::vec3(0,100,-100), //Position
        glm::vec3(0,0,0), //Look at
        glm::vec3(0,1,0) //up
    );

    geometry->bindGlBuffers();

    Light::Ptr light = createLight(glm::vec3(0,10,0), glm::vec3(1, .5, .4), 1.0f);

    Texture::Ptr texture = createTextureFromFile("./tests/assets/texture.jpg");

    setUniformTexture(program, "sampler", texture, 0);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glEnable(GL_DEPTH_TEST);

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glfwSetCursorPos(window, width/2, height/2);
    glfwSwapBuffers(window);
    glfwPollEvents();

    TextureCube::Ptr cube = createTextureCubeWithPrefix("./tests/assets/cube", "png");
    setUniformTexture(program, "cube", texture, 0);

    while (!glfwWindowShouldClose(window))
    {
      glfwGetFramebufferSize(window, &width, &height);
      glViewport(0, 0, width, height);

      float right = glfwGetKey(window, GLFW_KEY_D) == GLFW_RELEASE ? 0 : 1;
      right += glfwGetKey(window, GLFW_KEY_A) == GLFW_RELEASE ? 0 :-1;

      float in = glfwGetKey(window, GLFW_KEY_W) == GLFW_RELEASE ? 0 : 1;
      in += glfwGetKey(window, GLFW_KEY_S) == GLFW_RELEASE ? 0 :-1;

      float scale = 3;
      //CameraControls::panHorizontal(camera, right, scale);
      CameraControls::panInto(camera, in * scale);
      CameraControls::panHorizontal(camera, -right * scale);

      double newCursorX, newCursorY;
      float rotateScale = .4f;
      glfwGetCursorPos(window, &newCursorX, &newCursorY);
      glfwSetCursorPos(window, width/2, height/2);
      CameraControls::rotateHorizontal(camera, (newCursorX - width/2) * rotateScale);
      CameraControls::rotateVertical(camera, (newCursorY - height/2) * rotateScale);

      /* Render here */
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear depthbit here if depth on

      renderModelFromCamera(camera, model, program);

      light->position.x += .1f;
      setLightUniform(program, light);
      /* Swap front and back buffers */
      glfwSwapBuffers(window);
      /* Poll for and process events */
      glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
<commit_msg>changed debug message to use ARB version for greater compatibility<commit_after>#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <vector>

#include "Shader.h"
#include "Program.h"
#include "Uniforms.h"
#include "Geometry.h"
#include "Model.h"
#include "Camera.h"
#include "CameraControls.h"
#include "Texture.h"
#include "TextureCube.h"

#include "DebugOpengl.h"

static std::string vertexShaderSource = "\
#version 150\n\
in vec3 iPosition;\
in vec3 iNormal;\
out vec3 normal;\
out vec3 position;\
uniform mat4 uModelView;\
void main() \
{ \
  gl_Position = uModelView * vec4(iPosition, 1); \
  normal = iNormal;\n\
  position = iPosition;\n\
}";

static std::string fragmentShaderSource = "\
#version 150\n\
struct Light \
{ \
  vec3 color; \
  vec3 position;\
  float intensity; \
}; \
uniform Light light;\
uniform sampler2D sampler;\
uniform samplerCube cube;\
in vec3 normal;\n\
in vec3 position; \n\
out vec4 oColor;\n\
void main(void)\n\
{\n\
  vec3 lightDir = light.position - position;\n\
  lightDir = normalize(lightDir);\n\
  float NdotL = max( dot(normal, lightDir), 0.0f );\n\
  oColor = vec4(vec3(0.3f, 0.3f, 0.3f) * light.color * NdotL, 1);\n\
  vec4 res = texture2D(sampler, position.xz/10);\n\
  oColor = vec4(res.xyz, 1);\n\
  oColor = texture(cube, normal);\n\
}";

int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if(!glfwInit())
      return -1;

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(2*640, 2*480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    glewExperimental = GL_TRUE;
    /* Initialize extension loader once context up*/
    if(GLEW_OK != glewInit())
      return -1;

    if (glewIsSupported("GL_ARB_debug_output")) {
        glDebugMessageCallbackARB(DebugCallbackARB, stderr); // print debug output to stderr
        glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
    } else {
      std::cerr << "Error detection not supported" << std::endl;
      assert(0);
    }

    std::cout << "VENDOR: " << glGetString(GL_VENDOR) << std::endl;
    std::cout << "RENDERER: " << glGetString(GL_RENDERER) << std::endl;
    std::cout << "VERSION: " << glGetString(GL_VERSION) << std::endl;
    std::cout << "GLSL: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
    //Setup inputs
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    Shader::Ptr vertexShader = createShaderFromSource(Shader::Type::Vertex, vertexShaderSource);
    Shader::Ptr fragmentShader = createShaderFromSource(Shader::Type::Fragment, fragmentShaderSource);

    std::vector<Shader::Ptr> shaders{vertexShader, fragmentShader};
    Program::Ptr program = createProgramWithShaders(shaders);

    Geometry::Ptr geometry = createGeometryFromFile("./assets/perlin.geo");

    Model::Ptr model = createModel(geometry);
    Camera::Ptr camera = createCamera();
    camera->projection = glm::perspective(45.0f, 4.0f/3.0f, 0.1f, 500.0f);
    camera->view = glm::lookAt(
        glm::vec3(0,100,-100), //Position
        glm::vec3(0,0,0), //Look at
        glm::vec3(0,1,0) //up
    );

    geometry->bindGlBuffers();

    Light::Ptr light = createLight(glm::vec3(0,10,0), glm::vec3(1, .5, .4), 1.0f);

    Texture::Ptr texture = createTextureFromFile("./tests/assets/texture.jpg");

    setUniformTexture(program, "sampler", texture, 0);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glEnable(GL_DEPTH_TEST);

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glfwSetCursorPos(window, width/2, height/2);
    glfwSwapBuffers(window);
    glfwPollEvents();

    TextureCube::Ptr cube = createTextureCubeWithPrefix("./tests/assets/cube", "png");
    setUniformTexture(program, "cube", texture, 0);

    while (!glfwWindowShouldClose(window))
    {
      glfwGetFramebufferSize(window, &width, &height);
      glViewport(0, 0, width, height);

      float right = glfwGetKey(window, GLFW_KEY_D) == GLFW_RELEASE ? 0 : 1;
      right += glfwGetKey(window, GLFW_KEY_A) == GLFW_RELEASE ? 0 :-1;

      float in = glfwGetKey(window, GLFW_KEY_W) == GLFW_RELEASE ? 0 : 1;
      in += glfwGetKey(window, GLFW_KEY_S) == GLFW_RELEASE ? 0 :-1;

      float scale = 3;
      //CameraControls::panHorizontal(camera, right, scale);
      CameraControls::panInto(camera, in * scale);
      CameraControls::panHorizontal(camera, -right * scale);

      double newCursorX, newCursorY;
      float rotateScale = .4f;
      glfwGetCursorPos(window, &newCursorX, &newCursorY);
      glfwSetCursorPos(window, width/2, height/2);
      CameraControls::rotateHorizontal(camera, (newCursorX - width/2) * rotateScale);
      CameraControls::rotateVertical(camera, (newCursorY - height/2) * rotateScale);

      /* Render here */
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear depthbit here if depth on

      renderModelFromCamera(camera, model, program);

      light->position.x += .1f;
      setLightUniform(program, light);
      /* Swap front and back buffers */
      glfwSwapBuffers(window);
      /* Poll for and process events */
      glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkAdaptImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
/**
 *
 *  This program illustrates the AdaptImageFilter
 *
 *  The example shows how an Accessor can be used to
 *  convert an RGBPixel image to an image that has
 *  just the red component.
 *
 *  That will allow to pass the red component of this
 *  image as input any filter that expects
 *  a float image
 *
 */

#include <itkAdaptImageFilter.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkRGBPixel.h>
#include <itkRedPixelAccessor.h>
#include <itkGreenPixelAccessor.h>
#include <itkBluePixelAccessor.h>
#include "itkFilterWatcher.h"

#include <vnl/vnl_sample.h>

//-------------------------------------
//     Typedefs for convenience
//-------------------------------------
typedef itk::Image< itk::RGBPixel<float>,   2 > myRGBImageType;
typedef itk::ImageRegionIteratorWithIndex< myRGBImageType >  myRGBIteratorType;

typedef itk::RedPixelAccessor<float> myRedAccessorType;
typedef itk::GreenPixelAccessor<float> myGreenAccessorType;
typedef itk::BluePixelAccessor<float> myBlueAccessorType;

typedef itk::Image< float,   2 > myImageType;
typedef itk::ImageRegionIteratorWithIndex< myImageType >  myIteratorType;

//-------------------------
//
//   Main code
//
//-------------------------
int itkAdaptImageFilterTest(int, char* [] ) {

  myRGBImageType::SizeType size;
  size[0] = 2;
  size[1] = 2;

  myRGBImageType::IndexType index;
  index[0] = 0;
  index[1] = 0;

  myRGBImageType::RegionType region;
  region.SetIndex( index );
  region.SetSize(  size  );

  myRGBImageType::Pointer myImage = myRGBImageType::New();

  myImage->SetRegions( region );
  myImage->Allocate();

  myRGBIteratorType  it1( myImage, myImage->GetRequestedRegion() );

  // Value to initialize the pixels
  myRGBImageType::PixelType color;

  // Initializing all the pixel in the image
  it1.GoToBegin();
  while( !it1.IsAtEnd() )
    {
    color.Set( (float) vnl_sample_uniform(0.0, 1.0),
               (float) vnl_sample_uniform(0.0, 1.0),
               (float) vnl_sample_uniform(0.0, 1.0) );
    it1.Set(color);
    ++it1;
    }

  // Reading the values to verify the image content
  std::cout << "--- Initial image --- " << std::endl;
  it1.GoToBegin();
  while( !it1.IsAtEnd() )
    {
    const myRGBImageType::PixelType c( it1.Get() );
    std::cout << c.GetRed()   << "  ";
    std::cout << c.GetGreen() << "  ";
    std::cout << c.GetBlue()  << std::endl;
    ++it1;
    }

  bool passed = true;

  // Convert to a red image
  itk::AdaptImageFilter<myRGBImageType, myImageType, myRedAccessorType>::Pointer  adaptImageToRed = itk::AdaptImageFilter<myRGBImageType, myImageType, myRedAccessorType>::New();
  FilterWatcher redWatcher(adaptImageToRed, "Red");
  adaptImageToRed->SetInput(myImage);
  adaptImageToRed->UpdateLargestPossibleRegion();
  adaptImageToRed->SetFunctor(adaptImageToRed->GetFunctor());

  myIteratorType  it( adaptImageToRed->GetOutput(), adaptImageToRed->GetOutput()->GetRequestedRegion() );

  std::cout << "--- Red values --- " << std::endl;

  it.GoToBegin();
  it1.GoToBegin();
  while( !it.IsAtEnd() )
  {
  std::cout << it.Get()   << std::endl;
  if (it.Get() != it1.Get().GetRed())
    {
    passed = false;
    }

  ++it;
  ++it1;
  }

  // Convert to a green image
  itk::AdaptImageFilter<myRGBImageType, myImageType, myGreenAccessorType>::Pointer  adaptImageToGreen = itk::AdaptImageFilter<myRGBImageType, myImageType, myGreenAccessorType>::New();
  FilterWatcher greenWatcher(adaptImageToGreen, "Green");

  adaptImageToGreen->SetInput(myImage);
  adaptImageToGreen->UpdateLargestPossibleRegion();

  it = myIteratorType( adaptImageToGreen->GetOutput(), adaptImageToGreen->GetOutput()->GetRequestedRegion() );

  std::cout << "--- Green values --- " << std::endl;

  it.GoToBegin();
  it1.GoToBegin();
  while( !it.IsAtEnd() )
  {
  std::cout << it.Get()   << std::endl;
  if (it.Get() != it1.Get().GetGreen())
    {
    passed = false;
    }

  ++it;
  ++it1;
  }

  // Convert to a blue image
  itk::AdaptImageFilter<myRGBImageType, myImageType, myBlueAccessorType>::Pointer  adaptImageToBlue = itk::AdaptImageFilter<myRGBImageType, myImageType, myBlueAccessorType>::New();
  FilterWatcher blueWatcher(adaptImageToBlue, "Blue");

  adaptImageToBlue->SetInput(myImage);
  adaptImageToBlue->UpdateLargestPossibleRegion();

  it = myIteratorType( adaptImageToBlue->GetOutput(), adaptImageToBlue->GetOutput()->GetRequestedRegion() );

  std::cout << "--- Blue values --- " << std::endl;

  it.GoToBegin();
  it1.GoToBegin();
  while( !it.IsAtEnd() )
  {
  std::cout << it.Get()   << std::endl;
  if (it.Get() != it1.Get().GetBlue())
    {
    passed = false;
    }

  ++it;
  ++it1;
  }

  std::cout << std::endl;
  if (passed)
    {
    std::cout << "AdaptImageFilterTest passed" << std::endl;
    return EXIT_SUCCESS;
    }
  else
    {
    std::cout << "AdaptImageFilterTest passed" << std::endl;
    return EXIT_FAILURE;
    }
}

<commit_msg>STYLE: Fixed style regarding test pass/failure message. Both 'cout' a 'pass.'        Has been adjusted to 'cerr', and EXIT_FAILURE reflects the failure.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkAdaptImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
/**
 *
 *  This program illustrates the AdaptImageFilter
 *
 *  The example shows how an Accessor can be used to
 *  convert an RGBPixel image to an image that has
 *  just the red component.
 *
 *  That will allow to pass the red component of this
 *  image as input any filter that expects
 *  a float image
 *
 */

#include <itkAdaptImageFilter.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkRGBPixel.h>
#include <itkRedPixelAccessor.h>
#include <itkGreenPixelAccessor.h>
#include <itkBluePixelAccessor.h>
#include "itkFilterWatcher.h"

#include <vnl/vnl_sample.h>

//-------------------------------------
//     Typedefs for convenience
//-------------------------------------
typedef itk::Image< itk::RGBPixel<float>,   2 > myRGBImageType;
typedef itk::ImageRegionIteratorWithIndex< myRGBImageType >  myRGBIteratorType;

typedef itk::RedPixelAccessor<float> myRedAccessorType;
typedef itk::GreenPixelAccessor<float> myGreenAccessorType;
typedef itk::BluePixelAccessor<float> myBlueAccessorType;

typedef itk::Image< float,   2 > myImageType;
typedef itk::ImageRegionIteratorWithIndex< myImageType >  myIteratorType;

//-------------------------
//
//   Main code
//
//-------------------------
int itkAdaptImageFilterTest(int, char* [] ) {

  myRGBImageType::SizeType size;
  size[0] = 2;
  size[1] = 2;

  myRGBImageType::IndexType index;
  index[0] = 0;
  index[1] = 0;

  myRGBImageType::RegionType region;
  region.SetIndex( index );
  region.SetSize(  size  );

  myRGBImageType::Pointer myImage = myRGBImageType::New();

  myImage->SetRegions( region );
  myImage->Allocate();

  myRGBIteratorType  it1( myImage, myImage->GetRequestedRegion() );

  // Value to initialize the pixels
  myRGBImageType::PixelType color;

  // Initializing all the pixel in the image
  it1.GoToBegin();
  while( !it1.IsAtEnd() )
    {
    color.Set( (float) vnl_sample_uniform(0.0, 1.0),
               (float) vnl_sample_uniform(0.0, 1.0),
               (float) vnl_sample_uniform(0.0, 1.0) );
    it1.Set(color);
    ++it1;
    }

  // Reading the values to verify the image content
  std::cout << "--- Initial image --- " << std::endl;
  it1.GoToBegin();
  while( !it1.IsAtEnd() )
    {
    const myRGBImageType::PixelType c( it1.Get() );
    std::cout << c.GetRed()   << "  ";
    std::cout << c.GetGreen() << "  ";
    std::cout << c.GetBlue()  << std::endl;
    ++it1;
    }

  bool passed = true;

  // Convert to a red image
  itk::AdaptImageFilter<myRGBImageType, myImageType, myRedAccessorType>::Pointer  adaptImageToRed = itk::AdaptImageFilter<myRGBImageType, myImageType, myRedAccessorType>::New();
  FilterWatcher redWatcher(adaptImageToRed, "Red");
  adaptImageToRed->SetInput(myImage);
  adaptImageToRed->UpdateLargestPossibleRegion();
  adaptImageToRed->SetFunctor(adaptImageToRed->GetFunctor());

  myIteratorType  it( adaptImageToRed->GetOutput(), adaptImageToRed->GetOutput()->GetRequestedRegion() );

  std::cout << "--- Red values --- " << std::endl;

  it.GoToBegin();
  it1.GoToBegin();
  while( !it.IsAtEnd() )
  {
  std::cout << it.Get()   << std::endl;
  if (it.Get() != it1.Get().GetRed())
    {
    passed = false;
    }

  ++it;
  ++it1;
  }

  // Convert to a green image
  itk::AdaptImageFilter<myRGBImageType, myImageType, myGreenAccessorType>::Pointer  adaptImageToGreen = itk::AdaptImageFilter<myRGBImageType, myImageType, myGreenAccessorType>::New();
  FilterWatcher greenWatcher(adaptImageToGreen, "Green");

  adaptImageToGreen->SetInput(myImage);
  adaptImageToGreen->UpdateLargestPossibleRegion();

  it = myIteratorType( adaptImageToGreen->GetOutput(), adaptImageToGreen->GetOutput()->GetRequestedRegion() );

  std::cout << "--- Green values --- " << std::endl;

  it.GoToBegin();
  it1.GoToBegin();
  while( !it.IsAtEnd() )
  {
  std::cout << it.Get()   << std::endl;
  if (it.Get() != it1.Get().GetGreen())
    {
    passed = false;
    }

  ++it;
  ++it1;
  }

  // Convert to a blue image
  itk::AdaptImageFilter<myRGBImageType, myImageType, myBlueAccessorType>::Pointer  adaptImageToBlue = itk::AdaptImageFilter<myRGBImageType, myImageType, myBlueAccessorType>::New();
  FilterWatcher blueWatcher(adaptImageToBlue, "Blue");

  adaptImageToBlue->SetInput(myImage);
  adaptImageToBlue->UpdateLargestPossibleRegion();

  it = myIteratorType( adaptImageToBlue->GetOutput(), adaptImageToBlue->GetOutput()->GetRequestedRegion() );

  std::cout << "--- Blue values --- " << std::endl;

  it.GoToBegin();
  it1.GoToBegin();
  while( !it.IsAtEnd() )
  {
  std::cout << it.Get()   << std::endl;
  if (it.Get() != it1.Get().GetBlue())
    {
    passed = false;
    }

  ++it;
  ++it1;
  }

  std::cout << std::endl;
  if (passed)
    {
    std::cerr << "AdaptImageFilterTest passed." << std::endl;
    return EXIT_SUCCESS;
    }
  else
    {
    std::cerr << "AdaptImageFilterTest failed." << std::endl;
    return EXIT_FAILURE;
    }
}

<|endoftext|>


<commit_before>/**
 ** \file runner/interpreter.hh
 ** \brief Definition of runner::Interpreter.
 */

#ifndef RUNNER_INTERPRETER_HH
# define RUNNER_INTERPRETER_HH

# include <boost/tuple/tuple.hpp>

# include <libport/hash.hh>

# include <ast/fwd.hh>
# include <object/object.hh>
# include <scheduler/scheduler.hh>
# include <scheduler/job.hh>

# include <runner/runner.hh>
# include <runner/stacks.hh>

namespace runner
{

  /// Ast executor.
  class Interpreter : public runner::Runner
  {
  public:
    /// \name Useful shorthands.
    /// \{
    /// Super class type.
    typedef runner::Runner super_type;
    typedef object::rObject rObject;
    typedef object::rrObject rrObject;
    typedef object::rRoutine rRoutine;
    typedef object::rLobby rLobby;
    typedef object::objects_type objects_type;
    /// \}

    /// \name Ctor & dtor.
    /// \{
    /// Construct a \c Interpreter in the \a lobby.  The runner needs
    /// to know its \a scheduler and will execute \a ast.  Memory
    /// ownership of \a ast is transferred to the Interpreter.  The
    /// new runner has no parent.
    Interpreter(rLobby lobby,
                scheduler::Scheduler& scheduler,
                ast::rConstAst ast,
                const libport::Symbol& name = SYMBOL());

    Interpreter(const Interpreter&,
                rObject code,
                const libport::Symbol& name = SYMBOL(),
                const objects_type& args = objects_type());

    /// Create a copy of a runner starting with another ast.
    Interpreter(const Interpreter&,
                ast::rConstAst ast,
                const libport::Symbol& name = SYMBOL());

    /// Destroy a Interpreter.
    virtual ~Interpreter();
    /// \}

    /// The entry point: visit \a e.
    object::rObject operator() (const ast::Ast* e);

    /// \ name Accessors.
    /// \{
  public:
    /// \}

    /// Execute the code of function \a func with arguments \a args in
    /// the local runner.
    ///
    /// \param func  the "function" to call: Primitive, Delegate, Code
    ///              or even rObject, in which case it is returned.
    ///
    /// \param msg   the name of the called method, as it should be stored
    ///              in a call message in case further processing is
    ///              required.
    ///
    /// \param args  the arguments.  Used as given, they are not evaluated
    ///              here.
    ///
    /// \param call_message  the callMessage.  Valid only for \a func
    ///             being Code.
    ///
    /// One cannot have both a call message and args.
    virtual rObject apply(const rObject& func,
                          const libport::Symbol msg,
                          object::objects_type& args,
                          rObject call_message = 0);

    virtual rObject apply(const rObject& func,
                          const libport::Symbol msg,
                          object::objects_type& args,
                          boost::optional<ast::loc> loc,
                          rObject call_message = 0);

    /// Helpers to apply a function with the arguments as ast chunks
    rObject apply(const rObject& tgt,
                  const libport::Symbol& msg,
                  const ast::exps_type* args,
                  boost::optional<ast::loc> loc);
    rObject apply(const rObject& tgt,
                  const rObject& f,
                  const libport::Symbol& msg,
                  const ast::exps_type* args,
                  boost::optional<ast::loc> loc);

    /// Return the result of the latest evaluation.
    virtual rObject result_get();

    /// Evaluate an expression in the current scope and return its result.
    rObject eval(ast::rConstAst);

    /// Evaluate a tag and create it as well as the intermediate levels
    /// if needed.
    rObject eval_tag(ast::rConstExp);

    /// Make an urbi function from an ast chunk
    object::rRoutine make_routine(ast::rConstRoutine f) const;

  protected:
    /// \name Evaluation.
    /// \{
    /// Build an evaluated arguments list containing \a tgt and
    /// arguments coming from \a args evaluated in the current context.
    /// Raise an error if any argument is void.
    void push_evaluated_arguments (object::objects_type& args,
				   const ast::exps_type& ue_args);

    /// Build a call message
    virtual rObject
    build_call_message(const rObject& tgt,
		       const rObject& code,
		       const libport::Symbol& msg,
                       const object::objects_type& args);

    /// Build a call message
    rObject build_call_message(const rObject& tgt,
			       const rObject& code,
			       const libport::Symbol& msg,
                               const ast::exps_type& args);

  public:

    object::rObject visit(const ast::And* n);
    object::rObject visit(const ast::Assignment* n);
    object::rObject visit(const ast::Call* n);
    object::rObject visit(const ast::CallMsg* n);
    object::rObject visit(const ast::Closure* n);
    object::rObject visit(const ast::Do* n);
    object::rObject visit(const ast::Declaration* n);
    object::rObject visit(const ast::Float* n);
    object::rObject visit(const ast::Foreach* n);
    object::rObject visit(const ast::Function* n);
    object::rObject visit(const ast::If* n);
    object::rObject visit(const ast::Lazy* n);
    object::rObject visit(const ast::List* n);
    object::rObject visit(const ast::Local* n);
    object::rObject visit(const ast::Message* n);
    object::rObject visit(const ast::Nary* n);
    object::rObject visit(const ast::Noop* n);
    object::rObject visit(const ast::Pipe* n);
    object::rObject visit(const ast::Scope* n);
    object::rObject visit(const ast::Stmt* n);
    object::rObject visit(const ast::String* n);
    object::rObject visit(const ast::Tag* n);
    object::rObject visit(const ast::TaggedStmt* n);
    object::rObject visit(const ast::This* n);
    object::rObject visit(const ast::While* n);

    object::rObject visit(const ast::Binding* n);
    object::rObject visit(const ast::Break* n);
    object::rObject visit(const ast::Continue* n);
    object::rObject visit(const ast::Implicit* n);
    object::rObject visit(const ast::MetaExp* n);
    object::rObject visit(const ast::Return* n);
    /// \}

    /// Do the actual work.  Implementation of \c Job::run.
    virtual void work ();

    virtual void show_backtrace(const std::string& chan);
    virtual backtrace_type backtrace_get() const;

  protected:
    void show_error_ (object::UrbiException& ue);

  private:
    void init();
    /// Reset result_, set the location and call stack of ue.
    void propagate_error_(object::UrbiException& ue, const ast::loc& l);
    rObject apply_urbi (rRoutine func,
			const libport::Symbol& msg,
			const object::objects_type& args,
			rObject call_message);

  private:
    /// Factor handling of Function and Closure
    object::rObject visit(const ast::Routine* e, bool closure);

    /// The root of the AST being executed.
    ast::rConstAst ast_;

    /// The urbi Code object to execute
    rObject code_;
    /// Its arguments
    objects_type args_;

    /// The current value during the evaluation of the AST.
    rObject result_;

    /// The call stack.
    typedef object::UrbiException::call_stack_type call_stack_type;
    typedef object::UrbiException::call_type call_type;
    call_stack_type call_stack_;
    void show_backtrace(const call_stack_type& bt,
                        const std::string& chan);

    /// The local variable stacks
    Stacks stacks_;
  };

} // namespace runner

# include <runner/interpreter.hxx>

#endif // !RUNNER_INTERPRETER_HH
<commit_msg>Force visit functions inlining.<commit_after>/**
 ** \file runner/interpreter.hh
 ** \brief Definition of runner::Interpreter.
 */

#ifndef RUNNER_INTERPRETER_HH
# define RUNNER_INTERPRETER_HH

# include <boost/tuple/tuple.hpp>

# include <libport/hash.hh>

# include <ast/fwd.hh>
# include <object/object.hh>
# include <scheduler/scheduler.hh>
# include <scheduler/job.hh>

# include <runner/runner.hh>
# include <runner/stacks.hh>

namespace runner
{

  /// Ast executor.
  class Interpreter : public runner::Runner
  {
  public:
    /// \name Useful shorthands.
    /// \{
    /// Super class type.
    typedef runner::Runner super_type;
    typedef object::rObject rObject;
    typedef object::rrObject rrObject;
    typedef object::rRoutine rRoutine;
    typedef object::rLobby rLobby;
    typedef object::objects_type objects_type;
    /// \}

    /// \name Ctor & dtor.
    /// \{
    /// Construct a \c Interpreter in the \a lobby.  The runner needs
    /// to know its \a scheduler and will execute \a ast.  Memory
    /// ownership of \a ast is transferred to the Interpreter.  The
    /// new runner has no parent.
    Interpreter(rLobby lobby,
                scheduler::Scheduler& scheduler,
                ast::rConstAst ast,
                const libport::Symbol& name = SYMBOL());

    Interpreter(const Interpreter&,
                rObject code,
                const libport::Symbol& name = SYMBOL(),
                const objects_type& args = objects_type());

    /// Create a copy of a runner starting with another ast.
    Interpreter(const Interpreter&,
                ast::rConstAst ast,
                const libport::Symbol& name = SYMBOL());

    /// Destroy a Interpreter.
    virtual ~Interpreter();
    /// \}

    /// The entry point: visit \a e.
    object::rObject operator() (const ast::Ast* e) __attribute__((always_inline));

    /// \ name Accessors.
    /// \{
  public:
    /// \}

    /// Execute the code of function \a func with arguments \a args in
    /// the local runner.
    ///
    /// \param func  the "function" to call: Primitive, Delegate, Code
    ///              or even rObject, in which case it is returned.
    ///
    /// \param msg   the name of the called method, as it should be stored
    ///              in a call message in case further processing is
    ///              required.
    ///
    /// \param args  the arguments.  Used as given, they are not evaluated
    ///              here.
    ///
    /// \param call_message  the callMessage.  Valid only for \a func
    ///             being Code.
    ///
    /// One cannot have both a call message and args.
    virtual rObject apply(const rObject& func,
                          const libport::Symbol msg,
                          object::objects_type& args,
                          rObject call_message = 0);

    virtual rObject apply(const rObject& func,
                          const libport::Symbol msg,
                          object::objects_type& args,
                          boost::optional<ast::loc> loc,
                          rObject call_message = 0);

    /// Helpers to apply a function with the arguments as ast chunks
    rObject apply(const rObject& tgt,
                  const libport::Symbol& msg,
                  const ast::exps_type* args,
                  boost::optional<ast::loc> loc);
    rObject apply(const rObject& tgt,
                  const rObject& f,
                  const libport::Symbol& msg,
                  const ast::exps_type* args,
                  boost::optional<ast::loc> loc);

    /// Return the result of the latest evaluation.
    virtual rObject result_get();

    /// Evaluate an expression in the current scope and return its result.
    rObject eval(ast::rConstAst);

    /// Evaluate a tag and create it as well as the intermediate levels
    /// if needed.
    rObject eval_tag(ast::rConstExp);

    /// Make an urbi function from an ast chunk
    object::rRoutine make_routine(ast::rConstRoutine f) const;

  protected:
    /// \name Evaluation.
    /// \{
    /// Build an evaluated arguments list containing \a tgt and
    /// arguments coming from \a args evaluated in the current context.
    /// Raise an error if any argument is void.
    void push_evaluated_arguments (object::objects_type& args,
				   const ast::exps_type& ue_args);

    /// Build a call message
    virtual rObject
    build_call_message(const rObject& tgt,
		       const rObject& code,
		       const libport::Symbol& msg,
                       const object::objects_type& args);

    /// Build a call message
    rObject build_call_message(const rObject& tgt,
			       const rObject& code,
			       const libport::Symbol& msg,
                               const ast::exps_type& args);

  public:

    object::rObject visit(const ast::And* n) __attribute__((always_inline));
    object::rObject visit(const ast::Assignment* n) __attribute__((always_inline));
    object::rObject visit(const ast::Call* n) __attribute__((always_inline));
    object::rObject visit(const ast::CallMsg* n) __attribute__((always_inline));
    object::rObject visit(const ast::Closure* n) __attribute__((always_inline));
    object::rObject visit(const ast::Do* n) __attribute__((always_inline));
    object::rObject visit(const ast::Declaration* n) __attribute__((always_inline));
    object::rObject visit(const ast::Float* n) __attribute__((always_inline));
    object::rObject visit(const ast::Foreach* n) __attribute__((always_inline));
    object::rObject visit(const ast::Function* n) __attribute__((always_inline));
    object::rObject visit(const ast::If* n) __attribute__((always_inline));
    object::rObject visit(const ast::Lazy* n) __attribute__((always_inline));
    object::rObject visit(const ast::List* n) __attribute__((always_inline));
    object::rObject visit(const ast::Local* n) __attribute__((always_inline));
    object::rObject visit(const ast::Message* n) __attribute__((always_inline));
    object::rObject visit(const ast::Nary* n) __attribute__((always_inline));
    object::rObject visit(const ast::Noop* n) __attribute__((always_inline));
    object::rObject visit(const ast::Pipe* n) __attribute__((always_inline));
    object::rObject visit(const ast::Scope* n) __attribute__((always_inline));
    object::rObject visit(const ast::Stmt* n) __attribute__((always_inline));
    object::rObject visit(const ast::String* n) __attribute__((always_inline));
    object::rObject visit(const ast::Tag* n) __attribute__((always_inline));
    object::rObject visit(const ast::TaggedStmt* n) __attribute__((always_inline));
    object::rObject visit(const ast::This* n) __attribute__((always_inline));
    object::rObject visit(const ast::While* n) __attribute__((always_inline));

    object::rObject visit(const ast::Binding* n) __attribute__((always_inline));
    object::rObject visit(const ast::Break* n) __attribute__((always_inline));
    object::rObject visit(const ast::Continue* n) __attribute__((always_inline));
    object::rObject visit(const ast::Implicit* n) __attribute__((always_inline));
    object::rObject visit(const ast::MetaExp* n) __attribute__((always_inline));
    object::rObject visit(const ast::Return* n) __attribute__((always_inline));
    /// \}

    /// Do the actual work.  Implementation of \c Job::run.
    virtual void work ();

    virtual void show_backtrace(const std::string& chan);
    virtual backtrace_type backtrace_get() const;

  protected:
    void show_error_ (object::UrbiException& ue);

  private:
    void init();
    /// Reset result_, set the location and call stack of ue.
    void propagate_error_(object::UrbiException& ue, const ast::loc& l);
    rObject apply_urbi (rRoutine func,
			const libport::Symbol& msg,
			const object::objects_type& args,
			rObject call_message);

  private:
    /// Factor handling of Function and Closure
    object::rObject visit(const ast::Routine* e, bool closure);

    /// The root of the AST being executed.
    ast::rConstAst ast_;

    /// The urbi Code object to execute
    rObject code_;
    /// Its arguments
    objects_type args_;

    /// The current value during the evaluation of the AST.
    rObject result_;

    /// The call stack.
    typedef object::UrbiException::call_stack_type call_stack_type;
    typedef object::UrbiException::call_type call_type;
    call_stack_type call_stack_;
    void show_backtrace(const call_stack_type& bt,
                        const std::string& chan);

    /// The local variable stacks
    Stacks stacks_;
  };

} // namespace runner

# include <runner/interpreter.hxx>

#endif // !RUNNER_INTERPRETER_HH
<|endoftext|>