<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iomanip>
#include <istream>
#include <sstream>
#include <iostream>
#include <string>

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <boost/spirit/include/classic_position_iterator.hpp>

#include "parser/SpiritParser.hpp"
#include "lexer/SpiritLexer.hpp"

#include "ast/Program.hpp"

namespace qi = boost::spirit::qi;

using namespace eddic;

template <typename Iterator, typename AttributeT>
struct Rule {
    typedef typename boost::spirit::qi::rule<Iterator, AttributeT> type;
};

template <typename Iterator, typename Lexer>
struct EddiGrammar : qi::grammar<Iterator, ast::Program()> {
    EddiGrammar(const Lexer& lexer) : EddiGrammar::base_type(program, "EDDI Grammar") {
        value = additiveValue.alias();

        additiveValue %=
                multiplicativeValue
            >>  *(
                    (lexer.addition > multiplicativeValue)
                |   (lexer.subtraction > multiplicativeValue)
                );

        multiplicativeValue %=
                unaryValue
            >>  *(
                    (lexer.multiplication > unaryValue)
                |   (lexer.division > unaryValue)
                |   (lexer.modulo > unaryValue)
                );

        //TODO Support + - primaryValue
        unaryValue = primaryValue.alias();

        primaryValue =
                constant
            |   variable
            |   arrayValue
            |   (lexer.left_parenth >> value > lexer.right_parenth);

        integer %=
                qi::eps
            >>  lexer.integer;

        variable %=
                qi::eps
            >>  lexer.word;

        arrayValue %=
                lexer.word
            >>  lexer.left_brace
            >>  value
            >>  lexer.right_brace;

        litteral %=
                qi::eps
            >> lexer.litteral;

        constant %=
                integer
            |   litteral;

        true_ %=
                qi::eps
            >>  lexer.true_;

        false_ %=
                qi::eps
            >>  lexer.false_;

        binary_condition %=
                value
            >>  (
                    lexer.greater_equals
                |   lexer.greater
                |   lexer.less_equals
                |   lexer.less
                |   lexer.not_equals
                |   lexer.equals
                )
            >>   value;

        condition %=
                true_
            |   false_
            |   binary_condition;

        else_if_ %=
                lexer.else_
            >>  lexer.if_
            >>  lexer.left_parenth
            >>  condition
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        else_ %=
                lexer.else_
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        if_ %=
                lexer.if_
            >>  lexer.left_parenth
            >>  condition
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace
            >>  *(else_if_)
            >>  -(else_);

        for_ %=
                lexer.for_
            >   lexer.left_parenth
            >   -declaration
            >   lexer.stop
            >   -condition
            >   lexer.stop
            >   -repeatable_instruction
            >   lexer.right_parenth
            >   lexer.left_brace
            >   (*instruction)
            >   lexer.right_brace;

        foreach_ =
                lexer.foreach_
            >   lexer.left_parenth
            >   lexer.word
            >   lexer.word
            >   lexer.from_
            >   lexer.integer
            >   lexer.to_
            >   lexer.integer
            >   lexer.right_parenth
            >   lexer.left_brace
            >   *(instruction)
            >   lexer.right_brace;

        while_ %=
                lexer.while_
            >   lexer.left_parenth
            >   condition
            >   lexer.right_parenth
            >   lexer.left_brace
            >   *(instruction)
            >   lexer.right_brace;

        declaration %=
                lexer.word
            >>  lexer.word
            >>  -(lexer.assign >> value);

        assignment %=
                lexer.word
            >>  lexer.assign
            >>  value;

        globalDeclaration %=
                lexer.word
            >>  lexer.word
            >>  -(lexer.assign >> constant)
            >>  lexer.stop;

        globalArrayDeclaration %=
                lexer.word
            >>  lexer.word
            >>  lexer.left_bracket
            >>  lexer.integer
            >>  lexer.right_bracket
            >>  lexer.stop;

        functionCall %=
                lexer.word
            >>  lexer.left_parenth
            >>  -( value >> *( lexer.comma > value))
            >>  lexer.right_parenth;

        swap %=
                lexer.word
            >>  lexer.swap
            >>  lexer.word;

        instruction %=
                (functionCall > lexer.stop)
            |   (assignment > lexer.stop)
            |   (declaration > lexer.stop)
            |   if_
            |   for_
            |   while_
            |   foreach_
            |   (swap > lexer.stop);

        repeatable_instruction = assignment | declaration | swap;

        arg %=
                lexer.word
            >>  lexer.word;

        function %=
                lexer.word
            >>  lexer.word
            >>  lexer.left_parenth
            >>  -( arg >> *( lexer.comma > arg))
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        program %=
                qi::eps
            >>  *(function | globalDeclaration | globalArrayDeclaration);

        //Name the rules
        globalDeclaration.name("EDDI global variable");
        function.name("EDDI function declaration");
        program.name("EDDI program");
    }

    qi::rule<Iterator, ast::Program()> program;
    qi::rule<Iterator, ast::GlobalVariableDeclaration()> globalDeclaration;
    qi::rule<Iterator, ast::GlobalArrayDeclaration()> globalArrayDeclaration;
    qi::rule<Iterator, ast::FunctionDeclaration()> function;
    qi::rule<Iterator, ast::FunctionParameter()> arg;

    qi::rule<Iterator, ast::Instruction()> instruction;
    qi::rule<Iterator, ast::Instruction()> repeatable_instruction;
    qi::rule<Iterator, ast::Swap()> swap;
    qi::rule<Iterator, ast::FunctionCall()> functionCall;
    qi::rule<Iterator, ast::Declaration()> declaration;
    qi::rule<Iterator, ast::Assignment()> assignment;
    qi::rule<Iterator, ast::While()> while_;
    qi::rule<Iterator, ast::For()> for_;
    qi::rule<Iterator, ast::Foreach()> foreach_;
    qi::rule<Iterator, ast::If()> if_;

    qi::rule<Iterator, ast::Else()> else_;
    qi::rule<Iterator, ast::ElseIf()> else_if_;

    qi::rule<Iterator, ast::Value()> value;
    qi::rule<Iterator, ast::Value()> primaryValue;
    qi::rule<Iterator, ast::Value()> unaryValue;
    qi::rule<Iterator, ast::ComposedValue()> additiveValue;
    qi::rule<Iterator, ast::ComposedValue()> multiplicativeValue;
    qi::rule<Iterator, ast::Value()> constant;
    qi::rule<Iterator, ast::Integer()> integer;
    qi::rule<Iterator, ast::Litteral()> litteral;
    qi::rule<Iterator, ast::VariableValue()> variable;
    qi::rule<Iterator, ast::ArrayValue()> arrayValue;

    qi::rule<Iterator, ast::Condition()> condition;
    qi::rule<Iterator, ast::True()> true_;
    qi::rule<Iterator, ast::False()> false_;
    qi::rule<Iterator, ast::BinaryCondition()> binary_condition;
};

bool SpiritParser::parse(const std::string& file, ast::Program& program){
    std::ifstream in(file.c_str());
    in.unsetf(std::ios::skipws);

    in.seekg(0, std::istream::end);
    std::size_t size(static_cast<size_t>(in.tellg()));

    in.seekg(0, std::istream::beg);

    std::string contents(size, 0);
    in.read(&contents[0], size);

    pos_iterator_type position_begin(contents.begin(), contents.end(), file);
    pos_iterator_type position_end;

    SimpleLexer<lexer_type> lexer;
    EddiGrammar<lexer_type::iterator_type, SimpleLexer<lexer_type>> grammar(lexer);

    try {
        bool r = lex::tokenize_and_parse(position_begin, position_end, lexer, grammar, program);

        if(r && position_begin == position_end) {
            return true;
        } else {
            std::cout << "Parsing failed" << std::endl;
            const spirit::classic::file_position_base<std::string>& pos = position_begin.get_position();
            std::cout <<
                "Error at file " << pos.file << " line " << pos.line << " column " << pos.column << std::endl <<
                "'" << position_begin.get_currentline() << "'" << std::endl <<
                std::setw(pos.column) << " " << "^- here";

            return false;
        }
    } catch (const qi::expectation_failure<lexer_type::iterator_type>& exception) {
        std::cout << "Parsing failed" << std::endl;

        //TODO Improve to get information from exception
        const spirit::classic::file_position_base<std::string>& pos = position_begin.get_position();

        std::cout <<
            "Error at file " << pos.file << " line " << pos.line << " column " << pos.column << " Expecting " << exception.what_ << std::endl <<
            "'" << position_begin.get_currentline() << "'" << std::endl <<
            std::setw(pos.column) << " " << "^- here" << std::endl;

        return false;
    }
}
<commit_msg>Fix the grammar for array values<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iomanip>
#include <istream>
#include <sstream>
#include <iostream>
#include <string>

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <boost/spirit/include/classic_position_iterator.hpp>

