<commit_before>//=============================================================================================================
/**
* @file     babymeginfo.cpp
* @author   Limin Sun <liminsun@nmr.mgh.harvard.edu>;
*           Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     April, 2013
*
* @section  LICENSE
*
* Copyright (C) 2013, Limin Sun, Christoph Dinh and Matti Hamalainen. 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 Massachusetts General Hospital 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 MASSACHUSETTS GENERAL HOSPITAL 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.
*
*
* @brief     implementation of the BabyMEGInfo Class.
*
*/

#include "babymeginfo.h"

//*************************************************************************************************************

BabyMEGInfo::BabyMEGInfo()
: g_maxlen(500)
{
}
//*************************************************************************************************************

void BabyMEGInfo::MGH_LM_Send_CMDPackage(QByteArray DATA)
{
//    qDebug()<<"[BabyMEGInfo]CMD Size:"<<DATA.size();
    emit SendCMDPackage(DATA);
}
//*************************************************************************************************************

void BabyMEGInfo::MGH_LM_Send_DataPackage(QByteArray DATA)
{
//    qDebug()<<"[BabyMEGInfo]Data Size:"<<DATA.size();
    emit SendDataPackage(DATA);
}

//*************************************************************************************************************

QByteArray BabyMEGInfo::MGH_LM_Get_Field(QByteArray cmdstr)
{
    bool Start = false;
    qint32 bPos = 0;
    qint32 ePos = 0;
    qint32 cn = 0;
    for(qint32 i=0;i<cmdstr.size();i++)
    {
        if (cmdstr[i] == ':')
        { // get channel number
            Start = !Start;
            if (Start)
            {
                bPos = i;
            }
            else
            {
                ePos = i;
            }
            cn ++;
        }
        if (cn == 2)
        { // find the first ":" and the next ":"
            break;
        }

    }

    return cmdstr.mid(bPos,ePos-bPos);

}

//*************************************************************************************************************

QStringList BabyMEGInfo::MGH_LM_Exact_Single_Channel_Info(QByteArray cmdstr)
{
    QStringList sList;
    qint32 sp =0;
    qint32 ep =0;
    //extract single channel information by char ';'
    for (qint32 i=0;i<cmdstr.size();i++)
    {
        if (cmdstr[i]==';')
        {
            ep = i;
            QString t =  cmdstr.mid(sp,ep-sp);
            //qDebug()<<"[BabyMEGInfo] chan-name"<<t;
            sList.append(t);
            sp = i+1;
        }
    }

    return sList;

}

//*************************************************************************************************************

void BabyMEGInfo::MGH_LM_Get_Channel_Info(QByteArray cmdstr)
{
    //operation about lm_ch_names
    if (cmdstr[0]==':')
        cmdstr.remove(0,1);

    QStringList sList = MGH_LM_Exact_Single_Channel_Info(cmdstr);

    lm_ch_names.clear();
    lm_ch_scales.clear();
    lm_ch_pos1.clear();
    lm_ch_pos2.clear();
    lm_ch_pos3.clear();
    lm_ch_pos4.clear();
    lm_ch_pos5.clear();
    lm_ch_pos6.clear();
    lm_ch_pos7.clear();
    lm_ch_pos8.clear();
    lm_ch_pos9.clear();
    lm_ch_pos10.clear();
    lm_ch_pos11.clear();
    lm_ch_pos12.clear();

    // parse the information for each channel
    for(qint32 k =0; k<sList.size(); k++)
    {
        QString t = sList.at(k);
        for (qint32 z=0;z<t.size();z++)
        {
            if (t[z]=='|')
            {
                lm_ch_names.append(t.left(z));
                //qDebug()<<t.left(z);
                //extract the substring contained channel information: scale and coil positions
                QString tt = t.mid(z);
                //qDebug()<<tt;
                //extract value array from tt by separated char ","
                QStringList schp = tt.split(",");

                // scale
                lm_ch_scales.append(schp.at(0));
                // positions : x,y,z and units of x,y,z
                lm_ch_pos1.append(schp.at(1));
                lm_ch_pos2.append(schp.at(2));
                lm_ch_pos3.append(schp.at(3));
                lm_ch_pos4.append(schp.at(4));
                lm_ch_pos5.append(schp.at(5));
                lm_ch_pos6.append(schp.at(6));
                lm_ch_pos7.append(schp.at(7));
                lm_ch_pos8.append(schp.at(8));
                lm_ch_pos9.append(schp.at(9));
                lm_ch_pos10.append(schp.at(10));
                lm_ch_pos11.append(schp.at(11));
                lm_ch_pos12.append(schp.at(12));

//                qDebug()<<lm_ch_scales;
//                qDebug()<<lm_ch_pos2;

            }
        }
    }
    return;
}

//*************************************************************************************************************

void BabyMEGInfo::MGH_LM_Parse_Para(QByteArray cmdstr)
{

    QByteArray CMD = cmdstr.left(4);
    if (CMD == "INFO")
    {
        //remove INFO
        cmdstr.remove(0,4);
        //ACQ the number of channels
        QByteArray T = MGH_LM_Get_Field(cmdstr);
        cmdstr.remove(0,T.size());
        T.remove(0,1);
        chnNum = T.toInt();
        //ACQ the length of data package
        T = MGH_LM_Get_Field(cmdstr);
        cmdstr.remove(0,T.size());
        T.remove(0,1);
        dataLength = T.toInt();
        // ACQ sampling rate
        T = MGH_LM_Get_Field(cmdstr);
        cmdstr.remove(0,T.size());
        T.remove(0,1);
        sfreq = T.toDouble();
        qDebug()<<"[babyMEGinfo] chnNum:" << chnNum << "Data Length" <<dataLength<<"sampling rate"<<sfreq;
        //qDebug()<<"cmdstr"<<cmdstr;
        // Start to acquire the channel's name and channel's scale
        MGH_LM_Get_Channel_Info(cmdstr);

    }
    else
    {
        chnNum = 464;
        dataLength = 5000;
        sfreq = 10000;
    }

    // Parameters
    m_FiffInfo.file_id.version = 0; //ToDo

    m_FiffInfo.meas_date[0] = 0;
    m_FiffInfo.meas_date[1] = 0;
    m_FiffInfo.sfreq = sfreq;
    m_FiffInfo.highpass = 0;
    m_FiffInfo.lowpass = m_FiffInfo.sfreq/2;
    m_FiffInfo.acq_pars = QString("BabyMEG");
    m_FiffInfo.acq_stim = QString("");
    m_FiffInfo.filename = QString("");
    m_FiffInfo.meas_id.version = 1;
    m_FiffInfo.nchan = chnNum; //464;

    //MEG
    for(qint32 i = 0; i < chnNum; i++)
    {
        FiffChInfo t_ch;

        t_ch.ch_name = lm_ch_names.at(i); //QString("MEG%1").arg(i);
        //qDebug()<<t_ch.ch_name;
        t_ch.scanno = i;
        t_ch.logno = i+1;
        //t_ch.cal = 1;
        t_ch.cal = lm_ch_scales.at(i).toFloat(); // set scale
        qDebug()<<t_ch.cal;
        t_ch.range = 1;
        t_ch.loc.setZero(12,1);

        //set loc
        t_ch.loc(0,0) = lm_ch_pos1.at(i).toDouble();
        t_ch.loc(1,0) = lm_ch_pos2.at(i).toDouble();
        t_ch.loc(2,0) = lm_ch_pos3.at(i).toDouble();
        t_ch.loc(3,0) = lm_ch_pos4.at(i).toDouble();
        t_ch.loc(4,0) = lm_ch_pos5.at(i).toDouble();
        t_ch.loc(5,0) = lm_ch_pos6.at(i).toDouble();
        t_ch.loc(6,0) = lm_ch_pos7.at(i).toDouble();
        t_ch.loc(7,0) = lm_ch_pos8.at(i).toDouble();
        t_ch.loc(8,0) = lm_ch_pos9.at(i).toDouble();
        t_ch.loc(9,0) = lm_ch_pos10.at(i).toDouble();
        t_ch.loc(10,0) = lm_ch_pos11.at(i).toDouble();
        t_ch.loc(11,0) = lm_ch_pos12.at(i).toDouble();

        qDebug()<<t_ch.loc(0,0)<<t_ch.loc(1,0)<<t_ch.loc(2,0);

        QString type = t_ch.ch_name.left(3);
        int ntype = 0;
        if (type == "MEG")
            ntype = 1;
        else if (type == "EEG")
            ntype = 2;
        switch (ntype)
        {
        case 1:
                t_ch.kind = FIFFV_MEG_CH;
                t_ch.unit = FIFF_UNIT_T;
                t_ch.unit_mul = FIFF_UNITM_NONE;
                t_ch.coil_type = FIFFV_COIL_BABY_MAG;// ToDo FIFFV_COIL_BABY_REF_MAG
            break;
        case 2:
                t_ch.kind = FIFFV_EEG_CH;
                t_ch.unit = FIFF_UNIT_V;
                t_ch.unit_mul = FIFF_UNITM_NONE;
                t_ch.coil_type = FIFFV_COIL_EEG;
            break;
        default:
            t_ch.kind = FIFFV_MEG_CH;
            t_ch.unit = FIFF_UNIT_T;
            t_ch.unit_mul = FIFF_UNITM_NONE;
            t_ch.coil_type = FIFFV_COIL_BABY_MAG;// ToDo FIFFV_COIL_BABY_REF_MAG

            break;
        }
        m_FiffInfo.chs.append(t_ch);
        m_FiffInfo.ch_names.append(t_ch.ch_name);
    }

    emit fiffInfoAvailable(m_FiffInfo);

    return;
}

//*************************************************************************************************************

void BabyMEGInfo::EnQueue(QByteArray DataIn)
{
    g_mutex.lock();
    if (g_queue.size() == g_maxlen) {
        qDebug() << "g_queue is full, waiting!";
        g_queueNotFull.wait(&g_mutex);
    }
    g_queue.enqueue(DataIn);
    g_queueNotEmpty.wakeAll();
    g_mutex.unlock();
    qDebug() << "Data In...[size="<<g_queue.size()<<"]";
}
//*************************************************************************************************************

