Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / environment.h
blob09f794659684518423b3bd5dd1aa8368bedfdee8
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 2008 Henrik Tidefelt
19 #pragma once
21 #include <cstring>
22 //#include <climits>
23 #include <limits>
25 #include "Shapes_Kernel_decls.h"
26 #include "Shapes_Lang_decls.h"
27 #include "Shapes_Ast_decls.h"
29 #include "refcount.h"
30 #include "charptrless.h"
31 #include "ptrowner.h"
32 #include "sourcelocation.h"
33 #include "shapesexceptions.h"
34 #include "shapesvalue.h"
35 // #include "dynamicenvironment.h"
37 #include <map>
38 #include <set>
39 #include <vector>
42 namespace Shapes
45 namespace Computation
48 enum SpecialUnit { SPECIALU_DIST = 0x0001, SPECIALU_CIRC = 0x0002, SPECIALU_CORR = 0x0004, SPECIALU_NOINFLEX = 0x0008 };
52 namespace Kernel
55 class Thunk
57 Kernel::PassedEnv env_;
58 Kernel::PassedDyn dyn_;
59 Ast::Expression * expr_;
60 mutable bool forced_;
61 public:
62 Thunk( Kernel::PassedEnv _env, Kernel::PassedDyn _dyn, Ast::Expression * _expr );
63 void force( Kernel::EvalState * evalState, bool onlyOnce = true ) const;
64 Thunk * deepCopy( );
65 void gcMark( Kernel::GCMarkedSet & marked );
66 Ast::Expression * getExpr( );
67 void printEnv( std::ostream & os ) const;
70 /* Although there are several kinds of variables, I don't use c++ polymorphism for efficiency reasons.
72 class Variable
74 static const unsigned char THUNK = 0x03;
75 static const unsigned char FORCING = 0x02;
76 static const unsigned char COLD = 0x00;
77 mutable Kernel::Thunk * thunk_; /* thunk != 0 means that the thunk waits to be forced */
78 mutable RefCountPtr< const Lang::Value > val_;
79 mutable unsigned char state_;
80 private:
81 Variable( const Kernel::Variable & orig );
82 public:
83 Variable( const RefCountPtr< const Lang::Value > & _val );
84 Variable( Kernel::Thunk * _thunk );
85 ~Variable( );
86 void force( Kernel::VariableHandle & selfRef, Kernel::EvalState * evalState ) const;
87 RefCountPtr< const Lang::Value > & getUntyped( ) const;
88 template< class T >
89 RefCountPtr< T > getVal( ) const
91 if( val_ == NullPtr< const Lang::Value >( ) )
93 throw Exceptions::InternalError( strrefdup( "The value is not ready to be get without continuation." ) );
95 RefCountPtr< T > res = val_.down_cast< T >( );
96 if( res == NullPtr< T >( ) )
98 throw Exceptions::TypeMismatch( val_->getTypeName( ), T::staticTypeName( ) );
100 return res;
102 template< class T >
103 RefCountPtr< T > getVal( const char * hint ) const
105 if( val_ == NullPtr< const Lang::Value >( ) )
107 throw Exceptions::InternalError( strrefdup( "The value is not ready to be get without continuation." ) );
109 RefCountPtr< T > res = val_.down_cast< T >( );
110 if( res == NullPtr< T >( ) )
112 throw Exceptions::TypeMismatch( Ast::THE_UNKNOWN_LOCATION, hint, val_->getTypeName( ), T::staticTypeName( ) );
114 return res;
116 template< class T >
117 RefCountPtr< T > getVal( const Ast::SourceLocation & loc ) const
119 if( val_ == NullPtr< const Lang::Value >( ) )
121 throw Exceptions::InternalError( strrefdup( "The value is not ready to be get without continuation." ) );
123 RefCountPtr< T > res = val_.down_cast< T >( );
124 if( res == NullPtr< T >( ) )
126 throw Exceptions::TypeMismatch( loc, val_->getTypeName( ), T::staticTypeName( ) );
128 return res;
130 template< class T >
131 RefCountPtr< T > tryVal( ) const
133 if( val_ == NullPtr< const Lang::Value >( ) )
135 throw Exceptions::InternalError( strrefdup( "The value is not ready to be get without continuation." ) );
137 RefCountPtr< T > res = val_.down_cast< T >( );
138 if( res == NullPtr< T >( ) )
140 throw NonLocalExit::NotThisType( );
142 return res;
144 bool isThunk( ) const;
145 Kernel::Thunk * copyThunk( ) const;
146 void gcMark( Kernel::GCMarkedSet & marked );
147 private:
148 void setValue( const RefCountPtr< const Lang::Value > & _val ) const;
149 friend class Kernel::StoreVariableContinuation;
150 friend class Kernel::StmtStoreVariableContinuation;
153 class State
155 bool alive_;
157 private:
158 State( const Kernel::State & orig );
159 public:
160 State( );
161 virtual ~State( );
162 void tackOn( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc );
163 void peek( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc );
164 void freeze( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc );
166 RefCountPtr< const Lang::Function > getMutator( const char * mutatorID );
168 virtual const RefCountPtr< const ::Shapes::Lang::Class > & getClass( ) const = 0;
169 RefCountPtr< const char > getTypeName( ) const;
170 bool isAlive( ) const;
171 virtual void gcMark( Kernel::GCMarkedSet & marked ) = 0;
173 protected:
174 virtual void tackOnImpl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc ) = 0;
175 virtual void peekImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc ) = 0;
176 virtual void freezeImpl( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc ) = 0;
179 class DynamicVariableProperties
181 protected:
182 const char * name_;
183 public:
184 DynamicVariableProperties( const char * name )
185 : name_( name )
187 virtual ~DynamicVariableProperties( );
188 const char * getName( ) const { return name_; }
189 virtual Kernel::VariableHandle fetch( const Kernel::PassedDyn & dyn ) const = 0;
190 virtual bool forceValue( ) const { return true; };
191 virtual void makeBinding( Kernel::VariableHandle val, const Ast::DynamicBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const = 0;
194 class DynamicStateProperties
196 protected:
197 const char * name_;
198 public:
199 DynamicStateProperties( const char * name )
200 : name_( name )
202 virtual ~DynamicStateProperties( );
203 const char * getName( ) const { return name_; }
204 virtual Kernel::StateHandle fetch( const Kernel::PassedDyn & dyn ) const = 0;
205 virtual void makeBinding( Kernel::StateHandle val, const Ast::DynamicStateBindingExpression * bindingExpr, Kernel::EvalState * evalState ) const = 0;
208 class Environment
210 public:
211 class LexicalKey
213 public:
214 size_t up_;
215 size_t pos_;
216 LexicalKey( size_t up, size_t pos )
217 : up_( up ), pos_( pos )
218 { };
219 LexicalKey( const LexicalKey & orig )
220 : up_( orig.up_ ), pos_( orig.pos_ )
221 { };
222 LexicalKey & oneAbove( )
224 ++up_;
225 return *this;
227 bool isMissing( ) const { return pos_ == std::numeric_limits< size_t >::max( ); }
229 static LexicalKey theMissingKey;
230 typedef RefCountPtr< std::vector< VariableHandle > > ValueVector;
231 typedef RefCountPtr< std::vector< StateHandle > > StateVector;
232 private:
233 Environment * parent_;
234 typedef std::map< const char *, size_t, charPtrLess > MapType; /* this is not constant to simplify initialization of the global environment */
236 MapType * bindings_;
237 ValueVector values_;
238 MapType * dynamicKeyBindings_;
239 std::vector< DynamicVariableProperties * > * dynamicKeyValues_;
241 MapType * stateBindings_;
242 StateVector states_;
243 MapType * dynamicStateKeyBindings_;
244 std::vector< DynamicStateProperties * > * dynamicStateKeyValues_;
246 PtrOwner_back_Access< std::list< const char * > > charPtrDeletionList_;
247 bool functionBoundary_;
249 bool gcMarked_;
251 const char * debugName_;
253 public:
254 Environment( std::list< Kernel::Environment * > & garbageArea, const char * debugName );
255 Environment( std::list< Kernel::Environment * > & garbageArea, Environment * _parent, MapType * _bindings, const ValueVector & _values, MapType * _stateBindings, const StateVector & states, const char * debugName );
256 ~Environment( );
257 void setParent( Environment * _parent );
258 void setupDynamicKeyVariables( MapType * _dynamicKeyBindings );
259 void setupDynamicStateKeyVariables( MapType * _dynamicStateKeyBindings );
260 void extendVectors( );
261 void activateFunctionBoundary( );
262 Kernel::Environment * getParent( );
263 const Kernel::Environment * getParent( ) const;
264 void clear( );
265 Ast::AnalysisEnvironment * newAnalysisEnvironment( Ast::AnalysisEnvironment * parent = 0 ) const;
267 void clear_gcMarked( ) { gcMarked_ = false; }
268 bool gcMarked( ) const { return gcMarked_; }
269 void gcMark( Kernel::GCMarkedSet & marked );
271 static void collect( std::list< Kernel::Environment * > & garbageArea );
273 void define( size_t pos, const Kernel::VariableHandle & val );
274 void lookup( const LexicalKey & lexKey, Kernel::EvalState * evalState ) const;
275 void lookup( size_t pos, Kernel::EvalState * evalState ) const;
276 VariableHandle getVarHandle( const LexicalKey & lexKey );
277 VariableHandle getVarHandle( size_t pos );
279 void introduceState( size_t pos, Kernel::State * state );
280 void freeze( size_t pos, Kernel::EvalState * evalState, const Ast::SourceLocation & loc );
281 void peek( const LexicalKey & lexKey, Kernel::EvalState * evalState, const Ast::SourceLocation & loc );
282 void tackOn( const LexicalKey & lexKey, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc );
283 StateHandle getStateHandle( const LexicalKey & lexKey );
284 StateHandle getStateHandle( size_t pos );
286 void defineDynamic( const char * debugName, size_t pos, const RefCountPtr< const Lang::Function > & filter, const Kernel::VariableHandle & defaultVal );
288 const DynamicVariableProperties & lookupDynamicVariable( const LexicalKey & lexKey ) const;
289 const DynamicVariableProperties & lookupDynamicVariable( size_t pos ) const;
291 void defineDynamicState( const char * debugName, size_t pos, Kernel::EvalState * evalState, Ast::StateReference * defaultState );
293 const DynamicStateProperties & lookupDynamicState( const LexicalKey & lexKey ) const;
294 const DynamicStateProperties & lookupDynamicState( size_t pos ) const;
297 size_t size( ) const;
299 static size_t createdCount;
300 static size_t liveCount;
302 void print( std::ostream & os ) const;
303 size_t recursivePrint( std::ostream & os, std::set< MapType::key_type > * shadowed, std::set< MapType::key_type > * shadowedStates ) const;
305 bool isBaseEnvironment( ) const { return parent_ == 0; };
307 /* The following public methods shall only be unsed on the base environment immediately after it has been created.
309 void initDefineCoreFunction( Lang::CoreFunction * fun );
310 void initDefineCoreFunction( RefCountPtr< const Lang::CoreFunction > fun );
311 void initDefineHandle( const char * id, const Kernel::VariableHandle & val );
312 void initDefine( const char * id, const RefCountPtr< const Lang::Value > & val );
313 void initDefine( const char * id, Kernel::StateHandle state );
314 void initDefineClass( const RefCountPtr< const Lang::Class > & cls );
315 void initDefineDynamic( DynamicVariableProperties * dynProps );
316 void initDefineDynamic( const char * id, const RefCountPtr< const Lang::Function > & filter, const Kernel::VariableHandle & defaultVal );
317 void initDefineDynamicHandler( const char * id, const char * msg );
319 private:
320 const char * reverseMapVariable( size_t pos ) const;
321 const char * reverseMapDynamic( size_t pos ) const;
322 const char * reverseMapState( size_t pos ) const;
323 const char * reverseMapDynamicState( size_t pos ) const;
328 namespace Ast
330 class AnalysisEnvironment
332 public:
333 typedef Kernel::Environment::LexicalKey LexicalKey;
334 private:
335 AnalysisEnvironment * parent_;
336 typedef std::map< const char *, size_t, charPtrLess > MapType; /* this is not constant to simplify initialization of the global environment */
337 typedef std::vector< StateID > StateVector;
339 const MapType * bindings_;
340 const MapType * dynamicKeyBindings_;
341 const MapType * stateBindings_;
342 static StateID nextStateID;
343 StateVector states_;
344 const MapType * dynamicStateKeyBindings_;
346 bool functionBoundary_;
348 public:
349 AnalysisEnvironment( PtrOwner_back_Access< std::list< Ast::AnalysisEnvironment * > > & deleter, Ast::AnalysisEnvironment * parent, const MapType * bindings, const MapType * stateBindings );
350 ~AnalysisEnvironment( );
351 void updateBindings( ); /* Call this method when additional bindings have been introduced after the AnalysisEnvironment was initialized. */
352 Ast::AnalysisEnvironment * getParent( ) const;
353 void setupDynamicKeyVariables( const MapType * _dynamicKeyBindings );
354 void setupDynamicStateKeyVariables( const MapType * _dynamicStateKeyBindings );
355 void activateFunctionBoundary( );
357 size_t findLocalVariablePosition( const Ast::SourceLocation & loc, const char * id ) const;
358 LexicalKey findLexicalVariableKey( const Ast::SourceLocation & loc, const char * id ) const;
360 // These only differ from those above by the error messages they may generate.
361 LexicalKey findLexicalTypeKey( const Ast::SourceLocation & loc, const char * id ) const;
363 size_t findLocalStatePosition( const Ast::SourceLocation & loc, const char * id ) const;
364 LexicalKey findLexicalStateKey( const Ast::SourceLocation & loc, const char * id ) const;
365 StateID getStateID( const LexicalKey & lexKey ) const;
366 StateID getStateID( size_t pos ) const;
367 static StateID getTheAnyStateID( );
369 size_t findLocalDynamicPosition( const Ast::SourceLocation & loc, const char * id ) const;
370 LexicalKey findLexicalDynamicKey( const Ast::SourceLocation & loc, const char * id ) const;
372 size_t findLocalDynamicStatePosition( const Ast::SourceLocation & loc, const char * id ) const;
373 LexicalKey findLexicalDynamicStateKey( const Ast::SourceLocation & loc, const char * id ) const;
375 bool isBaseEnvironment( ) const { return parent_ == 0; };
379 class StateIDSet : public std::set< Ast::StateID >
380 { };