#include "parser/SpiritParser.hpp"
#include "lexer/SpiritLexer.hpp"

#include "ast/Program.hpp"

namespace qi = boost::spirit::qi;

using namespace eddic;

template <typename Iterator, typename AttributeT>
struct Rule {
    typedef typename boost::spirit::qi::rule<Iterator, AttributeT> type;
};

template <typename Iterator, typename Lexer>
struct EddiGrammar : qi::grammar<Iterator, ast::Program()> {
    EddiGrammar(const Lexer& lexer) : EddiGrammar::base_type(program, "EDDI Grammar") {
        value = additiveValue.alias();

        additiveValue %=
                multiplicativeValue
            >>  *(
                    (lexer.addition > multiplicativeValue)
                |   (lexer.subtraction > multiplicativeValue)
                );

        multiplicativeValue %=
                unaryValue
            >>  *(
                    (lexer.multiplication > unaryValue)
                |   (lexer.division > unaryValue)
                |   (lexer.modulo > unaryValue)
                );

        //TODO Support + - primaryValue
        unaryValue = primaryValue.alias();

        primaryValue =
                constant
            |   arrayValue
            |   variable
            |   (lexer.left_parenth >> value > lexer.right_parenth);

        integer %=
                qi::eps
            >>  lexer.integer;

        variable %=
                qi::eps
            >>  lexer.word;

        arrayValue %=
                lexer.word
            >>  lexer.left_bracket
            >>  value
            >>  lexer.right_bracket;

        litteral %=
                qi::eps
            >> lexer.litteral;

        constant %=
                integer
            |   litteral;

        true_ %=
                qi::eps
            >>  lexer.true_;

        false_ %=
                qi::eps
            >>  lexer.false_;

        binary_condition %=
                value
            >>  (
                    lexer.greater_equals
                |   lexer.greater
                |   lexer.less_equals
                |   lexer.less
                |   lexer.not_equals
                |   lexer.equals
                )
            >>   value;

        condition %=
                true_
            |   false_
            |   binary_condition;

        else_if_ %=
                lexer.else_
            >>  lexer.if_
            >>  lexer.left_parenth
            >>  condition
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        else_ %=
                lexer.else_
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        if_ %=
                lexer.if_
            >>  lexer.left_parenth
            >>  condition
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace
            >>  *(else_if_)
            >>  -(else_);

        for_ %=
                lexer.for_
            >   lexer.left_parenth
            >   -declaration
            >   lexer.stop
            >   -condition
            >   lexer.stop
            >   -repeatable_instruction
            >   lexer.right_parenth
            >   lexer.left_brace
            >   (*instruction)
            >   lexer.right_brace;

        foreach_ =
                lexer.foreach_
            >   lexer.left_parenth
            >   lexer.word
            >   lexer.word
            >   lexer.from_
            >   lexer.integer
            >   lexer.to_
            >   lexer.integer
            >   lexer.right_parenth
            >   lexer.left_brace
            >   *(instruction)
            >   lexer.right_brace;

        while_ %=
                lexer.while_
            >   lexer.left_parenth
            >   condition
            >   lexer.right_parenth
            >   lexer.left_brace
            >   *(instruction)
            >   lexer.right_brace;

        declaration %=
                lexer.word
            >>  lexer.word
            >>  -(lexer.assign >> value);

        assignment %=
                lexer.word
            >>  lexer.assign
            >>  value;

        globalDeclaration %=
                lexer.word
            >>  lexer.word
            >>  -(lexer.assign >> constant)
            >>  lexer.stop;

        globalArrayDeclaration %=
                lexer.word
            >>  lexer.word
            >>  lexer.left_bracket
            >>  lexer.integer
            >>  lexer.right_bracket
            >>  lexer.stop;

        functionCall %=
                lexer.word
            >>  lexer.left_parenth
            >>  -( value >> *( lexer.comma > value))
            >>  lexer.right_parenth;

        swap %=
                lexer.word
            >>  lexer.swap
            >>  lexer.word;

        instruction %=
                (functionCall > lexer.stop)
            |   (assignment > lexer.stop)
            |   (declaration > lexer.stop)
            |   if_
            |   for_
            |   while_
            |   foreach_
            |   (swap > lexer.stop);

        repeatable_instruction = assignment | declaration | swap;

        arg %=
                lexer.word
            >>  lexer.word;

        function %=
                lexer.word
            >>  lexer.word
            >>  lexer.left_parenth
            >>  -( arg >> *( lexer.comma > arg))
            >>  lexer.right_parenth
            >>  lexer.left_brace
            >>  *(instruction)
            >>  lexer.right_brace;

        program %=
                qi::eps
            >>  *(function | globalDeclaration | globalArrayDeclaration);

        //Name the rules
        globalDeclaration.name("EDDI global variable");
        function.name("EDDI function declaration");
        program.name("EDDI program");
    }

    qi::rule<Iterator, ast::Program()> program;
    qi::rule<Iterator, ast::GlobalVariableDeclaration()> globalDeclaration;
    qi::rule<Iterator, ast::GlobalArrayDeclaration()> globalArrayDeclaration;
    qi::rule<Iterator, ast::FunctionDeclaration()> function;
    qi::rule<Iterator, ast::FunctionParameter()> arg;

    qi::rule<Iterator, ast::Instruction()> instruction;
    qi::rule<Iterator, ast::Instruction()> repeatable_instruction;
    qi::rule<Iterator, ast::Swap()> swap;
    qi::rule<Iterator, ast::FunctionCall()> functionCall;
    qi::rule<Iterator, ast::Declaration()> declaration;
    qi::rule<Iterator, ast::Assignment()> assignment;
    qi::rule<Iterator, ast::While()> while_;
    qi::rule<Iterator, ast::For()> for_;
    qi::rule<Iterator, ast::Foreach()> foreach_;
    qi::rule<Iterator, ast::If()> if_;

    qi::rule<Iterator, ast::Else()> else_;
    qi::rule<Iterator, ast::ElseIf()> else_if_;

    qi::rule<Iterator, ast::Value()> value;
    qi::rule<Iterator, ast::Value()> primaryValue;
    qi::rule<Iterator, ast::Value()> unaryValue;
    qi::rule<Iterator, ast::ComposedValue()> additiveValue;
    qi::rule<Iterator, ast::ComposedValue()> multiplicativeValue;
    qi::rule<Iterator, ast::Value()> constant;
    qi::rule<Iterator, ast::Integer()> integer;
    qi::rule<Iterator, ast::Litteral()> litteral;
    qi::rule<Iterator, ast::VariableValue()> variable;
    qi::rule<Iterator, ast::ArrayValue()> arrayValue;

    qi::rule<Iterator, ast::Condition()> condition;
    qi::rule<Iterator, ast::True()> true_;
    qi::rule<Iterator, ast::False()> false_;
    qi::rule<Iterator, ast::BinaryCondition()> binary_condition;
};

bool SpiritParser::parse(const std::string& file, ast::Program& program){
    std::ifstream in(file.c_str());
    in.unsetf(std::ios::skipws);

    in.seekg(0, std::istream::end);
    std::size_t size(static_cast<size_t>(in.tellg()));

    in.seekg(0, std::istream::beg);

    std::string contents(size, 0);
    in.read(&contents[0], size);

    pos_iterator_type position_begin(contents.begin(), contents.end(), file);
    pos_iterator_type position_end;

    SimpleLexer<lexer_type> lexer;
    EddiGrammar<lexer_type::iterator_type, SimpleLexer<lexer_type>> grammar(lexer);

    try {
        bool r = lex::tokenize_and_parse(position_begin, position_end, lexer, grammar, program);

        if(r && position_begin == position_end) {
            return true;
        } else {
            std::cout << "Parsing failed" << std::endl;
            const spirit::classic::file_position_base<std::string>& pos = position_begin.get_position();
            std::cout <<
                "Error at file " << pos.file << " line " << pos.line << " column " << pos.column << std::endl <<
                "'" << position_begin.get_currentline() << "'" << std::endl <<
                std::setw(pos.column) << " " << "^- here";

            return false;
        }
    } catch (const qi::expectation_failure<lexer_type::iterator_type>& exception) {
        std::cout << "Parsing failed" << std::endl;

        //TODO Improve to get information from exception
        const spirit::classic::file_position_base<std::string>& pos = position_begin.get_position();

        std::cout <<
            "Error at file " << pos.file << " line " << pos.line << " column " << pos.column << " Expecting " << exception.what_ << std::endl <<
            "'" << position_begin.get_currentline() << "'" << std::endl <<
            std::setw(pos.column) << " " << "^- here" << std::endl;

        return false;
    }
}
<|endoftext|>