QByteArray BabyMEGInfo::DeQueue()
{
    QMutexLocker locker(&g_mutex);
    if (g_queue.isEmpty()) {
    qDebug() << "g_queue empty, waiting!";
    g_queueNotEmpty.wait(&g_mutex);
    }
    QByteArray val = g_queue.dequeue();
    g_queueNotFull.wakeAll();
    qDebug() << "Data Out...[size="<<g_queue.size()<<"]";
    return val;
}
<commit_msg>set scale value to unitmult in fiff structure<commit_after>//=============================================================================================================
/**
* @file     babymeginfo.cpp
* @author   Limin Sun <liminsun@nmr.mgh.harvard.edu>;
*           Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     April, 2013
*
* @section  LICENSE
*
* Copyright (C) 2013, Limin Sun, Christoph Dinh and Matti Hamalainen. 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 Massachusetts General Hospital 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 MASSACHUSETTS GENERAL HOSPITAL 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.
*
*
* @brief     implementation of the BabyMEGInfo Class.
*
*/

#include "babymeginfo.h"

//*************************************************************************************************************

BabyMEGInfo::BabyMEGInfo()
: g_maxlen(500)
{
}
//*************************************************************************************************************

void BabyMEGInfo::MGH_LM_Send_CMDPackage(QByteArray DATA)
{
//    qDebug()<<"[BabyMEGInfo]CMD Size:"<<DATA.size();
    emit SendCMDPackage(DATA);
}
//*************************************************************************************************************

void BabyMEGInfo::MGH_LM_Send_DataPackage(QByteArray DATA)
{
//    qDebug()<<"[BabyMEGInfo]Data Size:"<<DATA.size();
    emit SendDataPackage(DATA);
}

//*************************************************************************************************************

QByteArray BabyMEGInfo::MGH_LM_Get_Field(QByteArray cmdstr)
{
    bool Start = false;
    qint32 bPos = 0;
    qint32 ePos = 0;
    qint32 cn = 0;
    for(qint32 i=0;i<cmdstr.size();i++)
    {
        if (cmdstr[i] == ':')
        { // get channel number
            Start = !Start;
            if (Start)
            {
                bPos = i;
            }
            else
            {
                ePos = i;
            }
            cn ++;
        }
        if (cn == 2)
        { // find the first ":" and the next ":"
            break;
        }

    }

    return cmdstr.mid(bPos,ePos-bPos);

}

//*************************************************************************************************************

QStringList BabyMEGInfo::MGH_LM_Exact_Single_Channel_Info(QByteArray cmdstr)
{
    QStringList sList;
    qint32 sp =0;
    qint32 ep =0;
    //extract single channel information by char ';'
    for (qint32 i=0;i<cmdstr.size();i++)
    {
        if (cmdstr[i]==';')
        {
            ep = i;
            QString t =  cmdstr.mid(sp,ep-sp);
            //qDebug()<<"[BabyMEGInfo] chan-name"<<t;
            sList.append(t);
            sp = i+1;
        }
    }

    return sList;

}

//*************************************************************************************************************

void BabyMEGInfo::MGH_LM_Get_Channel_Info(QByteArray cmdstr)
{
    //operation about lm_ch_names
    if (cmdstr[0]==':')
        cmdstr.remove(0,1);

    QStringList sList = MGH_LM_Exact_Single_Channel_Info(cmdstr);

    lm_ch_names.clear();
    lm_ch_scales.clear();
    lm_ch_pos1.clear();
    lm_ch_pos2.clear();
    lm_ch_pos3.clear();
    lm_ch_pos4.clear();
    lm_ch_pos5.clear();
    lm_ch_pos6.clear();
    lm_ch_pos7.clear();
    lm_ch_pos8.clear();
    lm_ch_pos9.clear();
    lm_ch_pos10.clear();
    lm_ch_pos11.clear();
    lm_ch_pos12.clear();

    // parse the information for each channel
    for(qint32 k =0; k<sList.size(); k++)
    {
        QString t = sList.at(k);
        for (qint32 z=0;z<t.size();z++)
        {
            if (t[z]=='|')
            {
                lm_ch_names.append(t.left(z));
                //qDebug()<<t.left(z);
                //extract the substring contained channel information: scale and coil positions
                QString tt = t.mid(z);
                //qDebug()<<tt;
                //extract value array from tt by separated char ","
                QStringList schp = tt.split(",");

                // scale
                lm_ch_scales.append(schp.at(0));
                // positions : x,y,z and units of x,y,z
                lm_ch_pos1.append(schp.at(1));
                lm_ch_pos2.append(schp.at(2));
                lm_ch_pos3.append(schp.at(3));
                lm_ch_pos4.append(schp.at(4));
                lm_ch_pos5.append(schp.at(5));
                lm_ch_pos6.append(schp.at(6));
                lm_ch_pos7.append(schp.at(7));
                lm_ch_pos8.append(schp.at(8));
                lm_ch_pos9.append(schp.at(9));
                lm_ch_pos10.append(schp.at(10));
                lm_ch_pos11.append(schp.at(11));
                lm_ch_pos12.append(schp.at(12));

//                qDebug()<<lm_ch_scales;
//                qDebug()<<lm_ch_pos2;

            }
        }
    }
    return;
}

//*************************************************************************************************************

void BabyMEGInfo::MGH_LM_Parse_Para(QByteArray cmdstr)
{

    QByteArray CMD = cmdstr.left(4);
    if (CMD == "INFO")
    {
        //remove INFO
        cmdstr.remove(0,4);
        //ACQ the number of channels
        QByteArray T = MGH_LM_Get_Field(cmdstr);
        cmdstr.remove(0,T.size());
        T.remove(0,1);
        chnNum = T.toInt();
        //ACQ the length of data package
        T = MGH_LM_Get_Field(cmdstr);
        cmdstr.remove(0,T.size());
        T.remove(0,1);
        dataLength = T.toInt();
        // ACQ sampling rate
        T = MGH_LM_Get_Field(cmdstr);
        cmdstr.remove(0,T.size());
        T.remove(0,1);
        sfreq = T.toDouble();
        qDebug()<<"[babyMEGinfo] chnNum:" << chnNum << "Data Length" <<dataLength<<"sampling rate"<<sfreq;
        //qDebug()<<"cmdstr"<<cmdstr;
        // Start to acquire the channel's name and channel's scale
        MGH_LM_Get_Channel_Info(cmdstr);

    }
    else
    {
        chnNum = 464;
        dataLength = 5000;
        sfreq = 10000;
    }

    // Parameters
    m_FiffInfo.file_id.version = 0; //ToDo

    m_FiffInfo.meas_date[0] = 0;
    m_FiffInfo.meas_date[1] = 0;
    m_FiffInfo.sfreq = sfreq;
    m_FiffInfo.highpass = 0;
    m_FiffInfo.lowpass = m_FiffInfo.sfreq/2;
    m_FiffInfo.acq_pars = QString("BabyMEG");
    m_FiffInfo.acq_stim = QString("");
    m_FiffInfo.filename = QString("");
    m_FiffInfo.meas_id.version = 1;
    m_FiffInfo.nchan = chnNum; //464;

    //MEG
    for(qint32 i = 0; i < chnNum; i++)
    {
        FiffChInfo t_ch;

        t_ch.ch_name = lm_ch_names.at(i); //QString("MEG%1").arg(i);
        //qDebug()<<t_ch.ch_name;
        t_ch.scanno = i;
        t_ch.logno = i+1;
        t_ch.cal = 1;
        t_ch.unit_mul = lm_ch_scales.at(i).toFloat(); // set scale
        //qDebug()<<t_ch.cal;
        t_ch.range = 1;
        t_ch.loc.setZero(12,1);

        //set loc
        t_ch.loc(0,0) = lm_ch_pos1.at(i).toDouble();
        t_ch.loc(1,0) = lm_ch_pos2.at(i).toDouble();
        t_ch.loc(2,0) = lm_ch_pos3.at(i).toDouble();
        t_ch.loc(3,0) = lm_ch_pos4.at(i).toDouble();
        t_ch.loc(4,0) = lm_ch_pos5.at(i).toDouble();
        t_ch.loc(5,0) = lm_ch_pos6.at(i).toDouble();
        t_ch.loc(6,0) = lm_ch_pos7.at(i).toDouble();
        t_ch.loc(7,0) = lm_ch_pos8.at(i).toDouble();
        t_ch.loc(8,0) = lm_ch_pos9.at(i).toDouble();
        t_ch.loc(9,0) = lm_ch_pos10.at(i).toDouble();
        t_ch.loc(10,0) = lm_ch_pos11.at(i).toDouble();
        t_ch.loc(11,0) = lm_ch_pos12.at(i).toDouble();

        //qDebug()<<t_ch.loc(0,0)<<t_ch.loc(1,0)<<t_ch.loc(2,0);

        QString type = t_ch.ch_name.left(3);
        int ntype = 0;
        if (type == "MEG")
            ntype = 1;
        else if (type == "EEG")
            ntype = 2;
        switch (ntype)
        {
        case 1:
                t_ch.kind = FIFFV_MEG_CH;
                t_ch.unit = FIFF_UNIT_T;
                t_ch.unit_mul = FIFF_UNITM_NONE;
                t_ch.coil_type = FIFFV_COIL_BABY_MAG;// ToDo FIFFV_COIL_BABY_REF_MAG
            break;
        case 2:
                t_ch.kind = FIFFV_EEG_CH;
                t_ch.unit = FIFF_UNIT_V;
                t_ch.unit_mul = FIFF_UNITM_NONE;
                t_ch.coil_type = FIFFV_COIL_EEG;
            break;
        default:
            t_ch.kind = FIFFV_MEG_CH;
            t_ch.unit = FIFF_UNIT_T;
            t_ch.unit_mul = FIFF_UNITM_NONE;
            t_ch.coil_type = FIFFV_COIL_BABY_MAG;// ToDo FIFFV_COIL_BABY_REF_MAG

            break;
        }
        m_FiffInfo.chs.append(t_ch);
        m_FiffInfo.ch_names.append(t_ch.ch_name);
    }

    emit fiffInfoAvailable(m_FiffInfo);

    return;
}

