Update procedures
[shapes.git] / source / ast.cc
blobfdce52749b2149281b1d48c2f8a6754daa19f464
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, 2009, 2014 Henrik Tidefelt
19 #include "ast.h"
20 #include "globals.h"
21 #include "check.h"
23 using namespace Shapes;
24 using namespace std;
27 void
28 Kernel::Continuation::takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool callingMyself ) const
30 if( val->isThunk( ) )
32 val->force( val, evalState );
34 else if( callingMyself )
36 throw Exceptions::InternalError( strrefdup( "Continuation is just calling itself..." ) );
38 else
40 this->takeValue( val->getUntyped( ), evalState, true );
44 void
45 Kernel::Continuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool callingMyself ) const
47 if( callingMyself )
49 throw Exceptions::InternalError( strrefdup( "Continuation is just calling itself..." ) );
51 this->takeHandle( Kernel::VariableHandle( new Kernel::Variable( val ) ), evalState, true );
54 const Ast::SourceLocation &
55 Kernel::Continuation::traceLoc( ) const
57 return traceLoc_;
60 void
61 Kernel::Continuation::backTrace( std::ostream & os ) const
63 typedef std::list< std::pair< const Kernel::Continuation *, RefCountPtr< const char > > > ListType;
64 ListType trace;
66 const Kernel::Continuation * tmp = this;
67 while( tmp != 0 )
69 trace.push_front( ListType::value_type( tmp, tmp->description( ) ) );
70 tmp = tmp->up( ).getPtr( );
73 ListType::const_iterator i = trace.begin( );
74 ListType::const_iterator next = i;
75 ++next;
76 for( ; i != trace.end( ); ++i, ++next )
78 if( next == trace.end( ) ||
79 not i->first->traceLoc( ).contains( next->first->traceLoc( ) ) )
81 os << " " << i->first->traceLoc( ) << "\t" << i->second << std::endl ;
86 namespace Shapes
88 namespace Kernel
91 class ForcedStructureContinuationHelper : public Kernel::Continuation
93 const ForcedStructureContinuation * cont_; // This does not have proper memory management...
94 Kernel::ContRef contMem_; // and this is not properly down-casted.
95 RefCountPtr< const Lang::Structure > structure_;
96 RefCountPtr< const Lang::SingleList > lst_;
97 public:
98 ForcedStructureContinuationHelper( const ForcedStructureContinuation * cont, Kernel::ContRef contMem, const RefCountPtr< const Lang::Structure > & structure, const RefCountPtr< const Lang::SingleList > & lst, const Ast::SourceLocation & traceLoc )
99 : Kernel::Continuation( traceLoc ), cont_( cont ), contMem_( contMem ), structure_( structure ), lst_( lst )
101 virtual ~ForcedStructureContinuationHelper( )
103 virtual void takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
105 // Getting here means that some value that _we_ don't care about has been forced.
107 RefCountPtr< const Lang::SingleList > firstUnforced = Kernel::ForcedStructureContinuation::findUnforced( lst_ );
108 if( firstUnforced->isNull( ) )
110 cont_->takeStructure( structure_, evalState );
112 else
114 typedef const Lang::SingleListPair ArgType;
115 RefCountPtr< ArgType > p = Helpers::down_cast< ArgType >( firstUnforced, "< internal error: SingleListPair contradicting isNull( )" );
116 evalState->cont_ = Kernel::ContRef( new Kernel::ForcedStructureContinuationHelper( cont_, contMem_, structure_, p->cdr_, traceLoc_ ) );
117 p->car_->force( const_cast< Kernel::VariableHandle & >( p->car_ ), evalState );
121 virtual Kernel::ContRef up( ) const
123 return contMem_;
125 virtual RefCountPtr< const char > description( ) const
127 return strrefdup( "< Forcing structure >" );
129 virtual void gcMark( Kernel::GCMarkedSet & marked )
131 const_cast< Lang::Structure * >( structure_.getPtr( ) )->gcMark( marked );
132 const_cast< Lang::SingleList * >( lst_.getPtr( ) )->gcMark( marked );
133 contMem_->gcMark( marked );
141 Kernel::ForcedStructureContinuation::ForcedStructureContinuation( const char * continuationName, const Ast::SourceLocation & traceLoc )
142 : Kernel::Continuation( traceLoc ), continuationName_( continuationName )
145 Kernel::ForcedStructureContinuation::~ForcedStructureContinuation( )
148 void
149 Kernel::ForcedStructureContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
151 typedef const Lang::Structure ArgType;
152 RefCountPtr< ArgType > structure = Helpers::down_cast< ArgType >( val, continuationName_ );
154 RefCountPtr< const Lang::SingleList > firstUnforced = findUnforced( structure->values_ );
155 if( firstUnforced->isNull( ) )
157 this->takeStructure( structure, evalState );
159 else
161 typedef const Lang::SingleListPair ArgType;
162 RefCountPtr< ArgType > p = Helpers::down_cast< ArgType >( structure->values_, "< internal error: SingleListPair contradicting isNull( )" );
163 evalState->cont_ = Kernel::ContRef( new Kernel::ForcedStructureContinuationHelper( this, evalState->cont_, structure, p->cdr_, traceLoc_ ) );
164 p->car_->force( const_cast< Kernel::VariableHandle & >( p->car_ ), evalState );
168 RefCountPtr< const Lang::SingleList >
169 Kernel::ForcedStructureContinuation::findUnforced( RefCountPtr< const Lang::SingleList > lst )
173 while( true )
175 typedef const Lang::SingleListPair ArgType;
176 RefCountPtr< ArgType > p = Helpers::try_cast_CoreArgument< ArgType >( lst );
177 if( p->car_->isThunk( ) )
179 return lst;
181 lst = p->cdr_;
184 catch( const NonLocalExit::NotThisType & ball )
186 // This means we reached the end of the list.
188 return lst;
192 Ast::Node::Node( const Ast::SourceLocation & loc )
193 : parent_( NULL ), analysisEnv_( NULL ), loc_( loc, bool( ) )
196 Ast::Node::Node( const Ast::SourceLocation & firstLoc, const Ast::SourceLocation & lastLoc )
197 : parent_( NULL ), analysisEnv_( NULL ), loc_( firstLoc, lastLoc )
200 Ast::Node::~Node( )
203 void
204 Ast::Node::analyze( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
206 setParent( parent, env );
207 this->analyze_impl( parent, env, freeStatesDst );
210 void
211 Ast::Node::setParent( Ast::Node * parent, Ast::AnalysisEnvironment * env )
213 CHECK( if( parent_ != NULL && parent != parent_ )
215 throw Exceptions::InternalError( "Ast::Node::setParent: parent_ has already been set." );
216 } );
217 parent_ = parent;
218 CHECK( if( analysisEnv_ != NULL && env != analysisEnv_ )
220 throw Exceptions::InternalError( "Ast::Node::setParent: analysisEnv_ has already been set." );
221 } );
222 analysisEnv_ = env;
224 if( parent != NULL ){
225 parent->children_.push_back( this );
226 if( parent->loc_.file_ != loc_.file_ &&
227 loc_.file_->hasPosition( ) )
229 loc_.file_->nodes( ).push_back( this );
234 void
235 Ast::Node::changeParent( Ast::Node * parent )
237 CHECK( if( parent_ == NULL )
239 throw Exceptions::InternalError( "Ast::Node::changeParent: parent_ hasn't been set." );
240 } );
242 Ast::Node * parentLastChild = parent_->children_.back( );
243 parent_->children_.pop_back( );
244 if( parentLastChild != this ){
245 throw Exceptions::InternalError( "Ast::Node::changeParent: Not the latest child of the old parent node." );
248 parent_ = parent;
249 parent_->children_.push_back( this );
251 /* Not sure if the loc_.file_->nodes( ) should also be updated here.
252 * Compare Ast::Node::analyze.
256 Ast::Node *
257 Ast::Node::parent( )
259 return parent_;
262 Ast::Node::ChildrenType &
263 Ast::Node::children( )
265 return children_;
268 Ast::AnalysisEnvironment *
269 Ast::Node::getEnv( )
271 return analysisEnv_;
274 Ast::Expression *
275 Ast::Node::findExpressionSameFile( const Ast::SourceLocation & loc )
277 if( loc_.file_ != loc.file_ )
279 return 0;
281 if( ! loc_.contains( loc ) )
283 return 0;
285 /* If we get here, we have a match, but we should try to find the deepest match...
287 typedef typeof children_ ListType;
288 for( ListType::iterator i = children_.begin( ); i != children_.end( ); ++i )
290 Ast::Expression * tmp = (*i)->findExpressionSameFile( loc );
291 if( tmp != 0 )
293 return tmp;
296 /* None of our children was a match, so then this is the deepest match.
297 * If we're not an Expression, some of our parents should be the sought expression.
298 * Returning 0 in that case will be the correct thing to do!
300 return dynamic_cast< Ast::Expression * >( this );
304 Ast::Expression::Expression( const Ast::SourceLocation & loc )
305 : Ast::Node( loc ), immediate_( false ), breakpoint_( 0 )
308 Ast::Expression::Expression( const Ast::SourceLocation & firstLoc, const Ast::SourceLocation & lastLoc )
309 : Ast::Node( firstLoc, lastLoc ), immediate_( false ), breakpoint_( 0 )
312 Ast::Expression::~Expression( )
316 const Ast::SourceLocation &
317 Ast::Node::loc( ) const
319 return loc_;
323 Ast::BindNode::BindNode( const Ast::SourceLocation & loc, const Ast::SourceLocation & idLoc, const Ast::PlacedIdentifier * id )
324 : Ast::Node( loc ), idLoc_( idLoc, bool( ) ), id_( id )
327 Ast::BindNode::BindNode( const Ast::SourceLocation & firstLoc, const Ast::SourceLocation & lastLoc, const Ast::SourceLocation & idLoc, const Ast::PlacedIdentifier * id )
328 : Ast::Node( firstLoc, lastLoc ), idLoc_( idLoc, bool( ) ), id_( id )
331 Ast::BindNode::~BindNode( )
333 if( id_ != 0 )
335 delete id_;
339 const Ast::PlacedIdentifier *
340 Ast::BindNode::id( ) const
342 return id_;
345 const Ast::SourceLocation &
346 Ast::BindNode::idLoc( ) const
348 return idLoc_;
352 Ast::Assertion::Assertion( const Ast::SourceLocation & loc )
353 : Ast::Expression( loc )
355 immediate_ = true;
358 Ast::Assertion::~Assertion( )
362 Ast::ErrorExpression::ErrorExpression( const Ast::SourceLocation & loc )
363 : Ast::Expression( loc )
366 Ast::ErrorExpression::~ErrorExpression( )
369 void
370 Ast::ErrorExpression::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
373 That this is an error should have generated the appropriate messages elsewhere.
377 void
378 Ast::ErrorExpression::eval( Kernel::EvalState * evalState ) const
380 throw Exceptions::InternalError( loc_, "An ErrorExpression was evaluated" );