Update procedures
[shapes.git] / source / singlelistrange.h
blob641def48f06502e21ab967a0adcac584675496c2
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2010, 2013 Henrik Tidefelt
19 #include "containertypes.h"
20 #include "shapesexceptions.h"
21 #include "continuations.h"
22 #include "globals.h"
24 /* This file is divided in two parts. The first part contains the declarations.
26 namespace Shapes
28 namespace Lang
31 template< class T >
32 class SingleListRange : public Lang::SingleList
34 typedef typename T::ValueType elem_type;
35 elem_type begin_;
36 elem_type step_;
37 size_t count_;
38 public:
39 SingleListRange( elem_type begin, elem_type step, size_t count );
40 virtual ~SingleListRange( );
41 virtual void show( std::ostream & os ) const;
42 virtual bool isNull( ) const;
43 virtual bool isForced( ) const;
44 virtual void foldl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, const Ast::SourceLocation & callLoc ) const;
45 virtual void foldr( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, const Ast::SourceLocation & callLoc ) const;
46 virtual void foldsl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const;
47 virtual void foldsr( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const;
48 virtual void gcMark( Kernel::GCMarkedSet & marked ){ };
49 virtual Kernel::VariableHandle getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const;
51 RefCountPtr< const Lang::SingleListPair > consify( ) const;
52 void expand( std::vector< elem_type > * dst ) const;
59 /* This is the start of the second part of the file, containing the implementation of the templates declared in the first part.
61 namespace Shapes
64 template< class T >
65 Lang::SingleListRange< T >::SingleListRange( elem_type begin, elem_type step, size_t count )
66 : begin_( begin ), step_( step ), count_( count )
68 if( count_ == 0 )
69 throw Exceptions::InternalError( "Attempt to construct SingleListRange with zero count." );
72 template< class T >
73 Lang::SingleListRange< T >::~SingleListRange( )
74 { }
76 template< class T >
77 void
78 Lang::SingleListRange< T >::show( std::ostream & os ) const
80 os << "< range with " << count_ << " elements >" ;
83 template< class T >
84 bool
85 Lang::SingleListRange< T >::isNull( ) const
87 return false;
90 template< class T >
91 bool
92 Lang::SingleListRange< T >::isForced( ) const
94 return true;
97 template< class T >
98 void
99 Lang::SingleListRange< T >::foldl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, const Ast::SourceLocation & callLoc ) const
101 if( count_ > 1 ){
102 evalState->cont_ = Kernel::ContRef( new Kernel::SingleFoldLCont( RefCountPtr< const Lang::SingleList >( new Lang::SingleListRange< T >( begin_ + step_, step_, count_ - 1 ) ),
103 op, evalState->dyn_, evalState->cont_, callLoc ) );
106 op->call( op, evalState, nullResult, Helpers::newValHandle( new T( begin_ ) ), callLoc );
109 template< class T >
110 void
111 Lang::SingleListRange< T >::foldr( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, const Ast::SourceLocation & callLoc ) const
113 evalState->cont_ = Kernel::ContRef( new Kernel::SingleFoldRCont( Helpers::newValHandle( new T( begin_ ) ), op, evalState->dyn_, evalState->cont_, callLoc ) );
115 if( count_ > 1 ){
116 Lang::SingleListRange< T >( begin_ + step_, step_, count_ - 1 ).foldr( evalState, op, nullResult, callLoc );
117 }else{
118 Kernel::ContRef cont = evalState->cont_;
119 cont->takeHandle( nullResult,
120 evalState );
124 template< class T >
125 void
126 Lang::SingleListRange< T >::foldsl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const
128 if( count_ > 1 ){
129 evalState->cont_ = Kernel::ContRef( new Kernel::SingleFoldSLCont( RefCountPtr< const Lang::SingleList >( new Lang::SingleListRange< T >( begin_ + step_, step_, count_ - 1 ) ),
130 op, state, evalState->dyn_, evalState->cont_, callLoc ) );
133 op->call( op, evalState, nullResult, Helpers::newValHandle( new T( begin_ ) ), state, callLoc );
136 template< class T >
137 void
138 Lang::SingleListRange< T >::foldsr( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const
140 evalState->cont_ = Kernel::ContRef( new Kernel::SingleFoldSRCont( Helpers::newValHandle( new T( begin_ ) ), op, state, evalState->dyn_, evalState->cont_, callLoc ) );
142 if( count_ > 1 ){
143 Lang::SingleListRange< T >( begin_ + step_, step_, count_ - 1 ).foldsr( evalState, op, nullResult, state, callLoc );
144 }else{
145 Kernel::ContRef cont = evalState->cont_;
146 cont->takeHandle( nullResult,
147 evalState );
151 template< class T >
152 Kernel::VariableHandle
153 Lang::SingleListRange< T >::getField( const char * fieldId, const RefCountPtr< const Lang::Value > & selfRef ) const
155 if( strcmp( fieldId, "car" ) == 0 )
157 return Helpers::newValHandle( new T( begin_ ) );
159 if( strcmp( fieldId, "cdr" ) == 0 )
161 if( count_ == 1 ){
162 return Kernel::VariableHandle( new Kernel::Variable( Lang::THE_CONS_NULL ) );
164 return Helpers::newValHandle( new SingleListRange< T >( begin_ + step_, step_, count_ - 1 ) );
167 return SingleList::getField( fieldId, selfRef ); /* This will throw if there is no such method. */
170 template< class T >
171 RefCountPtr< const Lang::SingleListPair >
172 Lang::SingleListRange< T >::consify( ) const
174 std::vector< elem_type > mem;
175 mem.reserve( count_ );
176 size_t c = count_;
177 elem_type i = begin_;
178 while( c > 0 )
180 mem.push_back( i );
181 i += step_;
182 --c;
185 RefCountPtr< const Lang::SingleListPair > result =
186 RefCountPtr< const Lang::SingleListPair >
187 ( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( Kernel::ValueRef( new T( mem.back( ) ) ) ) ),
188 Lang::THE_CONS_NULL ) );
189 mem.pop_back( );
190 while( ! mem.empty( ) ){
191 result =
192 RefCountPtr< const Lang::SingleListPair >
193 ( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( Kernel::ValueRef( new T( mem.back( ) ) ) ) ),
194 result ) );
195 mem.pop_back( );
198 return result;
201 template< class T >
202 void
203 Lang::SingleListRange< T >::expand( std::vector< elem_type > * dst ) const
205 dst->reserve( dst->size( ) + count_ );
206 size_t c = count_;
207 elem_type i = begin_;
208 while( c > 0 )
210 dst->push_back( i );
211 i += step_;
212 --c;