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
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
25 #include "Shapes_Kernel_decls.h"
26 #include "Shapes_Lang_decls.h"
27 #include "Shapes_Ast_decls.h"
30 #include "charptrless.h"
32 #include "sourcelocation.h"
33 #include "shapesexceptions.h"
34 #include "shapesvalue.h"
35 // #include "dynamicenvironment.h"
48 enum SpecialUnit
{ SPECIALU_DIST
= 0x0001, SPECIALU_CIRC
= 0x0002, SPECIALU_CORR
= 0x0004, SPECIALU_NOINFLEX
= 0x0008 };
57 Kernel::PassedEnv env_
;
58 Kernel::PassedDyn dyn_
;
59 Ast::Expression
* expr_
;
62 Thunk( Kernel::PassedEnv _env
, Kernel::PassedDyn _dyn
, Ast::Expression
* _expr
);
63 void force( Kernel::EvalState
* evalState
, bool onlyOnce
= true ) const;
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.
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_
;
81 Variable( const Kernel::Variable
& orig
);
83 Variable( const RefCountPtr
< const Lang::Value
> & _val
);
84 Variable( Kernel::Thunk
* _thunk
);
86 void force( Kernel::VariableHandle
& selfRef
, Kernel::EvalState
* evalState
) const;
87 RefCountPtr
< const Lang::Value
> & getUntyped( ) const;
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( ) );
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( ) );
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( ) );
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( );
144 bool isThunk( ) const;
145 Kernel::Thunk
* copyThunk( ) const;
146 void gcMark( Kernel::GCMarkedSet
& marked
);
148 void setValue( const RefCountPtr
< const Lang::Value
> & _val
) const;
149 friend class Kernel::StoreVariableContinuation
;
150 friend class Kernel::StmtStoreVariableContinuation
;
158 State( const Kernel::State
& orig
);
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;
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
184 DynamicVariableProperties( const char * 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
199 DynamicStateProperties( const char * 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;
216 LexicalKey( size_t up
, size_t pos
)
217 : up_( up
), pos_( pos
)
219 LexicalKey( const LexicalKey
& orig
)
220 : up_( orig
.up_
), pos_( orig
.pos_
)
222 LexicalKey
& oneAbove( )
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
;
233 Environment
* parent_
;
234 typedef std::map
< const char *, size_t, charPtrLess
> MapType
; /* this is not constant to simplify initialization of the global environment */
238 MapType
* dynamicKeyBindings_
;
239 std::vector
< DynamicVariableProperties
* > * dynamicKeyValues_
;
241 MapType
* stateBindings_
;
243 MapType
* dynamicStateKeyBindings_
;
244 std::vector
< DynamicStateProperties
* > * dynamicStateKeyValues_
;
246 PtrOwner_back_Access
< std::list
< const char * > > charPtrDeletionList_
;
247 bool functionBoundary_
;
251 const char * debugName_
;
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
);
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;
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
);
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;
330 class AnalysisEnvironment
333 typedef Kernel::Environment::LexicalKey LexicalKey
;
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
;
344 const MapType
* dynamicStateKeyBindings_
;
346 bool functionBoundary_
;
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
>