<commit_before>#ifndef DOMHEADER_GUARD_HPP
#define DOMHEADER_GUARD_HPP

/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

//
//  This is the primary header file for inclusion in application
//  programs using the C++ XML Document Object Model API.
//

#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMCDATASection.hpp>
#include <xercesc/dom/DOMCharacterData.hpp>
#include <xercesc/dom/DOMComment.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMDocumentFragment.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMEntity.hpp>
#include <xercesc/dom/DOMEntityReference.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMNodeList.hpp>
#include <xercesc/dom/DOMNotation.hpp>
#include <xercesc/dom/DOMProcessingInstruction.hpp>
#include <xercesc/dom/DOMText.hpp>

// Introduced in DOM Level 2
#include <xercesc/dom/DOMDocumentRange.hpp>
#include <xercesc/dom/DOMDocumentTraversal.hpp>
#include <xercesc/dom/DOMNodeFilter.hpp>
#include <xercesc/dom/DOMNodeIterator.hpp>
#include <xercesc/dom/DOMRange.hpp>
#include <xercesc/dom/DOMRangeException.hpp>
#include <xercesc/dom/DOMTreeWalker.hpp>

// Introduced in DOM Level 3
// Experimental - subject to change
#include <xercesc/dom/DOMBuilder.hpp>
#include <xercesc/dom/DOMEntityResolver.hpp>
#include <xercesc/dom/DOMError.hpp>
#include <xercesc/dom/DOMErrorHandler.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMImplementationRegistry.hpp>
#include <xercesc/dom/DOMImplementationSource.hpp>
#include <xercesc/dom/DOMInputSource.hpp>
#include <xercesc/dom/DOMLocator.hpp>
#include <xercesc/dom/DOMUserDataHandler.hpp>
#include <xercesc/dom/DOMWriter.hpp>
#include <xercesc/dom/DOMWriterFilter.hpp>

#endif
<commit_msg>added DOMTypeInfo.hpp<commit_after>#ifndef DOMHEADER_GUARD_HPP
#define DOMHEADER_GUARD_HPP

/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

//
//  This is the primary header file for inclusion in application
//  programs using the C++ XML Document Object Model API.
//

#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMCDATASection.hpp>
#include <xercesc/dom/DOMCharacterData.hpp>
#include <xercesc/dom/DOMComment.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMDocumentFragment.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMEntity.hpp>
#include <xercesc/dom/DOMEntityReference.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMNodeList.hpp>
#include <xercesc/dom/DOMNotation.hpp>
#include <xercesc/dom/DOMProcessingInstruction.hpp>
#include <xercesc/dom/DOMText.hpp>

// Introduced in DOM Level 2
#include <xercesc/dom/DOMDocumentRange.hpp>
#include <xercesc/dom/DOMDocumentTraversal.hpp>
#include <xercesc/dom/DOMNodeFilter.hpp>
#include <xercesc/dom/DOMNodeIterator.hpp>
#include <xercesc/dom/DOMRange.hpp>
#include <xercesc/dom/DOMRangeException.hpp>
#include <xercesc/dom/DOMTreeWalker.hpp>

// Introduced in DOM Level 3
// Experimental - subject to change
#include <xercesc/dom/DOMBuilder.hpp>
#include <xercesc/dom/DOMEntityResolver.hpp>
#include <xercesc/dom/DOMError.hpp>
#include <xercesc/dom/DOMErrorHandler.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMImplementationRegistry.hpp>
#include <xercesc/dom/DOMImplementationSource.hpp>
#include <xercesc/dom/DOMInputSource.hpp>
#include <xercesc/dom/DOMLocator.hpp>
#include <xercesc/dom/DOMTypeInfo.hpp>
#include <xercesc/dom/DOMUserDataHandler.hpp>
#include <xercesc/dom/DOMWriter.hpp>
#include <xercesc/dom/DOMWriterFilter.hpp>

#endif
<|endoftext|>


<commit_before>#ifndef DOMHEADER_GUARD_HPP
#define DOMHEADER_GUARD_HPP

/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

//
//  This is the primary header file for inclusion in application
//  programs using the C++ XML Document Object Model API.
//

#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMCDATASection.hpp>
#include <xercesc/dom/DOMCharacterData.hpp>
#include <xercesc/dom/DOMComment.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMDocumentFragment.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMEntity.hpp>
#include <xercesc/dom/DOMEntityReference.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMNodeList.hpp>
#include <xercesc/dom/DOMNotation.hpp>
#include <xercesc/dom/DOMProcessingInstruction.hpp>
#include <xercesc/dom/DOMText.hpp>

// Introduced in DOM Level 2
#include <xercesc/dom/DOMDocumentRange.hpp>
#include <xercesc/dom/DOMDocumentTraversal.hpp>
#include <xercesc/dom/DOMNodeFilter.hpp>
#include <xercesc/dom/DOMNodeIterator.hpp>
#include <xercesc/dom/DOMRange.hpp>
#include <xercesc/dom/DOMRangeException.hpp>
#include <xercesc/dom/DOMTreeWalker.hpp>

// Introduced in DOM Level 3
// Experimental - subject to change
#include <xercesc/dom/DOMBuilder.hpp>
#include <xercesc/dom/DOMEntityResolver.hpp>
#include <xercesc/dom/DOMError.hpp>
#include <xercesc/dom/DOMErrorHandler.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMImplementationRegistry.hpp>
#include <xercesc/dom/DOMImplementationSource.hpp>
#include <xercesc/dom/DOMInputSource.hpp>
#include <xercesc/dom/DOMLocator.hpp>
#include <xercesc/dom/DOMTypeInfo.hpp>
#include <xercesc/dom/DOMUserDataHandler.hpp>
#include <xercesc/dom/DOMWriter.hpp>
#include <xercesc/dom/DOMWriterFilter.hpp>

#endif
<commit_msg>Added DOMConfiguration.<commit_after>#ifndef DOMHEADER_GUARD_HPP
#define DOMHEADER_GUARD_HPP

/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

//
//  This is the primary header file for inclusion in application
//  programs using the C++ XML Document Object Model API.
//

#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMCDATASection.hpp>
#include <xercesc/dom/DOMCharacterData.hpp>
#include <xercesc/dom/DOMComment.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMDocumentFragment.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMEntity.hpp>
#include <xercesc/dom/DOMEntityReference.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMNodeList.hpp>
#include <xercesc/dom/DOMNotation.hpp>
#include <xercesc/dom/DOMProcessingInstruction.hpp>
#include <xercesc/dom/DOMText.hpp>

// Introduced in DOM Level 2
#include <xercesc/dom/DOMDocumentRange.hpp>
#include <xercesc/dom/DOMDocumentTraversal.hpp>
#include <xercesc/dom/DOMNodeFilter.hpp>
#include <xercesc/dom/DOMNodeIterator.hpp>
#include <xercesc/dom/DOMRange.hpp>
#include <xercesc/dom/DOMRangeException.hpp>
#include <xercesc/dom/DOMTreeWalker.hpp>

// Introduced in DOM Level 3
// Experimental - subject to change
#include <xercesc/dom/DOMBuilder.hpp>
#include <xercesc/dom/DOMConfiguration.hpp>
#include <xercesc/dom/DOMEntityResolver.hpp>
#include <xercesc/dom/DOMError.hpp>
#include <xercesc/dom/DOMErrorHandler.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMImplementationRegistry.hpp>
#include <xercesc/dom/DOMImplementationSource.hpp>
#include <xercesc/dom/DOMInputSource.hpp>
#include <xercesc/dom/DOMLocator.hpp>
#include <xercesc/dom/DOMTypeInfo.hpp>
#include <xercesc/dom/DOMUserDataHandler.hpp>
#include <xercesc/dom/DOMWriter.hpp>
#include <xercesc/dom/DOMWriterFilter.hpp>

#endif
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// create_plan.cpp
//
// Identification: src/planner/create_plan.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "planner/create_plan.h"

#include "storage/data_table.h"
#include "catalog/bootstrapper.h"
#include "parser/create_parse.h"
#include "parser/statement_create.h"

