Skip to content

Commit 51977e6

Browse files
author
Florian Thake
committed
fixed header only compile mode for Engine and CoroutineScriptEngine ...
... for the case the corresponding headers were included in more than one .cpp file. - set version to 0.15.1
1 parent 80f62e9 commit 51977e6

File tree

5 files changed

+83
-35
lines changed

5 files changed

+83
-35
lines changed

include/teascript/CoroutineScriptEngine.hpp

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ using ProgramPtr = std::shared_ptr<Program>;
2727
} // namespace StackVM
2828

2929

30+
// header only and non-header only compile mode handling.
31+
#if !defined(TEASCRIPT_DISABLE_HEADER_ONLY)
32+
# define TEASCRIPT_DISABLE_HEADER_ONLY 0
33+
#endif
34+
// depending on the mode we need to declare member functions inline or not for resolve linker issues.
35+
#if !defined( TEASCRIPT_COMPILE_MODE_INLINE )
36+
# if TEASCRIPT_DISABLE_HEADER_ONLY
37+
# define TEASCRIPT_COMPILE_MODE_INLINE
38+
# else
39+
# define TEASCRIPT_COMPILE_MODE_INLINE inline
40+
# endif
41+
#endif
42+
43+
44+
3045
/// The class CoroutineScriptEngine can be used for execute TeaScript code similar
3146
/// like coroutines. The scripts can be suspended (by themselves, by constraints or
3247
/// by request) and they are able to yield values at any point and continue execution
@@ -55,34 +70,34 @@ class CoroutineScriptEngine
5570

5671
public:
5772
/// Default constructor will bootstrap the full Core Library into the context. No coroutine loaded yet.
58-
CoroutineScriptEngine();
73+
TEASCRIPT_COMPILE_MODE_INLINE CoroutineScriptEngine();
5974
/// Will use the given context as the context for the coroutine (see class teascript::ContextFactory for a handy helper.)
6075
/// \note any prior existing local scope will be removed from the context.
61-
explicit CoroutineScriptEngine( Context &&rContext );
76+
TEASCRIPT_COMPILE_MODE_INLINE explicit CoroutineScriptEngine( Context &&rContext );
6277
/// Will prepare to execute the given program as coroutine and bootstrap the full Core Library into the context.
63-
explicit CoroutineScriptEngine( StackVM::ProgramPtr const &coroutine );
78+
TEASCRIPT_COMPILE_MODE_INLINE explicit CoroutineScriptEngine( StackVM::ProgramPtr const &coroutine );
6479
/// Will prepare to execute the given program as coroutine and use the given context as the context for the coroutine.
6580
/// \note any prior existing local scope will be removed from the context.
66-
CoroutineScriptEngine( StackVM::ProgramPtr const &coroutine, Context &&rContext );
81+
TEASCRIPT_COMPILE_MODE_INLINE CoroutineScriptEngine( StackVM::ProgramPtr const &coroutine, Context &&rContext );
6782

6883
/// builds a coroutine program from given source.
6984
/// \see also teascript::StackVM::Program::Load()
7085
/// \see also class teascript::Engine for more possibilities to compile a program.
71-
static StackVM::ProgramPtr Build( Content const &rContent, eOptimize const opt_level = eOptimize::O0, std::string const &name = "_USER_CORO_" );
86+
TEASCRIPT_COMPILE_MODE_INLINE static StackVM::ProgramPtr Build( Content const &rContent, eOptimize const opt_level = eOptimize::O0, std::string const &name = "_USER_CORO_" );
7287

7388
/// Will prepare to execute the given program as coroutine, the old coroutine will be removed.
7489
/// The current coroutine must not be running actually!
75-
void ChangeCoroutine( StackVM::ProgramPtr const &coroutine );
90+
TEASCRIPT_COMPILE_MODE_INLINE void ChangeCoroutine( StackVM::ProgramPtr const &coroutine );
7691

7792
/// Resets state and prepares actual set coroutine for execution. same as ChangeCoroutine( old_coroutine ).
78-
void Reset();
93+
TEASCRIPT_COMPILE_MODE_INLINE void Reset();
7994

8095
/// \returns whether the coroutine is neither running, nor yet finished and no error occurred, so that in can be continued (e.g., for yielding more values)
81-
bool CanBeContinued() const;
96+
TEASCRIPT_COMPILE_MODE_INLINE bool CanBeContinued() const;
8297