//*************************************************************************************************************

void BabyMEGInfo::EnQueue(QByteArray DataIn)
{
    g_mutex.lock();
    if (g_queue.size() == g_maxlen) {
        qDebug() << "g_queue is full, waiting!";
        g_queueNotFull.wait(&g_mutex);
    }
    g_queue.enqueue(DataIn);
    g_queueNotEmpty.wakeAll();
    g_mutex.unlock();
    qDebug() << "Data In...[size="<<g_queue.size()<<"]";
}
//*************************************************************************************************************

QByteArray BabyMEGInfo::DeQueue()
{
    QMutexLocker locker(&g_mutex);
    if (g_queue.isEmpty()) {
    qDebug() << "g_queue empty, waiting!";
    g_queueNotEmpty.wait(&g_mutex);
    }
    QByteArray val = g_queue.dequeue();
    g_queueNotFull.wakeAll();
    qDebug() << "Data Out...[size="<<g_queue.size()<<"]";
    return val;
}
<|endoftext|>


<commit_before>#include <config.h>

#include <chrono>
#include <stdexcept>
#include <thread>
#include <vector>
#include <gtest/gtest.h>
#include <primitiv/naive_device.h>
#include <primitiv/shape.h>
#include <primitiv/tensor.h>
#include <test_utils.h>

using std::vector;
using test_utils::vector_match;

namespace primitiv {

class NaiveDeviceTest : public testing::Test {};

TEST_F(NaiveDeviceTest, CheckDeviceType) {
  devices::Naive dev;
  EXPECT_EQ(Device::DEVICE_TYPE_CPU, dev.type());
}

TEST_F(NaiveDeviceTest, CheckNewDelete) {
  {
    devices::Naive dev;
    {
      Tensor x1 = dev.new_tensor(Shape());  // 1 value
      Tensor x2 = dev.new_tensor(Shape({16, 16}));  // 256 values
      Tensor x3 = dev.new_tensor(Shape({16, 16, 16}, 16));  // 65536 values
    }
    // All tensors are already deleted before arriving here.
  }
  SUCCEED();
}

TEST_F(NaiveDeviceTest, CheckDanglingTensor) {
  {
    Tensor x1;
    {
      devices::Naive dev;
      x1 = dev.new_tensor(Shape());
    }
    // x1 still has valid object,
    // but there is no guarantee that the memory is alive.
    // Our implementation only guarantees the safety to delete Tensors anytime.
  }
  SUCCEED();
}

TEST_F(NaiveDeviceTest, CheckRandomBernoulli) {
  vector<vector<float>> history;
  for (unsigned i = 0; i < 10; ++i) {
    devices::Naive dev;
    const Tensor x = dev.random_bernoulli(Shape({3, 3}, 3), 0.3);
    const vector<float> x_val = x.to_vector();

    std::cout << "Epoch " << i << ':';
    for (float x_i : x_val) {
      std::cout << ' ' << x_i;
    }
    std::cout << std::endl;

    for (const vector<float> &h_val : history) {
      EXPECT_FALSE(vector_match(x_val, h_val));
    }
    history.emplace_back(x_val);

    // Wait for updating the device randomizer.
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
  }
}

TEST_F(NaiveDeviceTest, CheckRandomBernoulliWithSeed) {
  const vector<float> expected {
    0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0,
    0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
  };
  devices::Naive dev(12345);
  const Tensor x = dev.random_bernoulli(Shape({4, 4}, 4), 0.3);
  EXPECT_TRUE(vector_match(expected, x.to_vector()));
}

TEST_F(NaiveDeviceTest, CheckRandomUniform) {
  vector<vector<float>> history;
  for (unsigned i = 0; i < 10; ++i) {
    devices::Naive dev;
    const Tensor x = dev.random_uniform(Shape({2, 2}, 2), -9, 9);
    const vector<float> x_val = x.to_vector();

    std::cout << "Epoch " << i << ':';
    for (float x_i : x_val) {
      std::cout << ' ' << x_i;
    }
    std::cout << std::endl;

    for (const vector<float> &h_val : history) {
      EXPECT_FALSE(vector_match(x_val, h_val));
    }
    history.emplace_back(x_val);

    // Wait for updating the device randomizer.
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
  }
}

TEST_F(NaiveDeviceTest, CheckRandomUniformWithSeed) {
  const vector<float> expected {
    7.7330894e+00, 7.0227852e+00, -3.3052402e+00, -6.6472688e+00,
    -5.6894612e+00, -8.2843294e+00, -5.3179150e+00, 5.8758497e+00,
  };
  devices::Naive dev(12345);
  const Tensor x = dev.random_uniform(Shape({2, 2}, 2), -9, 9);
  EXPECT_TRUE(vector_match(expected, x.to_vector()));
}

TEST_F(NaiveDeviceTest, CheckRandomNormal) {
  vector<vector<float>> history;
  for (unsigned i = 0; i < 10; ++i) {
    devices::Naive dev;
    const Tensor x = dev.random_normal(Shape({2, 2}, 2), 1, 3);
    const vector<float> x_val = x.to_vector();

    std::cout << "Epoch " << i << ':';
    for (float x_i : x_val) {
      std::cout << ' ' << x_i;
    }
    std::cout << std::endl;

    for (const vector<float> &h_val : history) {
      EXPECT_FALSE(vector_match(x_val, h_val));
    }
    history.emplace_back(x_val);

    // Wait for updating the device randomizer.
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
  }
}

TEST_F(NaiveDeviceTest, CheckRandomNormalWithSeed) {
  const vector<float> expected {
    -1.3574908e+00, -1.7222166e-01, 2.5865970e+00, -4.3594337e-01,
    4.5383353e+00, 8.4703674e+00, 2.5535507e+00, 1.3252910e+00,
  };
  devices::Naive dev(12345);
  const Tensor x = dev.random_normal(Shape({2, 2}, 2), 1, 3);
  EXPECT_TRUE(vector_match(expected, x.to_vector()));
}

TEST_F(NaiveDeviceTest, CheckRandomLogNormal) {
  vector<vector<float>> history;
  for (unsigned i = 0; i < 10; ++i) {
    devices::Naive dev;
    const Tensor x = dev.random_log_normal(Shape({2, 2}, 2), 1, 3);
    const vector<float> x_val = x.to_vector();

    std::cout << "Epoch " << i << ':';
    for (float x_i : x_val) {
      std::cout << ' ' << x_i;
    }
    std::cout << std::endl;

    for (const vector<float> &h_val : history) {
      EXPECT_FALSE(vector_match(x_val, h_val));
    }
    history.emplace_back(x_val);

    // Wait for updating the device randomizer.
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
  }
}

TEST_F(NaiveDeviceTest, CheckRandomLogNormalWithSeed) {
  const vector<float> expected {
    2.5730559e-01, 8.4179258e-01, 1.3284487e+01, 6.4665437e-01,
    9.3534966e+01, 4.7712681e+03, 1.2852659e+01, 3.7632804e+00,
  };
  devices::Naive dev(12345);
  const Tensor x = dev.random_log_normal(Shape({2, 2}, 2), 1, 3);
  EXPECT_TRUE(vector_match(expected, x.to_vector()));
}

}  // namespace primitiv
<commit_msg>Add expected results of naive_device_test for libcpp<commit_after>#include <config.h>

#include <chrono>
#include <stdexcept>
#include <thread>
#include <vector>
#include <gtest/gtest.h>
#include <primitiv/naive_device.h>
#include <primitiv/shape.h>
#include <primitiv/tensor.h>
#include <test_utils.h>

using std::vector;
using test_utils::vector_match;

