<commit_before>/*************************************************************************
 *
 *  $RCSfile: hangulhanjadlg.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-17 17:42:06 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SVX_HANGUL_HANJA_DLG_HXX
#define SVX_HANGUL_HANJA_DLG_HXX

#ifndef _SV_DIALOG_HXX
#include <vcl/dialog.hxx>
#endif
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif
#ifndef _SV_FIXED_HXX
#include <vcl/fixed.hxx>
#endif
#ifndef SVX_HANGUL_HANJA_CONVERSION_HXX
#include "hangulhanja.hxx"
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif

#include <memory>   // for auto_ptr

class SvxCommonLinguisticControl;
//.............................................................................
namespace svx
{
//.............................................................................

    //=========================================================================
    //= HangulHanjaConversionDialog
    //=========================================================================

    class HangulHanjaConversionDialog : public  ModalDialog
    {
    private:
        ::std::auto_ptr< SvxCommonLinguisticControl >
                    m_pPlayground;                  // oder matters: before all other controls!

        PushButton      m_aFind;
        ListBox         m_aSuggestions;
        FixedText       m_aFormat;
        RadioButton     m_aSimpleConversion;
        RadioButton     m_aHangulBracketed;
        RadioButton     m_aHanjaBracketed;
        ::std::auto_ptr< RadioButton >  m_pHanjaAbove;
        ::std::auto_ptr< RadioButton >  m_pHanjaBelow;
        ::std::auto_ptr< RadioButton >  m_pHangulAbove;
        ::std::auto_ptr< RadioButton >  m_pHangulBelow;
        FixedText       m_aConversion;
        CheckBox        m_aHangulOnly;
        CheckBox        m_aHanjaOnly;
        CheckBox        m_aReplaceByChar;

        CheckBox*       m_pIgnoreNonPrimary;
        bool            m_bDocumentMode;
                            // are we working for a document? This is normally true, but in case
                            // the user uses the "find" functionality, we switch to working
                            // with what the user entered, which then does not have any relation to
                            // the document anymore. Some functionality must be disabled then

    public:
        HangulHanjaConversionDialog(
                Window* _pParent,
                HangulHanjaConversion::ConversionDirection _ePrimaryDirection );
        ~HangulHanjaConversionDialog( );

    public:
        void    SetIgnoreHdl( const Link& _rHdl );
        void    SetIgnoreAllHdl( const Link& _rHdl );
        void    SetChangeHdl( const Link& _rHdl );
        void    SetChangeAllHdl( const Link& _rHdl );

        void    SetClickByCharacterHdl( const Link& _rHdl );
        void    SetConversionFormatChangedHdl( const Link& _rHdl );
        void    SetFindHdl( const Link& _rHdl );

        String  GetCurrentString( ) const;
        void    SetCurrentString(
                    const String& _rNewString,
                    const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rSuggestions,
                    bool _bOriginatesFromDocument = true
                );

        void    FocusSuggestion( );

        // retrieves the current suggestion
        String  GetCurrentSuggestion( ) const;

        void        SetConversionFormat( HangulHanjaConversion::ConversionFormat _eType );
        HangulHanjaConversion::ConversionFormat    GetConversionFormat( ) const;

        void            SetByCharacter( sal_Bool _bByCharacter );
        sal_Bool        GetByCharacter( ) const;

        // should text which does not fit the primary conversion direction be ignored
        void            SetUseBothDirections( sal_Bool _bBoth ) const;
        sal_Bool        GetUseBothDirections( ) const;

    private:
        DECL_LINK( OnClose, void* );
        DECL_LINK( OnSuggestionModified, void* );
        DECL_LINK( OnSuggestionSelected, void* );

        // fill the suggestion list box with suggestions for the actual input
        void FillSuggestions( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rSuggestions );
    };

//.............................................................................
}   // namespace svx
//.............................................................................

#endif // SVX_HANGUL_HANJA_HXX
<commit_msg>INTEGRATION: CWS tl01 (1.2.120); FILE MERGED 2004/03/18 13:40:23 gt 1.2.120.6: #111170# 2004/03/16 13:55:23 gt 1.2.120.5: #111170# hangul hanja conversion options dlg 2004/03/11 16:14:11 gt 1.2.120.4: #111170# intermediate changes 2003/11/18 11:40:19 tl 1.2.120.3: #109443# include statement fixed 2003/11/02 18:01:40 gt 1.2.120.2: #111170# common ui 2003/08/29 09:44:54 tl 1.2.120.1: #110177# Hangul/Hanja conversion for Sdr objects (EditEngine)<commit_after>/*************************************************************************
 *
 *  $RCSfile: hangulhanjadlg.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2004-04-27 15:46:58 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef SVX_HANGUL_HANJA_DLG_HXX
#define SVX_HANGUL_HANJA_DLG_HXX

#ifndef _SV_DIALOG_HXX
#include <vcl/dialog.hxx>
#endif
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _SV_LSTBOX_HXX
#include <vcl/lstbox.hxx>
#endif
#ifndef _SV_COMBOBOX_HXX
#include <vcl/combobox.hxx>
#endif
#ifndef _SV_FIXED_HXX
#include <vcl/fixed.hxx>
#endif
#ifndef _SV_SCRBAR_HXX
#include <vcl/scrbar.hxx>
#endif
#ifndef _SVX_CHECKLBX_HXX
#include "checklbx.hxx"
#endif
#ifndef SVX_HANGUL_HANJA_CONVERSION_HXX
#include "hangulhanja.hxx"
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _UNO_LINGU_HXX
#include "unolingu.hxx"
#endif
#ifndef _COM_SUN_STAR_LINGUISTIC2_XCONVERSIONDICTIONARYLIST_HPP_
#include <com/sun/star/linguistic2/XConversionDictionaryList.hpp>
#endif

#include <memory>   // for auto_ptr

class SvxCommonLinguisticControl;
//.............................................................................
namespace svx
{
//.............................................................................

    //=========================================================================
    //= HangulHanjaConversionDialog
    //=========================================================================

    class HangulHanjaConversionDialog : public  ModalDialog
    {
    private:
        ::std::auto_ptr< SvxCommonLinguisticControl >
                    m_pPlayground;                  // order matters: before all other controls!

        PushButton      m_aFind;
        ListBox         m_aSuggestions;
        FixedText       m_aFormat;
        RadioButton     m_aSimpleConversion;
        RadioButton     m_aHangulBracketed;
        RadioButton     m_aHanjaBracketed;
        ::std::auto_ptr< RadioButton >  m_pHanjaAbove;
        ::std::auto_ptr< RadioButton >  m_pHanjaBelow;
        ::std::auto_ptr< RadioButton >  m_pHangulAbove;
        ::std::auto_ptr< RadioButton >  m_pHangulBelow;
        FixedText       m_aConversion;
        CheckBox        m_aHangulOnly;
        CheckBox        m_aHanjaOnly;
        CheckBox        m_aReplaceByChar;

        CheckBox*       m_pIgnoreNonPrimary;
        bool            m_bDocumentMode;
                            // are we working for a document? This is normally true, but in case
                            // the user uses the "find" functionality, we switch to working
                            // with what the user entered, which then does not have any relation to
                            // the document anymore. Some functionality must be disabled then
    public:
        HangulHanjaConversionDialog(
                Window* _pParent,
                HangulHanjaConversion::ConversionDirection _ePrimaryDirection );
        ~HangulHanjaConversionDialog( );

    public:
        void    SetIgnoreHdl( const Link& _rHdl );
        void    SetIgnoreAllHdl( const Link& _rHdl );
        void    SetChangeHdl( const Link& _rHdl );
        void    SetChangeAllHdl( const Link& _rHdl );
        void    SetOptionsHdl( const Link& _rHdl );

        void    SetClickByCharacterHdl( const Link& _rHdl );
        void    SetConversionFormatChangedHdl( const Link& _rHdl );
        void    SetFindHdl( const Link& _rHdl );

        String  GetCurrentString( ) const;
        void    SetCurrentString(
                    const String& _rNewString,
                    const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rSuggestions,
                    bool _bOriginatesFromDocument = true
                );

        void    FocusSuggestion( );

        // retrieves the current suggestion
        String  GetCurrentSuggestion( ) const;

        void        SetConversionFormat( HangulHanjaConversion::ConversionFormat _eType );
        HangulHanjaConversion::ConversionFormat    GetConversionFormat( ) const;

        void            SetByCharacter( sal_Bool _bByCharacter );
        sal_Bool        GetByCharacter( ) const;

        // should text which does not fit the primary conversion direction be ignored
        void            SetUseBothDirections( sal_Bool _bBoth ) const;
        sal_Bool        GetUseBothDirections( ) const;

        // enables or disbales the checkboxes for ruby formatted replacements
        void            EnableRubySupport( sal_Bool bVal );

    private:
        DECL_LINK( OnClose, void* );
        DECL_LINK( OnOption, void* );
        DECL_LINK( OnSuggestionModified, void* );
        DECL_LINK( OnSuggestionSelected, void* );

        // fill the suggestion list box with suggestions for the actual input
        void FillSuggestions( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rSuggestions );
    };

    class HHDictList
    {
    private:
        ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XConversionDictionary > >
                            m_aList;
        sal_uInt32          m_nNew;     // position where the next dictionary will be inserted
    protected:
    public:
                            HHDictList( void );
        virtual             ~HHDictList();

        void                Clear( void );
        void                Add( ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XConversionDictionary > _xDict );
        sal_uInt32          Count( void ) const;
        ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XConversionDictionary >
                            Get( sal_uInt32 _nInd );
        String              GetName( sal_uInt32 _nInd );
        bool                GetIsActive( sal_uInt32 _nInd );
    };

    class HangulHanjaOptionsDialog : public ModalDialog
    {
    private:
        FixedText           m_aUserdefdictFT;
        SvxCheckListBox     m_aDictsLB;
        FixedLine           m_aOptionsFL;
        CheckBox            m_aIgnorepostCB;
        CheckBox            m_aAutocloseCB;
        CheckBox            m_aShowrecentlyfirstCB;
        CheckBox            m_aAutoreplaceuniqueCB;
        PushButton          m_aNewPB;
        PushButton          m_aEditPB;
        PushButton          m_aDeletePB;
        OKButton            m_aOkPB;
        CancelButton        m_aCancelPB;
        HelpButton          m_aHelpPB;

        SvLBoxButtonData*   m_pCheckButtonData;

        HHDictList          m_aDictList;

        DECL_LINK( OkHdl, void* );
        DECL_LINK( OnNew, void* );
        DECL_LINK( OnEdit, void* );
        DECL_LINK( OnDelete, void* );
        DECL_LINK( DictsLB_SelectHdl, void* );
        DECL_LINK( NewDictHdl, void* );
        DECL_LINK( EditDictHdl, void* );
        DECL_LINK( DeleteDictHdl, void* );

        void                Init( void );       // reads settings from core and init controls
    public:
                            HangulHanjaOptionsDialog( Window* _pParent );
        virtual             ~HangulHanjaOptionsDialog();

        void                AddDict( const String& _rName, bool _bChecked );
    };

    class HangulHanjaNewDictDialog : public ModalDialog
    {
    private:
        FixedLine           m_aNewDictFL;
        FixedText           m_aDictNameFT;
        Edit                m_aDictNameED;
        OKButton            m_aOkBtn;
        CancelButton        m_aCancelBtn;
        HelpButton          m_aHelpBtn;

        bool                m_bEntered;

        DECL_LINK( OKHdl, void* );
        DECL_LINK( ModifyHdl, void* );
    protected:
    public:
                            HangulHanjaNewDictDialog( Window* _pParent );
        virtual             ~HangulHanjaNewDictDialog();

        bool                GetName( String& _rRetName ) const;
    };

    class SuggestionList;

    class SuggestionEdit : public Edit
    {
    private:
        SuggestionEdit*     m_pPrev;
        SuggestionEdit*     m_pNext;
        ScrollBar&          m_rScrollBar;

        bool                ShouldScroll( bool _bUp ) const;
        void                DoJump( bool _bUp );
    public:
                            SuggestionEdit( Window* pParent, const ResId& rResId,
                                    ScrollBar& _rScrollBar,
                                    SuggestionEdit* _pPrev, SuggestionEdit* _pNext );
        virtual             ~SuggestionEdit();
        virtual long        PreNotify( NotifyEvent& rNEvt );
    };

    class HangulHanjaEditDictDialog : public ModalDialog
    {
    private:
        enum EditState
        {
            ES_NIL,                 // neither original nor suggestion(s) entered
            ES_NEW_ORG_EMPTY,       // a new original was entered, no suggestion(s)
            ES_NEW_SUGG,            // no original was entered but at least one suggestion
            ES_NEW_ORG_SUGG,        // a new original and at least one suggestion was entered
            ES_EXIST_ORG,           // while typing, an existing entry matched
            ES_EXIST_ORG_MOD        // an existing entry has been modified
        };
        EditState       m_eState;
        const String    m_aEditHintText;
        HHDictList&     m_rDictList;
        sal_uInt32      m_nCurrentDict;

        String          m_aOriginal;
        SuggestionList* m_pSuggestions;

        FixedText       m_aBookFT;
        ListBox         m_aBookLB;
        FixedText       m_aOriginalFT;
        ComboBox        m_aOriginalLB;
        CheckBox        m_aReplacebycharCB;
        FixedText       m_aSuggestionsFT;
        SuggestionEdit  m_aEdit1;
        SuggestionEdit  m_aEdit2;
        SuggestionEdit  m_aEdit3;
        SuggestionEdit  m_aEdit4;
        ScrollBar       m_aScrollSB;
        PushButton      m_aNewPB;
        PushButton      m_aDeletePB;
        HelpButton      m_aHelpPB;
        CancelButton    m_aClosePB;

        bool            m_bModified;
        bool            m_bNew;
        sal_uInt16      m_nTopPos;

        DECL_LINK( OriginalModifyHdl, void* );
        DECL_LINK( OriginalFocusLostHdl, void* );
        DECL_LINK( ScrollHdl, void* );
        DECL_LINK( EditModifyHdl1, Edit* );
        DECL_LINK( EditModifyHdl2, Edit* );
        DECL_LINK( EditModifyHdl3, Edit* );
        DECL_LINK( EditModifyHdl4, Edit* );
        DECL_LINK( EditFocusLostHdl1, Edit* );
        DECL_LINK( EditFocusLostHdl2, Edit* );
        DECL_LINK( EditFocusLostHdl3, Edit* );
        DECL_LINK( EditFocusLostHdl4, Edit* );

        DECL_LINK( BookLBSelectHdl, void* );
        DECL_LINK( OriginalLBSelectHdl, void* );
        DECL_LINK( NewPBPushHdl, void* );
        DECL_LINK( DeletePBPushHdl, void* );

        void            Init( sal_uInt32 _nSelDict );
        void            UpdateOriginalLB( void );
        void            UpdateSuggestions( void );
        void            UpdateSuggestions( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rSuggestions );
        void            Leave( void );
        void            CheckNewState( void );
                        // checks if enough data is entered to enable "New" Button and set Button state accordingly
        void            SetSuggestion( const String& _rText, sal_uInt16 _nEntryNum );
        void            ResetSuggestion( sal_uInt16 _nEntryNum );
        void            SetEditText( Edit& _rEdit, sal_uInt16 _nEntryNum );
        void            EditModify( Edit* _pEdit, sal_uInt8 _nEntryOffset );
        void            EditFocusLost( Edit* _pEdit, sal_uInt8 _nEntryOffset );
    public:
                        HangulHanjaEditDictDialog( Window* _pParent, HHDictList& _rDictList, sal_uInt32 _nSelDict );
                        ~HangulHanjaEditDictDialog();

        void            UpdateScrollbar( void );
    };

//.............................................................................
}   // namespace svx
//.............................................................................

#endif // SVX_HANGUL_HANJA_HXX
<|endoftext|>


<commit_before>#include "ConstantProp.hpp"

using namespace IR;

void determineGlobalConstants()
{
  for(auto& s : IR::ir)
  {
    auto subr = s.second;
    auto writes = subr->getWrites();
    for(auto v : writes)
    {
      if(v->isGlobal())
      {
        IR::globalConstants[v] = false;
      }
    }
  }
}

//Convert a constant expression to another type
//conv->value must already be folded and be constant
static Expression* convertConstant(Converted* conv)
{
  if(auto intConst = dynamic_cast<IntConstant*>(conv->value))
  {
    //do the conversion which tests for overflow
    return intConst->convert(conv->type);
  }
  else if(auto floatConst = dynamic_cast<FloatConstant*>(conv->value))
  {
    return floatConst->convert(conv->type);
  }
  else if(auto enumConst = dynamic_cast<EnumExpr*>(conv->value))
  {
    return enumConst->convert(conv->type);
  }
  //array/struct/tuple constants can be converted implicitly
  //to each other (all use CompoundLiteral) but individual
  //members (primitives) may need conversion
  else if(auto compLit = dynamic_cast<CompoundLiteral*>(conv->value))
  {
    //attempt to fold all elements (can't proceed unless every
    //one is a constant)
    bool allConstant = true;
    for(auto& mem : compLit->members)
      allConstant = allConstant && foldExpression(mem);
    if(!allConstant)
      return false;
    if(auto st = dynamic_cast<StructType*>(conv->type))
    {
    }
    else if(auto tt = dynamic_cast<TupleType*>(conv->type))
    {
    }
    else if(auto mt = dynamic_cast<MapType*>(conv->type))
    {
      expr = new MapConstant;
      //convert key/value pairs to
    }
  }
}

//Try to fold an expression, bottom-up
//Can fold all constants in one pass
//
//Return true if any IR changes are made
//Set constant to true if expr is now, or was already, a constant
static bool foldExpression(Expression*& expr)
{
  if(dynamic_cast<IntConstant*>(expr) ||
      dynamic_cast<FloatConstant*>(expr) ||
      dynamic_cast<StringConstant*>(expr) ||
      dynamic_cast<EnumExpr*>(expr) ||
      dynamic_cast<BoolConstant*>(expr) ||
      dynamic_cast<MapConstant*>(expr) ||
      dynamic_cast<ErrorVal*>(expr))
  {
    //already completely folded constant, nothing to do
    return true;
  }
  else if(auto conv = dynamic_cast<Converted*>(expr))
  {
    foldExpression(conv->value);
    if(conv->value->constant())
    {
      expr = convertConstant(conv);
      return true;
    }
    else
    {
      return false;
    }
  }
  {
    //already constant and nothing to do
    constant = true;
    return false;
  }
  else if(auto& binArith = dynamic_cast<BinaryArith*&>(expr))
  {
    bool lhsConstant = false;
    bool rhsConstant = false;
    foldExpression(binArith->lhs, lhsConstant);
    foldExpression(binArith->rhs, rhsConstant);
    if(lhsConstant && rhsConstant)
    {
      constant = true;
      return true;
    }
    else
    {
      return false;
    }
  }
  else if(
}

bool constantFold(IR::SubroutineIR* subr)
{
  //every expression (including parts of an assignment LHS)
  //may be folded (i.e. myArray[5 + 3] = 8 % 3)
  //
  //recursivly attempt to fold expressions bottom-up,
  //remembering which input expressions are constants
}

bool constantPropagation(SubroutineIR* subr)
{
  bool update = false;
  //First, go through each BB and replace general Expressions
  //with constants wherever possible (constant folding)
  //
  //Also record which variables hold constant values at exit of BBs
  //
  //Then do constant propagation dataflow analysis across BBs
  //
  //VarExprs of constant variables can then be replaced by constant
  for(auto bb : subr->blocks)
  {
    for(int i = bb->start; i < bb->end; i++)
    {
      Statement* stmt = subr->stmts[i];
    }
  }
  return update;
}

<commit_msg>Improved global constant analysis<commit_after>#include "ConstantProp.hpp"

using namespace IR;

void determineGlobalConstants()
{
  for(auto& s : IR::ir)
  {
    auto subr = s.second;
    for(auto stmt : subr->stmts)
    {
      auto outputs = stmt->getOutput();
      for(auto out : outputs)
      {
        auto writes = out->getWrites();
        for(auto w : writes)
        {
          if(w->isGlobal())
          {
            //there is an assignment to w,
            //so w is not a constant
            IR::globalConstants[w] = false;
          }
        }
      }
    }
  }
}

//Convert a constant expression to another type
//conv->value must already be folded and be constant
static Expression* convertConstant(Converted* conv)
{
  if(auto intConst = dynamic_cast<IntConstant*>(conv->value))
  {
    //do the conversion which tests for overflow
    return intConst->convert(conv->type);
  }
  else if(auto floatConst = dynamic_cast<FloatConstant*>(conv->value))
  {
    return floatConst->convert(conv->type);
  }
  else if(auto enumConst = dynamic_cast<EnumExpr*>(conv->value))
  {
    return enumConst->convert(conv->type);
  }
  //array/struct/tuple constants can be converted implicitly
  //to each other (all use CompoundLiteral) but individual
  //members (primitives) may need conversion
  else if(auto compLit = dynamic_cast<CompoundLiteral*>(conv->value))
  {
    //attempt to fold all elements (can't proceed unless every
    //one is a constant)
    bool allConstant = true;
    for(auto& mem : compLit->members)
      allConstant = allConstant && foldExpression(mem);
    if(!allConstant)
      return false;
    if(auto st = dynamic_cast<StructType*>(conv->type))
    {
    }
    else if(auto tt = dynamic_cast<TupleType*>(conv->type))
    {
    }
    else if(auto mt = dynamic_cast<MapType*>(conv->type))
    {
      expr = new MapConstant;
      //convert key/value pairs to
    }
  }
}

//Try to fold an expression, bottom-up
//Can fold all constants in one pass
//
//Return true if any IR changes are made
//Set constant to true if expr is now, or was already, a constant
static bool foldExpression(Expression*& expr)
{
  if(dynamic_cast<IntConstant*>(expr) ||
      dynamic_cast<FloatConstant*>(expr) ||
      dynamic_cast<StringConstant*>(expr) ||
      dynamic_cast<EnumExpr*>(expr) ||
      dynamic_cast<BoolConstant*>(expr) ||
      dynamic_cast<MapConstant*>(expr) ||
      dynamic_cast<ErrorVal*>(expr))
  {
    //already completely folded constant, nothing to do
    return true;
  }
  else if(auto conv = dynamic_cast<Converted*>(expr))
  {
    foldExpression(conv->value);
    if(conv->value->constant())
    {
      expr = convertConstant(conv);
      return true;
    }
    else
    {
      return false;
    }
  }
  {
    //already constant and nothing to do
    constant = true;
    return false;
  }
  else if(auto& binArith = dynamic_cast<BinaryArith*&>(expr))
  {
    bool lhsConstant = false;
    bool rhsConstant = false;
    foldExpression(binArith->lhs, lhsConstant);
    foldExpression(binArith->rhs, rhsConstant);
    if(lhsConstant && rhsConstant)
    {
      constant = true;
      return true;
    }
    else
    {
      return false;
    }
  }
  else if(
}

bool constantFold(IR::SubroutineIR* subr)
{
  //every expression (including parts of an assignment LHS)
  //may be folded (i.e. myArray[5 + 3] = 8 % 3)
  //
  //recursivly attempt to fold expressions bottom-up,
  //remembering which input expressions are constants
}

bool constantPropagation(SubroutineIR* subr)
{
  bool update = false;
  //First, go through each BB and replace general Expressions
  //with constants wherever possible (constant folding)
  //
  //Also record which variables hold constant values at exit of BBs
  //
  //Then do constant propagation dataflow analysis across BBs
  //
  //VarExprs of constant variables can then be replaced by constant
  for(auto bb : subr->blocks)
  {
    for(int i = bb->start; i < bb->end; i++)
    {
      Statement* stmt = subr->stmts[i];
    }
  }
  return update;
}

<|endoftext|>


<commit_before>#include "CssTokenizer.h"

CssTokenizer::CssTokenizer(istream* in){
  this->in = in;
  line = 1;
  column = 0;
  readChar();
}

CssTokenizer::~CssTokenizer(){
}

void CssTokenizer::readChar(){
  if (in != NULL) {
    // Last char was a newline. Increment the line counter.
    if (lastReadEq('\n')) {
      line++;
      column = 0;
    }

    in->get(lastRead);

    // check for end of file or escape key
    if(in->eof() || lastRead == 27)
      in = NULL;
    else if (in->fail() || in->bad())
      throw new IOException("Error reading input");

    if (!lastReadEq('\n')) // count chars that aren't newlines
      column++;
  }
}

Token::Type CssTokenizer::readNextToken(){
  if (in == NULL) {
    currentToken.type = Token::EOS;
    return Token::EOS;
  }

  currentToken.clear();
  switch (lastRead) {
  case '@':
    currentToken.type = Token::ATKEYWORD;
    currentToken.add(lastRead);
    readChar();
    if (!readIdent()) {
      currentToken.type = Token::OTHER;
    }
    break;

  case '#':
    currentToken.type = Token::HASH;
    currentToken.add(lastRead);
    readChar();
    if (!readName()) {
      throw new ParseException(&lastRead,
                               "name following '#'");
    }
    break;

  case '-':
    currentToken.add(lastRead);
    readChar();
    if (readNum()) {
      currentToken.type = Token::NUMBER;
      if (lastReadEq('%')) {
        currentToken.type = Token::PERCENTAGE;
        currentToken.add(lastRead);
        readChar();
      } else if (readIdent())
        currentToken.type = Token::DIMENSION;
    } else if (readIdent()) {
      currentToken.type = Token::IDENTIFIER;
      if (lastRead == '(') {
        currentToken.add(lastRead);
        readChar();
        currentToken.type = Token::FUNCTION;
      }
    } else
      currentToken.type = Token::OTHER;
    break;

  case '~':
    currentToken.add(lastRead);
    readChar();
    if (lastRead == '=') {
      currentToken.add(lastRead);
      readChar();
      currentToken.type = Token::INCLUDES;
    } else
      currentToken.type = Token::OTHER;
    break;

  case '|':
    currentToken.add(lastRead);
    readChar();
    if (lastRead == '=') {
      currentToken.add(lastRead);
      readChar();
      currentToken.type = Token::DASHMATCH;
    } else
      currentToken.type = Token::OTHER;
    break;

  case '/':
    currentToken.add(lastRead);
    readChar();
    if (readComment())
      currentToken.type = Token::COMMENT;
    else
      currentToken.type = Token::OTHER;
    break;

  case ';':
    currentToken.type = Token::DELIMITER;
    currentToken.add(lastRead);
    readChar();
    break;
  case ':':
    currentToken.type = Token::COLON;
    currentToken.add(lastRead);
    readChar();
    break;
  case '{':
    currentToken.type = Token::BRACKET_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case '}':
    currentToken.type = Token::BRACKET_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;
  case '(':
    currentToken.type = Token::PAREN_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case ')':
    currentToken.type = Token::PAREN_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;
  case '[':
    currentToken.type = Token::BRACE_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case ']':
    currentToken.type = Token::BRACE_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;

  default:
    if (readString())
      currentToken.type = Token::STRING;
    else if (readNum()) {
      currentToken.type = Token::NUMBER;
      if (lastRead == '%') {
        currentToken.type = Token::PERCENTAGE;
        currentToken.add(lastRead);
        readChar();
      } else if (readIdent())
        currentToken.type = Token::DIMENSION;

    } else if (readIdent()) {
      currentToken.type = Token::IDENTIFIER;

      if (currentToken.str == "url" && readUrl())
        currentToken.type = Token::URL;
      else if (currentToken.str == "u" && lastReadEq('+')) {
        currentToken.add(lastRead);
        readChar();
        currentToken.type = Token::UNICODE_RANGE;
        readUnicodeRange();
      } else if (lastReadEq('(')) {
        currentToken.add(lastRead);
        readChar();
        currentToken.type = Token::FUNCTION;
      }
    } else if (readWhitespace()) {
      currentToken.type = Token::WHITESPACE;
      while (readWhitespace()) {};
    }
  }
  return currentToken.type;
}

bool CssTokenizer::readIdent () {
  if (lastReadEq('-')) {
    currentToken.add(lastRead);
    readChar();
  }
  if (!readNMStart())
    return false;
  else
    while (readNMChar()) {}
  return true;
}

bool CssTokenizer::readName () {
  if (!readNMChar())
    return false;
  while (readNMChar()) {}
  return true;
}

bool CssTokenizer::readNMStart () {
  if (in == NULL)
    return false;

  if (lastReadEq('_') ||
      lastReadInRange('a', 'z') ||
      lastReadInRange('A', 'Z')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return (readNonAscii() || readEscape());
}
bool CssTokenizer::readNonAscii () {
  if (in == NULL)
    return false;

  if (lastRead >= 0) {
    return false;
  } else {
    currentToken.add(lastRead);
    readChar();
    return true;
  }
}
bool CssTokenizer::readEscape () {
  if (!lastReadEq('\\'))
    return false;
  currentToken.add(lastRead);
  readChar();

  if (readUnicode())
    return true;
  else if (!lastReadEq('\n') &&
           !lastReadEq('\r') &&
           !lastReadEq('\f')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return false;
}
bool CssTokenizer::readUnicode () {
  if (!lastReadIsHex())
    return false;

  // [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
  for (int i=0; i < 6; i++) {
    if (readWhitespace())
      break;
    currentToken.add(lastRead);
    readChar();
    if (!lastReadIsHex()) {
      /*throw new ParseException(&lastRead,
        "hex code(0-9a-f) in unicode character");*/
      /* Just ignore and assume the unicode stops here  */
      break;
    }
  }
  return true;
}

