From 8dafd0435fc272841d90081d5827936e88d40092 Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Sun, 14 Dec 2014 11:51:35 +0100 Subject: [PATCH] build: different location for clang release libs on UNIX This change fixes the clang cmake config to use release libs of clang, adds the TicTacToe source files to bin/app/src/ and adds time measuring to the parse call in Project. --- bin/app/data/src/{ => test}/header.h | 0 bin/app/data/src/{ => test}/main.cpp | 0 bin/app/data/src/{ => test}/test.h | 0 bin/app/data/src/tictactoe/computer.h | 82 ++++++++++++++ bin/app/data/src/tictactoe/field.h | 147 +++++++++++++++++++++++++ bin/app/data/src/tictactoe/human.h | 51 +++++++++ bin/app/data/src/tictactoe/input.h | 20 ++++ bin/app/data/src/tictactoe/main.cpp | 11 ++ bin/app/data/src/tictactoe/player.h | 22 ++++ bin/app/data/src/tictactoe/tictactoe.h | 93 ++++++++++++++++ cmake/CLANGConfig.cmake | 7 ++ src/lib/Project.cpp | 10 +- src/lib/data/parser/cxx/ASTVisitor.cpp | 6 +- 13 files changed, 446 insertions(+), 3 deletions(-) rename bin/app/data/src/{ => test}/header.h (100%) rename bin/app/data/src/{ => test}/main.cpp (100%) rename bin/app/data/src/{ => test}/test.h (100%) create mode 100644 bin/app/data/src/tictactoe/computer.h create mode 100644 bin/app/data/src/tictactoe/field.h create mode 100644 bin/app/data/src/tictactoe/human.h create mode 100644 bin/app/data/src/tictactoe/input.h create mode 100644 bin/app/data/src/tictactoe/main.cpp create mode 100644 bin/app/data/src/tictactoe/player.h create mode 100644 bin/app/data/src/tictactoe/tictactoe.h diff --git a/bin/app/data/src/header.h b/bin/app/data/src/test/header.h similarity index 100% rename from bin/app/data/src/header.h rename to bin/app/data/src/test/header.h diff --git a/bin/app/data/src/main.cpp b/bin/app/data/src/test/main.cpp similarity index 100% rename from bin/app/data/src/main.cpp rename to bin/app/data/src/test/main.cpp diff --git a/bin/app/data/src/test.h b/bin/app/data/src/test/test.h similarity index 100% rename from bin/app/data/src/test.h rename to bin/app/data/src/test/test.h diff --git a/bin/app/data/src/tictactoe/computer.h b/bin/app/data/src/tictactoe/computer.h new file mode 100644 index 00000000..293fb4a5 --- /dev/null +++ b/bin/app/data/src/tictactoe/computer.h @@ -0,0 +1,82 @@ +#ifndef _ARTIFICIAL_ +#define _ARTIFICIAL_ + +#include +#include +#include "player.h" + +class ArtificialPlayer : public Player { +public: + ArtificialPlayer( Field::Token token, const std::string& name ) + : Player( token, name ) { + } + virtual ~ArtificialPlayer() {} + + virtual Field::Move Turn( const Field& field ) const { +// srand( static_cast( time( NULL ) ) ); + Field fakeField = field.Clone(); + Node node = MinMax( fakeField, token_ ); + return node.move; + } + +private: + struct Node { + Field::Move move; + int value; + }; + + Node MinMax( Field& field, Field::Token token ) const { + Node node; + node.value = -10000; + + Field::Move move; + int sameMove; + + for ( int i = 0; i < 3; i++ ) { + move.row = i; + + for ( int j = 0; j < 3; j++ ) { + move.col = j; + + if ( !field.IsEmpty( move ) ) { + continue; + } + + field.MakeMove( move, token ); + + int turnValue = Evaluate( field, token ); + if ( !turnValue && !field.IsFull() ) { + turnValue = -MinMax( field, Field::Opponent( token ) ).value; + } + + field.ClearMove( move ); + + if ( turnValue > node.value ) { + node.move = move; + node.value = turnValue; + sameMove = 1; + } else if ( turnValue == node.value ) { + sameMove++; + if ( 1 % sameMove == 0 ) { + node.move = move; + } + } + } + } + + return node; + } + + int Evaluate( const Field& field, Field::Token token ) const { + if ( field.SameInRow( token, 3 ) ) { + return 2; + } else if ( field.SameInRow( Field::Opponent( token ), 2 ) ) { + return -1; + } else if ( field.SameInRow( token, 2 ) > 1 ) { + return 1; + } + return 0; + } +}; + +#endif // _ARTIFICIAL_ diff --git a/bin/app/data/src/tictactoe/field.h b/bin/app/data/src/tictactoe/field.h new file mode 100644 index 00000000..24c3588a --- /dev/null +++ b/bin/app/data/src/tictactoe/field.h @@ -0,0 +1,147 @@ +#ifndef _FIELD_ +#define _FIELD_ + +#include +#include + +class Field { +public: + enum Token { + None = 0, + PlayerA = 1, + PlayerB = 4 + }; + + static Token Opponent( Token token ) { + assert( token != None ); + if ( token == PlayerA ) { + return PlayerB; + } else { + return PlayerA; + } + } + + struct Move { + int row; + int col; + }; + + Field() + : left_( 9 ) { + grid_ = new Token* [3]; + for ( int i = 0; i < 3 ; i++ ) { + grid_[i] = new Token[3]; + } + } + + ~Field() { + for ( int i = 0; i < 3; i++ ) { + delete grid_[i]; + } + delete [] grid_; + } + + Field Clone() const { + Field field; + for ( int i = 0; i < 3; i++ ) { + for ( int j = 0; j < 3; j++ ) { + field.grid_[i][j] = grid_[i][j]; + } + } + field.left_ = left_; + return field; + } + + void Clear() { + for ( int i = 0; i < 3; i++ ) { + for ( int j = 0; j < 3; j++ ) { + grid_[i][j] = None; + } + } + left_ = 9; + } + + void Show() const { + std::cout << " 1 2 3\n"; + for ( int row = 0; row < 3; row++ ) { + std::cout << row + 1 << " "; + + for ( int col = 0; col < 3; col++ ) { + if ( grid_[row][col] == PlayerA ) { + std::cout << " X "; + } else if ( grid_[row][col] == PlayerB ) { + std::cout << " O "; + } else { + std::cout << " "; + } + + if ( col < 2 ) { + std::cout << "|"; + } + } + + if ( row < 2 ) { + std::cout << "\n -----------\n"; + } + } + std::cout << "\n\n"; + } + + int SameInRow( Token token, int amount ) const { + int sum = amount * token; + int count = 0; + + for ( int i = 0; i < 3; i++ ) { + if ( grid_[i][0] + grid_[i][1] + grid_[i][2] == sum ) { + count++; + } else if ( grid_[0][i] + grid_[1][i] + grid_[2][i] == sum ) { + count++; + } + } + + if ( grid_[0][0] + grid_[1][1] + grid_[2][2] == sum ) { + count++; + } else if ( grid_[2][0] + grid_[1][1] + grid_[0][2] == sum ) { + count++; + } + + return count; + } + + bool InRange( const Move& move ) const { + return move.row >= 0 && move.row < 3 && move.col >= 0 && move.col < 3; + } + + bool IsEmpty( const Move& move ) const { + return grid_[move.row][move.col] == None; + } + + bool IsFull() const { + return left_ == 0; + } + + void MakeMove( const Move& move, Token token ) { + assert( InRange( move ) ); + assert( IsEmpty( move ) ); + assert( token != None ); + assert( left_ ); + + grid_[move.row][move.col] = token; + left_--; + } + + void ClearMove( const Move& move ) { + assert( InRange(move) ); + assert( !IsEmpty(move) ); + assert( left_ < 9 ); + + grid_[move.row][move.col] = None; + left_++; + } + +private: + Token** grid_; + int left_; +}; + +#endif // _FIELD_ diff --git a/bin/app/data/src/tictactoe/human.h b/bin/app/data/src/tictactoe/human.h new file mode 100644 index 00000000..52872d61 --- /dev/null +++ b/bin/app/data/src/tictactoe/human.h @@ -0,0 +1,51 @@ +#ifndef _HUMAN_ +#define _HUMAN_ + +#include "input.h" +#include "player.h" + +class HumanPlayer : public Player { +public: + HumanPlayer( Field::Token token, const std::string& name ) + : Player( token, name ) { + } + virtual ~HumanPlayer() {} + + virtual Field::Move Turn( const Field& field ) const { + Field::Move move; + std::cout << name_ << '\n'; + do { + move = Input(); + move.row -= 1; + move.col -= 1; + } while ( !Check( field, move ) ); + return move; + } + +private: + Field::Move Input() const { + Field::Move move; + + std::cout << "Insert row: "; + input::number( &move.row ); + + std::cout << "Insert column: "; + input::number( &move.col ); + + std::cout << '\n'; + return move; + } + + bool Check( const Field& field, const Field::Move& move ) const { + if ( !field.InRange( move ) ) { + std::cout << "Wrong input!\n"; + return false; + } else if ( !field.IsEmpty( move ) ) { + std::cout << "Is occupied!\n"; + return false; + } + return true; + } +}; + +#endif // _HUMAN_ diff --git a/bin/app/data/src/tictactoe/input.h b/bin/app/data/src/tictactoe/input.h new file mode 100644 index 00000000..9f0dfec2 --- /dev/null +++ b/bin/app/data/src/tictactoe/input.h @@ -0,0 +1,20 @@ +#ifndef _INPUT_ +#define _INPUT_ + +#include +#include +#include + +namespace input { + +template +void number( T* number ) { + std::string input; + getline( std::cin, input ); + std::stringstream stream( input ); + stream >> *number; +} + +} + +#endif // _INPUT_ diff --git a/bin/app/data/src/tictactoe/main.cpp b/bin/app/data/src/tictactoe/main.cpp new file mode 100644 index 00000000..8d15ea5f --- /dev/null +++ b/bin/app/data/src/tictactoe/main.cpp @@ -0,0 +1,11 @@ +#include "tictactoe.h" + +int main() { + TicTacToe tictactoe; + + while ( tictactoe.Start() ) { + tictactoe.Run(); + } + + return 0; +} diff --git a/bin/app/data/src/tictactoe/player.h b/bin/app/data/src/tictactoe/player.h new file mode 100644 index 00000000..5d748a6c --- /dev/null +++ b/bin/app/data/src/tictactoe/player.h @@ -0,0 +1,22 @@ +#ifndef _PLAYER_ +#define _PLAYER_ + +#include + +#include "field.h" + +class Player { +public: + Player( Field::Token token, const std::string& name ) + : token_( token ) + , name_( name ) { + } + virtual ~Player() {} + + virtual Field::Move Turn( const Field& field ) const = 0; + + const Field::Token token_; + const std::string name_; +}; + +#endif // _PLAYER_ diff --git a/bin/app/data/src/tictactoe/tictactoe.h b/bin/app/data/src/tictactoe/tictactoe.h new file mode 100644 index 00000000..6c800560 --- /dev/null +++ b/bin/app/data/src/tictactoe/tictactoe.h @@ -0,0 +1,93 @@ +#ifndef _TIC_TAC_TOE_ +#define _TIC_TAC_TOE_ + +#include "computer.h" +#include "field.h" +#include "human.h" +#include "input.h" +#include "player.h" + +class TicTacToe { +public: + TicTacToe() { + players_[0] = NULL; + players_[1] = NULL; + } + + ~TicTacToe() { + Reset(); + } + + bool Start() { + Reset(); + std::cout << "Tic Tac Toe\n\n[1] Human\n[2] Computer\n[3] Quit\n\n"; + + players_[0] = SelectPlayer( Field::PlayerA, "PlayerA" ); + if ( !players_[0] ) { + return false; + } + + players_[1] = SelectPlayer( Field::PlayerB, "PlayerB" ); + if ( !players_[1] ) { + return false; + } + + std::cout << '\n'; + return true; + } + + void Run() { + field_.Show(); + + int playerIndex = 0; + + for ( int i = 0; i < 9; i++ ) { + Player& player = *players_[playerIndex]; + + field_.MakeMove( player.Turn( field_ ), player.token_ ); + field_.Show(); + + if ( field_.SameInRow( player.token_, 3 ) ) { + std::cout << player.name_ << " won!\n\n"; + return; + } + + playerIndex = ( playerIndex + 1 ) % 2; + } + + std::cout << "Game ends in draw!\n\n"; + } + +private: + void Reset() { + field_.Clear(); + + for ( int i = 0; i < 2; i++ ) { + if ( players_[i] ) { + delete players_[i]; + players_[i] = NULL; + } + } + } + + Player* SelectPlayer( Field::Token token, const std::string& name ) const { + int selection; + + while ( true ) { + std::cout << "Choose " << name << ": "; + input::number( &selection ); + + switch ( selection ) { + case 1 : return new HumanPlayer( token, name ); + case 2 : return new ArtificialPlayer( token, name ); + case 3 : return NULL; + default : std::cout << "Wrong input!\n"; + } + } + } + + Player* players_[2]; + Field field_; +}; + +#endif // _TIC_TAC_TOE_ diff --git a/cmake/CLANGConfig.cmake b/cmake/CLANGConfig.cmake index 8d4f0c29..fb8db6cf 100644 --- a/cmake/CLANGConfig.cmake +++ b/cmake/CLANGConfig.cmake @@ -8,7 +8,14 @@ set(CLANG_INCLUDE_DIRS "$ENV{CLANG_DIR}/build/tools/clang/include" ) + set(CLANG_LIBRARY_DIRS "$ENV{CLANG_DIR}/build/lib") +if (UNIX) + if (${CMAKE_BUILD_TYPE} STREQUAL "Release") + set(CLANG_LIBRARY_DIRS "$ENV{CLANG_DIR}/build/Release+Asserts/lib") + endif() +endif () + set(CLANG_LIBRARIES #clangApplyReplacements diff --git a/src/lib/Project.cpp b/src/lib/Project.cpp index 02aab432..78114ce1 100644 --- a/src/lib/Project.cpp +++ b/src/lib/Project.cpp @@ -1,7 +1,10 @@ #include "Project.h" +#include +#include #include #include +#include #include "ApplicationSettings.h" #include "data/access/GraphAccessProxy.h" @@ -49,7 +52,7 @@ bool Project::saveProjectSettings( const std::string& projectSettingsFile ) return false; } LOG_INFO_STREAM(<< "Projectsettings saved in File: " << m_projectSettingsFilepath); - return true; + return true; } void Project::clearProjectSettings() @@ -90,15 +93,20 @@ void Project::parseCode() headerSearchPaths.push_back(sourcePath); CxxParser parser(m_storage.get()); + + clock_t time = clock(); parser.parseFiles( FileSystem::getSourceFilesFromDirectory(sourcePath, extensions), ApplicationSettings::getInstance()->getHeaderSearchPaths(), headerSearchPaths ); + time = clock() - time; m_storage->logGraph(); m_storage->logLocations(); + LOG_INFO_STREAM(<< "parse time: " << (double)(time) / CLOCKS_PER_SEC); + MessageFinishedParsing().dispatch(); } } diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index bbfcbd2b..dcf55889 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -581,14 +581,16 @@ ParseTypeUsage ASTVisitor::getParseTypeUsage(clang::TypeLoc typeLoc, const clang ParseTypeUsage ASTVisitor::getParseTypeUsageOfReturnType(clang::FunctionDecl* declaration) const { - // TODO: use FunctionDecl::getReturnTypeSourceRange() in newer clang version clang::TypeLoc typeLoc; const clang::TypeSourceInfo *TSI = declaration->getTypeSourceInfo(); if (TSI) { const clang::FunctionTypeLoc FTL = TSI->getTypeLoc().IgnoreParens().getAs(); - typeLoc = FTL.getReturnLoc(); + if (FTL) + { + typeLoc = FTL.getReturnLoc(); + } } return getParseTypeUsage(typeLoc, declaration->getReturnType());