namespace primitiv {

class NaiveDeviceTest : public testing::Test {};

TEST_F(NaiveDeviceTest, CheckDeviceType) {
  devices::Naive dev;
  EXPECT_EQ(Device::DEVICE_TYPE_CPU, dev.type());
}

TEST_F(NaiveDeviceTest, CheckNewDelete) {
  {
    devices::Naive dev;
    {
      Tensor x1 = dev.new_tensor(Shape());  // 1 value
      Tensor x2 = dev.new_tensor(Shape({16, 16}));  // 256 values
      Tensor x3 = dev.new_tensor(Shape({16, 16, 16}, 16));  // 65536 values
    }
    // All tensors are already deleted before arriving here.
  }
  SUCCEED();
}

TEST_F(NaiveDeviceTest, CheckDanglingTensor) {
  {
    Tensor x1;
    {
      devices::Naive dev;
      x1 = dev.new_tensor(Shape());
    }
    // x1 still has valid object,
    // but there is no guarantee that the memory is alive.
    // Our implementation only guarantees the safety to delete Tensors anytime.
  }
  SUCCEED();
}

TEST_F(NaiveDeviceTest, CheckRandomBernoulli) {
  vector<vector<float>> history;
  for (unsigned i = 0; i < 10; ++i) {
    devices::Naive dev;
    const Tensor x = dev.random_bernoulli(Shape({3, 3}, 3), 0.3);
    const vector<float> x_val = x.to_vector();

    std::cout << "Epoch " << i << ':';
    for (float x_i : x_val) {
      std::cout << ' ' << x_i;
    }
    std::cout << std::endl;

    for (const vector<float> &h_val : history) {
      EXPECT_FALSE(vector_match(x_val, h_val));
    }
    history.emplace_back(x_val);

    // Wait for updating the device randomizer.
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
  }
}

TEST_F(NaiveDeviceTest, CheckRandomBernoulliWithSeed) {
  const vector<float> expected {
    0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0,
    0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
  };
  devices::Naive dev(12345);
  const Tensor x = dev.random_bernoulli(Shape({4, 4}, 4), 0.3);
  EXPECT_TRUE(vector_match(expected, x.to_vector()));
}

TEST_F(NaiveDeviceTest, CheckRandomUniform) {
  vector<vector<float>> history;
  for (unsigned i = 0; i < 10; ++i) {
    devices::Naive dev;
    const Tensor x = dev.random_uniform(Shape({2, 2}, 2), -9, 9);
    const vector<float> x_val = x.to_vector();

    std::cout << "Epoch " << i << ':';
    for (float x_i : x_val) {
      std::cout << ' ' << x_i;
    }
    std::cout << std::endl;

    for (const vector<float> &h_val : history) {
      EXPECT_FALSE(vector_match(x_val, h_val));
    }
    history.emplace_back(x_val);

    // Wait for updating the device randomizer.
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
  }
}

TEST_F(NaiveDeviceTest, CheckRandomUniformWithSeed) {
  const vector<float> expected {
    7.7330894e+00, 7.0227852e+00, -3.3052402e+00, -6.6472688e+00,
    -5.6894612e+00, -8.2843294e+00, -5.3179150e+00, 5.8758497e+00,
  };
  devices::Naive dev(12345);
  const Tensor x = dev.random_uniform(Shape({2, 2}, 2), -9, 9);
  EXPECT_TRUE(vector_match(expected, x.to_vector()));
}

TEST_F(NaiveDeviceTest, CheckRandomNormal) {
  vector<vector<float>> history;
  for (unsigned i = 0; i < 10; ++i) {
    devices::Naive dev;
    const Tensor x = dev.random_normal(Shape({2, 2}, 2), 1, 3);
    const vector<float> x_val = x.to_vector();

    std::cout << "Epoch " << i << ':';
    for (float x_i : x_val) {
      std::cout << ' ' << x_i;
    }
    std::cout << std::endl;

    for (const vector<float> &h_val : history) {
      EXPECT_FALSE(vector_match(x_val, h_val));
    }
    history.emplace_back(x_val);

    // Wait for updating the device randomizer.
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
  }
}

TEST_F(NaiveDeviceTest, CheckRandomNormalWithSeed) {
#ifdef __GLIBCXX__
  const vector<float> expected {
    -1.3574908e+00, -1.7222166e-01, 2.5865970e+00, -4.3594337e-01,
    4.5383353e+00, 8.4703674e+00, 2.5535507e+00, 1.3252910e+00,
  };
#elif defined _LIBCPP_VERSION
  const vector<float> expected {
    -1.7222166e-01, -1.3574908e+00, -4.3594337e-01, 2.5865970e+00,
    8.4703674e+00, 4.5383353e+00, 1.3252910e+00, 2.5535507e+00,
  };
#else
  const vector<float> expected {};
#endif
  devices::Naive dev(12345);
  const Tensor x = dev.random_normal(Shape({2, 2}, 2), 1, 3);
  EXPECT_TRUE(vector_match(expected, x.to_vector()));
}

TEST_F(NaiveDeviceTest, CheckRandomLogNormal) {
  vector<vector<float>> history;
  for (unsigned i = 0; i < 10; ++i) {
    devices::Naive dev;
    const Tensor x = dev.random_log_normal(Shape({2, 2}, 2), 1, 3);
    const vector<float> x_val = x.to_vector();

    std::cout << "Epoch " << i << ':';
    for (float x_i : x_val) {
      std::cout << ' ' << x_i;
    }
    std::cout << std::endl;

    for (const vector<float> &h_val : history) {
      EXPECT_FALSE(vector_match(x_val, h_val));
    }
    history.emplace_back(x_val);

    // Wait for updating the device randomizer.
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
  }
}

TEST_F(NaiveDeviceTest, CheckRandomLogNormalWithSeed) {
#ifdef __GLIBCXX__
  const vector<float> expected {
    2.5730559e-01, 8.4179258e-01, 1.3284487e+01, 6.4665437e-01,
    9.3534966e+01, 4.7712681e+03, 1.2852659e+01, 3.7632804e+00,
  };
#elif defined _LIBCPP_VERSION
  const vector<float> expected {
    8.4179258e-01, 2.5730559e-01, 6.4665437e-01, 1.3284487e+01,
    4.7712681e+03, 9.3534966e+01, 3.7632804e+00, 1.2852659e+01,
  };
#else
  const vector<float> expected {};
#endif
  devices::Naive dev(12345);
  const Tensor x = dev.random_log_normal(Shape({2, 2}, 2), 1, 3);
  EXPECT_TRUE(vector_match(expected, x.to_vector()));
}

}  // namespace primitiv
<|endoftext|>


<commit_before>/* A BlockEnvironment is created when a block is created. Its primary
 * operation is call, which activates the code associated with the block. */

#include "block_environment.hpp"
#include "objectmemory.hpp"

#include "builtin/compiledmethod.hpp"
#include "builtin/contexts.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/symbol.hpp"
#include "builtin/task.hpp"
#include "builtin/tuple.hpp"

namespace rubinius {
  void BlockEnvironment::call(STATE, Task* task, size_t args) {
    OBJECT val;
    if(args > 0) {
      Tuple* tup = Tuple::create(state, args);
      for(int i = args - 1; i >= 0; i--) {
        tup->put(state, i, task->pop());
      }

      val = tup;
    } else {
      val = Qnil;
    }
    task->pop(); // Remove this from the stack.
    BlockContext* ctx = create_context(state, task->active);
    task->make_active(ctx);
    task->push(val);
  }

  void BlockEnvironment::call(STATE, Message& msg) {
    throw std::runtime_error("call2: not implemented");
  }

  // TODO - Untested!!!!!!!!!!
  bool BlockEnvironment::call_prim(STATE, VMExecutable* exec, Task* task, Message& msg) {
    call(state, task, msg.args);
    return true;
  }

  /*
   * Allocates a context, adjusting the initial stack pointer by the number of
   * locals the method requires.
   */
  BlockContext* BlockEnvironment::create_context(STATE, MethodContext* sender) {
    BlockContext* ctx = BlockContext::create(state, method->stack_size->to_native());
    SET(ctx, sender, sender);
    SET(ctx, name, (SYMBOL)this);
    SET(ctx, cm, method);
    SET(ctx, home, home);

    ctx->vmm = vmm;
    ctx->ip = 0;
    // HACK dup'd from MethodContext
    ctx->position_stack(method->number_of_locals() - 1);

    return ctx;
  }

  BlockEnvironment* BlockEnvironment::under_context(STATE, CompiledMethod* cm,
      MethodContext* parent, MethodContext* active, size_t index) {

    BlockEnvironment* be = (BlockEnvironment*)state->new_object(G(blokenv));

    VMMethod* vmm;
    if((vmm = active->vmm->blocks[index]) == NULL) {
      vmm = new VMMethod(state, cm);
      if(active->vmm->type) {
        vmm->specialize(active->vmm->type);
      }
      active->vmm->blocks[index] = vmm;
    }

    SET(be, home, parent);
    SET(be, home_block, active);
    SET(be, method, cm);
    SET(be, local_count, cm->local_count);
    be->vmm = vmm;

    return be;
  }
}
<commit_msg>Add HACK about non-Symbol cast<commit_after>/* A BlockEnvironment is created when a block is created. Its primary
 * operation is call, which activates the code associated with the block. */

#include "block_environment.hpp"
#include "objectmemory.hpp"

#include "builtin/compiledmethod.hpp"
#include "builtin/contexts.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/symbol.hpp"
#include "builtin/task.hpp"
#include "builtin/tuple.hpp"

namespace rubinius {
  void BlockEnvironment::call(STATE, Task* task, size_t args) {
    OBJECT val;
    if(args > 0) {
      Tuple* tup = Tuple::create(state, args);
      for(int i = args - 1; i >= 0; i--) {
        tup->put(state, i, task->pop());
      }

      val = tup;
    } else {
      val = Qnil;
    }
    task->pop(); // Remove this from the stack.
    BlockContext* ctx = create_context(state, task->active);
    task->make_active(ctx);
    task->push(val);
  }

  void BlockEnvironment::call(STATE, Message& msg) {
    throw std::runtime_error("call2: not implemented");
  }

  // TODO - Untested!!!!!!!!!!
  bool BlockEnvironment::call_prim(STATE, VMExecutable* exec, Task* task, Message& msg) {
    call(state, task, msg.args);
    return true;
  }

  /*
   * Allocates a context, adjusting the initial stack pointer by the number of
   * locals the method requires.
   */
  BlockContext* BlockEnvironment::create_context(STATE, MethodContext* sender) {
    BlockContext* ctx = BlockContext::create(state, method->stack_size->to_native());
    SET(ctx, sender, sender);
    SET(ctx, name, (SYMBOL)this); // HACK don't cast non-Symbol to Symbol
    SET(ctx, cm, method);
    SET(ctx, home, home);

    ctx->vmm = vmm;
    ctx->ip = 0;
    // HACK dup'd from MethodContext
    ctx->position_stack(method->number_of_locals() - 1);

    return ctx;
  }

  BlockEnvironment* BlockEnvironment::under_context(STATE, CompiledMethod* cm,
      MethodContext* parent, MethodContext* active, size_t index) {

    BlockEnvironment* be = (BlockEnvironment*)state->new_object(G(blokenv));

    VMMethod* vmm;
    if((vmm = active->vmm->blocks[index]) == NULL) {
      vmm = new VMMethod(state, cm);
      if(active->vmm->type) {
        vmm->specialize(active->vmm->type);
      }
      active->vmm->blocks[index] = vmm;
    }

    SET(be, home, parent);
    SET(be, home_block, active);
    SET(be, method, cm);
    SET(be, local_count, cm->local_count);
    be->vmm = vmm;

    return be;
  }
}
<|endoftext|>


<commit_before>//===- FunctionResolution.cpp - Resolve declarations to implementations ---===//
//
// Loop over the functions that are in the module and look for functions that
// have the same name.  More often than not, there will be things like:
//
//    declare void %foo(...)
//    void %foo(int, int) { ... }
//
// because of the way things are declared in C.  If this is the case, patch
// things up.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constant.h"
#include "Support/StatisticReporter.h"
#include <iostream>
#include <algorithm>

using std::vector;
using std::string;
using std::cerr;

namespace {
  Statistic<>NumResolved("funcresolve\t- Number of varargs functions resolved");

  struct FunctionResolvingPass : public Pass {
    bool run(Module &M);
  };
  RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}

Pass *createFunctionResolvingPass() {
  return new FunctionResolvingPass();
}