namespace peloton {
namespace planner {

CreatePlan::CreatePlan(storage::DataTable *table) {
  target_table_ = table;
  table_schema = nullptr;
}

CreatePlan::CreatePlan(std::string name, std::unique_ptr<catalog::Schema> schema) {
  table_name = name;
  table_schema = schema.release();
}

CreatePlan::CreatePlan(parser::CreateParse *parse_tree) {
  table_name = parse_tree->GetTableName();
  table_schema = parse_tree->GetSchema();
}

CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) {
  table_name = std::string(parse_tree->name);
  std::vector<catalog::Column> columns;
  std::vector<catalog::Constraint> column_contraints;
  for(auto col : *parse_tree->columns){
    ValueType val = col->GetValueType(col->type);

    //Check main constraints
    if(col->primary_key){
      catalog::Constraint constraint(CONSTRAINT_TYPE_PRIMARY, "con_primary");
      column_contraints.push_back(constraint);
    }

    if(col->not_null){
      catalog::Constraint constraint(CONSTRAINT_TYPE_NOTNULL, "con_not_null");
      column_contraints.push_back(constraint);
    }

    auto column = catalog::Column(val,GetTypeSize(val),std::string(col->name),false);
    for(auto con : column_contraints){
      column.AddConstraint(con);
    }

    column_contraints.clear();
    columns.push_back(column);
  }
  catalog::Schema* schema = new catalog::Schema(columns);
  table_schema = schema;
}

}  // namespace planner
}  // namespace peloton
<commit_msg>Fix a bug in CreatePlan on primary key checking.<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// create_plan.cpp
//
// Identification: src/planner/create_plan.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "planner/create_plan.h"

#include "storage/data_table.h"
#include "catalog/bootstrapper.h"
#include "parser/create_parse.h"
#include "parser/statement_create.h"

namespace peloton {
namespace planner {

CreatePlan::CreatePlan(storage::DataTable *table) {
  target_table_ = table;
  table_schema = nullptr;
}

CreatePlan::CreatePlan(std::string name,
                       std::unique_ptr<catalog::Schema> schema) {
  table_name = name;
  table_schema = schema.release();
}

CreatePlan::CreatePlan(parser::CreateParse *parse_tree) {
  table_name = parse_tree->GetTableName();
  table_schema = parse_tree->GetSchema();
}

CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) {
  table_name = std::string(parse_tree->name);
  std::vector<catalog::Column> columns;
  std::vector<catalog::Constraint> column_contraints;
  for (auto col : *parse_tree->columns) {
    ValueType val = col->GetValueType(col->type);

    LOG_INFO("Column name: %s; Is primary key: %d", col->name, col->primary);

    // Check main constraints
    if (col->primary) {
      catalog::Constraint constraint(CONSTRAINT_TYPE_PRIMARY, "con_primary");
      column_contraints.push_back(constraint);
      LOG_INFO("Added a primary key constraint on column \"%s\"", col->name);
    }

    if (col->not_null) {
      catalog::Constraint constraint(CONSTRAINT_TYPE_NOTNULL, "con_not_null");
      column_contraints.push_back(constraint);
    }

    auto column =
        catalog::Column(val, GetTypeSize(val), std::string(col->name), false);
    for (auto con : column_contraints) {
      column.AddConstraint(con);
    }

    column_contraints.clear();
    columns.push_back(column);
  }
  catalog::Schema *schema = new catalog::Schema(columns);
  table_schema = schema;
}

}  // namespace planner
}  // namespace peloton
<|endoftext|>


<commit_before>/* Copyright (c) 2013-2015 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Display.h"

#include "DisplayGL.h"
#include "DisplayQt.h"
#include "LogController.h"

using namespace QGBA;

#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
Display::Driver Display::s_driver = Display::Driver::OPENGL;
#else
Display::Driver Display::s_driver = Display::Driver::QT;
#endif

Display* Display::create(QWidget* parent) {
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
	QSurfaceFormat format;
	format.setSwapInterval(1);
	format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
#endif

	switch (s_driver) {
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
	case Driver::OPENGL:
		if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
			format.setVersion(2, 0);
		} else {
			format.setVersion(3, 2);
		}
		format.setProfile(QSurfaceFormat::CoreProfile);
		if (!DisplayGL::supportsFormat(format)) {
#ifdef BUILD_GL
			LOG(QT, WARN) << ("Failed to create an OpenGL Core context, trying old-style...");
			format.setVersion(1, 4);
			format.setOption(QSurfaceFormat::DeprecatedFunctions);
			if (!DisplayGL::supportsFormat(format)) {
				return nullptr;
			}
#else
			return nullptr;
#endif
		}
		return new DisplayGL(format, parent);
#endif
#ifdef BUILD_GL
	case Driver::OPENGL1:
		format.setVersion(1, 4);
		if (!DisplayGL::supportsFormat(format)) {
			return nullptr;
		}
		return new DisplayGL(format, parent);
#endif

	case Driver::QT:
		return new DisplayQt(parent);

	default:
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
		return new DisplayGL(format, parent);
#else
		return new DisplayQt(parent);
#endif
	}
}

Display::Display(QWidget* parent)
	: QWidget(parent)
{
	setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
	connect(&m_mouseTimer, &QTimer::timeout, this, &Display::hideCursor);
	m_mouseTimer.setSingleShot(true);
	m_mouseTimer.setInterval(MOUSE_DISAPPEAR_TIMER);
	setMouseTracking(true);
}

void Display::resizeEvent(QResizeEvent*) {
	m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
}

void Display::lockAspectRatio(bool lock) {
	m_lockAspectRatio = lock;
	m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
}

void Display::lockIntegerScaling(bool lock) {
	m_lockIntegerScaling = lock;
}

void Display::interframeBlending(bool lock) {
	m_interframeBlending = lock;
}

void Display::showOSDMessages(bool enable) {
	m_showOSD = enable;
}

void Display::filter(bool filter) {
	m_filter = filter;
}

void Display::showMessage(const QString& message) {
	m_messagePainter.showMessage(message);
	if (!isDrawing()) {
		forceDraw();
	}
}

void Display::mouseMoveEvent(QMouseEvent*) {
	emit showCursor();
	m_mouseTimer.stop();
	m_mouseTimer.start();
}
<commit_msg>Qt: Don't attempt to create a GL2 context if GL2 is disabled<commit_after>/* Copyright (c) 2013-2015 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Display.h"

#include "DisplayGL.h"
#include "DisplayQt.h"
#include "LogController.h"

using namespace QGBA;

#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
Display::Driver Display::s_driver = Display::Driver::OPENGL;
#else
Display::Driver Display::s_driver = Display::Driver::QT;
#endif

Display* Display::create(QWidget* parent) {
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
	QSurfaceFormat format;
	format.setSwapInterval(1);
	format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
#endif

	switch (s_driver) {
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
	case Driver::OPENGL:
#if defined(BUILD_GLES2) || defined(USE_EPOXY)
		if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
			format.setVersion(2, 0);
		} else {
			format.setVersion(3, 2);
		}
		format.setProfile(QSurfaceFormat::CoreProfile);
		if (!DisplayGL::supportsFormat(format)) {
#ifdef BUILD_GL
			LOG(QT, WARN) << ("Failed to create an OpenGL Core context, trying old-style...");
			format.setVersion(1, 4);
			format.setOption(QSurfaceFormat::DeprecatedFunctions);
			if (!DisplayGL::supportsFormat(format)) {
				return nullptr;
			}
#else
			return nullptr;
#endif
		}
		return new DisplayGL(format, parent);
#endif
#endif
#ifdef BUILD_GL
	case Driver::OPENGL1:
		format.setVersion(1, 4);
		if (!DisplayGL::supportsFormat(format)) {
			return nullptr;
		}
		return new DisplayGL(format, parent);
#endif

	case Driver::QT:
		return new DisplayQt(parent);

	default:
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
		return new DisplayGL(format, parent);
#else
		return new DisplayQt(parent);
#endif
	}
}

Display::Display(QWidget* parent)
	: QWidget(parent)
{
	setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
	connect(&m_mouseTimer, &QTimer::timeout, this, &Display::hideCursor);
	m_mouseTimer.setSingleShot(true);
	m_mouseTimer.setInterval(MOUSE_DISAPPEAR_TIMER);
	setMouseTracking(true);
}

void Display::resizeEvent(QResizeEvent*) {
	m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
}

void Display::lockAspectRatio(bool lock) {
	m_lockAspectRatio = lock;
	m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
}

void Display::lockIntegerScaling(bool lock) {
	m_lockIntegerScaling = lock;
}

void Display::interframeBlending(bool lock) {
	m_interframeBlending = lock;
}

void Display::showOSDMessages(bool enable) {
	m_showOSD = enable;
}

void Display::filter(bool filter) {
	m_filter = filter;
}

void Display::showMessage(const QString& message) {
	m_messagePainter.showMessage(message);
	if (!isDrawing()) {
		forceDraw();
	}
}

void Display::mouseMoveEvent(QMouseEvent*) {
	emit showCursor();
	m_mouseTimer.stop();
	m_mouseTimer.start();
}
<|endoftext|>


<commit_before>//Copyright (c) 2019 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include <gtest/gtest.h>

#include "../src/Application.h" //To set up a scene and load settings that the layer plan and merger need.
#include "../src/FanSpeedLayerTime.h" //Required to construct a layer plan. Doesn't influence our tests.
#include "../src/pathPlanning/GCodePath.h" //The paths that we're going to be merging.
#include "../src/LayerPlan.h" //Constructing plans that the mergers can merge lines in.
#include "../src/MergeInfillLines.h" //The class under test.
#include "../src/RetractionConfig.h" //Required to construct a layer plan. Doesn't influence our tests.
#include "../src/Slice.h" //To set up a scene and load settings that the layer plan and merger need.
#include "../src/settings/types/LayerIndex.h" //Required to construct a layer plan. Doesn't influence our tests.

namespace cura
{

class MergeInfillLinesTest : public testing::Test
{
public:
    //These settings don't matter for this test so they are all the same for every fixture.
    const size_t extruder_nr = 0;
    const LayerIndex layer_nr = 0;
    const bool is_initial_layer = false;
    const bool is_raft_layer = false;
    const coord_t layer_thickness = 100;
    const Point starting_position; //All plans start at 0,0.

    /*
     * A merger to test with.
     */
    ExtruderPlan* extruder_plan;
    MergeInfillLines* merger;

    /*
     * These fields are required for constructing layer plans and must be held
     * constant for as long as the lifetime of the plans. Construct them once
     * and store them in this fixture class.
     */
    const FanSpeedLayerTimeSettings fan_speed_layer_time;
    const RetractionConfig retraction_config;
    const GCodePathConfig skin_config;

    /*
     * A path of skin lines without any points.
     */
    GCodePath empty_skin;

    /*
     * A path of a single skin line.
     */
    GCodePath single_skin;

    /*
     * A path of multiple skin lines that together form a straight line.
     *
     * This path should not get merged together to a single line.
     */
    GCodePath lengthwise_skin;

    MergeInfillLinesTest()
     : starting_position(0, 0)
     , fan_speed_layer_time()
     , retraction_config()
     , skin_config(PrintFeatureType::Skin, 400, layer_thickness, 1, GCodePathConfig::SpeedDerivatives{50, 1000, 10})
     , empty_skin(skin_config, "merge_infill_lines_mesh", SpaceFillType::None, 1.0, false)
     , single_skin(skin_config, "merge_infill_lines_mesh", SpaceFillType::Lines, 1.0, false)
     , lengthwise_skin(skin_config, "merge_infill_lines_mesh", SpaceFillType::Lines, 1.0, false)
    {
         single_skin.points.emplace_back(1000, 0);

         lengthwise_skin.points = {Point(1000, 0),
                                   Point(2000, 0),
                                   Point(3000, 0),
                                   Point(4000, 0)};
    }

    void SetUp()
    {
        //Set up a scene so that we may request settings.
        Application::getInstance().current_slice = new Slice(1);
        Application::getInstance().current_slice->scene.extruders.emplace_back(0, nullptr);
        ExtruderTrain& train = Application::getInstance().current_slice->scene.extruders.back();
        train.settings.add("machine_nozzle_size", "0.4");
        train.settings.add("meshfix_maximum_deviation", "0.1");

        extruder_plan = new ExtruderPlan(extruder_nr, layer_nr, is_initial_layer, is_raft_layer, layer_thickness, fan_speed_layer_time, retraction_config);
        merger = new MergeInfillLines(*extruder_plan);
    }

    void TearDown()
    {
        delete extruder_plan;
        delete merger;
        delete Application::getInstance().current_slice;
    }
};