8398
/// \returns whether the coroutine is completely finished (no more values can be yielded / no instruction left to be executed).
8499
/// \note depending on the coroutine code this state might be never reached!
85-
bool IsFinished() const;
100+
TEASCRIPT_COMPILE_MODE_INLINE bool IsFinished() const;
86101

87102
/// \returns whether the actual set coroutine is running, i.e. a thread is inside Run()/operator()/RunFor() or ChangeCoroutine().
88103
inline
@@ -94,18 +109,18 @@ class CoroutineScriptEngine
94109

95110
/// \returns whether on this platform it is possible to send a suspend request to a running coroutine from another thread.
96111
/// \note: see class teascript::StackVM::Machine for details.
97-
bool IsSuspendRequestPossible() const;
112+
TEASCRIPT_COMPILE_MODE_INLINE bool IsSuspendRequestPossible() const;
98113

99114
/// sends a suspend request to the (running) coroutine from (most likely) a different thread.
100115
/// \returns true if it make sense to wait for coroutine is suspeneded, false if a request could not be sent (error).
101116
/// \see class teascript::StackVM::Machine::Suspend() for details.
102-
bool Suspend() const;
117+
TEASCRIPT_COMPILE_MODE_INLINE bool Suspend() const;
103118

104119
/// Runs the coroutine until yield, suspend, finished or error occurred.
105120
/// \returns the yielded value if any, or NaV (Not A Value).
106121
/// \throws exception::runtime_error or a derived class, or (rarely) only a std::exception based exception.
107122
/// \note A running coroutine can be suspended from another thread via Suspend() if IsSuspendRequestPossible() returns true.
108-
ValueObject Run();
123+
TEASCRIPT_COMPILE_MODE_INLINE ValueObject Run();
109124

110125
/// Runs the coroutine until yield, suspend, finished or error occurred.
111126
/// \returns the yielded value if any, or NaV (Not A Value).
@@ -120,12 +135,12 @@ class CoroutineScriptEngine
120135
/// \returns the yielded value if any, or NaV (Not A Value).
121136
/// \throws exception::runtime_error or a derived class, or (rarely) only a std::exception based exception.
122137
/// \note A running coroutine can be suspended from another thread via Suspend() if IsSuspendRequestPossible() returns true.
123-
ValueObject RunFor( StackVM::Constraints const &constraint );
138+
TEASCRIPT_COMPILE_MODE_INLINE ValueObject RunFor( StackVM::Constraints const &constraint );
124139

125140
/// Adds given ValueObjects as a tuple "args[idx]". Additionally adding an "argN" variable indicating the parameter amount. The coroutine must be suspended.
126141
/// The ValueObjects for the parameters must be in shared state (created with ValueShared or a MakeShared() call issued).
127142
/// \note this function is _not_ thread safe. Only one thread is allowed to call this function the _same_ time and the coroutine must not be running!
128-
void SetInputParameters( std::vector<ValueObject> const &params );
143+
TEASCRIPT_COMPILE_MODE_INLINE void SetInputParameters( std::vector<ValueObject> const &params );
129144

130145
/// Adds given parameters as ValueObjects as a tuple "args[idx]". Additionally adding an "argN" variable indicating the parameter amount. The coroutine must be suspended.
131146
/// \note this function is _not_ thread safe. Only one thread is allowed to call this function the _same_ time and the coroutine must not be running!
@@ -140,10 +155,6 @@ class CoroutineScriptEngine
140155
} // namespace teascript
141156

142157

143-
#if !defined(TEASCRIPT_DISABLE_HEADER_ONLY)
144-
# define TEASCRIPT_DISABLE_HEADER_ONLY 0
145-
#endif
146-
147158
// check for broken header only / not header only configurations.
148159
#if (0==TEASCRIPT_DISABLE_HEADER_ONLY) && defined(TEASCRIPT_INCLUDE_DEFINITIONS)
149160
# error header only config broken, TEASCRIPT_DISABLE_HEADER_ONLY is 0 but TEASCRIPT_INCLUDE_DEFINITIONS is defined.

include/teascript/CoroutineScriptEngine_Impl.ipp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,29 @@
2323