// ConvertCallTo - Convert a call to a varargs function with no arg types
// specified to a concrete nonvarargs function.
//
static void ConvertCallTo(CallInst *CI, Function *Dest) {
  const FunctionType::ParamTypes &ParamTys =
    Dest->getFunctionType()->getParamTypes();
  BasicBlock *BB = CI->getParent();

  // Keep an iterator to where we want to insert cast instructions if the
  // argument types don't agree.
  //
  BasicBlock::iterator BBI = CI;
  assert(CI->getNumOperands()-1 == ParamTys.size() &&
         "Function calls resolved funny somehow, incompatible number of args");

  vector<Value*> Params;

  // Convert all of the call arguments over... inserting cast instructions if
  // the types are not compatible.
  for (unsigned i = 1; i < CI->getNumOperands(); ++i) {
    Value *V = CI->getOperand(i);

    if (V->getType() != ParamTys[i-1]) { // Must insert a cast...
      Instruction *Cast = new CastInst(V, ParamTys[i-1]);
      BBI = ++BB->getInstList().insert(BBI, Cast);
      V = Cast;
    }

    Params.push_back(V);
  }

  Instruction *NewCall = new CallInst(Dest, Params);

  // Replace the old call instruction with a new call instruction that calls
  // the real function.
  //
  BBI = ++BB->getInstList().insert(BBI, NewCall);

  // Remove the old call instruction from the program...
  BB->getInstList().remove(BBI);

  // Transfer the name over...
  NewCall->setName(CI->getName());

  // Replace uses of the old instruction with the appropriate values...
  //
  if (NewCall->getType() == CI->getType()) {
    CI->replaceAllUsesWith(NewCall);
    NewCall->setName(CI->getName());

  } else if (NewCall->getType() == Type::VoidTy) {
    // Resolved function does not return a value but the prototype does.  This
    // often occurs because undefined functions default to returning integers.
    // Just replace uses of the call (which are broken anyway) with dummy
    // values.
    CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
  } else if (CI->getType() == Type::VoidTy) {
    // If we are gaining a new return value, we don't have to do anything
    // special here, because it will automatically be ignored.
  } else {
    // Insert a cast instruction to convert the return value of the function
    // into it's new type.  Of course we only need to do this if the return
    // value of the function is actually USED.
    //
    if (!CI->use_empty()) {
      CastInst *NewCast = new CastInst(NewCall, CI->getType(),
                                       NewCall->getName());
      CI->replaceAllUsesWith(NewCast);
      // Insert the new cast instruction...
      BB->getInstList().insert(BBI, NewCast);
    }
  }

  // The old instruction is no longer needed, destroy it!
  delete CI;
}

bool FunctionResolvingPass::run(Module &M) {
  SymbolTable *ST = M.getSymbolTable();
  if (!ST) return false;

  std::map<string, vector<Function*> > Functions;

  // Loop over the entries in the symbol table. If an entry is a func pointer,
  // then add it to the Functions map.  We do a two pass algorithm here to avoid
  // problems with iterators getting invalidated if we did a one pass scheme.
  //
  for (SymbolTable::iterator I = ST->begin(), E = ST->end(); I != E; ++I)
    if (const PointerType *PT = dyn_cast<PointerType>(I->first))
      if (isa<FunctionType>(PT->getElementType())) {
        SymbolTable::VarMap &Plane = I->second;
        for (SymbolTable::type_iterator PI = Plane.begin(), PE = Plane.end();
             PI != PE; ++PI) {
          Function *F = cast<Function>(PI->second);
          assert(PI->first == F->getName() &&
                 "Function name and symbol table do not agree!");
          if (F->hasExternalLinkage())  // Only resolve decls to external fns
            Functions[PI->first].push_back(F);
        }
      }

  bool Changed = false;

  // Now we have a list of all functions with a particular name.  If there is
  // more than one entry in a list, merge the functions together.
  //
  for (std::map<string, vector<Function*> >::iterator I = Functions.begin(),
         E = Functions.end(); I != E; ++I) {
    vector<Function*> &Functions = I->second;
    Function *Implementation = 0;     // Find the implementation
    Function *Concrete = 0;
    for (unsigned i = 0; i < Functions.size(); ) {
      if (!Functions[i]->isExternal()) {  // Found an implementation
        if (Implementation != 0)
        assert(Implementation == 0 && "Multiple definitions of the same"
               " function. Case not handled yet!");
        Implementation = Functions[i];
      } else {
        // Ignore functions that are never used so they don't cause spurious
        // warnings... here we will actually DCE the function so that it isn't
        // used later.
        //
        if (Functions[i]->use_empty()) {
          M.getFunctionList().erase(Functions[i]);
          Functions.erase(Functions.begin()+i);
          Changed = true;
          ++NumResolved;
          continue;
        }
      }

      if (Functions[i] && (!Functions[i]->getFunctionType()->isVarArg())) {
        if (Concrete) {  // Found two different functions types.  Can't choose
          Concrete = 0;
          break;
        }
        Concrete = Functions[i];
      }
      ++i;
    }

    if (Functions.size() > 1) {         // Found a multiply defined function...
      // We should find exactly one non-vararg function definition, which is
      // probably the implementation.  Change all of the function definitions
      // and uses to use it instead.
      //
      if (!Concrete) {
        cerr << "Warning: Found functions types that are not compatible:\n";
        for (unsigned i = 0; i < Functions.size(); ++i) {
          cerr << "\t" << Functions[i]->getType()->getDescription() << " %"
               << Functions[i]->getName() << "\n";
        }
        cerr << "  No linkage of functions named '" << Functions[0]->getName()
             << "' performed!\n";
      } else {
        for (unsigned i = 0; i < Functions.size(); ++i)
          if (Functions[i] != Concrete) {
            Function *Old = Functions[i];
            const FunctionType *OldMT = Old->getFunctionType();
            const FunctionType *ConcreteMT = Concrete->getFunctionType();
            bool Broken = false;

            assert(OldMT->getParamTypes().size() <=
                   ConcreteMT->getParamTypes().size() &&
                   "Concrete type must have more specified parameters!");

            // Check to make sure that if there are specified types, that they
            // match...
            //
            for (unsigned i = 0; i < OldMT->getParamTypes().size(); ++i)
              if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i]) {
                cerr << "Parameter types conflict for" << OldMT
                     << " and " << ConcreteMT;
                Broken = true;
              }
            if (Broken) break;  // Can't process this one!

            // Attempt to convert all of the uses of the old function to the
            // concrete form of the function.  If there is a use of the fn that
            // we don't understand here we punt to avoid making a bad
            // transformation.
            //
            // At this point, we know that the return values are the same for
            // our two functions and that the Old function has no varargs fns
            // specified.  In otherwords it's just <retty> (...)
            //
            for (unsigned i = 0; i < Old->use_size(); ) {
              User *U = *(Old->use_begin()+i);
              if (CastInst *CI = dyn_cast<CastInst>(U)) {
                // Convert casts directly
                assert(CI->getOperand(0) == Old);
                CI->setOperand(0, Concrete);
                Changed = true;
                ++NumResolved;
              } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
                // Can only fix up calls TO the argument, not args passed in.
                if (CI->getCalledValue() == Old) {
                  ConvertCallTo(CI, Concrete);
                  Changed = true;
                  ++NumResolved;
                } else {
                  cerr << "Couldn't cleanup this function call, must be an"
                       << " argument or something!" << CI;
                  ++i;
                }
              } else {
                cerr << "Cannot convert use of function: " << U << "\n";
                ++i;
              }
            }
          }
        }
    }
  }

  return Changed;
}
<commit_msg>Fix bug with last patch which would occur when a call returned void and we attempted to assign it a name.<commit_after>//===- FunctionResolution.cpp - Resolve declarations to implementations ---===//
//
// Loop over the functions that are in the module and look for functions that
// have the same name.  More often than not, there will be things like:
//
//    declare void %foo(...)
//    void %foo(int, int) { ... }
//
// because of the way things are declared in C.  If this is the case, patch
// things up.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constant.h"
#include "Support/StatisticReporter.h"
#include <iostream>
#include <algorithm>

using std::vector;
using std::string;
using std::cerr;

namespace {
  Statistic<>NumResolved("funcresolve\t- Number of varargs functions resolved");

  struct FunctionResolvingPass : public Pass {
    bool run(Module &M);
  };
  RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}

Pass *createFunctionResolvingPass() {
  return new FunctionResolvingPass();
}

// ConvertCallTo - Convert a call to a varargs function with no arg types
// specified to a concrete nonvarargs function.
//
static void ConvertCallTo(CallInst *CI, Function *Dest) {
  const FunctionType::ParamTypes &ParamTys =
    Dest->getFunctionType()->getParamTypes();
  BasicBlock *BB = CI->getParent();

  // Keep an iterator to where we want to insert cast instructions if the
  // argument types don't agree.
  //
  BasicBlock::iterator BBI = CI;
  assert(CI->getNumOperands()-1 == ParamTys.size() &&
         "Function calls resolved funny somehow, incompatible number of args");

  vector<Value*> Params;

  // Convert all of the call arguments over... inserting cast instructions if
  // the types are not compatible.
  for (unsigned i = 1; i < CI->getNumOperands(); ++i) {
    Value *V = CI->getOperand(i);

    if (V->getType() != ParamTys[i-1]) { // Must insert a cast...
      Instruction *Cast = new CastInst(V, ParamTys[i-1]);
      BBI = ++BB->getInstList().insert(BBI, Cast);
      V = Cast;
    }

    Params.push_back(V);
  }

  Instruction *NewCall = new CallInst(Dest, Params);

  // Replace the old call instruction with a new call instruction that calls
  // the real function.
  //
  BBI = ++BB->getInstList().insert(BBI, NewCall);

  // Remove the old call instruction from the program...
  BB->getInstList().remove(BBI);

  // Transfer the name over...
  if (NewCall->getType() != Type::VoidTy)
    NewCall->setName(CI->getName());

  // Replace uses of the old instruction with the appropriate values...
  //
  if (NewCall->getType() == CI->getType()) {
    CI->replaceAllUsesWith(NewCall);
    NewCall->setName(CI->getName());

  } else if (NewCall->getType() == Type::VoidTy) {
    // Resolved function does not return a value but the prototype does.  This
    // often occurs because undefined functions default to returning integers.
    // Just replace uses of the call (which are broken anyway) with dummy
    // values.
    CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
  } else if (CI->getType() == Type::VoidTy) {
    // If we are gaining a new return value, we don't have to do anything
    // special here, because it will automatically be ignored.
  } else {
    // Insert a cast instruction to convert the return value of the function
    // into it's new type.  Of course we only need to do this if the return
    // value of the function is actually USED.
    //
    if (!CI->use_empty()) {
      CastInst *NewCast = new CastInst(NewCall, CI->getType(),
                                       NewCall->getName());
      CI->replaceAllUsesWith(NewCast);
      // Insert the new cast instruction...
      BB->getInstList().insert(BBI, NewCast);
    }
  }

  // The old instruction is no longer needed, destroy it!
  delete CI;
}

