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, 2013, 2014 Henrik Tidefelt
21 #include "shapesexceptions.h"
23 #include "continuations.h"
25 using namespace Shapes
;
29 // Shapes::IfExpr::IfExpr( const Ast::SourceLocation & _loc, Ast::Expression * _predicate, Ast::Expression * _consequence, Ast::Expression * _alternative )
30 // : Ast::Expression( _loc ), predicate( _predicate ), consequence( _consequence ), alternative( _alternative )
32 // predicate->setParent( this );
33 // consequence->setParent( this );
34 // alternative->setParent( this );
37 // Shapes::IfExpr::IfExpr( const Ast::SourceLocation & _loc, Ast::Expression * _predicate, Ast::Expression * _consequence )
38 // : loc( _loc ), predicate( _predicate ), consequence( _consequence ), alternative( 0 )
40 // predicate->setParent( this );
41 // consequence->setParent( this );
44 // Shapes::IfExpr::~IfExpr( )
47 // delete consequence;
48 // if( alternative != 0 )
50 // delete alternative;
54 // RefCountPtr< const Lang::Value >
55 // Shapes::IfExpr::value( Kernel::Environment::VariableHandle dstgroup, SimplePDF::PDF_out * pdfo, Kernel::GraphicsState * metaState, Kernel::PassedEnv env ) const
57 // RefCountPtr< const Lang::Value > predUntyped( predicate->value( dstgroup, pdfo, metaState, env ) );
58 // typedef const Lang::Boolean PredType;
59 // PredType * predVal = dynamic_cast< PredType * >( predUntyped.getPtr( ) );
62 // throw Exceptions::TypeMismatch( predicate, predVal->getTypeName( ), PredType::staticTypeName( ) );
66 // return consequence->value( dstgroup, pdfo, metaState, env );
68 // else if( alternative != 0 )
70 // return alternative->value( dstgroup, pdfo, metaState, env );
74 // return Shapes::THE_VOID;
79 Ast::ForceExpr::ForceExpr( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
80 : Ast::Expression( loc
), expr_( expr
)
85 Ast::ForceExpr::~ForceExpr( )
89 Ast::ForceExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
91 expr_
->analyze( this, env
, freeStatesDst
);
95 Ast::ForceExpr::eval( Kernel::EvalState
* evalState
) const
97 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingContinuation( evalState
->cont_
, expr_
->loc( ) ) );
98 evalState
->expr_
= expr_
;
102 Ast::LetDynamicECExpr::LetDynamicECExpr( const Ast::SourceLocation
& loc
, const Ast::SourceLocation
& idLoc
, const char * id
, Ast::Expression
* expr
)
103 : Ast::Expression( loc
), idLoc_( idLoc
, bool( ) ), id_( id
), expr_( expr
)
105 /* Should this expression have
107 * or not? Looking at an example like the following, taken from the amb.blank example,
108 * (escape_continuation return
110 * !(escape_continuation amb_fail
111 * (escape_continue return [fun]))])
112 * it might be tempting to make the explicit forcing superflous by setting the immediate_ flag.
113 * However, it would then also be required that the expression inside is also immediate, which it
114 * is not (see comment in shapesparser.yy). This setting immediate_ for this expression wouldn't
115 * solve the problem, and not being immediate_ is the normal state for an expression, this should
116 * be the best choice for this expression as well.
118 * What matters is not whether this expression is immedate or not. What matters is that expr_ is
119 * forced. If expr_ is not forced, this expression may first return with a thunk, and later when
120 * that thunk is forced, this expression may return again as a consequence of the escape continuation
121 * being invoked inside the thunk. Returning more than once from an expression seems like a very
124 * It may even be considered a good thing that the explicit forcing is needed, making it clearly
125 * visible that tricky things are going on here.
129 Ast::LetDynamicECExpr::~LetDynamicECExpr( )
136 Ast::LetDynamicECExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
138 expr_
->analyze( this, env
, freeStatesDst
);
142 Ast::LetDynamicECExpr::eval( Kernel::EvalState
* evalState
) const
144 evalState
->dyn_
= Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState
->dyn_
, id_
, evalState
->cont_
) );
145 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingContinuation( evalState
->cont_
, expr_
->loc( ) ) );
146 evalState
->expr_
= expr_
;
149 Ast::ContinueDynamicECFunction::ContinueDynamicECFunction( const Ast::SourceLocation
& idLoc
, const char * id
, Ast::Expression
* expr
)
150 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< dynamic escape continuation >" ), true ) ), idLoc_( idLoc
, bool( ) ), id_( id
), expr_( expr
)
153 Ast::ContinueDynamicECFunction::~ContinueDynamicECFunction( )
160 Ast::ContinueDynamicECFunction::push_exprs( Ast::ArgListExprs
* args
) const
162 args
->orderedExprs_
->push_back( expr_
);
166 Ast::ContinueDynamicECFunction::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
168 /* Nothing to analyze?
171 /* expr_ shall be analyzed from the calling expression.
172 * Here, it is only used to locate errors.
177 Ast::ContinueDynamicECFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
179 Kernel::ContRef cont
= evalState
->dyn_
->getEscapeContinuation( id_
, idLoc_
);
180 evalState
->cont_
= cont
;
181 evalState
->expr_
= 0; /* If the next call fails, it may be very confusing if expr_ points to something completely irrelevant to the error. */
182 cont
->takeHandle( args
.getHandle( 0 ),
186 Ast::GetECBacktraceExpr::GetECBacktraceExpr( const Ast::SourceLocation
& idLoc
, const char * id
)
187 : Ast::Expression( idLoc
), id_( id
)
190 Ast::GetECBacktraceExpr::~GetECBacktraceExpr( )
194 Ast::GetECBacktraceExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
200 Ast::GetECBacktraceExpr::eval( Kernel::EvalState
* evalState
) const
202 Kernel::ContRef cont
= evalState
->cont_
;
203 cont
->takeValue( Kernel::ValueRef( new Lang::Continuation( evalState
->dyn_
->getEscapeContinuation( id_
, loc_
) ) ),