TEST_F(MergeInfillLinesTest, CalcPathLengthEmpty)
{
    EXPECT_EQ(0, merger->calcPathLength(starting_position, empty_skin));
}

TEST_F(MergeInfillLinesTest, CalcPathLengthSingle)
{
    EXPECT_EQ(1000, merger->calcPathLength(starting_position, single_skin));
}

TEST_F(MergeInfillLinesTest, CalcPathLengthMultiple)
{
    EXPECT_EQ(4000, merger->calcPathLength(starting_position, lengthwise_skin));
}

/*
 * Tries merging an empty set of paths together.
 *
 * This changes nothing in the paths, since there is nothing to change.
 */
TEST_F(MergeInfillLinesTest, MergeEmpty)
{
    std::vector<GCodePath> paths; //Empty. No paths to merge.

    const bool result = merger->mergeInfillLines(paths, starting_position);

    EXPECT_FALSE(result) << "There are no lines to merge.";
    EXPECT_EQ(paths.size(), 0) << "The number of paths should still be zero.";
}

/*
 * Tries merging a single path of a single line.
 *
 * This changes nothing in the paths, since the line cannot be merged with
 * anything else.
 */
TEST_F(MergeInfillLinesTest, MergeSingle)
{
    std::vector<GCodePath> paths;
    paths.push_back(single_skin);

    const bool result = merger->mergeInfillLines(paths, starting_position);

    EXPECT_FALSE(result) << "There is only one line, so it can't be merged with other lines.";
    ASSERT_EQ(paths.size(), 1) << "The path should not get removed.";
    EXPECT_EQ(paths[0].points.size(), 1) << "The path should not be modified.";
}

/*
 * Tries merging a single path that consists of multiple vertices in a straight
 * line.
 *
 * This should not change anything in the paths, since the lines are in a single
 * path without travel moves in between. It's just drawing a curve, and that
 * curve should not get modified.
 *
 * This is basically the case that went wrong with the "Weird Fat Infill" bug
 * (CURA-5776).
 */
TEST_F(MergeInfillLinesTest, MergeLenthwise)
{
    std::vector<GCodePath> paths;
    paths.push_back(lengthwise_skin);

    const bool result = merger->mergeInfillLines(paths, starting_position);

    EXPECT_FALSE(result) << "Patterns like Gyroid infill with many (almost) lengthwise lines should not get merged, even if those lines are short.";
    ASSERT_EQ(paths.size(), 1) << "The path should not get removed or split.";
    EXPECT_EQ(paths[0].points.size(), 4) << "The path should not be modified.";
}

} //namespace cura<commit_msg>Add test for basic happy path of merging infill lines<commit_after>//Copyright (c) 2019 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include <gtest/gtest.h>

#include "../src/Application.h" //To set up a scene and load settings that the layer plan and merger need.
#include "../src/FanSpeedLayerTime.h" //Required to construct a layer plan. Doesn't influence our tests.
#include "../src/pathPlanning/GCodePath.h" //The paths that we're going to be merging.
#include "../src/LayerPlan.h" //Constructing plans that the mergers can merge lines in.
#include "../src/MergeInfillLines.h" //The class under test.
#include "../src/RetractionConfig.h" //Required to construct a layer plan. Doesn't influence our tests.
#include "../src/Slice.h" //To set up a scene and load settings that the layer plan and merger need.
#include "../src/settings/types/LayerIndex.h" //Required to construct a layer plan. Doesn't influence our tests.

namespace cura
{

class MergeInfillLinesTest : public testing::Test
{
public:
    //These settings don't matter for this test so they are all the same for every fixture.
    const size_t extruder_nr = 0;
    const LayerIndex layer_nr = 0;
    const bool is_initial_layer = false;
    const bool is_raft_layer = false;
    const coord_t layer_thickness = 100;
    const Point starting_position; //All plans start at 0,0.

    /*
     * A merger to test with.
     */
    ExtruderPlan* extruder_plan;
    MergeInfillLines* merger;

    /*
     * These fields are required for constructing layer plans and must be held
     * constant for as long as the lifetime of the plans. Construct them once
     * and store them in this fixture class.
     */
    const FanSpeedLayerTimeSettings fan_speed_layer_time;
    const RetractionConfig retraction_config;
    const GCodePathConfig skin_config;
    const GCodePathConfig travel_config;

    /*
     * A path of skin lines without any points.
     */
    GCodePath empty_skin;

    /*
     * A path of a single skin line.
     */
    GCodePath single_skin;

    /*
     * A path of multiple skin lines that together form a straight line.
     *
     * This path should not get merged together to a single line.
     */
    GCodePath lengthwise_skin;