bool FunctionResolvingPass::run(Module &M) {
  SymbolTable *ST = M.getSymbolTable();
  if (!ST) return false;

  std::map<string, vector<Function*> > Functions;

  // Loop over the entries in the symbol table. If an entry is a func pointer,
  // then add it to the Functions map.  We do a two pass algorithm here to avoid
  // problems with iterators getting invalidated if we did a one pass scheme.
  //
  for (SymbolTable::iterator I = ST->begin(), E = ST->end(); I != E; ++I)
    if (const PointerType *PT = dyn_cast<PointerType>(I->first))
      if (isa<FunctionType>(PT->getElementType())) {
        SymbolTable::VarMap &Plane = I->second;
        for (SymbolTable::type_iterator PI = Plane.begin(), PE = Plane.end();
             PI != PE; ++PI) {
          Function *F = cast<Function>(PI->second);
          assert(PI->first == F->getName() &&
                 "Function name and symbol table do not agree!");
          if (F->hasExternalLinkage())  // Only resolve decls to external fns
            Functions[PI->first].push_back(F);
        }
      }

  bool Changed = false;

  // Now we have a list of all functions with a particular name.  If there is
  // more than one entry in a list, merge the functions together.
  //
  for (std::map<string, vector<Function*> >::iterator I = Functions.begin(),
         E = Functions.end(); I != E; ++I) {
    vector<Function*> &Functions = I->second;
    Function *Implementation = 0;     // Find the implementation
    Function *Concrete = 0;
    for (unsigned i = 0; i < Functions.size(); ) {
      if (!Functions[i]->isExternal()) {  // Found an implementation
        if (Implementation != 0)
        assert(Implementation == 0 && "Multiple definitions of the same"
               " function. Case not handled yet!");
        Implementation = Functions[i];
      } else {
        // Ignore functions that are never used so they don't cause spurious
        // warnings... here we will actually DCE the function so that it isn't
        // used later.
        //
        if (Functions[i]->use_empty()) {
          M.getFunctionList().erase(Functions[i]);
          Functions.erase(Functions.begin()+i);
          Changed = true;
          ++NumResolved;
          continue;
        }
      }

      if (Functions[i] && (!Functions[i]->getFunctionType()->isVarArg())) {
        if (Concrete) {  // Found two different functions types.  Can't choose
          Concrete = 0;
          break;
        }
        Concrete = Functions[i];
      }
      ++i;
    }

    if (Functions.size() > 1) {         // Found a multiply defined function...
      // We should find exactly one non-vararg function definition, which is
      // probably the implementation.  Change all of the function definitions
      // and uses to use it instead.
      //
      if (!Concrete) {
        cerr << "Warning: Found functions types that are not compatible:\n";
        for (unsigned i = 0; i < Functions.size(); ++i) {
          cerr << "\t" << Functions[i]->getType()->getDescription() << " %"
               << Functions[i]->getName() << "\n";
        }
        cerr << "  No linkage of functions named '" << Functions[0]->getName()
             << "' performed!\n";
      } else {
        for (unsigned i = 0; i < Functions.size(); ++i)
          if (Functions[i] != Concrete) {
            Function *Old = Functions[i];
            const FunctionType *OldMT = Old->getFunctionType();
            const FunctionType *ConcreteMT = Concrete->getFunctionType();
            bool Broken = false;

            assert(OldMT->getParamTypes().size() <=
                   ConcreteMT->getParamTypes().size() &&
                   "Concrete type must have more specified parameters!");

            // Check to make sure that if there are specified types, that they
            // match...
            //
            for (unsigned i = 0; i < OldMT->getParamTypes().size(); ++i)
              if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i]) {
                cerr << "Parameter types conflict for" << OldMT
                     << " and " << ConcreteMT;
                Broken = true;
              }
            if (Broken) break;  // Can't process this one!

            // Attempt to convert all of the uses of the old function to the
            // concrete form of the function.  If there is a use of the fn that
            // we don't understand here we punt to avoid making a bad
            // transformation.
            //
            // At this point, we know that the return values are the same for
            // our two functions and that the Old function has no varargs fns
            // specified.  In otherwords it's just <retty> (...)
            //
            for (unsigned i = 0; i < Old->use_size(); ) {
              User *U = *(Old->use_begin()+i);
              if (CastInst *CI = dyn_cast<CastInst>(U)) {
                // Convert casts directly
                assert(CI->getOperand(0) == Old);
                CI->setOperand(0, Concrete);
                Changed = true;
                ++NumResolved;
              } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
                // Can only fix up calls TO the argument, not args passed in.
                if (CI->getCalledValue() == Old) {
                  ConvertCallTo(CI, Concrete);
                  Changed = true;
                  ++NumResolved;
                } else {
                  cerr << "Couldn't cleanup this function call, must be an"
                       << " argument or something!" << CI;
                  ++i;
                }
              } else {
                cerr << "Cannot convert use of function: " << U << "\n";
                ++i;
              }
            }
          }
        }
    }
  }

  return Changed;
}
<|endoftext|>


<commit_before><commit_msg>Add empty strings localized_strings to fix build breakage.<commit_after><|endoftext|>


<commit_before><commit_msg>AutoFill: Temporarily remove a NOTREACHED until WK is fixed to not send in empty strings.<commit_after><|endoftext|>


<commit_before>/* -*-  mode: c++; indent-tabs-mode: nil -*- */

/*
  The elevation evaluator gets the subsurface temperature and computes the thaw depth
  over time.

  Authors: Ahmad Jan (jana@ornl.gov)
*/

#include "thaw_depth_evaluator.hh"

namespace Amanzi {
namespace Flow {

ThawDepthEvaluator::ThawDepthEvaluator(Teuchos::ParameterList& plist)
    : SecondaryVariableFieldEvaluator(plist)
{
  std::string domain_name=Keys::getDomain(my_key_);
  my_key_ = plist_.get<std::string>("thaw depth key", Keys::getKey(domain_name, "thaw_depth"));
}

ThawDepthEvaluator::ThawDepthEvaluator(const ThawDepthEvaluator& other)
    : SecondaryVariableFieldEvaluator(other)
{}

Teuchos::RCP<FieldEvaluator>
ThawDepthEvaluator::Clone() const
{
  return Teuchos::rcp(new ThawDepthEvaluator(*this));
}

void
ThawDepthEvaluator::EvaluateField_(const Teuchos::Ptr<State>& S,
        const Teuchos::Ptr<CompositeVector>& result)
{
  Epetra_MultiVector& res_c = *result->ViewComponent("cell",false);

  int ncells = res_c.MyLength();
  for (int c=0; c!=ncells; c++){
    const auto& top_z_centroid = S->GetMesh(domain.str())->face_centroid(0);
    AmanziGeometry::Point z_centroid(top_z_centroid);

    int id = S->GetMesh("surface_star")->cell_map(false).GID(c);
    std::stringstream domain;
    domain << "column_" << id;

    // search through the column and find the deepest unfrozen cell
    const auto& temp_c = *S->GetFieldData(Keys::getKey(domain.str(),"temperature"))
                         ->ViewComponent("cell", false);
    int col_cells = temp_c.MyLength();
    for (int i=0; i!=col_cells; ++i) {
      if (temp_c[0][i] >= 273.25) { // this hard codes in the transition width to 0.2 K
        z_centroid = S->GetMesh(domain.str())->face_centroid(i+1);
      }
    }

    res_c[0][c] = top_z_centroid[2] - z_centroid[2];
  }
}

void
ThawDepthEvaluator::EvaluateFieldPartialDerivative_(const Teuchos::Ptr<State>& S,
               Key wrt_key, const Teuchos::Ptr<CompositeVector>& result)
{}

// Custom EnsureCompatibility forces this to be updated once.
bool
ThawDepthEvaluator::HasFieldChanged(const Teuchos::Ptr<State>& S,
        Key request)
{
  bool changed = SecondaryVariableFieldEvaluator::HasFieldChanged(S,request);

  if (!updated_once_) {
    UpdateField_(S);
    updated_once_ = true;
    return true;
  }
  return changed;
}

void
ThawDepthEvaluator::EnsureCompatibility(const Teuchos::Ptr<State>& S)
{
  Key domain = Keys::getDomain(my_key_);
  AMANZI_ASSERT(domain == "surface_star");

  int ncells = S->GetMesh("surface_star")->num_entities(AmanziMesh::CELL,
          AmanziMesh::Parallel_type::OWNED);

  if (domain == "surface_star") {
    for (int c =0; c < ncells; c++){
      std::stringstream name;
      int id = S->GetMesh("surface_star")->cell_map(false).GID(c);
      name << "column_"<< id;
      Key temp_key = Keys::getKey(name.str(),"temperature");
      dependencies_.insert(temp_key);
    }
  }

  // Ensure my field exists.  Requirements should be already set.
  AMANZI_ASSERT(my_key_ != std::string(""));

  Teuchos::RCP<CompositeVectorSpace> my_fac = S->RequireField(my_key_, my_key_);

  // check plist for vis or checkpointing control
  bool io_my_key = plist_.get<bool>(std::string("visualize ")+my_key_, true);
  S->GetField(my_key_, my_key_)->set_io_vis(io_my_key);
  bool checkpoint_my_key = plist_.get<bool>(std::string("checkpoint ")+my_key_, false);
  S->GetField(my_key_, my_key_)->set_io_checkpoint(checkpoint_my_key);

  if (my_fac->Mesh() != Teuchos::null) {
    // Recurse into the tree to propagate info to leaves.
    for (KeySet::const_iterator key=dependencies_.begin();
         key!=dependencies_.end(); ++key) {
      S->RequireFieldEvaluator(*key)->EnsureCompatibility(S);
    }
  }
}

} //namespace
} //namespace
<commit_msg>fixes bug in thaw depth evaluator<commit_after>/* -*-  mode: c++; indent-tabs-mode: nil -*- */

