Update suitable examples and tests to use blank mode
[shapes.git] / source / eval_non_interactive.cc
blob3148ff1f7b53614c94644908b261c29dd4bbc2b2
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 Henrik Tidefelt
19 #include "main.h"
21 #include <typeinfo>
23 using namespace Shapes;
24 using namespace SimplePDF;
26 void
27 nonInteractiveEvaluation( Kernel::WarmCatalog::ShipoutList & documents, SplitMode splitMode,
28 bool evalTrace, bool evalBackTrace, bool cleanupMemory,
29 RefCountPtr< std::ifstream > & labelDBFile, const std::string & labelDBName )
31 try
33 shapesparse( );
34 initCore( labelDBFile, labelDBName );
36 RefCountPtr< const Kernel::GraphicsState > graphicsState( new Kernel::GraphicsState( true ) );
37 Kernel::PassedDyn baseDyn( new Kernel::DynamicEnvironment( graphicsState ) );
39 bool done = false;
40 Kernel::ValueRef resultUntyped = NullPtr< const Lang::Value >( );
41 Kernel::EvalState evalState( Ast::theProgram,
42 Kernel::theGlobalEnvironment,
43 baseDyn,
44 Kernel::ContRef( new Kernel::StoreValueContinuation( & resultUntyped,
45 Kernel::ContRef( new Kernel::ExitContinuation( & done, Ast::theProgram->loc( ) ) ),
46 Ast::theProgram->loc( ) ) ) );
48 restart:
49 try
51 while( ! done )
53 if( evalTrace )
55 if( evalBackTrace )
57 evalState.cont_->backTrace( std::cerr );
58 std::cerr << "--- Bottom of trace ---" << std::endl ;
60 else
62 std::cerr << "Eval trace: Cont: " << evalState.cont_->traceLoc( ) << " Expr: " << evalState.expr_->loc( ) << std::endl ;
65 Ast::Expression * expr = evalState.expr_;
66 expr->eval( & evalState );
69 catch( const Exceptions::StaticInconsistency & ball )
71 std::cout.flush( );
72 std::cerr << ball.loc( ) << ": " ;
73 ball.display( std::cerr );
74 abortProcedure( ball.exitCode( ) );
76 catch( const Exceptions::CatchableError & ball )
78 Kernel::ContRef cont = evalState.dyn_->getEscapeContinuation( Lang::CONTINUATION_ID_ERROR, ball.getLoc( ) );
79 cont->takeValue( ball.clone( evalState.cont_ ),
80 & evalState );
81 goto restart;
83 catch( const Exceptions::UncaughtError & uncaught )
85 const Lang::Exception & ball = *uncaught.ball( );
86 std::cout.flush( );
87 if( Interaction::debugBacktrace )
89 ball.cont( )->backTrace( std::cerr );
92 if( ! ball.loc( ).isUnknown( ) )
94 std::cerr << ball.loc( ) << Exceptions::Exception::locsep ;
96 else
98 std::cerr << ball.cont( )->traceLoc( ) << Exceptions::Exception::locsep ;
100 ball.show( std::cerr );
101 abortProcedure( ball.exitCode( ) );
103 catch( const Exceptions::Exception & ball )
105 std::cout.flush( );
106 if( Interaction::debugBacktrace )
108 evalState.cont_->backTrace( std::cerr );
113 const Exceptions::RuntimeError & rerr = dynamic_cast< const Exceptions::RuntimeError & >( ball );
114 if( rerr.getLoc( ).isUnknown( ) )
116 throw std::bad_cast( ); /* It's not a bad cast, but the cast value is just as little useful as a bad cast. */
118 std::cerr << rerr.getLoc( ) << Exceptions::Exception::locsep ;
120 catch( std::bad_cast & bad_cast_ball )
122 std::cerr << evalState.cont_->traceLoc( ) << Exceptions::Exception::locsep ;
124 ball.display( std::cerr );
125 abortProcedure( ball.exitCode( ) );
128 if( ! Interaction::blankMode )
129 shipout( resultUntyped, baseDyn, & documents, splitMode );
131 if( cleanupMemory )
133 Kernel::theGlobalEnvironment->clear( );
136 delete Kernel::theGlobalEnvironment;
137 delete Ast::theProgram;
139 catch( const Exceptions::StaticInconsistency & ball )
141 std::cout.flush( );
142 std::cerr << ball.loc( ) << ": " ;
143 ball.display( std::cerr );
144 abortProcedure( ball.exitCode( ) );
146 catch( const Exceptions::UncaughtError & uncaught )
148 const Lang::Exception & ball = *uncaught.ball( );
149 std::cout.flush( );
150 if( Interaction::debugBacktrace )
152 ball.cont( )->backTrace( std::cerr );
155 if( ! ball.loc( ).isUnknown( ) )
157 std::cerr << ball.loc( ) << Exceptions::Exception::locsep ;
159 else
161 std::cerr << ball.cont( )->traceLoc( ) << Exceptions::Exception::locsep ;
163 ball.show( std::cerr );
164 abortProcedure( ball.exitCode( ) );
166 catch( const Exceptions::Exception & ball )
168 std::cout.flush( );
169 ball.display( std::cerr );
170 abortProcedure( ball.exitCode( ) );
175 void
176 shipout( Kernel::ValueRef resultUntyped, Kernel::PassedDyn baseDyn, Kernel::WarmCatalog::ShipoutList * documents, SplitMode splitMode )
178 Kernel::WarmCatalog * catalog = dynamic_cast< Kernel::WarmCatalog * >( Kernel::theGlobalEnvironment->getStateHandle( Ast::theGlobalAnalysisEnvironment->findLocalStatePosition( Ast::THE_UNKNOWN_LOCATION, Lang::CATALOG_ID ) ) );
179 RefCountPtr< const Lang::Group2D > finalPicture = dynamic_cast< Kernel::WarmGroup2D * >( Kernel::theGlobalEnvironment->getStateHandle( Ast::theGlobalAnalysisEnvironment->findLocalStatePosition( Ast::THE_UNKNOWN_LOCATION, Lang::CANVAS_ID ) ) )->getPile( );
180 RefCountPtr< const Lang::Drawable2D > result = Helpers::down_cast< const Lang::Drawable2D >( resultUntyped, "", true ); /* True means "void is null". */
181 if( result != NullPtr< const Lang::Drawable2D >( ) && result == Lang::THE_NULL2D )
183 throw Exceptions::MiscellaneousRequirement( "Program evaluated to a null-value." );
185 if( result == NullPtr< const Lang::Drawable2D >( ) && catalog->isEmpty( ) && finalPicture->isNull( ) )
187 throw Exceptions::EmptyFinalPicture( );
189 if( catalog->isEmpty( ) )
191 if( result != NullPtr< const Lang::Drawable2D >( ) )
193 catalog->tackOnPage( baseDyn, result, Ast::THE_UNKNOWN_LOCATION );
195 else
197 catalog->tackOnPage( baseDyn, finalPicture, Ast::THE_UNKNOWN_LOCATION );
200 else
202 if( result != NullPtr< const Lang::Drawable2D >( ) )
204 throw Exceptions::MiscellaneousRequirement( "Ambiguous program output; #catalog was non-empty, and program returned with a value." );
208 catalog->shipout( splitMode != SPLIT_NO, documents );
212 void
213 initCore( RefCountPtr< std::ifstream > & labelDBFile, const std::string & labelDBName )
215 Kernel::theGlobalEnvironment = new Kernel::Environment( Kernel::theEnvironmentList, "Global" );
216 Kernel::registerGlobals( Kernel::theGlobalEnvironment );
217 Kernel::registerDynamic( Kernel::theGlobalEnvironment );
218 Kernel::registerHot( Kernel::theGlobalEnvironment );
219 Kernel::registerClasses( Kernel::theGlobalEnvironment );
220 Kernel::registerCore_elem( Kernel::theGlobalEnvironment );
221 Kernel::registerCore_point( Kernel::theGlobalEnvironment );
222 Kernel::registerCore_path( Kernel::theGlobalEnvironment );
223 Kernel::registerCore_draw( Kernel::theGlobalEnvironment );
224 Kernel::registerCore_construct( Kernel::theGlobalEnvironment );
225 Kernel::registerCore_font( Kernel::theGlobalEnvironment );
226 Kernel::registerCore_misc( Kernel::theGlobalEnvironment );
227 Kernel::registerCore_sort( Kernel::theGlobalEnvironment );
228 Kernel::registerCore_state( Kernel::theGlobalEnvironment );
229 Kernel::registerCore_annotation( Kernel::theGlobalEnvironment );
230 Kernel::registerCore_decomp( Kernel::theGlobalEnvironment );
231 Ast::theGlobalAnalysisEnvironment = Kernel::theGlobalEnvironment->newAnalysisEnvironment( );
233 Ast::StateIDSet freeStates;
234 Ast::theProgram->analyze( 0, Ast::theGlobalAnalysisEnvironment, & freeStates );
236 if( ! Ast::theAnalysisErrorsList.empty( ) )
238 std::cout.flush( );
239 typedef typeof Ast::theAnalysisErrorsList ListType;
240 for( ListType::const_iterator i = Ast::theAnalysisErrorsList.begin( ); i != Ast::theAnalysisErrorsList.end( ); ++i )
243 typedef const Exceptions::StaticInconsistency ErrorType;
244 ErrorType * err = dynamic_cast< ErrorType * >( *i );
245 if( err != 0 )
247 std::cerr << err->loc( ) << ": " ;
248 err->display( std::cerr );
249 continue;
252 std::cerr << "(Bad exception type)" << ": " ;
253 (*i)->display( std::cerr );
255 abortProcedure( Interaction::EXIT_USER_ERROR );
258 // The display unit is looked up after the input is scanned, so the user may use her own units
259 Interaction::displayUnitFactor = Ast::theShapesScanner.lookupLengthUnitFactor( Interaction::displayUnitName );
260 if( Interaction::displayUnitFactor <= 0 )
262 std::cerr << "Invalid display unit: " << Interaction::displayUnitName << std::endl ;
263 abortProcedure( Interaction::EXIT_INVOCATION_ERROR );
265 Interaction::displayUnit = Concrete::Length( 1 / Interaction::displayUnitFactor );
266 labelDBFile = performIterativeStartup( labelDBName );