    MergeInfillLinesTest()
     : starting_position(0, 0)
     , fan_speed_layer_time()
     , retraction_config()
     , skin_config(PrintFeatureType::Skin, 400, layer_thickness, 1, GCodePathConfig::SpeedDerivatives{50, 1000, 10})
     , travel_config(PrintFeatureType::MoveCombing, 0, layer_thickness, 0, GCodePathConfig::SpeedDerivatives{100, 1000, 10})
     , empty_skin(skin_config, "merge_infill_lines_mesh", SpaceFillType::None, 1.0, false)
     , single_skin(skin_config, "merge_infill_lines_mesh", SpaceFillType::Lines, 1.0, false)
     , lengthwise_skin(skin_config, "merge_infill_lines_mesh", SpaceFillType::Lines, 1.0, false)
    {
         single_skin.points.emplace_back(1000, 0);

         lengthwise_skin.points = {Point(1000, 0),
                                   Point(2000, 0),
                                   Point(3000, 0),
                                   Point(4000, 0)};
    }

    void SetUp()
    {
        //Set up a scene so that we may request settings.
        Application::getInstance().current_slice = new Slice(1);
        Application::getInstance().current_slice->scene.extruders.emplace_back(0, nullptr);
        ExtruderTrain& train = Application::getInstance().current_slice->scene.extruders.back();
        train.settings.add("machine_nozzle_size", "0.4");
        train.settings.add("meshfix_maximum_deviation", "0.1");

        extruder_plan = new ExtruderPlan(extruder_nr, layer_nr, is_initial_layer, is_raft_layer, layer_thickness, fan_speed_layer_time, retraction_config);
        merger = new MergeInfillLines(*extruder_plan);
    }

    void TearDown()
    {
        delete extruder_plan;
        delete merger;
        delete Application::getInstance().current_slice;
    }
};

TEST_F(MergeInfillLinesTest, CalcPathLengthEmpty)
{
    EXPECT_EQ(0, merger->calcPathLength(starting_position, empty_skin));
}

TEST_F(MergeInfillLinesTest, CalcPathLengthSingle)
{
    EXPECT_EQ(1000, merger->calcPathLength(starting_position, single_skin));
}

TEST_F(MergeInfillLinesTest, CalcPathLengthMultiple)
{
    EXPECT_EQ(4000, merger->calcPathLength(starting_position, lengthwise_skin));
}

/*
 * Tries merging an empty set of paths together.
 *
 * This changes nothing in the paths, since there is nothing to change.
 */
TEST_F(MergeInfillLinesTest, MergeEmpty)
{
    std::vector<GCodePath> paths; //Empty. No paths to merge.

    const bool result = merger->mergeInfillLines(paths, starting_position);

    EXPECT_FALSE(result) << "There are no lines to merge.";
    EXPECT_EQ(paths.size(), 0) << "The number of paths should still be zero.";
}

/*
 * Tries merging a single path of a single line.
 *
 * This changes nothing in the paths, since the line cannot be merged with
 * anything else.
 */
TEST_F(MergeInfillLinesTest, MergeSingle)
{
    std::vector<GCodePath> paths;
    paths.push_back(single_skin);

    const bool result = merger->mergeInfillLines(paths, starting_position);

    EXPECT_FALSE(result) << "There is only one line, so it can't be merged with other lines.";
    ASSERT_EQ(paths.size(), 1) << "The path should not get removed.";
    EXPECT_EQ(paths[0].points.size(), 1) << "The path should not be modified.";
}

/*
 * Tries merging a single path that consists of multiple vertices in a straight
 * line.
 *
 * This should not change anything in the paths, since the lines are in a single
 * path without travel moves in between. It's just drawing a curve, and that
 * curve should not get modified.
 *
 * This is basically the case that went wrong with the "Weird Fat Infill" bug
 * (CURA-5776).
 */
TEST_F(MergeInfillLinesTest, MergeLenthwise)
{
    std::vector<GCodePath> paths;
    paths.push_back(lengthwise_skin);

    const bool result = merger->mergeInfillLines(paths, starting_position);

    EXPECT_FALSE(result) << "Patterns like Gyroid infill with many (almost) lengthwise lines should not get merged, even if those lines are short.";
    ASSERT_EQ(paths.size(), 1) << "The path should not get removed or split.";
    EXPECT_EQ(paths[0].points.size(), 4) << "The path should not be modified.";
}

/*
 * Tries merging a bunch of parallel lines with travel moves in between.
 *
 * This is the basic use case for merging infill lines.
 */
TEST_F(MergeInfillLinesTest, MergeParallel)
{
    std::vector<GCodePath> paths;
    constexpr Ratio normal_flow = 1.0;
    constexpr bool no_spiralize = false;
    constexpr size_t num_lines = 10; //How big the test is.
    //Creates a zig-zag line with extrusion moves when moving in the Y direction and travel moves in between:
    //  _   _   _
    // | |_| |_| |_|
    for(size_t i = 0; i < num_lines; i++)
    {
        paths.emplace_back(skin_config, "merge_infill_lines_mesh", SpaceFillType::Lines, normal_flow, no_spiralize);
        paths.back().points.emplace_back(400 * i, 100 * ((i + 1) % 2));
        paths.emplace_back(travel_config, "merge_infill_lines_mesh", SpaceFillType::None, normal_flow, no_spiralize);
        paths.back().points.emplace_back(400 * (i + 1), 100 * ((i + 1) % 2));
    }
    //End with an extrusion move, not a travel move.
    paths.emplace_back(skin_config, "merge_infill_lines_mesh", SpaceFillType::Lines, normal_flow, no_spiralize);
    paths.back().points.emplace_back(400 * num_lines, 100 * ((num_lines + 1) % 2));

    const bool result = merger->mergeInfillLines(paths, starting_position);

    EXPECT_TRUE(result) << "The simple zig-zag pattern should get merged fine.";
    EXPECT_LE(paths.size(), 5); //Some lenience. Ideally it'd be one.
}

} //namespace cura<|endoftext|>


<commit_before>#include "Catch/catch.hpp"
#include "slang.h"

using namespace slang;