/*
  The elevation evaluator gets the subsurface temperature and computes the thaw depth
  over time.

  Authors: Ahmad Jan (jana@ornl.gov)
*/

#include "thaw_depth_evaluator.hh"

namespace Amanzi {
namespace Flow {

ThawDepthEvaluator::ThawDepthEvaluator(Teuchos::ParameterList& plist)
    : SecondaryVariableFieldEvaluator(plist)
{
  std::string domain_name=Keys::getDomain(my_key_);
  my_key_ = plist_.get<std::string>("thaw depth key", Keys::getKey(domain_name, "thaw_depth"));
}

ThawDepthEvaluator::ThawDepthEvaluator(const ThawDepthEvaluator& other)
    : SecondaryVariableFieldEvaluator(other)
{}

Teuchos::RCP<FieldEvaluator>
ThawDepthEvaluator::Clone() const
{
  return Teuchos::rcp(new ThawDepthEvaluator(*this));
}

void
ThawDepthEvaluator::EvaluateField_(const Teuchos::Ptr<State>& S,
        const Teuchos::Ptr<CompositeVector>& result)
{
  Epetra_MultiVector& res_c = *result->ViewComponent("cell",false);

  int ncells = res_c.MyLength();
  for (int c=0; c!=ncells; c++){
    int id = S->GetMesh("surface_star")->cell_map(false).GID(c);
    std::stringstream domain;
    domain << "column_" << id;

    const auto& top_z_centroid = S->GetMesh(domain.str())->face_centroid(0);
    AmanziGeometry::Point z_centroid(top_z_centroid);

    // search through the column and find the deepest unfrozen cell
    const auto& temp_c = *S->GetFieldData(Keys::getKey(domain.str(),"temperature"))
                         ->ViewComponent("cell", false);
    int col_cells = temp_c.MyLength();
    for (int i=0; i!=col_cells; ++i) {
      if (temp_c[0][i] >= 273.25) { // this hard codes in the transition width to 0.2 K
        z_centroid = S->GetMesh(domain.str())->face_centroid(i+1);
      }
    }

    res_c[0][c] = top_z_centroid[2] - z_centroid[2];
  }
}

void
ThawDepthEvaluator::EvaluateFieldPartialDerivative_(const Teuchos::Ptr<State>& S,
               Key wrt_key, const Teuchos::Ptr<CompositeVector>& result)
{}

// Custom EnsureCompatibility forces this to be updated once.
bool
ThawDepthEvaluator::HasFieldChanged(const Teuchos::Ptr<State>& S,
        Key request)
{
  bool changed = SecondaryVariableFieldEvaluator::HasFieldChanged(S,request);

  if (!updated_once_) {
    UpdateField_(S);
    updated_once_ = true;
    return true;
  }
  return changed;
}

void
ThawDepthEvaluator::EnsureCompatibility(const Teuchos::Ptr<State>& S)
{
  Key domain = Keys::getDomain(my_key_);
  AMANZI_ASSERT(domain == "surface_star");

  int ncells = S->GetMesh("surface_star")->num_entities(AmanziMesh::CELL,
          AmanziMesh::Parallel_type::OWNED);

  if (domain == "surface_star") {
    for (int c =0; c < ncells; c++){
      std::stringstream name;
      int id = S->GetMesh("surface_star")->cell_map(false).GID(c);
      name << "column_"<< id;
      Key temp_key = Keys::getKey(name.str(),"temperature");
      dependencies_.insert(temp_key);
    }
  }

  // Ensure my field exists.  Requirements should be already set.
  AMANZI_ASSERT(my_key_ != std::string(""));

  Teuchos::RCP<CompositeVectorSpace> my_fac = S->RequireField(my_key_, my_key_);

  // check plist for vis or checkpointing control
  bool io_my_key = plist_.get<bool>(std::string("visualize ")+my_key_, true);
  S->GetField(my_key_, my_key_)->set_io_vis(io_my_key);
  bool checkpoint_my_key = plist_.get<bool>(std::string("checkpoint ")+my_key_, false);
  S->GetField(my_key_, my_key_)->set_io_checkpoint(checkpoint_my_key);

  if (my_fac->Mesh() != Teuchos::null) {
    // Recurse into the tree to propagate info to leaves.
    for (KeySet::const_iterator key=dependencies_.begin();
         key!=dependencies_.end(); ++key) {
      S->RequireFieldEvaluator(*key)->EnsureCompatibility(S);
    }
  }
}

} //namespace
} //namespace
<|endoftext|>


