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, 2009 Henrik Tidefelt
23 using namespace Shapes
;
24 using namespace SimplePDF
;
27 nonInteractiveEvaluation( Kernel::WarmCatalog::ShipoutList
& documents
, SplitMode splitMode
,
28 bool evalTrace
, bool evalBackTrace
, bool cleanupMemory
,
29 RefCountPtr
< std::ifstream
> & labelDBFile
, const std::string
& labelDBName
)
34 initCore( labelDBFile
, labelDBName
);
36 RefCountPtr
< const Kernel::GraphicsState
> graphicsState( new Kernel::GraphicsState( true ) );
37 Kernel::PassedDyn
baseDyn( new Kernel::DynamicEnvironment( graphicsState
) );
40 Kernel::ValueRef resultUntyped
= NullPtr
< const Lang::Value
>( );
41 Kernel::EvalState
evalState( Ast::theProgram
,
42 Kernel::theGlobalEnvironment
,
44 Kernel::ContRef( new Kernel::StoreValueContinuation( & resultUntyped
,
45 Kernel::ContRef( new Kernel::ExitContinuation( & done
, Ast::theProgram
->loc( ) ) ),
46 Ast::theProgram
->loc( ) ) ) );
57 evalState
.cont_
->backTrace( std::cerr
);
58 std::cerr
<< "--- Bottom of trace ---" << std::endl
;
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
)
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_
),
83 catch( const Exceptions::UncaughtError
& uncaught
)
85 const Lang::Exception
& ball
= *uncaught
.ball( );
87 if( Interaction::debugBacktrace
)
89 ball
.cont( )->backTrace( std::cerr
);
92 if( ! ball
.loc( ).isUnknown( ) )
94 std::cerr
<< ball
.loc( ) << Exceptions::Exception::locsep
;
98 std::cerr
<< ball
.cont( )->traceLoc( ) << Exceptions::Exception::locsep
;
100 ball
.show( std::cerr
);
101 abortProcedure( ball
.exitCode( ) );
103 catch( const Exceptions::Exception
& ball
)
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
);
133 Kernel::theGlobalEnvironment
->clear( );
136 delete Kernel::theGlobalEnvironment
;
137 delete Ast::theProgram
;
139 catch( const Exceptions::StaticInconsistency
& ball
)
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( );
150 if( Interaction::debugBacktrace
)
152 ball
.cont( )->backTrace( std::cerr
);
155 if( ! ball
.loc( ).isUnknown( ) )
157 std::cerr
<< ball
.loc( ) << Exceptions::Exception::locsep
;
161 std::cerr
<< ball
.cont( )->traceLoc( ) << Exceptions::Exception::locsep
;
163 ball
.show( std::cerr
);
164 abortProcedure( ball
.exitCode( ) );
166 catch( const Exceptions::Exception
& ball
)
169 ball
.display( std::cerr
);
170 abortProcedure( ball
.exitCode( ) );
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
);
197 catalog
->tackOnPage( baseDyn
, finalPicture
, Ast::THE_UNKNOWN_LOCATION
);
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
);
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( ) )
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
);
247 std::cerr
<< err
->loc( ) << ": " ;
248 err
->display( std::cerr
);
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
);