namespace {

TEST_CASE("Simple eval", "[eval]") {
    ScriptSession session;
    auto value = session.eval("3 * 3");
    CHECK(value.integer() == 9);

    session.eval("int i = 4;");
    value = session.eval("i + 9");
    CHECK(value.integer() == 13);
}

TEST_CASE("Eval function calls", "[eval]") {
    ScriptSession session;
    session.eval(R"(
function logic [15:0] foo(int a, int b);
    return a + b;
endfunction
)");

    auto value = session.eval("foo(3, 4)");
    CHECK(value.integer() == 7);

    session.eval(R"(
function int bar();
    return 2;
    return 3;
endfunction
)");

    value = session.eval("bar()");
    CHECK(value.integer() == 2);
}

TEST_CASE("Nested functions", "[eval]") {
    ScriptSession session;
    session.eval(R"(
function automatic int symbols_in_data(int dataBitsPerSymbol, int data_width);
    return data_width / dataBitsPerSymbol;
endfunction
)");

    session.eval(R"(
function automatic int num_words_in_address_space(int dataBitsPerSymbol, int data_width, int address_width);
    // Riviera-PRO 2015.10 crashes when calling a function from
    // within a function. After all this is understandable since
    // this is a really hard CS problem that has never been solved
    // before... ???
    //
    int address_bits_per_word = $clog2(symbols_in_data(dataBitsPerSymbol, data_width));
    return 2**(address_width - address_bits_per_word);
endfunction
)");

    auto value = session.eval("num_words_in_address_space(8, 64, 20)");

    auto diagnostics = session.reportDiagnostics();
    if (!diagnostics.empty())
        WARN(diagnostics.c_str());

    CHECK(value.integer() == 131072);
}

TEST_CASE("Module param", "[eval]") {
    ScriptSession session;
    auto module = session.eval("module A#(parameter int P); localparam LP = P + 3; endmodule");
    CHECK(module);
    auto instance = session.eval("A #(.P(2)) a0();");
    CHECK(instance);
    auto value = session.eval("a0.LP");
    CHECK(value.integer() == 5);
}

TEST_CASE("Interface param", "[eval]") {
    ScriptSession session;
    auto interface = session.eval("interface IFACE1#(parameter int W = 8); logic valid; logic [W-1:0] data; endinterface");
    CHECK(interface);
    auto instance = session.eval("IFACE1 #(6) i0();");
    CHECK(instance);
    auto value = session.eval("i0.W");
    CHECK(value.integer() == 6);
}

TEST_CASE("Interface port param", "[eval]") {
    ScriptSession session;
    auto interface = session.eval("interface IFACE2 #(parameter int W = 8); logic valid; logic [W-1:0] data; endinterface");
    CHECK(interface);
    auto module = session.eval("module M(IFACE2 i); localparam int LP = i.W; endmodule");
    CHECK(module);
    auto port = session.eval("IFACE2 #(6) i0();");
    CHECK(port);
    auto instance = session.eval("M m0(i0);");
    CHECK(instance);
    auto value = session.eval("m0.LP");
    CHECK(value.integer() == 6);
}

TEST_CASE("Eval if statement", "[eval]") {
    ScriptSession session;
    session.eval(R"(
function logic [15:0] foo(int a);
    if (a == 3)
        return 4;
    else
        return 5;
endfunction
)");

    auto value = session.eval("foo(3)");
    CHECK(value.integer() == 4);

    auto elseValue = session.eval("foo(2)");
    CHECK(elseValue.integer() == 5);
}

TEST_CASE("Eval for loop", "[eval]") {
    ScriptSession session;
    session.eval(R"(
function logic [15:0] foo(int a);
    logic [15:0] result = 1;
    for (int i = 0; i < a; i+=1)
        result *= 2;
    return result;
endfunction
)");

    auto value0 = session.eval("foo(0)");
    CHECK(value0.integer() == 1);

    auto value1 = session.eval("foo(1)");
    CHECK(value1.integer() == 2);

    auto value2 = session.eval("foo(2)");
    CHECK(value2.integer() == 4);

    auto value3 = session.eval("foo(3)");
    CHECK(value3.integer() == 8);
}

// Simple test wrapper, uses ==(uint64_t) to check result
#define EVAL_TEST(descr, expr, result) \
TEST_CASE(descr, "[eval]") { \
    ScriptSession session; \
    auto value = session.eval(expr).integer(); \
    CHECK(value == result); \
}

// Wrapper uses exactlyEqual and parses a text-specificied SVInt
#define EVAL_TEST_EX(descr, expr, result) \
TEST_CASE(descr, "[eval]") { \
    ScriptSession session; \
    auto value = session.eval(expr).integer(); \
    auto res = SVInt(StringRef(result)); \
    /* uncomment for diagonstics: printf("%s = %s\n", value.toString(LiteralBase::Binary).c_str(), res.toString(LiteralBase::Binary).c_str());*/ \
    CHECK(exactlyEqual(value, res)); \
}

EVAL_TEST("lshl", "4 << 2", 16);
EVAL_TEST("ashl", "4 <<< 2", 16);
EVAL_TEST("lshr", "4 >> 1", 2);
EVAL_TEST_EX("ashr", "-4 >>> 1", "-2");
EVAL_TEST_EX("ashr_long", "-65'sd4 >>> 1", "-65'sb10");
EVAL_TEST("conditionalT", "2 == 2 ? 5 : 4", 5);
EVAL_TEST("conditionalF", "(2 * 2) == 3 ? 5 : 4", 4);
EVAL_TEST_EX("conditionalU", "'z ? 5 : 6", "32'sb1xx");
EVAL_TEST_EX("conditionalU2", "(1 / 0) ? 128'b101 : 128'b110", "128'b1xx");
EVAL_TEST("conditionalUSame", "'x ? 5 : 5", 5);
EVAL_TEST("selfDeterminedUULiteral", "1 << '1", 2);
EVAL_TEST_EX("contextDeterminedUULiteral", "'1 + 65'b0", "65'h1ffffffffffffffff");
EVAL_TEST_EX("concatenationLeadingZeroes", "{2'b11, 4'b0010, 3'b101}", "9'b110010101");
EVAL_TEST_EX("concatenation", "{2'b11, 3'b101}", "5'b11101");
EVAL_TEST_EX("concatenation2", "{22'b0, 43'b100, 1'b1 / 1'b0}", "66'b100x");
EVAL_TEST_EX("replicate", "{4 {2'b10}}", "8'b10101010");
EVAL_TEST_EX("nontrivialReplicate", "{((2 + 2) - 4 + 4) {2'b01}}", "8'b01010101");
EVAL_TEST_EX("concatenation with zero-width replicate", "{2'b10, {0 {4'b1001}}, 2'b01}", "4'b1001");
EVAL_TEST("wildcardEq", "5'b11001 ==? {1'b1 / 1'b0, 4'b1001}", 1);
EVAL_TEST("wildcardEqNotCommute", "({1'b1 / 1'b0, 4'b1001} ==? 5'b11001) === 'x", 1);
EVAL_TEST("bitSelect", "3'd7[2]", 1);
EVAL_TEST("bitSelectSimpleRange", "5'd25[3:0]", 9);
EVAL_TEST("bitSelectSimpleRangeNonzerobased", "5'd25[3:1]", 4);
EVAL_TEST_EX("bitSelectSimpleRangeLarge", "65'h1ffffffffffffffff[64:62]", "3'b111");
EVAL_TEST("bitSelectAscendingRange", "5'd25[0 +: 3]", 9);
EVAL_TEST("bitSelectDescendingRange", "5'd25[3 -: 3]", 9);
EVAL_TEST_EX("bitselect with unknown address", "4'b1001[(1 / 0)]", "1'bx");
EVAL_TEST_EX("rangeselect with unknown address", "4'b1001[(1/ 0) +: 2]", "2'bxx");
EVAL_TEST_EX("partially oob rangeselect (right)", "4'b1001[3 : -1]", "5'b1001x");
EVAL_TEST_EX("partially oob rangeselect (left)", "4'b1001[4 : 1]", "4'bx100");
EVAL_TEST_EX("partially oob rangeselect (both)", "4'b1001[4 : -1]", "6'bx1001x");
EVAL_TEST_EX("totally oob rangeselect", "4'b1001[105 : 101]", "5'bxxxxx");
//TODO: Figure out why a test like this fails, seems like something wrong with literals with x's?
//EVAL_TEST_EX("lit", "43'b10x", "43'b10x");

TEST_CASE("bit select weird indexes", "[eval]") {
    // The above bit select cases test the "normal" case where vectors are specified
    // with [N : 0]. Here we test "up-vectors" and non-zero lower bounds.
    ScriptSession session;
    session.eval("logic [0 : 15] up_vect = 5'b10111;");

    auto value = session.eval("up_vect[12:14]").integer();
    CHECK(exactlyEqual(value, SVInt(StringRef("3'b011"))));

    value = session.eval("up_vect[12 -: 2]").integer();
    CHECK(exactlyEqual(value, SVInt(StringRef("3'b011"))));

    value = session.eval("up_vect[14 +: 2]").integer();
    CHECK(exactlyEqual(value, SVInt(StringRef("3'b011"))));

    session.eval("logic [20 : 5] down_vect = 5'd25");

    value = session.eval("down_vect[8:5]").integer();

    CHECK(exactlyEqual(value, SVInt(StringRef("4'd9"))));

    value = session.eval("down_vect[5 +: 3]").integer();
    CHECK(value == 9);

    value = session.eval("down_vect[8 -: 3]").integer();
    CHECK(value == 9);
}
}
<commit_msg>new tests<commit_after>#include "Catch/catch.hpp"
#include "slang.h"

using namespace slang;