<commit_before>/**
 * Zillians MMO
 * Copyright (C) 2007-2010 Zillians.com, Inc.
 * For more information see http://www.zillians.com
 *
 * Zillians MMO is the library and runtime for massive multiplayer online game
 * development in utility computing model, which runs as a service for every
 * developer to build their virtual world running on our GPU-assisted machines.
 *
 * This is a close source library intended to be used solely within Zillians.com
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "core/Prerequisite.h"
#include "language/tree/ASTNode.h"
#include "language/tree/ASTNodeFactory.h"
#include "language/tree/visitor/check/ErrorMessageAnnotationCheckVisitor.h"
#include "../ASTNodeSamples.h"
#include <iostream>
#include <string>
#include <limits>

#define BOOST_TEST_MODULE ThorScriptTreeTest_ErrorMessageAnnotationCheckVisitorTest
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

using namespace zillians;
using namespace zillians::language::tree;
using namespace zillians::language::tree::visitor;

BOOST_AUTO_TEST_SUITE( ThorScriptTreeTest_ErrorMessageAnnotationCheckVisitorTestSuite )

ASTNode* createOKSample()
{
	Program* program = new Program();
	{
		Package* com_package = new Package(new SimpleIdentifier(L"com"));
		program->root->addPackage(com_package);
		{
			Package* zillians_package = new Package(new SimpleIdentifier(L"zillians"));
			com_package->addPackage(zillians_package);
			{
				ClassDecl* class_decl = new ClassDecl(new SimpleIdentifier(L"some_class"));
				zillians_package->addObject(class_decl);
				{
					FunctionDecl* some_member_function = new FunctionDecl(
							new SimpleIdentifier(L"some_member_function"),
							NULL,
							true,
							Declaration::VisibilitySpecifier::PUBLIC,
							Declaration::StorageSpecifier::NONE);
					class_decl->addFunction(some_member_function);
					{
						Block* block = some_member_function->block;

						{
							DeclarativeStmt* stmt = new DeclarativeStmt(new VariableDecl(new SimpleIdentifier(L"a"), new TypeSpecifier(PrimitiveType::INT32), false, Declaration::VisibilitySpecifier::DEFAULT, Declaration::StorageSpecifier::NONE));
							block->appendObject(stmt);
						}

						{
							DeclarativeStmt* stmt = new DeclarativeStmt(new VariableDecl(new SimpleIdentifier(L"b"), new TypeSpecifier(PrimitiveType::INT32), false, Declaration::VisibilitySpecifier::DEFAULT, Declaration::StorageSpecifier::NONE));
							block->appendObject(stmt);
						}

						{
							// set error check annotation data
							Annotation* msgParams = new Annotation(NULL);
							msgParams->appendKeyValue(new SimpleIdentifier(L"id"), new StringLiteral(L"mCount"));
							msgParams->appendKeyValue(new SimpleIdentifier(L"type"), new StringLiteral(L"int"));
							Annotation* levelIdParams = new Annotation(NULL);
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"level"), new StringLiteral(L"warning"));
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"id"), new StringLiteral(L"undeclared_variable"));
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"parameters"), msgParams);

							Annotation* anno = new Annotation(new SimpleIdentifier(L"static_test"));
							anno->appendKeyValue(new SimpleIdentifier(L"expect_message"), levelIdParams);
							Annotations* annos = new Annotations();
							annos->appendAnnotation(anno);

							// set error message context data
							std::map<std::wstring, std::wstring> m;
							m[L"id"] = L"mCount";
							m[L"type"] = L"int";
							auto errorContext = new zillians::language::stage::LogInfoContext(L"warning", L"undeclared_variable", m);

							ExpressionStmt* stmt = new ExpressionStmt(new BinaryExpr(BinaryExpr::OpCode::ASSIGN, new PrimaryExpr(new SimpleIdentifier(L"undeclared_variable_name")), new PrimaryExpr(new SimpleIdentifier(L"b"))));
							stmt->setAnnotation(annos);
							stmt->set<zillians::language::stage::LogInfoContext>(errorContext);

							block->appendObject(stmt);
						}
					}
				}
			}
		}
	}
	return program;
}

ASTNode* createFailSample()
{
	Program* program = new Program();
	{
		Package* com_package = new Package(new SimpleIdentifier(L"com"));
		program->root->addPackage(com_package);
		{
			Package* zillians_package = new Package(new SimpleIdentifier(L"zillians"));
			com_package->addPackage(zillians_package);
			{
				ClassDecl* class_decl = new ClassDecl(new SimpleIdentifier(L"some_class"));
				zillians_package->addObject(class_decl);
				{
					FunctionDecl* some_member_function = new FunctionDecl(
							new SimpleIdentifier(L"some_member_function"),
							NULL,
							true,
							Declaration::VisibilitySpecifier::PUBLIC,
							Declaration::StorageSpecifier::NONE);
					class_decl->addFunction(some_member_function);
					{
						Block* block = some_member_function->block;

						{
							DeclarativeStmt* stmt = new DeclarativeStmt(new VariableDecl(new SimpleIdentifier(L"a"), new TypeSpecifier(PrimitiveType::INT32), false, Declaration::VisibilitySpecifier::DEFAULT, Declaration::StorageSpecifier::NONE));
							block->appendObject(stmt);
						}

						{
							DeclarativeStmt* stmt = new DeclarativeStmt(new VariableDecl(new SimpleIdentifier(L"b"), new TypeSpecifier(PrimitiveType::INT32), false, Declaration::VisibilitySpecifier::DEFAULT, Declaration::StorageSpecifier::NONE));
							block->appendObject(stmt);
						}

						{
							// set error check annotation data
							Annotation* msgParams = new Annotation(NULL);
							msgParams->appendKeyValue(new SimpleIdentifier(L"id"), new StringLiteral(L"mCount"));
							msgParams->appendKeyValue(new SimpleIdentifier(L"type"), new StringLiteral(L"int"));
							Annotation* levelIdParams = new Annotation(NULL);
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"level"), new StringLiteral(L"warning"));
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"id"), new StringLiteral(L"undeclared_variable"));
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"parameters"), msgParams);

							Annotation* anno = new Annotation(new SimpleIdentifier(L"static_test"));
							anno->appendKeyValue(new SimpleIdentifier(L"expect_message"), levelIdParams);
							Annotations* annos = new Annotations();
							annos->appendAnnotation(anno);

							// set error message context data
							std::map<std::wstring, std::wstring> m;
							m[L"id"] = L"mCount";
							m[L"type"] = L"int";
							m[L"extra_fail_key"] = L"extra_fail_value";
							auto errorContext = new zillians::language::stage::LogInfoContext(L"warning", L"undeclared_variable", m);

							ExpressionStmt* stmt = new ExpressionStmt(new BinaryExpr(BinaryExpr::OpCode::ASSIGN, new PrimaryExpr(new SimpleIdentifier(L"undeclared_variable_name")), new PrimaryExpr(new SimpleIdentifier(L"b"))));
							stmt->setAnnotation(annos);
							stmt->set<zillians::language::stage::LogInfoContext>(errorContext);

							block->appendObject(stmt);
						}
					}
				}
			}
		}
	}
	return program;
}

BOOST_AUTO_TEST_CASE( ThorScriptTreeTest_ErrorMessageAnnotationCheckVisitorTestCase1 )
{
	ErrorMessageAnnotationCheckVisitor checker;
	ASTNode* okProgram = createOKSample();
	checker.check(*okProgram);
	BOOST_CHECK(checker.isAllMatch());

	ASTNode* failProgram = createFailSample();
	checker.check(*failProgram);
	BOOST_CHECK(!checker.isAllMatch());
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>fix make fail<commit_after>/**
 * Zillians MMO
 * Copyright (C) 2007-2010 Zillians.com, Inc.
 * For more information see http://www.zillians.com
 *
 * Zillians MMO is the library and runtime for massive multiplayer online game
 * development in utility computing model, which runs as a service for every
 * developer to build their virtual world running on our GPU-assisted machines.
 *
 * This is a close source library intended to be used solely within Zillians.com
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "core/Prerequisite.h"
#include "language/tree/ASTNode.h"
#include "language/tree/ASTNodeFactory.h"
#include "language/tree/visitor/check/ErrorMessageAnnotationCheckVisitor.h"
#include "../ASTNodeSamples.h"
#include <iostream>
#include <string>
#include <limits>

#define BOOST_TEST_MODULE ThorScriptTreeTest_ErrorMessageAnnotationCheckVisitorTest
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

using namespace zillians;
using namespace zillians::language::tree;
using namespace zillians::language::tree::visitor;

BOOST_AUTO_TEST_SUITE( ThorScriptTreeTest_ErrorMessageAnnotationCheckVisitorTestSuite )

ASTNode* createOKSample()
{
	Program* program = new Program();
	{
		Package* com_package = new Package(new SimpleIdentifier(L"com"));
		program->root->addPackage(com_package);
		{
			Package* zillians_package = new Package(new SimpleIdentifier(L"zillians"));
			com_package->addPackage(zillians_package);
			{
				ClassDecl* class_decl = new ClassDecl(new SimpleIdentifier(L"some_class"));
				zillians_package->addObject(class_decl);
				{
					FunctionDecl* some_member_function = new FunctionDecl(
							new SimpleIdentifier(L"some_member_function"),
							NULL,
							true,
							false,
							Declaration::VisibilitySpecifier::PUBLIC);
					class_decl->addFunction(some_member_function);
					{
						Block* block = some_member_function->block;

						{
							DeclarativeStmt* stmt = new DeclarativeStmt(new VariableDecl(new SimpleIdentifier(L"a"), new TypeSpecifier(PrimitiveType::INT32), false, false, false, Declaration::VisibilitySpecifier::DEFAULT));
							block->appendObject(stmt);
						}

						{
							DeclarativeStmt* stmt = new DeclarativeStmt(new VariableDecl(new SimpleIdentifier(L"b"), new TypeSpecifier(PrimitiveType::INT32), false, false, false, Declaration::VisibilitySpecifier::DEFAULT));
							block->appendObject(stmt);
						}

						{
							// set error check annotation data
							Annotation* msgParams = new Annotation(NULL);
							msgParams->appendKeyValue(new SimpleIdentifier(L"id"), new StringLiteral(L"mCount"));
							msgParams->appendKeyValue(new SimpleIdentifier(L"type"), new StringLiteral(L"int"));
							Annotation* levelIdParams = new Annotation(NULL);
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"level"), new StringLiteral(L"warning"));
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"id"), new StringLiteral(L"undeclared_variable"));
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"parameters"), msgParams);

							Annotation* anno = new Annotation(new SimpleIdentifier(L"static_test"));
							anno->appendKeyValue(new SimpleIdentifier(L"expect_message"), levelIdParams);
							Annotations* annos = new Annotations();
							annos->appendAnnotation(anno);

							// set error message context data
							std::map<std::wstring, std::wstring> m;
							m[L"id"] = L"mCount";
							m[L"type"] = L"int";
							auto errorContext = new zillians::language::stage::LogInfoContext(L"warning", L"undeclared_variable", m);

							ExpressionStmt* stmt = new ExpressionStmt(new BinaryExpr(BinaryExpr::OpCode::ASSIGN, new PrimaryExpr(new SimpleIdentifier(L"undeclared_variable_name")), new PrimaryExpr(new SimpleIdentifier(L"b"))));
							stmt->setAnnotation(annos);
							stmt->set<zillians::language::stage::LogInfoContext>(errorContext);

							block->appendObject(stmt);
						}
					}
				}
			}
		}
	}
	return program;
}

ASTNode* createFailSample()
{
	Program* program = new Program();
	{
		Package* com_package = new Package(new SimpleIdentifier(L"com"));
		program->root->addPackage(com_package);
		{
			Package* zillians_package = new Package(new SimpleIdentifier(L"zillians"));
			com_package->addPackage(zillians_package);
			{
				ClassDecl* class_decl = new ClassDecl(new SimpleIdentifier(L"some_class"));
				zillians_package->addObject(class_decl);
				{
					FunctionDecl* some_member_function = new FunctionDecl(
							new SimpleIdentifier(L"some_member_function"),
							NULL,
							true,
							false,
							Declaration::VisibilitySpecifier::PUBLIC);
					class_decl->addFunction(some_member_function);
					{
						Block* block = some_member_function->block;

						{
							DeclarativeStmt* stmt = new DeclarativeStmt(new VariableDecl(new SimpleIdentifier(L"a"), new TypeSpecifier(PrimitiveType::INT32), false, false, false, Declaration::VisibilitySpecifier::DEFAULT));
							block->appendObject(stmt);
						}

						{
							DeclarativeStmt* stmt = new DeclarativeStmt(new VariableDecl(new SimpleIdentifier(L"b"), new TypeSpecifier(PrimitiveType::INT32), false, false, false, Declaration::VisibilitySpecifier::DEFAULT));
							block->appendObject(stmt);
						}

						{
							// set error check annotation data
							Annotation* msgParams = new Annotation(NULL);
							msgParams->appendKeyValue(new SimpleIdentifier(L"id"), new StringLiteral(L"mCount"));
							msgParams->appendKeyValue(new SimpleIdentifier(L"type"), new StringLiteral(L"int"));
							Annotation* levelIdParams = new Annotation(NULL);
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"level"), new StringLiteral(L"warning"));
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"id"), new StringLiteral(L"undeclared_variable"));
							levelIdParams->appendKeyValue(new SimpleIdentifier(L"parameters"), msgParams);

							Annotation* anno = new Annotation(new SimpleIdentifier(L"static_test"));
							anno->appendKeyValue(new SimpleIdentifier(L"expect_message"), levelIdParams);
							Annotations* annos = new Annotations();
							annos->appendAnnotation(anno);

							// set error message context data
							std::map<std::wstring, std::wstring> m;
							m[L"id"] = L"mCount";
							m[L"type"] = L"int";
							m[L"extra_fail_key"] = L"extra_fail_value";
							auto errorContext = new zillians::language::stage::LogInfoContext(L"warning", L"undeclared_variable", m);

							ExpressionStmt* stmt = new ExpressionStmt(new BinaryExpr(BinaryExpr::OpCode::ASSIGN, new PrimaryExpr(new SimpleIdentifier(L"undeclared_variable_name")), new PrimaryExpr(new SimpleIdentifier(L"b"))));
							stmt->setAnnotation(annos);
							stmt->set<zillians::language::stage::LogInfoContext>(errorContext);

							block->appendObject(stmt);
						}
					}
				}
			}
		}
	}
	return program;
}

BOOST_AUTO_TEST_CASE( ThorScriptTreeTest_ErrorMessageAnnotationCheckVisitorTestCase1 )
{
	ErrorMessageAnnotationCheckVisitor checker;
	ASTNode* okProgram = createOKSample();
	checker.check(*okProgram);
	BOOST_CHECK(checker.isAllMatch());

	ASTNode* failProgram = createFailSample();
	checker.check(*failProgram);
	BOOST_CHECK(!checker.isAllMatch());
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>