bool CssTokenizer::readNMChar () {
  if (in == NULL)
    return false;

  if (lastReadEq('_') ||
      lastReadInRange('a', 'z') ||
      lastReadInRange('A', 'Z') ||
      lastReadIsDigit() ||
      lastReadEq('-')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return (readNonAscii() || readEscape());
}

bool CssTokenizer::readNum () {
  if (!lastReadIsDigit() && !lastReadEq('.'))
    return false;
  while (lastReadIsDigit()) {
    currentToken.add(lastRead);
    readChar();
  }
  if (lastReadEq('.')) {
    currentToken.add(lastRead);
    readChar();

    while (lastReadIsDigit()) {
      currentToken.add(lastRead);
      readChar();
    }
  }
  return true;
}

bool CssTokenizer::readString() {
  if (!lastReadEq('"') && !lastReadEq('\''))
    return false;
  char delim = lastRead;

  currentToken.add(lastRead);
  readChar();
  while (in != NULL) {
    if (lastReadEq(delim)) {
      currentToken.add(lastRead);
      readChar();
      return true;
    } else if (lastReadEq('\n') ||
               lastReadEq('\r') ||
               lastReadEq('\f')) {
      throw new ParseException("end of line",
                               "end of string");
    } else if (lastReadEq('\\'))
      // note that even though readEscape() returns false it still
      // eats the '\'.
      readEscape() || readNewline();
    else {
      currentToken.add(lastRead);
      readChar();
    }
  }
  throw new ParseException("end of input",
                           "end of string");
  return false;
}

bool CssTokenizer::readNewline () {
  if (lastReadEq('\r')) {
    currentToken.add(lastRead);
    readChar();
    if (lastReadEq('\n')) {
      currentToken.add(lastRead);
      readChar();
    }
    return true;
  } else if (lastReadEq('\n') ||
             lastReadEq('\f')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return false;
}

bool CssTokenizer::readWhitespace () {
  if (!lastReadEq(' ') &&
      !lastReadEq('\t') &&
      !lastReadEq('\r') &&
      !lastReadEq('\n') &&
      !lastReadEq('\f'))
    return false;

  currentToken.add(lastRead);
  readChar();
  return true;
}

bool CssTokenizer::readUrl() {
  string urlchars = "!#$%&*-[]-~";

  if (!lastReadEq('('))
    return false;
  currentToken.add(lastRead);
  readChar();
  while(readWhitespace()) {};

  if (readString()) {
    if (lastReadEq(')')) {
      currentToken.add(lastRead);
      readChar();
      return true;
    } else {
      throw new ParseException(&lastRead,
                               "end of url (')')");
    }
  }

  while (in != NULL) {
    if (readWhitespace() || lastReadEq(')')) {
      while (readWhitespace()) {};
      if (lastReadEq(')')) {
        currentToken.add(lastRead);
        readChar();
        return true;
      } else {
        throw new ParseException(&lastRead,
                                 "end of url (')')");
      }
    } else if (in != NULL && urlchars.find(lastRead)) {
      currentToken.add(lastRead);
      readChar();
    } else if (!readNonAscii() &&
               !readEscape()) {
      throw new ParseException(&lastRead,
                               "end of url (')')");
    }
  }
  throw new ParseException(&lastRead,
                           "end of url (')')");
  return false;
}

bool CssTokenizer::readComment () {
  if (!lastReadEq('*'))
    return false;
  currentToken.add(lastRead);
  readChar();
  while (in != NULL) {
    if (lastReadEq('*')) {
      currentToken.add(lastRead);
      readChar();

      if (lastReadEq('/')) {
        currentToken.add(lastRead);
        readChar();
        return true;
      }
    }
    currentToken.add(lastRead);
    readChar();
  }
  throw new ParseException(&lastRead,
                           "end of comment (*/)");
  return false;
}

bool CssTokenizer::readUnicodeRange () {
  if (in == NULL)
    return false;
  for (int i=0; i < 6; i++) {
    if (!lastReadIsHex())
      break;
    currentToken.add(lastRead);
    readChar();
  }
  if (!lastReadEq('-'))
    return true;

  for (int i=0; i < 6; i++) {
    if (!lastReadIsHex())
      break;
    currentToken.add(lastRead);
    readChar();
  }
  return true;
}

Token* CssTokenizer::getToken(){
  return &currentToken;
}
Token::Type CssTokenizer::getTokenType() {
  return currentToken.type;
}

unsigned int CssTokenizer::getLineNumber(){
  return line;
}
unsigned int CssTokenizer::getColumn(){
  return column;
}

bool CssTokenizer::lastReadEq(char c) {
  return (in != NULL && lastRead == c);
}

bool CssTokenizer::lastReadInRange(char c1, char c2) {
  return (in != NULL && lastRead >= c1 && lastRead <= c2);
}
bool CssTokenizer::lastReadIsDigit() {
  return (in != NULL &&
          lastReadInRange('0', '9'));
}
bool CssTokenizer::lastReadIsHex() {
  return (in != NULL &&
          (lastReadIsDigit() ||
           lastReadInRange('a', 'f') ||
           lastReadInRange('A', 'F')));
}
<commit_msg>Cleaning up CssTokenizer.cpp.<commit_after>#include "CssTokenizer.h"

CssTokenizer::CssTokenizer(istream* in){
  this->in = in;
  line = 1;
  column = 0;
  readChar();
}

CssTokenizer::~CssTokenizer(){
}

void CssTokenizer::readChar(){
  if (in == NULL)
    return;

  // Last char was a newline. Increment the line counter.
  if (lastReadEq('\n')) {
    line++;
    column = 0;
  }

  in->get(lastRead);

  // check for end of file or escape key
  if(in->eof() || lastRead == 27)
    in = NULL;
  else if (in->fail() || in->bad())
    throw new IOException("Error reading input");

  if (!lastReadEq('\n')) // count chars that aren't newlines
    column++;
}

Token::Type CssTokenizer::readNextToken(){
  if (in == NULL) {
    currentToken.type = Token::EOS;
    return Token::EOS;
  }

  currentToken.clear();
  switch (lastRead) {
  case '@':
    currentToken.type = Token::ATKEYWORD;
    currentToken.add(lastRead);
    readChar();
    if (!readIdent()) {
      currentToken.type = Token::OTHER;
    }
    break;

  case '#':
    currentToken.type = Token::HASH;
    currentToken.add(lastRead);
    readChar();
    if (!readName()) {
      throw new ParseException(&lastRead,
                               "name following '#'");
    }
    break;

  case '-':
    currentToken.add(lastRead);
    readChar();
    if (readNum()) {
      currentToken.type = Token::NUMBER;
      if (lastReadEq('%')) {
        currentToken.type = Token::PERCENTAGE;
        currentToken.add(lastRead);
        readChar();
      } else if (readIdent())
        currentToken.type = Token::DIMENSION;
    } else if (readIdent()) {
      currentToken.type = Token::IDENTIFIER;
      if (lastRead == '(') {
        currentToken.add(lastRead);
        readChar();
        currentToken.type = Token::FUNCTION;
      }
    } else
      currentToken.type = Token::OTHER;
    break;

  case '~':
    currentToken.add(lastRead);
    readChar();
    if (lastRead == '=') {
      currentToken.add(lastRead);
      readChar();
      currentToken.type = Token::INCLUDES;
    } else
      currentToken.type = Token::OTHER;
    break;

  case '|':
    currentToken.add(lastRead);
    readChar();
    if (lastRead == '=') {
      currentToken.add(lastRead);
      readChar();
      currentToken.type = Token::DASHMATCH;
    } else
      currentToken.type = Token::OTHER;
    break;

  case '/':
    currentToken.add(lastRead);
    readChar();
    if (readComment())
      currentToken.type = Token::COMMENT;
    else
      currentToken.type = Token::OTHER;
    break;

  case ';':
    currentToken.type = Token::DELIMITER;
    currentToken.add(lastRead);
    readChar();
    break;
  case ':':
    currentToken.type = Token::COLON;
    currentToken.add(lastRead);
    readChar();
    break;
  case '{':
    currentToken.type = Token::BRACKET_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case '}':
    currentToken.type = Token::BRACKET_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;
  case '(':
    currentToken.type = Token::PAREN_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case ')':
    currentToken.type = Token::PAREN_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;
  case '[':
    currentToken.type = Token::BRACE_OPEN;
    currentToken.add(lastRead);
    readChar();
    break;
  case ']':
    currentToken.type = Token::BRACE_CLOSED;
    currentToken.add(lastRead);
    readChar();
    break;

  default:
    if (readString())
      currentToken.type = Token::STRING;
    else if (readNum()) {
      currentToken.type = Token::NUMBER;
      if (lastRead == '%') {
        currentToken.type = Token::PERCENTAGE;
        currentToken.add(lastRead);
        readChar();
      } else if (readIdent())
        currentToken.type = Token::DIMENSION;

    } else if (readIdent()) {
      currentToken.type = Token::IDENTIFIER;

      if (currentToken.str == "url" && readUrl())
        currentToken.type = Token::URL;
      else if (currentToken.str == "u" && lastReadEq('+')) {
        currentToken.add(lastRead);
        readChar();
        currentToken.type = Token::UNICODE_RANGE;
        readUnicodeRange();
      } else if (lastReadEq('(')) {
        currentToken.add(lastRead);
        readChar();
        currentToken.type = Token::FUNCTION;
      }
    } else if (readWhitespace()) {
      currentToken.type = Token::WHITESPACE;
      while (readWhitespace()) {};
    }
    break;
  }

  return currentToken.type;
}

bool CssTokenizer::readIdent () {
  if (lastReadEq('-')) {
    currentToken.add(lastRead);
    readChar();
  }
  if (!readNMStart())
    return false;
  else
    while (readNMChar()) {}
  return true;
}

bool CssTokenizer::readName () {
  if (!readNMChar())
    return false;
  while (readNMChar()) {}
  return true;
}

bool CssTokenizer::readNMStart () {
  if (in == NULL)
    return false;

  if (lastReadEq('_') ||
      lastReadInRange('a', 'z') ||
      lastReadInRange('A', 'Z')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return (readNonAscii() || readEscape());
}
bool CssTokenizer::readNonAscii () {
  if (in == NULL)
    return false;

  if (lastRead >= 0) {
    return false;
  } else {
    currentToken.add(lastRead);
    readChar();
    return true;
  }
}
bool CssTokenizer::readEscape () {
  if (!lastReadEq('\\'))
    return false;
  currentToken.add(lastRead);
  readChar();

  if (readUnicode())
    return true;
  else if (!lastReadEq('\n') &&
           !lastReadEq('\r') &&
           !lastReadEq('\f')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return false;
}
bool CssTokenizer::readUnicode () {
  if (!lastReadIsHex())
    return false;

  // [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
  for (int i=0; i < 6; i++) {
    currentToken.add(lastRead);
    readChar();
    if (readWhitespace() || !lastReadIsHex())
      break;
  }
  return true;
}

bool CssTokenizer::readNMChar () {
  if (in == NULL)
    return false;

  if (lastReadEq('_') ||
      lastReadInRange('a', 'z') ||
      lastReadInRange('A', 'Z') ||
      lastReadIsDigit() ||
      lastReadEq('-')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return (readNonAscii() || readEscape());
}

bool CssTokenizer::readNum () {
  if (!lastReadIsDigit() && !lastReadEq('.'))
    return false;
  while (lastReadIsDigit()) {
    currentToken.add(lastRead);
    readChar();
  }
  if (lastReadEq('.')) {
    currentToken.add(lastRead);
    readChar();

    while (lastReadIsDigit()) {
      currentToken.add(lastRead);
      readChar();
    }
  }
  return true;
}

bool CssTokenizer::readString() {
  if (!lastReadEq('"') && !lastReadEq('\''))
    return false;
  char delim = lastRead;

  currentToken.add(lastRead);
  readChar();
  while (in != NULL) {
    if (lastReadEq(delim)) {
      currentToken.add(lastRead);
      readChar();
      return true;
    } else if (lastReadEq('\n') ||
               lastReadEq('\r') ||
               lastReadEq('\f')) {
      throw new ParseException("end of line",
                               "end of string");
    } else if (lastReadEq('\\'))
      // note that even though readEscape() returns false it still
      // eats the '\'.
      readEscape() || readNewline();
    else {
      currentToken.add(lastRead);
      readChar();
    }
  }
  throw new ParseException("end of input",
                           "end of string");
  return false;
}

bool CssTokenizer::readNewline () {
  if (lastReadEq('\r')) {
    currentToken.add(lastRead);
    readChar();
    if (lastReadEq('\n')) {
      currentToken.add(lastRead);
      readChar();
    }
    return true;
  } else if (lastReadEq('\n') ||
             lastReadEq('\f')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return false;
}

bool CssTokenizer::readWhitespace () {
  if (lastReadEq(' ') ||
      lastReadEq('\t') ||
      lastReadEq('\r') ||
      lastReadEq('\n') ||
      lastReadEq('\f')) {
    currentToken.add(lastRead);
    readChar();
    return true;
  } else
    return false;
}

bool CssTokenizer::readUrl() {
  string urlchars = "!#$%&*-[]-~";

  if (!lastReadEq('('))
    return false;
  currentToken.add(lastRead);
  readChar();
  while(readWhitespace()) {};

  if (readString()) {
    if (lastReadEq(')')) {
      currentToken.add(lastRead);
      readChar();
      return true;
    } else {
      throw new ParseException(&lastRead,
                               "end of url (')')");
    }
  }

  while (in != NULL) {
    if (readWhitespace() || lastReadEq(')')) {
      while (readWhitespace()) {};
      if (lastReadEq(')')) {
        currentToken.add(lastRead);
        readChar();
        return true;
      } else {
        throw new ParseException(&lastRead,
                                 "end of url (')')");
      }
    } else if (in != NULL && urlchars.find(lastRead)) {
      currentToken.add(lastRead);
      readChar();
    } else if (!readNonAscii() &&
               !readEscape()) {
      throw new ParseException(&lastRead,
                               "end of url (')')");
    }
  }
  throw new ParseException(&lastRead,
                           "end of url (')')");
  return false;
}

bool CssTokenizer::readComment () {
  if (!lastReadEq('*'))
    return false;
  currentToken.add(lastRead);
  readChar();
  while (in != NULL) {
    if (lastReadEq('*')) {
      currentToken.add(lastRead);
      readChar();

      if (lastReadEq('/')) {
        currentToken.add(lastRead);
        readChar();
        return true;
      }
    }
    currentToken.add(lastRead);
    readChar();
  }
  throw new ParseException(&lastRead,
                           "end of comment (*/)");
  return false;
}

bool CssTokenizer::readUnicodeRange () {
  if (in == NULL)
    return false;
  for (int i=0; i < 6; i++) {
    if (!lastReadIsHex())
      break;
    currentToken.add(lastRead);
    readChar();
  }
  if (!lastReadEq('-'))
    return true;

  for (int i=0; i < 6; i++) {
    if (!lastReadIsHex())
      break;
    currentToken.add(lastRead);
    readChar();
  }
  return true;
}

Token* CssTokenizer::getToken(){
  return &currentToken;
}
Token::Type CssTokenizer::getTokenType() {
  return currentToken.type;
}

unsigned int CssTokenizer::getLineNumber(){
  return line;
}
unsigned int CssTokenizer::getColumn(){
  return column;
}

bool CssTokenizer::lastReadEq(char c) {
  return (in != NULL && lastRead == c);
}

bool CssTokenizer::lastReadInRange(char c1, char c2) {
  return (in != NULL && lastRead >= c1 && lastRead <= c2);
}
bool CssTokenizer::lastReadIsDigit() {
  return (in != NULL &&
          lastReadInRange('0', '9'));
}
bool CssTokenizer::lastReadIsHex() {
  return (in != NULL &&
          (lastReadIsDigit() ||
           lastReadInRange('a', 'f') ||
           lastReadInRange('A', 'F')));
}
<|endoftext|>


<commit_before>/* -*- mode:C++; -*- */
/* MIT License -- MyThOS: The Many-Threads Operating System
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Copyright 2014 Randolf Rotta, Maik Krüger, and contributors, BTU Cottbus-Senftenberg
 */
#pragma once

#include "util/compiler.hh"
#include <cstdint>
#include <cstddef>

#define KERNEL_CLM      __attribute__((section (".kernel_clm")))
#define KERNEL_CLM_HOT  __attribute__((section (".kernel_clm.hot")))

namespace mythos {

  class KernelCLM
  {
  public:
    static void init(size_t size) {
      blockSize = size;
      offset = 0;
    }
    static size_t getBlockSize() { return blockSize; }
    static size_t getOffset(size_t threadID) { return threadID*blockSize; }
    static size_t getOffset() { return get(&offset); }
    static void initOffset(size_t threadID) { setAt(threadID, &offset, threadID*blockSize); }

    template<class T>
    ALWAYS_INLINE static void set(uintptr_t& var, T* value) {
      setWord(reinterpret_cast<size_t*>(&var), reinterpret_cast<size_t>(value));
    }

    ALWAYS_INLINE static void set(size_t* var, size_t value) {
      setWord(var, value);
    }

    template<typename T>
    ALWAYS_INLINE static void setAt(size_t threadID, T* var, T value) {
      auto ptr = reinterpret_cast<uintptr_t>(var) + threadID*blockSize;
      *reinterpret_cast<T*>(ptr) = value;
    }

    template<class T>
    ALWAYS_INLINE static T* get(uintptr_t const& var) {
      return reinterpret_cast<T*>(getWord(reinterpret_cast<size_t const*>(&var)));
    }

    ALWAYS_INLINE static size_t get(size_t const* var) {
      return getWord(var);
    }

    ALWAYS_INLINE static size_t getAt(size_t threadID, size_t const* var) {
      char const *ptr = reinterpret_cast<char const*>(var) + threadID*blockSize;
      return *reinterpret_cast<size_t const*>(ptr);
    }

    template<typename T>
    ALWAYS_INLINE static T* toLocal(T* var) {
      return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(var)+getOffset());
    }

  protected:
    static void setWord(uint64_t* addr, uint64_t value) {
      asm("movq %1,%%gs:%0" : : "m" (*addr), "ri" (value));
    }

    static uint64_t getWord(uint64_t const* addr) {
      uint64_t value;
      asm("movq %%gs:%1,%0" : "=r" (value) : "m" (*addr));
      return value;
    }

    static size_t blockSize;
    static size_t offset KERNEL_CLM_HOT;
  };

  template<typename T>
  class CoreLocal
  {
  public:
    ALWAYS_INLINE T const* addr() const { return KernelCLM::toLocal(&var); }
    ALWAYS_INLINE T* addr() { return KernelCLM::toLocal(&var); }
    ALWAYS_INLINE T const* operator->() const { return addr(); }
    ALWAYS_INLINE T* operator->() { return addr(); }
    ALWAYS_INLINE T& operator*() { return *addr(); }
    ALWAYS_INLINE T const& operator*() const { return *addr(); }

    ALWAYS_INLINE T const& get() const { return *addr(); }
    ALWAYS_INLINE void set(T const& value) { *addr() = value; }
  protected:
    T var;
  };

  template<>
  class CoreLocal<size_t>
  {
  public:
    ALWAYS_INLINE size_t get() const { return KernelCLM::get(&var); }
    ALWAYS_INLINE void set(size_t value) { return KernelCLM::set(&var, value); }
    // ALWAYS_INLINE size_t operator[](size_t threadID) { return KernelCLM::getAt(threadID, &var); }
    ALWAYS_INLINE void setAt(size_t threadID, size_t value) { KernelCLM::setAt(threadID, &var, value); }
    ALWAYS_INLINE CoreLocal& operator= (size_t value) { set(value); return *this; }
    ALWAYS_INLINE operator size_t () const { return get(); }
  protected:
    size_t var;
  };

  template<typename T>
  class CoreLocal<T*>
  {
  public:
    ALWAYS_INLINE T* get() const { return KernelCLM::get<T>(var); }
    ALWAYS_INLINE void set(T* value) { KernelCLM::set<T>(var, value); }
    // ALWAYS_INLINE T* operator[](size_t threadID) {
    //   return reinterpret_cast<T*>(KernelCLM::getAt(threadID, reinterpret_cast<size_t const*>(&var)));
    // }
    ALWAYS_INLINE void setAt(size_t threadID, T* value) { KernelCLM::setAt(threadID, &var, uintptr_t(value)); }
    ALWAYS_INLINE T* operator-> () const { return get(); }
    ALWAYS_INLINE T& operator* () const { return *get(); }
    ALWAYS_INLINE CoreLocal& operator= (T* value) { set(value); return *this; }
    // ALWAYS_INLINE operator T* () const { return get(); }
  protected:
    uintptr_t var;
  };

  template<>
  class CoreLocal<void*>
  {
  public:
    ALWAYS_INLINE void* get() const { return KernelCLM::get<void>(var); }
    ALWAYS_INLINE void set(void* value) { KernelCLM::set<void>(var, value); }
    ALWAYS_INLINE CoreLocal& operator= (void* value) { set(value); return *this; }
    ALWAYS_INLINE operator void* () const { return get(); }
  protected:
    uintptr_t var;
  };

} // namespace mythos
<commit_msg>init CLM<commit_after>/* -*- mode:C++; -*- */
/* MIT License -- MyThOS: The Many-Threads Operating System
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * Copyright 2014 Randolf Rotta, Maik Krüger, and contributors, BTU Cottbus-Senftenberg
 */
#pragma once

#include "util/compiler.hh"
#include <cstdint>
#include <cstddef>

#define KERNEL_CLM      __attribute__((section (".kernel_clm")))
#define KERNEL_CLM_HOT  __attribute__((section (".kernel_clm.hot")))

extern char CLM_BLOCKEND;

namespace mythos {

  class KernelCLM
  {
  public:
    static void init(size_t size) {
      blockSize = size;
      offset = 0;
      memset(&CLM_BLOCKEND, 0, size * (MYTHOS_MAX_THREADS - 1));
    }
    static size_t getBlockSize() { return blockSize; }
    static size_t getOffset(size_t threadID) { return threadID*blockSize; }
    static size_t getOffset() { return get(&offset); }
    static void initOffset(size_t threadID) { setAt(threadID, &offset, threadID*blockSize); }

    template<class T>
    ALWAYS_INLINE static void set(uintptr_t& var, T* value) {
      setWord(reinterpret_cast<size_t*>(&var), reinterpret_cast<size_t>(value));
    }

    ALWAYS_INLINE static void set(size_t* var, size_t value) {
      setWord(var, value);
    }

    template<typename T>
    ALWAYS_INLINE static void setAt(size_t threadID, T* var, T value) {
      auto ptr = reinterpret_cast<uintptr_t>(var) + threadID*blockSize;
      *reinterpret_cast<T*>(ptr) = value;
    }

    template<class T>
    ALWAYS_INLINE static T* get(uintptr_t const& var) {
      return reinterpret_cast<T*>(getWord(reinterpret_cast<size_t const*>(&var)));
    }

    ALWAYS_INLINE static size_t get(size_t const* var) {
      return getWord(var);
    }

    ALWAYS_INLINE static size_t getAt(size_t threadID, size_t const* var) {
      char const *ptr = reinterpret_cast<char const*>(var) + threadID*blockSize;
      return *reinterpret_cast<size_t const*>(ptr);
    }

    template<typename T>
    ALWAYS_INLINE static T* toLocal(T* var) {
      return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(var)+getOffset());
    }

  protected:
    static void setWord(uint64_t* addr, uint64_t value) {
      asm("movq %1,%%gs:%0" : : "m" (*addr), "ri" (value));
    }

    static uint64_t getWord(uint64_t const* addr) {
      uint64_t value;
      asm("movq %%gs:%1,%0" : "=r" (value) : "m" (*addr));
      return value;
    }

    static size_t blockSize;
    static size_t offset KERNEL_CLM_HOT;
  };

  template<typename T>
  class CoreLocal
  {
  public:
    ALWAYS_INLINE T const* addr() const { return KernelCLM::toLocal(&var); }
    ALWAYS_INLINE T* addr() { return KernelCLM::toLocal(&var); }
    ALWAYS_INLINE T const* operator->() const { return addr(); }
    ALWAYS_INLINE T* operator->() { return addr(); }
    ALWAYS_INLINE T& operator*() { return *addr(); }
    ALWAYS_INLINE T const& operator*() const { return *addr(); }

    ALWAYS_INLINE T const& get() const { return *addr(); }
    ALWAYS_INLINE void set(T const& value) { *addr() = value; }
  protected:
    T var;
  };

  template<>
  class CoreLocal<size_t>
  {
  public:
    ALWAYS_INLINE size_t get() const { return KernelCLM::get(&var); }
    ALWAYS_INLINE void set(size_t value) { return KernelCLM::set(&var, value); }
    // ALWAYS_INLINE size_t operator[](size_t threadID) { return KernelCLM::getAt(threadID, &var); }
    ALWAYS_INLINE void setAt(size_t threadID, size_t value) { KernelCLM::setAt(threadID, &var, value); }
    ALWAYS_INLINE CoreLocal& operator= (size_t value) { set(value); return *this; }
    ALWAYS_INLINE operator size_t () const { return get(); }
  protected:
    size_t var;
  };

  template<typename T>
  class CoreLocal<T*>
  {
  public:
    ALWAYS_INLINE T* get() const { return KernelCLM::get<T>(var); }
    ALWAYS_INLINE void set(T* value) { KernelCLM::set<T>(var, value); }
    // ALWAYS_INLINE T* operator[](size_t threadID) {
    //   return reinterpret_cast<T*>(KernelCLM::getAt(threadID, reinterpret_cast<size_t const*>(&var)));
    // }
    ALWAYS_INLINE void setAt(size_t threadID, T* value) { KernelCLM::setAt(threadID, &var, uintptr_t(value)); }
    ALWAYS_INLINE T* operator-> () const { return get(); }
    ALWAYS_INLINE T& operator* () const { return *get(); }
    ALWAYS_INLINE CoreLocal& operator= (T* value) { set(value); return *this; }
    // ALWAYS_INLINE operator T* () const { return get(); }
  protected:
    uintptr_t var;
  };

  template<>
  class CoreLocal<void*>
  {
  public:
    ALWAYS_INLINE void* get() const { return KernelCLM::get<void>(var); }
    ALWAYS_INLINE void set(void* value) { KernelCLM::set<void>(var, value); }
    ALWAYS_INLINE CoreLocal& operator= (void* value) { set(value); return *this; }
    ALWAYS_INLINE operator void* () const { return get(); }
  protected:
    uintptr_t var;
  };

} // namespace mythos
<|endoftext|>


<commit_before><commit_msg>Template edit<commit_after><|endoftext|>


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

#include "SiconosConfig.h"

#include "BlockCSRMatrix.hpp"
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include "NonSmoothLaw.hpp"

#include "NewtonEulerDS.hpp"
#include "NewtonEulerR.hpp"
#include "SimulationGraphs.hpp"

#include "Tools.hpp"

// Default constructor: empty matrix
BlockCSRMatrix::BlockCSRMatrix():
  _nr(0),
  _blockCSR(new CompressedRowMat()),
  _sparseBlockStructuredMatrix(new SparseBlockStructuredMatrix()),
  _diagsize0(new IndexInt()),
  _diagsize1(new IndexInt()),
  rowPos(new IndexInt()),
  colPos(new IndexInt())
{}

// Constructor with dimensions
BlockCSRMatrix::BlockCSRMatrix(unsigned int nRow):
  _nr(nRow),
  // Only square-blocks matrices for the moment (ie nRow = nr = nrol)

  // Allocate memory and fill in the matrix rowPos, rowCol ... are
  // initialized with nr to reserve at first step the maximum possible
  // (according to given nr) space in memory.  Thus a future resize
  // will not require memory allocation or copy.
  _blockCSR(new CompressedRowMat(_nr, _nr)),
  _sparseBlockStructuredMatrix(new SparseBlockStructuredMatrix),
  _diagsize0(new IndexInt(_nr)),
  _diagsize1(new IndexInt(_nr)),
  rowPos(new IndexInt(_nr)),
  colPos(new IndexInt(_nr))
{}

// Basic constructor
BlockCSRMatrix::BlockCSRMatrix(SP::InteractionsGraph indexSet):
  _nr(indexSet->size()),
  _blockCSR(new CompressedRowMat(_nr, _nr)),
  _sparseBlockStructuredMatrix(new SparseBlockStructuredMatrix()),
  _diagsize0(new IndexInt(_nr)),
  _diagsize1(new IndexInt(_nr)),
  rowPos(new IndexInt(_nr)),
  colPos(new IndexInt(_nr))
{
  fill(indexSet);
}

BlockCSRMatrix::~BlockCSRMatrix()
{}

// Fill the SparseMat
void BlockCSRMatrix::fill(SP::InteractionsGraph indexSet)
{
  // ======> Aim: find inter1 and inter2 both in indexSets[level] and which
  // have common DynamicalSystems.  Then get the corresponding matrix
  // from map blocks.

  assert(indexSet);

  // Number of blocks in a row = number of active constraints.
  _nr = indexSet->size();

  // (re)allocate memory for ublas matrix
  _blockCSR->resize(_nr, _nr, false);

  _diagsize0->resize(_nr);
  _diagsize1->resize(_nr);

  // === Loop through "active" Interactions (ie present in
  // indexSets[level]) ===

  int sizeV = 0;

  InteractionsGraph::VIterator vi, viend;
  for (std11::tie(vi, viend) = indexSet->vertices();
       vi != viend; ++vi)
  {
    SP::Interaction inter = indexSet->bundle(*vi);

    assert(inter->nonSmoothLaw()->size() > 0);

    sizeV  += inter->nonSmoothLaw()->size();
    (*_diagsize0)[indexSet->index(*vi)] = sizeV;
    (*_diagsize1)[indexSet->index(*vi)] = sizeV;
    assert((*_diagsize0)[indexSet->index(*vi)] > 0);
    assert((*_diagsize1)[indexSet->index(*vi)] > 0);

    (*_blockCSR)(indexSet->index(*vi), indexSet->index(*vi)) =
      indexSet->properties(*vi).block->getArray();
  }

  InteractionsGraph::EIterator ei, eiend;
  for (std11::tie(ei, eiend) = indexSet->edges();
       ei != eiend; ++ei)
  {
    InteractionsGraph::VDescriptor vd1 = indexSet->source(*ei);
    InteractionsGraph::VDescriptor vd2 = indexSet->target(*ei);
    SP::Interaction inter1 = indexSet->bundle(vd1);
    SP::Interaction inter2 = indexSet->bundle(vd2);

    assert(indexSet->index(vd1) < _nr);
    assert(indexSet->index(vd2) < _nr);

    assert(indexSet->is_vertex(inter2));

    assert(vd2 == indexSet->descriptor(inter2));
    assert(indexSet->index(vd2) == indexSet->index(indexSet->descriptor(inter2)));

    unsigned int pos = indexSet->index(vd1);
    unsigned int col = indexSet->index(vd2);

    assert(pos != col);

    (*_blockCSR)(std::min(pos, col), std::max(pos, col)) =
      indexSet->properties(*ei).upper_block->getArray();

    (*_blockCSR)(std::max(pos, col), std::min(pos, col)) =
      indexSet->properties(*ei).lower_block->getArray();
  }
}

void BlockCSRMatrix::fillM(SP::InteractionsGraph indexSet)
{
  assert(indexSet);

  /* on adjoint graph a dynamical system may be on several edges */
  std::map<SP::DynamicalSystem, bool> involvedDS;
  InteractionsGraph::EIterator ei, eiend;
  for(std11::tie(ei, eiend) = indexSet->edges();
      ei != eiend; ++ei)
  {
    if (Type::value(*indexSet->bundle(*ei)) != Type::NewtonEulerDS)
    {
      RuntimeException::selfThrow("BlockCSRMatrix::fillM only for Newton EulerDS");
    }

    _nr = 0;

    if (involvedDS.find(indexSet->bundle(*ei)) == involvedDS.end())
    {
      _nr++;
      involvedDS[indexSet->bundle(*ei)] = true;
      _blockCSR->resize(_nr, _nr, false);

      (*_blockCSR)(_nr-1, _nr-1) = std11::static_pointer_cast<NewtonEulerDS>
        (indexSet->bundle(*ei))->mass()->getArray();
    }
  }

  _diagsize0->resize(involvedDS.size());
  _diagsize1->resize(involvedDS.size());

  /* here we suppose NewtonEuler with 6 dofs */
  /* it cannot be another case at this point */
  unsigned int index, ac;
  for (index = 0, ac = 6;
       index < involvedDS.size();
       ++index, ac+=6)
  {
    (*_diagsize0)[index] = ac;
    (*_diagsize1)[index] = ac;
  }

}

void BlockCSRMatrix::fillH(SP::InteractionsGraph indexSet)
{
  assert(indexSet);

  /* on adjoint graph a dynamical system may be on several edges */
  std::map<SP::DynamicalSystem, unsigned int> involvedDS;
  InteractionsGraph::EIterator ei, eiend;
  {
    unsigned int index;
    for(std11::tie(ei, eiend) = indexSet->edges(), index=0;
        ei != eiend; ++ei, ++index)
    {
      if (involvedDS.find(indexSet->bundle(*ei)) == involvedDS.end())
      {
        if (Type::value(*indexSet->bundle(*ei)) != Type::NewtonEulerDS)
        {
          RuntimeException::selfThrow("BlockCSRMatrix::fillH only for Newton EulerDS");
        }
        involvedDS[indexSet->bundle(*ei)] = index;
      }
    }
  }

  _nr = involvedDS.size();

  _blockCSR->resize(_nr, _nr, false);

  InteractionsGraph::VIterator vi, viend;
  for(std11::tie(vi, viend) = indexSet->vertices();
      vi != viend; ++vi)
  {

    SP::DynamicalSystem first = SP::DynamicalSystem();
    unsigned int pos=0, col=0;
    InteractionsGraph::EDescriptor ed1, ed2;
    InteractionsGraph::OEIterator oei, oeiend;
    for(std11::tie(oei, oeiend) = indexSet->out_edges(*vi);
        oei != oeiend; ++oei)
    {
      if (!first)
      {
        first = indexSet->bundle(*oei);
        col = involvedDS[first];
        pos = involvedDS[first];
      }
      else
      {
        if (indexSet->bundle(*oei) != first)
        {
          pos = involvedDS[indexSet->bundle(*oei)];
        }
      }
    }

    (*_blockCSR)(std::min(pos, col), std::max(pos, col)) =
      std11::static_pointer_cast<NewtonEulerR>(indexSet->bundle(*vi)->relation())->jachqT()->getArray();

    (*_blockCSR)(std::max(pos, col), std::min(pos, col)) =
      std11::static_pointer_cast<NewtonEulerR>(indexSet->bundle(*vi)->relation())->jachqT()->getArray();

  }

  _diagsize0->resize(involvedDS.size());
  _diagsize1->resize(involvedDS.size());

  /* only NewtonEulerFrom3DLocalFrameR */
  unsigned int index, ac0, ac1;
  for (index= 0, ac0 = 6, ac1 = 3;
       index < involvedDS.size();
       ++index, ac0 +=6, ac1 +=3)
  {
    (*_diagsize0)[index] = ac0;
    (*_diagsize1)[index] = ac1;
  }

}

// Fill the SparseMat
void BlockCSRMatrix::fill(SP::DynamicalSystemsSet DSSet,
                          MapOfDSMatrices& DSblocks)
{
  RuntimeException::selfThrow
  (" BlockCSRMatrix::fill(DynamicalSystemsSet* DSSet, MapOfDSMatrices& DSblocks), Not Yet Implemented");
}
// Fill the SparseMat
void BlockCSRMatrix::fill(SP::InteractionsGraph indexSet,
                          SP::DynamicalSystemsSet DSSet,
                          MapOfInteractionMapOfDSMatrices& interactionDSBlocks)
{
  RuntimeException::selfThrow
  (" BlockCSRMatrix::fill(DynamicalSystemsSet* DSSet, MapOfDSMatrices& DSblocks), Not Yet Implemented");
}

// convert _blockCSR to numerics structure
void BlockCSRMatrix::convert()
{
  _sparseBlockStructuredMatrix->blocknumber0 = _nr;
  _sparseBlockStructuredMatrix->blocknumber1 = _nr;  // nc not always set
  _sparseBlockStructuredMatrix->nbblocks = (*_blockCSR).nnz();
  // Next copies: pointer links!!
  _sparseBlockStructuredMatrix->blocksize0 =  &((*_diagsize0)[0]);
  _sparseBlockStructuredMatrix->blocksize1 =  &((*_diagsize1)[0]);  // nr = nc

  // boost
  _sparseBlockStructuredMatrix->filled1 = (*_blockCSR).filled1();
  _sparseBlockStructuredMatrix->filled2 = (*_blockCSR).filled2();
  _sparseBlockStructuredMatrix->index1_data = &((*_blockCSR).index1_data()[0]);
  if (_nr > 0)
  {
    _sparseBlockStructuredMatrix->index2_data = &((*_blockCSR).index2_data()[0]);
    _sparseBlockStructuredMatrix->block =  &((*_blockCSR).value_data()[0]);
  };

  //   // Loop through the non-null blocks
  //   for (SpMatIt1 i1 = _blockCSR->begin1(); i1 != _blockCSR->end1(); ++i1)
  //     {
  //       for (SpMatIt2 i2 = i1.begin(); i2 != i1.end(); ++i2)
  //  {
  //    block[i] = *i2;
  //  }
  //     }
}

// Display data
void BlockCSRMatrix::display() const
{
  std::cout << "----- Sparse Block Matrix with "
            << _nr << " blocks in a row/col and "
            << _blockCSR->nnz()
            << " non-null blocks" <<std::endl;
  std::cout << "filled1:" << _blockCSR->filled1() <<std::endl;
  std::cout << "filled2:" << _blockCSR->filled2() <<std::endl;
  std::cout << "index1_data:\n";
  print(_blockCSR->index1_data().begin(), _blockCSR->index1_data().end());
  std::cout <<std::endl;
  std::cout << "index2_data:\n";
  print(_blockCSR->index2_data().begin(), _blockCSR->index2_data().end());
  std::cout <<std::endl;
  std::cout << "Sum of sizes of the diagonal blocks:"
            <<std::endl;
  print(_diagsize0->begin(), _diagsize0->end());
  print(_diagsize1->begin(), _diagsize1->end());
}

unsigned int BlockCSRMatrix::getNbNonNullBlocks() const
{
  return _blockCSR->nnz();
};

<commit_msg>[kernel] add debug output.<commit_after>/* Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 *
 * Copyright 2016 INRIA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

#include "SiconosConfig.h"

#include "BlockCSRMatrix.hpp"
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include "NonSmoothLaw.hpp"

#include "NewtonEulerDS.hpp"
#include "NewtonEulerR.hpp"
#include "SimulationGraphs.hpp"

#include "Tools.hpp"

// #define DEBUG_STDOUT
// #define DEBUG_MESSAGES 1
#include "debug.h"

// Default constructor: empty matrix
BlockCSRMatrix::BlockCSRMatrix():
  _nr(0),
  _blockCSR(new CompressedRowMat()),
  _sparseBlockStructuredMatrix(new SparseBlockStructuredMatrix()),
  _diagsize0(new IndexInt()),
  _diagsize1(new IndexInt()),
  rowPos(new IndexInt()),
  colPos(new IndexInt())
{}

// Constructor with dimensions
BlockCSRMatrix::BlockCSRMatrix(unsigned int nRow):
  _nr(nRow),
  // Only square-blocks matrices for the moment (ie nRow = nr = nrol)

  // Allocate memory and fill in the matrix rowPos, rowCol ... are
  // initialized with nr to reserve at first step the maximum possible
  // (according to given nr) space in memory.  Thus a future resize
  // will not require memory allocation or copy.
  _blockCSR(new CompressedRowMat(_nr, _nr)),
  _sparseBlockStructuredMatrix(new SparseBlockStructuredMatrix()),
  _diagsize0(new IndexInt(_nr)),
  _diagsize1(new IndexInt(_nr)),
  rowPos(new IndexInt(_nr)),
  colPos(new IndexInt(_nr))
{}

// Basic constructor
BlockCSRMatrix::BlockCSRMatrix(SP::InteractionsGraph indexSet):
  _nr(indexSet->size()),
  _blockCSR(new CompressedRowMat(_nr, _nr)),
  _sparseBlockStructuredMatrix(new SparseBlockStructuredMatrix()),
  _diagsize0(new IndexInt(_nr)),
  _diagsize1(new IndexInt(_nr)),
  rowPos(new IndexInt(_nr)),
  colPos(new IndexInt(_nr))
{
  DEBUG_BEGIN("BlockCSRMatrix::BlockCSRMatrix(SP::InteractionsGraph indexSet)\n");
  fill(indexSet);
  DEBUG_END("BlockCSRMatrix::BlockCSRMatrix(SP::InteractionsGraph indexSet)\n");
}

BlockCSRMatrix::~BlockCSRMatrix()
{}

// Fill the SparseMat
void BlockCSRMatrix::fill(SP::InteractionsGraph indexSet)
{
  // ======> Aim: find inter1 and inter2 both in indexSets[level] and which
  // have common DynamicalSystems.  Then get the corresponding matrix
  // from map blocks.

  assert(indexSet);

  // Number of blocks in a row = number of active constraints.
  _nr = indexSet->size();

  // (re)allocate memory for ublas matrix
  _blockCSR->resize(_nr, _nr, false);

  _diagsize0->resize(_nr);
  _diagsize1->resize(_nr);

  // === Loop through "active" Interactions (ie present in
  // indexSets[level]) ===

  int sizeV = 0;

  InteractionsGraph::VIterator vi, viend;
  for (std11::tie(vi, viend) = indexSet->vertices();
       vi != viend; ++vi)
  {
    SP::Interaction inter = indexSet->bundle(*vi);

    assert(inter->nonSmoothLaw()->size() > 0);

    sizeV  += inter->nonSmoothLaw()->size();
    (*_diagsize0)[indexSet->index(*vi)] = sizeV;
    (*_diagsize1)[indexSet->index(*vi)] = sizeV;
    assert((*_diagsize0)[indexSet->index(*vi)] > 0);
    assert((*_diagsize1)[indexSet->index(*vi)] > 0);

    (*_blockCSR)(indexSet->index(*vi), indexSet->index(*vi)) =
      indexSet->properties(*vi).block->getArray();
  }

  InteractionsGraph::EIterator ei, eiend;
  for (std11::tie(ei, eiend) = indexSet->edges();
       ei != eiend; ++ei)
  {
    InteractionsGraph::VDescriptor vd1 = indexSet->source(*ei);
    InteractionsGraph::VDescriptor vd2 = indexSet->target(*ei);
    SP::Interaction inter1 = indexSet->bundle(vd1);
    SP::Interaction inter2 = indexSet->bundle(vd2);

    assert(indexSet->index(vd1) < _nr);
    assert(indexSet->index(vd2) < _nr);

    assert(indexSet->is_vertex(inter2));

    assert(vd2 == indexSet->descriptor(inter2));
    assert(indexSet->index(vd2) == indexSet->index(indexSet->descriptor(inter2)));

    unsigned int pos = indexSet->index(vd1);
    unsigned int col = indexSet->index(vd2);

    assert(pos != col);

    (*_blockCSR)(std::min(pos, col), std::max(pos, col)) =
      indexSet->properties(*ei).upper_block->getArray();

    (*_blockCSR)(std::max(pos, col), std::min(pos, col)) =
      indexSet->properties(*ei).lower_block->getArray();
  }
  DEBUG_EXPR(display(););
}

void BlockCSRMatrix::fillM(SP::InteractionsGraph indexSet)
{
  assert(indexSet);

  /* on adjoint graph a dynamical system may be on several edges */
  std::map<SP::DynamicalSystem, bool> involvedDS;
  InteractionsGraph::EIterator ei, eiend;
  for(std11::tie(ei, eiend) = indexSet->edges();
      ei != eiend; ++ei)
  {
    if (Type::value(*indexSet->bundle(*ei)) != Type::NewtonEulerDS)
    {
      RuntimeException::selfThrow("BlockCSRMatrix::fillM only for Newton EulerDS");
    }

    _nr = 0;

    if (involvedDS.find(indexSet->bundle(*ei)) == involvedDS.end())
    {
      _nr++;
      involvedDS[indexSet->bundle(*ei)] = true;
      _blockCSR->resize(_nr, _nr, false);

      (*_blockCSR)(_nr-1, _nr-1) = std11::static_pointer_cast<NewtonEulerDS>
        (indexSet->bundle(*ei))->mass()->getArray();
    }
  }

  _diagsize0->resize(involvedDS.size());
  _diagsize1->resize(involvedDS.size());

  /* here we suppose NewtonEuler with 6 dofs */
  /* it cannot be another case at this point */
  unsigned int index, ac;
  for (index = 0, ac = 6;
       index < involvedDS.size();
       ++index, ac+=6)
  {
    (*_diagsize0)[index] = ac;
    (*_diagsize1)[index] = ac;
  }

}

void BlockCSRMatrix::fillH(SP::InteractionsGraph indexSet)
{
  assert(indexSet);

  /* on adjoint graph a dynamical system may be on several edges */
  std::map<SP::DynamicalSystem, unsigned int> involvedDS;
  InteractionsGraph::EIterator ei, eiend;
  {
    unsigned int index;
    for(std11::tie(ei, eiend) = indexSet->edges(), index=0;
        ei != eiend; ++ei, ++index)
    {
      if (involvedDS.find(indexSet->bundle(*ei)) == involvedDS.end())
      {
        if (Type::value(*indexSet->bundle(*ei)) != Type::NewtonEulerDS)
        {
          RuntimeException::selfThrow("BlockCSRMatrix::fillH only for Newton EulerDS");
        }
        involvedDS[indexSet->bundle(*ei)] = index;
      }
    }
  }

  _nr = involvedDS.size();

  _blockCSR->resize(_nr, _nr, false);

  InteractionsGraph::VIterator vi, viend;
  for(std11::tie(vi, viend) = indexSet->vertices();
      vi != viend; ++vi)
  {

    SP::DynamicalSystem first = SP::DynamicalSystem();
    unsigned int pos=0, col=0;
    InteractionsGraph::EDescriptor ed1, ed2;
    InteractionsGraph::OEIterator oei, oeiend;
    for(std11::tie(oei, oeiend) = indexSet->out_edges(*vi);
        oei != oeiend; ++oei)
    {
      if (!first)
      {
        first = indexSet->bundle(*oei);
        col = involvedDS[first];
        pos = involvedDS[first];
      }
      else
      {
        if (indexSet->bundle(*oei) != first)
        {
          pos = involvedDS[indexSet->bundle(*oei)];
        }
      }
    }

    (*_blockCSR)(std::min(pos, col), std::max(pos, col)) =
      std11::static_pointer_cast<NewtonEulerR>(indexSet->bundle(*vi)->relation())->jachqT()->getArray();

    (*_blockCSR)(std::max(pos, col), std::min(pos, col)) =
      std11::static_pointer_cast<NewtonEulerR>(indexSet->bundle(*vi)->relation())->jachqT()->getArray();

  }

  _diagsize0->resize(involvedDS.size());
  _diagsize1->resize(involvedDS.size());

  /* only NewtonEulerFrom3DLocalFrameR */
  unsigned int index, ac0, ac1;
  for (index= 0, ac0 = 6, ac1 = 3;
       index < involvedDS.size();
       ++index, ac0 +=6, ac1 +=3)
  {
    (*_diagsize0)[index] = ac0;
    (*_diagsize1)[index] = ac1;
  }

}

// Fill the SparseMat
void BlockCSRMatrix::fill(SP::DynamicalSystemsSet DSSet,
                          MapOfDSMatrices& DSblocks)
{
  RuntimeException::selfThrow
  (" BlockCSRMatrix::fill(DynamicalSystemsSet* DSSet, MapOfDSMatrices& DSblocks), Not Yet Implemented");
}
// Fill the SparseMat
void BlockCSRMatrix::fill(SP::InteractionsGraph indexSet,
                          SP::DynamicalSystemsSet DSSet,
                          MapOfInteractionMapOfDSMatrices& interactionDSBlocks)
{
  RuntimeException::selfThrow
  (" BlockCSRMatrix::fill(DynamicalSystemsSet* DSSet, MapOfDSMatrices& DSblocks), Not Yet Implemented");
}

// convert _blockCSR to numerics structure
void BlockCSRMatrix::convert()
{
  _sparseBlockStructuredMatrix->blocknumber0 = _nr;
  _sparseBlockStructuredMatrix->blocknumber1 = _nr;  // nc not always set
  _sparseBlockStructuredMatrix->nbblocks = (*_blockCSR).nnz();
  // Next copies: pointer links!!
  _sparseBlockStructuredMatrix->blocksize0 =  &((*_diagsize0)[0]);
  _sparseBlockStructuredMatrix->blocksize1 =  &((*_diagsize1)[0]);  // nr = nc

  // boost
  _sparseBlockStructuredMatrix->filled1 = (*_blockCSR).filled1();
  _sparseBlockStructuredMatrix->filled2 = (*_blockCSR).filled2();
  _sparseBlockStructuredMatrix->index1_data = &((*_blockCSR).index1_data()[0]);
  if (_nr > 0)
  {
    _sparseBlockStructuredMatrix->index2_data = &((*_blockCSR).index2_data()[0]);
    _sparseBlockStructuredMatrix->block =  &((*_blockCSR).value_data()[0]);
  };

  //   // Loop through the non-null blocks
  //   for (SpMatIt1 i1 = _blockCSR->begin1(); i1 != _blockCSR->end1(); ++i1)
  //     {
  //       for (SpMatIt2 i2 = i1.begin(); i2 != i1.end(); ++i2)
  //  {
  //    block[i] = *i2;
  //  }
  //     }
}

// Display data
void BlockCSRMatrix::display() const
{
  std::cout << "----- Sparse Block Matrix with "
            << _nr << " blocks in a row/col and "
            << _blockCSR->nnz()
            << " non-null blocks" <<std::endl;
  std::cout << "filled1 (index of the last non empty line + 1):" << _blockCSR->filled1() <<std::endl;
  std::cout << "filled2 (number of non null blocks):" << _blockCSR->filled2() <<std::endl;
  std::cout << "_blockCSR->index1_data().size()" << _blockCSR->index1_data().size() << std::endl;
  print(_blockCSR->index1_data().begin(), _blockCSR->index1_data().end(),"index1_data", "\t");

  assert(_blockCSR->index2_data().size() >= _blockCSR->filled2() );

  std::cout << "_blockCSR->index2_data().size()" << _blockCSR->index2_data().size() << std::endl;
  print(_blockCSR->index2_data().begin(), _blockCSR->index2_data().end(), "index2_data (column number for each block)", "\t");

  std::cout << "last column number  "<<   _blockCSR->index2_data()[_blockCSR->filled2()-1] <<  " for block   " << _blockCSR->filled2() << std::endl;
  print(_diagsize0->begin(), _diagsize0->end(),"_diagsize0 , sum of row sizes of the diagonal blocks", "\t" );
  print(_diagsize1->begin(), _diagsize1->end(),"_diagsize1 , sum of col sizes of the diagonal blocks", "\t"  );
}

unsigned int BlockCSRMatrix::getNbNonNullBlocks() const
{
  return _blockCSR->nnz();
};
<|endoftext|>


<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 <iostream>

#include "EDDIFrontEnd.hpp"
#include "SemanticalException.hpp"
#include "DebugStopWatch.hpp"
#include "Options.hpp"
#include "StringPool.hpp"
#include "Type.hpp"

#include "parser/SpiritParser.hpp"

#include "ast/SourceFile.hpp"

//Annotators
#include "ast/DefaultValues.hpp"
#include "ast/ContextAnnotator.hpp"
#include "ast/FunctionsAnnotator.hpp"
#include "ast/VariablesAnnotator.hpp"
#include "ast/StructuresAnnotator.hpp"

//Checkers
#include "ast/StringChecker.hpp"
#include "ast/TypeChecker.hpp"

//Visitors
#include "ast/DependenciesResolver.hpp"
#include "ast/OptimizationEngine.hpp"
#include "ast/TransformerEngine.hpp"
#include "ast/WarningsEngine.hpp"
#include "ast/Printer.hpp"

#include "mtac/Compiler.hpp"
#include "mtac/RegisterAllocation.hpp"

using namespace eddic;

void checkForMain();

std::shared_ptr<mtac::Program> EDDIFrontEnd::compile(const std::string& file){
    parser::SpiritParser parser;

    //The program to build
    ast::SourceFile program;

    //Parse the file into the program
    bool parsing = parser.parse(file, program);

    //If the parsing was sucessfully
    if(parsing){
        set_string_pool(std::make_shared<StringPool>());

        //Read dependencies
        resolveDependencies(program, parser);

        //Apply some cleaning transformations
        ast::cleanAST(program);

        //Annotate the AST with more informations
        ast::defineDefaultValues(program);

        //Fill the string pool
        ast::checkStrings(program, *pool);

        //Add some more informations to the AST
        ast::defineStructures(program);
        ast::defineMemberFunctions(program);
        ast::defineContexts(program);
        ast::defineVariables(program);
        ast::defineFunctions(program);

        //Static analysis
        ast::checkTypes(program);

        //Check for warnings
        ast::checkForWarnings(program);

        //Check that there is a main in the program
        checkForMain();

        //Transform the AST
        ast::transformAST(program);

        //Optimize the AST
        ast::optimizeAST(program, *pool);

        //If the user asked for it, print the Abstract Syntax Tree
        if(option_defined("ast") || option_defined("ast-only")){
            ast::Printer printer;
            printer.print(program);
        }

        //If the user wants only the AST prints, it is not necessary to compile the AST
        if(option_defined("ast-only")){
            return nullptr;
        }

        std::shared_ptr<mtac::Program> mtacProgram = std::make_shared<mtac::Program>();

        //Generate Three-Address-Code language
        mtac::Compiler compiler;
        compiler.compile(program, pool, mtacProgram);

        return mtacProgram;
    }

    //If the parsing fails, the error is already printed to the console
    return nullptr;
}

void checkForMain(){
    if(!symbols.exists("main")){
        throw SemanticalException("Your program must contain a main function");
    }

    auto function = symbols.getFunction("main");

    if(function->parameters.size() > 1){
        throw SemanticalException("The signature of your main function is not valid");
    }

    if(function->parameters.size() == 1){
        auto type = function->parameters[0].paramType;

        if(type->data_type() != STRING || !type->is_array()){
            throw SemanticalException("The signature of your main function is not valid");
        }
    }
}
<commit_msg>Check for main with new mangling<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 <iostream>

#include "EDDIFrontEnd.hpp"
#include "SemanticalException.hpp"
#include "DebugStopWatch.hpp"
#include "Options.hpp"
#include "StringPool.hpp"
#include "Type.hpp"

#include "parser/SpiritParser.hpp"

#include "ast/SourceFile.hpp"

//Annotators
#include "ast/DefaultValues.hpp"
#include "ast/ContextAnnotator.hpp"
#include "ast/FunctionsAnnotator.hpp"
#include "ast/VariablesAnnotator.hpp"
#include "ast/StructuresAnnotator.hpp"

//Checkers
#include "ast/StringChecker.hpp"
#include "ast/TypeChecker.hpp"

//Visitors
#include "ast/DependenciesResolver.hpp"
#include "ast/OptimizationEngine.hpp"
#include "ast/TransformerEngine.hpp"
#include "ast/WarningsEngine.hpp"
#include "ast/Printer.hpp"

#include "mtac/Compiler.hpp"
#include "mtac/RegisterAllocation.hpp"

using namespace eddic;

void checkForMain();

std::shared_ptr<mtac::Program> EDDIFrontEnd::compile(const std::string& file){
    parser::SpiritParser parser;

    //The program to build
    ast::SourceFile program;

    //Parse the file into the program
    bool parsing = parser.parse(file, program);

    //If the parsing was sucessfully
    if(parsing){
        set_string_pool(std::make_shared<StringPool>());

        //Read dependencies
        resolveDependencies(program, parser);

        //Apply some cleaning transformations
        ast::cleanAST(program);

        //Annotate the AST with more informations
        ast::defineDefaultValues(program);

        //Fill the string pool
        ast::checkStrings(program, *pool);

        //Add some more informations to the AST
        ast::defineStructures(program);
        ast::defineMemberFunctions(program);
        ast::defineContexts(program);
        ast::defineVariables(program);
        ast::defineFunctions(program);

        //Static analysis
        ast::checkTypes(program);

        //Check for warnings
        ast::checkForWarnings(program);

        //Check that there is a main in the program
        checkForMain();

        //Transform the AST
        ast::transformAST(program);

        //Optimize the AST
        ast::optimizeAST(program, *pool);

        //If the user asked for it, print the Abstract Syntax Tree
        if(option_defined("ast") || option_defined("ast-only")){
            ast::Printer printer;
            printer.print(program);
        }

        //If the user wants only the AST prints, it is not necessary to compile the AST
        if(option_defined("ast-only")){
            return nullptr;
        }

        std::shared_ptr<mtac::Program> mtacProgram = std::make_shared<mtac::Program>();

        //Generate Three-Address-Code language
        mtac::Compiler compiler;
        compiler.compile(program, pool, mtacProgram);

        return mtacProgram;
    }

    //If the parsing fails, the error is already printed to the console
    return nullptr;
}

void checkForMain(){
    std::shared_ptr<Function> function;
    if(symbols.exists("_F4main")){
        function = symbols.getFunction("_F4main");
    } else if (symbols.exists("_F4mainAI")){
        function = symbols.getFunction("_F4mainAI");
    } else {
        throw SemanticalException("The program does not contain a valid main function");
    }
}
<|endoftext|>