2424
namespace teascript {
2525

26+
TEASCRIPT_COMPILE_MODE_INLINE
2627
CoroutineScriptEngine::CoroutineScriptEngine()
2728
: mMachine( std::make_shared<teascript::StackVM::Machine<true>>() )
2829
{
2930
CoreLibrary().Bootstrap( mContext, config::full() ); // we always use the complete core library by default.
3031
}
3132

33+
TEASCRIPT_COMPILE_MODE_INLINE
3234
CoroutineScriptEngine::CoroutineScriptEngine( Context &&rContext )
3335
: mContext( std::move( rContext ) )
3436
, mMachine( std::make_shared<teascript::StackVM::Machine<true>>() )
3537
{
3638
}
3739

40+
TEASCRIPT_COMPILE_MODE_INLINE
3841
CoroutineScriptEngine::CoroutineScriptEngine( StackVM::ProgramPtr const &coroutine )
3942
: mMachine( std::make_shared<teascript::StackVM::Machine<true>>() )
4043
{
4144
CoreLibrary().Bootstrap( mContext, config::full() ); // we always use the complete core library by default.
4245
ChangeCoroutine( coroutine );
4346
}
4447

48+
TEASCRIPT_COMPILE_MODE_INLINE
4549
CoroutineScriptEngine::CoroutineScriptEngine( StackVM::ProgramPtr const &coroutine, Context &&rContext )
4650
: mContext( std::move( rContext ) )
4751
, mMachine( std::make_shared<teascript::StackVM::Machine<true>>() )
@@ -50,6 +54,7 @@ CoroutineScriptEngine::CoroutineScriptEngine( StackVM::ProgramPtr const &corouti
5054
}
5155

5256
/*static*/
57+
TEASCRIPT_COMPILE_MODE_INLINE
5358
StackVM::ProgramPtr CoroutineScriptEngine::Build( Content const &rContent, eOptimize const opt_level, std::string const &name )
5459
{
5560
Parser p;
@@ -58,6 +63,7 @@ StackVM::ProgramPtr CoroutineScriptEngine::Build( Content const &rContent, eOpti
5863
return c.Compile( p.Parse( rContent, name ), opt_level );
5964
}
6065

66+
TEASCRIPT_COMPILE_MODE_INLINE
6167
void CoroutineScriptEngine::ChangeCoroutine( StackVM::ProgramPtr const &coroutine )
6268
{
6369
bool expected = false;
@@ -78,41 +84,48 @@ void CoroutineScriptEngine::ChangeCoroutine( StackVM::ProgramPtr const &coroutin
7884
mMachine->ThrowPossibleErrorException();
7985
}
8086

87+
TEASCRIPT_COMPILE_MODE_INLINE
8188
void CoroutineScriptEngine::Reset()
8289
{
8390
auto current = mMachine->GetMainProgram(); // copy is intended!
8491
ChangeCoroutine( current );
8592
}
8693

94+
TEASCRIPT_COMPILE_MODE_INLINE
8795
bool CoroutineScriptEngine::CanBeContinued() const
8896
{
8997
// NOTE: the potential race between && is ok, the state may change after the call anyway.
9098
// The target is to protect RunFor + ChangeCoroutine!
9199
return not IsRunning() && mMachine->IsSuspended();
92100
}
93101

102+
TEASCRIPT_COMPILE_MODE_INLINE
94103
bool CoroutineScriptEngine::IsFinished() const
95104
{
96105
// NOTE: the potential race between && is ok, the state may change after the call anyway.
97106
// The target is to protect RunFor + ChangeCoroutine!
98107
return not IsRunning() && mMachine->IsFinished();
99108
}
100109

110+
TEASCRIPT_COMPILE_MODE_INLINE
101111
bool CoroutineScriptEngine::IsSuspendRequestPossible() const
102112
{
103113
return mMachine->SuspendRequestPossible();
104114
}
105115

116+
TEASCRIPT_COMPILE_MODE_INLINE
106117
bool CoroutineScriptEngine::Suspend() const
107118
{
108119
return mMachine->Suspend();
109120
}
110121

122+
TEASCRIPT_COMPILE_MODE_INLINE
111123
ValueObject CoroutineScriptEngine::Run()
112124
{
113125
return RunFor( StackVM::Constraints::None() );
114126
}
115127

128+
TEASCRIPT_COMPILE_MODE_INLINE
116129
ValueObject CoroutineScriptEngine::RunFor( StackVM::Constraints const &constraint )
117130
{
118131
bool expected = false;
@@ -130,6 +143,7 @@ ValueObject CoroutineScriptEngine::RunFor( StackVM::Constraints const &constrain
130143
return {};
131144
}
132145

146+
TEASCRIPT_COMPILE_MODE_INLINE
133147
void CoroutineScriptEngine::SetInputParameters( std::vector<ValueObject> const &params )
134148
{
135149
// NOTE: This checks don't make the call threadsafe, it is just to potentially detect wrong usage.

include/teascript/Engine.hpp

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@ using ProgramPtr = std::shared_ptr<Program>;
4747
} // namespace StackVM
4848

4949

50+
// header only and non-header only compile mode handling.
51+
#if !defined(TEASCRIPT_DISABLE_HEADER_ONLY)
52+
# define TEASCRIPT_DISABLE_HEADER_ONLY 0
53+
#endif
54+
// depending on the mode we need to declare member functions inline or not for resolve linker issues.
55+
#if !defined( TEASCRIPT_COMPILE_MODE_INLINE )
56+
# if TEASCRIPT_DISABLE_HEADER_ONLY
57+
# define TEASCRIPT_COMPILE_MODE_INLINE
58+
# else
59+
# define TEASCRIPT_COMPILE_MODE_INLINE inline
60+
# endif
61+
#endif
62+
63+
5064
/// The TeaScript standard engine.
5165
/// This is a single-thread engine. You can use an instance of this class in
5266
/// one thread. If you use the same(!) instance in more than one thread,
@@ -79,18 +93,18 @@ class Engine : public EngineBase
7993
/// If \param bootstrap is true it will bootstrap the Core Library with specified config from \param config.
8094
/// \note This constructor is useful for derived classes which don't want the default bootstrapping, e.g.
8195
/// using another CoreLibrary or a derived class. Don't forget to override ResetState() in such a case.
82-
Engine( bool const bootstrap, config::eConfig const config, eMode const mode = eMode::Compile, eOptimize const opt_level = eOptimize::O0 );
96+
TEASCRIPT_COMPILE_MODE_INLINE Engine( bool const bootstrap, config::eConfig const config, eMode const mode = eMode::Compile, eOptimize const opt_level = eOptimize::O0 );
8397

8498
/// Adds the given ValuObject \param val to the current scope as name \param rName.
8599
/// \throw May throw exception::redefinition_of_variable or a different exception based on exception::eval_eror/runtime_error.
86-
void AddValueObject( std::string const &rName, ValueObject val ) override;
100+
TEASCRIPT_COMPILE_MODE_INLINE void AddValueObject( std::string const &rName, ValueObject val ) override;
87101

88102
/// Evaluates/Executes the given content as TeaScript.
89103
/// Depending on the mode the content will be either parsed and evaluated or parsed, compiled and executed.
90104
/// \param rContent The content to be evaluated.
91105
/// \param rName An arbitrary user defined name for referring to the content.
92106
/// \returns the result as ValueObject.
93-
ValueObject EvaluateContent( Content const &rContent, std::string const &rName ) override;
107+
TEASCRIPT_COMPILE_MODE_INLINE ValueObject EvaluateContent( Content const &rContent, std::string const &rName ) override;
94108

95109
public:
96110
/// The default Constructor constructs the engine with everything loaded and bootstrapped.
@@ -99,10 +113,10 @@ class Engine : public EngineBase
99113
}
100114

101115
/// Constructs the engine with the specified config. Use the helper funcions from config namespace to simplify the configuration.
102-
explicit Engine( config::eConfig const config, eMode const mode = eMode::Compile );
116+
TEASCRIPT_COMPILE_MODE_INLINE explicit Engine( config::eConfig const config, eMode const mode = eMode::Compile );
103117

104118
/// Convenience constructor for specifying the loading level and the opt-out feature mask separately.
105-
Engine( config::eConfig const level, unsigned int const opt_out )
119+
TEASCRIPT_COMPILE_MODE_INLINE Engine( config::eConfig const level, unsigned int const opt_out )
106120
: Engine( config::build( level, opt_out ) )
107121
{
108122
}
@@ -115,20 +129,20 @@ class Engine : public EngineBase
115129

116130
/// Resets the state of the context (+ parser and machine). Will do a fresh bootstrap of the CoreLibrary with the current saved configuration.
117131
/// \note This should be done usually prior each execution of a script to not interfer with old variables/modified environment.
118-
void ResetState() override;
132+
TEASCRIPT_COMPILE_MODE_INLINE void ResetState() override;
119133

120134
/// enables or disables debug mode (default: off). This will also set the optimization level to Debug.
121135
/// \note enabled debug mode will preserve the source code for the ASTNodes. Thus, the parsing will take slightly longer and the ASTNodes use more memory.
122-
void SetDebugMode( bool const enabled ) noexcept;
136+
TEASCRIPT_COMPILE_MODE_INLINE void SetDebugMode( bool const enabled ) noexcept;
123137

124138
/// Returns the stored variable with name \param rName starting search in the current scope up to toplevel scope.
125139
/// \throw May throw exception::unknown_identifier or a different excection based on exception::eval_eror/runtime_error.
126-
ValueObject GetVar( std::string const &rName ) const override;
140+
TEASCRIPT_COMPILE_MODE_INLINE ValueObject GetVar( std::string const &rName ) const override;
127141

128142
/// Invokes the TeaScript function with name rName with parameters in rParams. (see EngineBase for the nice convenience function CallFuncEx!)
129143
/// \returns the ValueObject result from the called fuction.
130144
/// \throw May throw exception::unknown_identifier or a different excection based on exception::eval_eror/runtime_error.
131-
ValueObject CallFunc( std::string const &rName, std::vector<ValueObject> &rParams ) override;
145+
TEASCRIPT_COMPILE_MODE_INLINE ValueObject CallFunc( std::string const &rName, std::vector<ValueObject> &rParams ) override;
132146

133147

134148
/// Registers the given callback function \param rCallback as name \param rName in the current scope.
@@ -162,7 +176,7 @@ class Engine : public EngineBase
162176
/// \note The legacy form of the arg variables "arg1", "arg2", ... is available via the compile setting TEASCRIPT_ENGINE_USE_LEGACY_ARGS=1
163177
/// \note \see EngineBase::ExecuteScript for further important details.
164178
/// \throw May throw exception::load_file_error or any exception based on exception::parsing_error/compile_error/eval_error/runtime_error/bad_value_cast.
165-
ValueObject ExecuteScript( std::filesystem::path const &path, std::vector<ValueObject> const &args );
179+
TEASCRIPT_COMPILE_MODE_INLINE ValueObject ExecuteScript( std::filesystem::path const &path, std::vector<ValueObject> const &args );
166180

167181

168182
/// Executes the given \param program in the TeaStackVM with the (optional) script parameters \param args.
@@ -172,16 +186,16 @@ class Engine : public EngineBase
172186
/// \note The legacy form of the arg variables "arg1", "arg2", ... is available via the compile setting TEASCRIPT_ENGINE_USE_LEGACY_ARGS=1
173187
/// \note \see EngineBase::ExecuteScript for further important details.
174188
/// \throw May throw an exception based on exception::eval_error/runtime_error/bad_value_cast.
175-
ValueObject ExecuteProgram( StackVM::ProgramPtr const &program, std::vector<ValueObject> const &args = {} );
189+
TEASCRIPT_COMPILE_MODE_INLINE ValueObject ExecuteProgram( StackVM::ProgramPtr const &program, std::vector<ValueObject> const &args = {} );
176190

177191

178192
/// Compiles the given \param rContent to a binary program for the TeaStackVM with the optimization level \param opt_level.
179193
/// \throw May throw an exception based on exception::compile_error/eval_error/runtime_error.
180-
StackVM::ProgramPtr CompileContent( Content const &rContent, eOptimize const opt_level = eOptimize::O0, std::string const &rName = "_USER_CODE_" );
194+
TEASCRIPT_COMPILE_MODE_INLINE StackVM::ProgramPtr CompileContent( Content const &rContent, eOptimize const opt_level = eOptimize::O0, std::string const &rName = "_USER_CODE_" );
181195

182196
/// Compiles the script referenced with file path \param path to a binary program for the TeaStackVM with the optimization level \param opt_level.
183197
/// \throw May throw exception::load_file_error or any exception based on exception::parsing_error/compile_error/eval_error/runtime_error.
184-
StackVM::ProgramPtr CompileScript( std::filesystem::path const &path, eOptimize const opt_level = eOptimize::O0 );
198+
TEASCRIPT_COMPILE_MODE_INLINE StackVM::ProgramPtr CompileScript( std::filesystem::path const &path, eOptimize const opt_level = eOptimize::O0 );
185199

186200
/// Compiles the TeaScript code in \param code to a binary program for the TeaStackVM with the optimization level \param opt_level.
187201
/// \param name is arbitrary user defined name for referring to the code.
@@ -212,9 +226,6 @@ class Engine : public EngineBase
212226

213227
} // namespace teascript
214228

215-
#if !defined(TEASCRIPT_DISABLE_HEADER_ONLY)
216-
# define TEASCRIPT_DISABLE_HEADER_ONLY 0
217-
#endif
218229

219230
// check for broken header only / not header only configurations.
220231
#if (0==TEASCRIPT_DISABLE_HEADER_ONLY) && defined(TEASCRIPT_INCLUDE_DEFINITIONS)

0 commit comments

Comments
 (0)