Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / astflow.cc
blob8167fefba14b2e7d2d75ff6e217abfd25ca02201
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 #include "astflow.h"
20 #include "globals.h"
21 #include "shapesexceptions.h"
22 #include "astfun.h"
24 using namespace Shapes;
25 using namespace std;
28 // Shapes::IfExpr::IfExpr( const Ast::SourceLocation & _loc, Ast::Expression * _predicate, Ast::Expression * _consequence, Ast::Expression * _alternative )
29 // : Ast::Expression( _loc ), predicate( _predicate ), consequence( _consequence ), alternative( _alternative )
30 // {
31 // predicate->setParent( this );
32 // consequence->setParent( this );
33 // alternative->setParent( this );
34 // }
36 // Shapes::IfExpr::IfExpr( const Ast::SourceLocation & _loc, Ast::Expression * _predicate, Ast::Expression * _consequence )
37 // : loc( _loc ), predicate( _predicate ), consequence( _consequence ), alternative( 0 )
38 // {
39 // predicate->setParent( this );
40 // consequence->setParent( this );
41 // }
43 // Shapes::IfExpr::~IfExpr( )
44 // {
45 // delete predicate;
46 // delete consequence;
47 // if( alternative != 0 )
48 // {
49 // delete alternative;
50 // }
51 // }
53 // RefCountPtr< const Lang::Value >
54 // Shapes::IfExpr::value( Kernel::Environment::VariableHandle dstgroup, SimplePDF::PDF_out * pdfo, Kernel::GraphicsState * metaState, Kernel::PassedEnv env ) const
55 // {
56 // RefCountPtr< const Lang::Value > predUntyped( predicate->value( dstgroup, pdfo, metaState, env ) );
57 // typedef const Lang::Boolean PredType;
58 // PredType * predVal = dynamic_cast< PredType * >( predUntyped.getPtr( ) );
59 // if( predVal == 0 )
60 // {
61 // throw Exceptions::TypeMismatch( predicate, predVal->getTypeName( ), PredType::staticTypeName( ) );
62 // }
63 // if( predVal->val )
64 // {
65 // return consequence->value( dstgroup, pdfo, metaState, env );
66 // }
67 // else if( alternative != 0 )
68 // {
69 // return alternative->value( dstgroup, pdfo, metaState, env );
70 // }
71 // else
72 // {
73 // return Shapes::THE_VOID;
74 // }
75 // }
77 Ast::LetDynamicECExpr::LetDynamicECExpr( const Ast::SourceLocation & loc, const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * expr )
78 : Ast::Expression( loc ), idLoc_( idLoc ), id_( id ), expr_( expr )
80 /* Should this expression have
81 * immediate_ = true;
82 * or not? Looking at an example like the following, taken from the amb.shape example,
83 * (escape_continuation return
84 * [( \ dummy → [list] )
85 * !!(escape_continuation amb_fail
86 * (escape_continue return [fun]))])
87 * it might be tempting to make the explicit forcing superflous by setting the immediate_ flag.
88 * However, it would then also be required that the expression inside is also immediate, which it
89 * is not (see comment in shapesparser.yy). This setting immediate_ for this expression wouldn't
90 * solve the problem, and not being immediate_ is the normal state for an expression, this should
91 * be the best choice for this expression as well.
93 * It may even be considered a good thing that the !! is needed, making it clearly visible that
94 * tricky things are going on here.
98 Ast::LetDynamicECExpr::~LetDynamicECExpr( )
100 delete id_;
101 delete expr_;
104 void
105 Ast::LetDynamicECExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
107 expr_->analyze( this, env, freeStatesDst );
110 void
111 Ast::LetDynamicECExpr::eval( Kernel::EvalState * evalState ) const
113 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, id_, evalState->cont_ ) );
114 evalState->expr_ = expr_;
117 Ast::ContinueDynamicECFunction::ContinueDynamicECFunction( const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * expr )
118 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< dynamic escape continuation >" ), true ) ), idLoc_( idLoc ), id_( id ), expr_( expr )
121 Ast::ContinueDynamicECFunction::~ContinueDynamicECFunction( )
123 delete expr_;
124 delete id_;
127 void
128 Ast::ContinueDynamicECFunction::push_exprs( Ast::ArgListExprs * args ) const
130 args->orderedExprs_->push_back( expr_ );
133 void
134 Ast::ContinueDynamicECFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
136 /* Nothing to analyze?
139 /* expr_ shall be analyzed from the calling expression.
140 * Here, it is only used to locate errors.
144 void
145 Ast::ContinueDynamicECFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
147 Kernel::ContRef cont = evalState->dyn_->getEscapeContinuation( id_, idLoc_ );
148 evalState->cont_ = cont;
149 evalState->expr_ = 0; /* If the next call fails, it may be very confusing if expr_ points to something completely irrelevant to the error. */
150 cont->takeHandle( args.getHandle( 0 ),
151 evalState );
154 Ast::GetECBacktraceExpr::GetECBacktraceExpr( const Ast::SourceLocation & idLoc, const char * id )
155 : Ast::Expression( idLoc ), id_( id )
158 Ast::GetECBacktraceExpr::~GetECBacktraceExpr( )
161 void
162 Ast::GetECBacktraceExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
164 /* Nothing to do. */
167 void
168 Ast::GetECBacktraceExpr::eval( Kernel::EvalState * evalState ) const
170 Kernel::ContRef cont = evalState->cont_;
171 cont->takeValue( Kernel::ValueRef( new Lang::Continuation( evalState->dyn_->getEscapeContinuation( id_, loc_ ) ) ),
172 evalState );