namespace {

TEST_CASE("Simple eval", "[eval]") {
    ScriptSession session;
    auto value = session.eval("3 * 3");
    CHECK(value.integer() == 9);

    session.eval("int i = 4;");
    value = session.eval("i + 9");
    CHECK(value.integer() == 13);
}

TEST_CASE("Eval function calls", "[eval]") {
    ScriptSession session;
    session.eval(R"(
function logic [15:0] foo(int a, int b);
    return a + b;
endfunction
)");

    auto value = session.eval("foo(3, 4)");
    CHECK(value.integer() == 7);

    session.eval(R"(
function int bar();
    return 2;
    return 3;
endfunction
)");

    value = session.eval("bar()");
    CHECK(value.integer() == 2);
}

TEST_CASE("Nested functions", "[eval]") {
    ScriptSession session;
    session.eval(R"(
function automatic int symbols_in_data(int dataBitsPerSymbol, int data_width);
    return data_width / dataBitsPerSymbol;
endfunction
)");

    session.eval(R"(
function automatic int num_words_in_address_space(int dataBitsPerSymbol, int data_width, int address_width);
    // Riviera-PRO 2015.10 crashes when calling a function from
    // within a function. After all this is understandable since
    // this is a really hard CS problem that has never been solved
    // before... ???
    //
    int address_bits_per_word = $clog2(symbols_in_data(dataBitsPerSymbol, data_width));
    return 2**(address_width - address_bits_per_word);
endfunction
)");

    auto value = session.eval("num_words_in_address_space(8, 64, 20)");

    auto diagnostics = session.reportDiagnostics();
    if (!diagnostics.empty())
        WARN(diagnostics.c_str());

    CHECK(value.integer() == 131072);
}

TEST_CASE("Module param", "[eval]") {
    ScriptSession session;
    auto module = session.eval("module A#(parameter int P); localparam LP = P + 3; endmodule");
    CHECK(module);
    auto instance = session.eval("A #(.P(2)) a0();");
    CHECK(instance);
    auto value = session.eval("a0.LP");
    CHECK(value.integer() == 5);
}

TEST_CASE("Interface param", "[eval]") {
    ScriptSession session;
    auto interface = session.eval("interface IFACE1#(parameter int W = 8); logic valid; logic [W-1:0] data; endinterface");
    CHECK(interface);
    auto instance = session.eval("IFACE1 #(6) i0();");
    CHECK(instance);
    auto value = session.eval("i0.W");
    CHECK(value.integer() == 6);
}

TEST_CASE("Interface port param", "[eval]") {
    ScriptSession session;
    auto interface = session.eval("interface IFACE2 #(parameter int W = 8); logic valid; logic [W-1:0] data; endinterface");
    CHECK(interface);
    auto module = session.eval("module M(IFACE2 i); localparam int LP = i.W; endmodule");
    CHECK(module);
    auto port = session.eval("IFACE2 #(6) i0();");
    CHECK(port);
    auto instance = session.eval("M m0(i0);");
    CHECK(instance);
    auto value = session.eval("m0.LP");
    CHECK(value.integer() == 6);
}

TEST_CASE("Interface array", "[eval]") {
    ScriptSession session;
    auto interface = session.eval("interface IFACE3 #(parameter int W = 8); logic valid; logic [W-1:0] data; endinterface");
    CHECK(interface);
    auto module = session.eval("module M(IFACE3 i); localparam int LP = i.W; endmodule");
    CHECK(module);
    auto param = session.eval("parameter int N = 1;");
    auto port = session.eval("IFACE3 #(6) i0 [N] ();");
    CHECK(port);
    auto instance = session.eval("M m [] (i0);");
    CHECK(instance);
    auto value = session.eval("m[N-1].LP");
    CHECK(value.integer() == 6);
}

TEST_CASE("Eval if statement", "[eval]") {
    ScriptSession session;
    session.eval(R"(
function logic [15:0] foo(int a);
    if (a == 3)
        return 4;
    else
        return 5;
endfunction
)");

    auto value = session.eval("foo(3)");
    CHECK(value.integer() == 4);

    auto elseValue = session.eval("foo(2)");
    CHECK(elseValue.integer() == 5);
}

TEST_CASE("Eval for loop", "[eval]") {
    ScriptSession session;
    session.eval(R"(
function logic [15:0] foo(int a);
    logic [15:0] result = 1;
    for (int i = 0; i < a; i+=1)
        result *= 2;
    return result;
endfunction
)");

    auto value0 = session.eval("foo(0)");
    CHECK(value0.integer() == 1);

    auto value1 = session.eval("foo(1)");
    CHECK(value1.integer() == 2);

    auto value2 = session.eval("foo(2)");
    CHECK(value2.integer() == 4);

    auto value3 = session.eval("foo(3)");
    CHECK(value3.integer() == 8);
}

// Simple test wrapper, uses ==(uint64_t) to check result
#define EVAL_TEST(descr, expr, result) \
TEST_CASE(descr, "[eval]") { \
    ScriptSession session; \
    auto value = session.eval(expr).integer(); \
    CHECK(value == result); \
}

// Wrapper uses exactlyEqual and parses a text-specificied SVInt
#define EVAL_TEST_EX(descr, expr, result) \
TEST_CASE(descr, "[eval]") { \
    ScriptSession session; \
    auto value = session.eval(expr).integer(); \
    auto res = SVInt(StringRef(result)); \
    /* uncomment for diagonstics: printf("%s = %s\n", value.toString(LiteralBase::Binary).c_str(), res.toString(LiteralBase::Binary).c_str());*/ \
    CHECK(exactlyEqual(value, res)); \
}

EVAL_TEST("lshl", "4 << 2", 16);
EVAL_TEST("ashl", "4 <<< 2", 16);
EVAL_TEST("lshr", "4 >> 1", 2);
EVAL_TEST_EX("ashr", "-4 >>> 1", "-2");
EVAL_TEST_EX("ashr_long", "-65'sd4 >>> 1", "-65'sb10");
EVAL_TEST("conditionalT", "2 == 2 ? 5 : 4", 5);
EVAL_TEST("conditionalF", "(2 * 2) == 3 ? 5 : 4", 4);
EVAL_TEST_EX("conditionalU", "'z ? 5 : 6", "32'sb1xx");
EVAL_TEST_EX("conditionalU2", "(1 / 0) ? 128'b101 : 128'b110", "128'b1xx");
EVAL_TEST("conditionalUSame", "'x ? 5 : 5", 5);
EVAL_TEST("selfDeterminedUULiteral", "1 << '1", 2);
EVAL_TEST_EX("contextDeterminedUULiteral", "'1 + 65'b0", "65'h1ffffffffffffffff");
EVAL_TEST_EX("concatenationLeadingZeroes", "{2'b11, 4'b0010, 3'b101}", "9'b110010101");
EVAL_TEST_EX("concatenation", "{2'b11, 3'b101}", "5'b11101");
EVAL_TEST_EX("concatenation2", "{22'b0, 43'b100, 1'b1 / 1'b0}", "66'b100x");
EVAL_TEST_EX("replicate", "{4 {2'b10}}", "8'b10101010");
EVAL_TEST_EX("nontrivialReplicate", "{((2 + 2) - 4 + 4) {2'b01}}", "8'b01010101");
EVAL_TEST_EX("concatenation with zero-width replicate", "{2'b10, {0 {4'b1001}}, 2'b01}", "4'b1001");
EVAL_TEST("wildcardEq", "5'b11001 ==? {1'b1 / 1'b0, 4'b1001}", 1);
EVAL_TEST("wildcardEqNotCommute", "({1'b1 / 1'b0, 4'b1001} ==? 5'b11001) === 'x", 1);
EVAL_TEST("bitSelect", "3'd7[2]", 1);
EVAL_TEST("bitSelectSimpleRange", "5'd25[3:0]", 9);
EVAL_TEST("bitSelectSimpleRangeNonzerobased", "5'd25[3:1]", 4);
EVAL_TEST_EX("bitSelectSimpleRangeLarge", "65'h1ffffffffffffffff[64:62]", "3'b111");
EVAL_TEST("bitSelectAscendingRange", "5'd25[0 +: 3]", 9);
EVAL_TEST("bitSelectDescendingRange", "5'd25[3 -: 3]", 9);
EVAL_TEST_EX("bitselect with unknown address", "4'b1001[(1 / 0)]", "1'bx");
EVAL_TEST_EX("rangeselect with unknown address", "4'b1001[(1/ 0) +: 2]", "2'bxx");
EVAL_TEST_EX("partially oob rangeselect (right)", "4'b1001[3 : -1]", "5'b1001x");
EVAL_TEST_EX("partially oob rangeselect (left)", "4'b1001[4 : 1]", "4'bx100");
EVAL_TEST_EX("partially oob rangeselect (both)", "4'b1001[4 : -1]", "6'bx1001x");
EVAL_TEST_EX("totally oob rangeselect", "4'b1001[105 : 101]", "5'bxxxxx");
//TODO: Figure out why a test like this fails, seems like something wrong with literals with x's?
//EVAL_TEST_EX("lit", "43'b10x", "43'b10x");

TEST_CASE("bit select weird indexes", "[eval]") {
    // The above bit select cases test the "normal" case where vectors are specified
    // with [N : 0]. Here we test "up-vectors" and non-zero lower bounds.
    ScriptSession session;
    session.eval("logic [0 : 15] up_vect = 5'b10111;");

    auto value = session.eval("up_vect[12:14]").integer();
    CHECK(exactlyEqual(value, SVInt(StringRef("3'b011"))));

    value = session.eval("up_vect[12 -: 2]").integer();
    CHECK(exactlyEqual(value, SVInt(StringRef("3'b011"))));

    value = session.eval("up_vect[14 +: 2]").integer();
    CHECK(exactlyEqual(value, SVInt(StringRef("3'b011"))));

    session.eval("logic [20 : 5] down_vect = 5'd25");

    value = session.eval("down_vect[8:5]").integer();

    CHECK(exactlyEqual(value, SVInt(StringRef("4'd9"))));

    value = session.eval("down_vect[5 +: 3]").integer();
    CHECK(value == 9);

    value = session.eval("down_vect[8 -: 3]").integer();
    CHECK(value == 9);
}
}
<|endoftext|>