Drop extra semicolon
[gnash.git] / libcore / vm / fn_call.h
blob3b77b99de9272b14d89fb6c71fdb53696ed81b66
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef GNASH_FN_CALL_H
20 #define GNASH_FN_CALL_H
22 #include <string>
23 #include <vector>
24 #include <cassert>
25 #include <ostream>
26 #include <sstream>
27 #include <algorithm>
29 #include "as_object.h"
30 #include "as_value.h"
31 #include "VM.h"
32 #include "GnashException.h"
33 #include "as_environment.h"
36 // Forward declarations
37 namespace gnash {
38 class movie_definition;
41 namespace gnash {
43 /// A class to contain transferable arguments for a fn_call.
45 /// The operators += and , are implemented for intuitive syntax:
47 /// FunctionArgs<as_value> args; args += 0.0, "string", NaN.
49 /// This may have unexpected side effects if it is used in unexpected ways,
50 /// so stick to using such lists, or use operator += repeatedly.
52 /// The arguments can be moved to another container, and this happens when
53 /// the FunctionArgs object is passed to fn_call. It will still be valid
54 /// afterwards, but will contain no arguments.
55 template<typename T>
56 class FunctionArgs
58 public:
60 typedef typename std::vector<T>::size_type size_type;
61 typedef std::vector<T> container_type;
62 typedef T value_type;
64 FunctionArgs() {}
66 /// The copy constructor copies all the arguments.
67 FunctionArgs(const FunctionArgs& other)
69 _v(other._v)
72 FunctionArgs& operator+=(const T& t) {
73 _v.push_back(t);
74 return *this;
77 FunctionArgs& operator,(const T& t) {
78 _v.push_back(t);
79 return *this;
82 /// Mark any reachable resources
84 /// This is only for cases where the lifetime of a FunctionArgs object
85 /// extends beyond a function call.
86 void setReachable() const {
87 std::for_each(_v.begin(), _v.end(),
88 std::mem_fun_ref(&as_value::setReachable));
91 void swap(std::vector<T>& to) {
92 std::swap(_v, to);
95 size_type size() const {
96 return _v.size();
99 private:
100 std::vector<T> _v;
104 /// \brief
105 /// Parameters/environment for builtin or user-defined functions
106 /// callable from ActionScript.
107 class fn_call
109 public:
111 typedef FunctionArgs<as_value> Args;
113 /// Construct a fn_call
115 /// @param isNew Pass true if this is a constructing fn_call,
116 /// i.e. if it is called as a result of 'new'.
117 /// @param super Pass an overridden super value to the function
118 /// call. If this is 0, the super reference will be
119 /// calculated from the this pointer (if that is not
120 /// null) whenever a function requires it.
121 fn_call(as_object* this_in, const as_environment& env_in,
122 Args& args, as_object* sup = 0, bool isNew = false)
124 this_ptr(this_in),
125 super(sup),
126 nargs(args.size()),
127 callerDef(0),
128 _env(env_in),
129 _new(isNew)
131 args.swap(_args);
134 fn_call(as_object* this_in, const as_environment& env_in)
136 this_ptr(this_in),
137 super(0),
138 nargs(0),
139 callerDef(0),
140 _env(env_in),
141 _new(false)
145 /// Copy constructor
146 fn_call(const fn_call& fn)
148 this_ptr(fn.this_ptr),
149 super(fn.super),
150 nargs(fn.nargs),
151 callerDef(fn.callerDef),
152 _env(fn._env),
153 _args(fn._args),
154 _new(false)
158 /// The as_object (or a pointer derived thereof) on which this call
159 /// is taking place.
160 as_object* this_ptr;
162 /// The "super" object in this function call context
164 /// If this is 0, the super may be constructed from the this pointer.
165 as_object* super;
167 /// Number of arguments to this ActionScript function call.
168 Args::size_type nargs;
170 /// Definition containing caller code. 0 if spontaneous (system event).
171 const movie_definition* callerDef;
173 /// Return the VM this fn_call is running from
174 VM& getVM() const {
175 return _env.getVM();
178 /// Return true if this call is an object instantiation
179 bool isInstantiation() const {
180 return _new;
183 /// Access a particular argument.
184 const Args::value_type& arg(unsigned int n) const {
185 assert(n < nargs);
186 return _args[n];
189 const Args::container_type& getArgs() const {
190 return _args;
193 void drop_bottom() {
194 assert(!_args.empty());
195 _args.erase(_args.begin());
196 --nargs;
199 const as_environment& env() const {
200 return _env;
203 /// Dump arguments to given output stream
204 void dump_args(std::ostream& os) const {
205 for (size_t i = 0; i < nargs; ++i) {
206 if (i) os << ", ";
207 os << arg(i);
211 void resetArgs() {
212 nargs = 0;
213 _args.clear();
216 void pushArg(const Args::value_type& arg) {
217 ++nargs;
218 _args.push_back(arg);
221 private:
223 /// The ActionScript environment in which the function call is taking
224 /// place. This contains, among other things, the function arguments.
225 const as_environment& _env;
227 /// The actual arguments
228 Args::container_type _args;
230 bool _new;
235 /// Check that the 'this' pointer has a particular native type ('Relay').
237 /// This is the most likely of the cases to reflect AS behaviour.
238 template<typename T>
239 struct ThisIsNative
241 typedef T value_type;
242 value_type* operator()(const as_object* o) const {
243 return dynamic_cast<value_type*>(o->relay());
247 /// Check that the 'this' pointer is a DisplayObject
249 /// By default this just checks for any DisplayObject type.
250 template<typename T = DisplayObject>
251 struct IsDisplayObject
253 typedef T value_type;
254 value_type* operator()(const as_object* o) const {
255 if (!o) return 0;
256 return dynamic_cast<T*>(o->displayObject());
260 /// Check that the 'this' pointer is not null.
261 struct ValidThis
263 typedef as_object value_type;
264 value_type* operator()(as_object* o) const {
265 return o;
269 /// Templated function to check the validity of a function call.
271 /// It throws an exception if the condition is not fulfilled, it throws
272 /// an ActionTypeError, resulting in the function call being aborted and
273 /// an undefined as_value returned.
275 /// Note that not carrying out a function because the this pointer is
276 /// undefined is not ActionScript behaviour in most cases. To avoid
277 /// spreading its usage outside AS function implementations, this function
278 /// now takes a fn_call as an argument.
280 /// @tparam T A struct defining a value_type and an operator() that
281 /// checks the as_object's validity. A pointer to the
282 /// value_type is returned on success, an exception thrown
283 /// on failure.
284 /// @param fn The function whose 'this' pointer should be checked.
285 /// @return If the cast succeeds, the pointer cast to the
286 /// requested type.
287 template<typename T>
288 typename T::value_type*
289 ensure(const fn_call& fn)
291 as_object* obj = fn.this_ptr;
292 if (!obj) throw ActionTypeError();
294 typename T::value_type* ret = T()(obj);
296 if (!ret) {
297 std::string target = typeName(ret);
298 std::string source = typeName(obj);
300 std::string msg = "Function requiring " + target + " as 'this' "
301 "called from " + source + " instance.";
303 throw ActionTypeError(msg);
305 return ret;
308 inline string_table&
309 getStringTable(const fn_call& fn)
311 return fn.getVM().getStringTable();
314 inline movie_root&
315 getRoot(const fn_call& fn)
317 return fn.getVM().getRoot();
320 inline int
321 getSWFVersion(const fn_call& fn)
323 return fn.getVM().getSWFVersion();
326 inline VM&
327 getVM(const fn_call& fn)
329 return fn.getVM();
332 inline Global_as&
333 getGlobal(const fn_call& fn)
335 return *fn.getVM().getGlobal();
338 } // namespace gnash
341 #endif
344 // Local Variables:
345 // mode: C++
346 // indent-tabs-mode: nil
347 // End: