thunks.h

Go to the documentation of this file.
00001 /*      Numbers.h - the Thunk family of classes - variable accessors for MAXScript
00002  *
00003  *      Copyright (c) John Wainwright, 1996
00004  *      
00005  *
00006  */
00007 
00008 #pragma once
00009 
00010 #include "..\kernel\value.h"
00011 #include "..\foundation\streams.h"
00012 #include "..\ui\rollouts.h"
00013 #include "..\ui\uiextend.h"
00014 // forward declarations
00015 class MouseTool;
00016 
00017 #pragma warning(push)
00018 #pragma warning(disable:4100)
00019 
00020 /* ----------------------- Thunk  ---------------------- */
00021 visible_class (Thunk)
00022 
00023 class Thunk : public Value
00024 {
00025 public:
00026     Value*  name;
00027     BOOL    clear_container; // outer-level prop in a prop sequence, clear current_container when done
00028 
00029             classof_methods (Thunk, Value);
00030 #   define  is_thunk(v) ((v)->_is_thunk())
00031 #   define  is_indirect_thunk(v) ((v)->_is_indirect_thunk())
00032     BOOL    _is_thunk() { DbgAssert(!is_sourcepositionwrapper(this)); return TRUE; }
00033     ScripterExport void gc_trace();
00034     Thunk() : clear_container(FALSE), name(NULL) { }
00035 
00036     Thunk*  to_thunk() {return this; }
00037     virtual Thunk* make_free_thunk(int level) { return NULL; }
00038     void    assign(Value* val) { assign_vf(&val, 1); }
00039 
00040     ScripterExport Value*   get_property(Value** arg_list, int count);
00041     ScripterExport Value*   set_property(Value** arg_list, int count);
00042 };
00043 
00044 /* -------------------- GlobalThunk  ------------------- */
00045 
00046 class GlobalThunk : public Thunk
00047 {
00048 public:
00049     Value*  cell;
00050 
00051     ScripterExport      GlobalThunk(Value* init_name) { init(init_name); }
00052     ScripterExport      GlobalThunk(Value* init_name, Value* init_val);
00053     ScripterExport void init(Value* init_name);
00054 #   define  is_globalthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_GLOBAL_THUNK_TAG)
00055 
00056     ScripterExport Value* eval();
00057 
00058     ScripterExport void gc_trace();
00059     void    collect() { delete this; }
00060     ScripterExport void sprin1(CharStream* s);
00061 
00062     Value*  assign_vf(Value**arg_list, int count);
00063 
00064 };
00065 
00066 class ConstGlobalThunk : public GlobalThunk
00067 {
00068 public:
00069             ConstGlobalThunk(Value* iname) : GlobalThunk(iname) { tag = INTERNAL_CONST_GLOBAL_THUNK_TAG; }
00070             ConstGlobalThunk(Value* iname, Value* ival) : GlobalThunk(iname, ival) { tag = INTERNAL_CONST_GLOBAL_THUNK_TAG; }
00071 #   define  is_constglobalthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_CONST_GLOBAL_THUNK_TAG)
00072 
00073     Value*  eval() { return cell->is_const() ? cell->copy_vf(NULL, 0) : cell; }
00074     void    collect() { delete this; }
00075 
00076     Value*  assign_vf(Value**arg_list, int count) { throw AssignToConstError (this); return &undefined; }
00077 };
00078 
00079 /* -------------------- SystemGlobalThunk  ------------------- */
00080 
00081 /* system globals are abstractions over some system state accessing functions, such as 
00082  * animation_range, current_renderer,e tc. */
00083 
00084 class SystemGlobalThunk : public Thunk
00085 {
00086     Value* (*get_fn)();
00087     Value* (*set_fn)(Value*);
00088 public:
00089     ScripterExport      SystemGlobalThunk(Value* init_name, Value* (*iget)(), Value* (*iset)(Value*));
00090 // LAM 4/1/00 - added following to prevent AF in name clash debugging output in HashTable::put_new()
00091 #   define  is_systemglobalthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_SYS_GLOBAL_THUNK_TAG)
00092 
00093     ScripterExport Value* eval();
00094 
00095     void    collect() { delete this; }
00096     ScripterExport void sprin1(CharStream* s) { s->printf(_M("SystemGlobal:%s"), name->to_string()); }
00097 
00098     Value*  assign_vf(Value**arg_list, int count);
00099 };
00100 
00101 /* -------------------- LocalThunk  ------------------- */
00102 
00103 class LocalThunk : public Thunk
00104 {
00105 public:
00106     int     frame_level;    // frame nest level at declaration
00107     int     index;          // local var's index in local frame
00108 
00109             LocalThunk(Value* init_name, int init_index, int iframe_lvl);
00110 #   define  is_localthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_LOCAL_THUNK_TAG)
00111 
00112     Thunk*  make_free_thunk(int level);
00113 
00114     Value*  eval();
00115     void    collect() { delete this; }
00116     void    sprin1(CharStream* s);
00117 
00118     Value*  assign_vf(Value**arg_list, int count);
00119 };
00120 
00121 class IndirectLocalThunk : public LocalThunk
00122 {
00123 public:
00124     IndirectLocalThunk(Value* init_name, int init_index, int iframe_lvl) :
00125                 LocalThunk(init_name, init_index, iframe_lvl) { }
00126 
00127     BOOL    _is_indirect_thunk() { DbgAssert(!is_sourcepositionwrapper(this)); return TRUE; }
00128     Thunk*  make_free_thunk(int level);
00129 
00130     Value*  eval();
00131     void    collect() { delete this; }
00132     void    sprin1(CharStream* s) { s->printf(_M("&")); LocalThunk::sprin1(s); }
00133     Value*  assign_vf(Value**arg_list, int count);
00134 };
00135 
00136 // ContextThunk created from an IndirectLocal/FreeThunk on entry to a MAXScript function apply
00137 //   to contain the callers frame context for evals and assigns
00138 class ContextThunk : public Thunk
00139 {
00140 public:
00141     Thunk*  thunk;          // the wrapped thunk
00142     Value** frame;          // callers frame
00143 
00144     ENABLE_STACK_ALLOCATE(ContextLocalThunk);
00145 
00146     ContextThunk(Thunk*  thunk, Value** frame) :
00147                 thunk(thunk), frame(frame) { tag = INTERNAL_CONTEXT_THUNK_TAG;  }
00148 #   define  is_contextthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_CONTEXT_THUNK_TAG)
00149 
00150     void    collect() { delete this; }
00151     void    sprin1(CharStream* s) { s->printf(_M("&")); thunk->sprin1(s); }
00152 
00153     Value*  eval();
00154     Value*  assign_vf(Value**arg_list, int count);
00155 };
00156 
00157 /* -------------------- FreeThunk  ------------------- */
00158 
00159 class FreeThunk : public Thunk
00160 {
00161 public:
00162     int     level;      // how many levels to reach back
00163     int     index;      // index there
00164             FreeThunk(Value* init_name, int level, int index);
00165 #   define  is_freethunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_FREE_THUNK_TAG)
00166 
00167     Thunk*  make_free_thunk(int level);
00168 
00169     void    collect() { delete this; }
00170     void    sprin1(CharStream* s);
00171 
00172     Value*  eval();
00173     Value*  assign_vf(Value**arg_list, int count);
00174 };
00175 
00176 class IndirectFreeThunk : public FreeThunk
00177 {
00178 public:
00179             IndirectFreeThunk(Value* init_name, int level, int index) :
00180                 FreeThunk(init_name, level, index) { }
00181 
00182     BOOL    _is_indirect_thunk() { DbgAssert(!is_sourcepositionwrapper(this)); return TRUE; }
00183     Thunk*  make_free_thunk(int level);
00184 
00185     void    collect() { delete this; }
00186     void    sprin1(CharStream* s) { s->printf(_M("&")); FreeThunk::sprin1(s); }
00187 
00188     Value* eval();
00189     Value*  assign_vf(Value**arg_list, int count);
00190 };
00191 
00192 /* -------------------- ClosureFreeThunk  ------------------- */
00193 
00194 class ClosureFreeThunk : public Thunk
00195 {
00196 public:
00197     ScripterExport Value* eval();
00198 
00199     void    gc_trace();
00200     void    collect() { delete this; }
00201     ScripterExport void sprin1(CharStream* s);
00202 
00203             ClosureFreeThunk();
00204             ~ClosureFreeThunk();
00205 };
00206 
00207 /* -------------------- PropertyThunk  ------------------- */
00208 
00209 class PropertyThunk : public Thunk
00210 {
00211 public:
00212     Value*      target_code;    // code to eval to get target
00213     Value*      property_name;  // property name
00214     getter_vf   getter;         // getter virtual fn for built-in properties
00215     setter_vf   setter;         // setter    "     "       "        "
00216 
00217                 PropertyThunk(Value* target, Value* prop_name);
00218                 PropertyThunk(Value* target, Value* prop_name, getter_vf get_fn, setter_vf set_fn);
00219 
00220     void        gc_trace();
00221     void        collect() { delete this; }
00222     ScripterExport void sprin1(CharStream* s);
00223 #   define      is_propertythunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_PROP_THUNK_TAG)
00224 
00225     ScripterExport Value* eval(Value**arg_list, int count);
00226     ScripterExport Value* eval() { return eval(NULL,0); }
00227     Value*      assign_vf(Value**arg_list, int count);
00228     Value*      op_assign_vf(Value**arg_list, int count);
00229 };
00230 
00231 // a PropThunk subclass that is used when a Prop access occurs in a function call
00232 // this is basically a hack to support OLE client method calls, since OLE IDISPATCH
00233 // cannot distinguish methods from props
00234 class FnCallPropertyThunk : public PropertyThunk
00235 {
00236 public:
00237                 FnCallPropertyThunk(Value* target, Value* prop_name, getter_vf get_fn, setter_vf set_fn) 
00238                     : PropertyThunk (target, prop_name, get_fn, set_fn) {}
00239     void        collect() { delete this; }
00240     ScripterExport Value* eval();
00241 };
00242 
00243 /* -------------------- IndexThunk  ------------------- */
00244 
00245 class IndexThunk : public Thunk
00246 {
00247     Value*      target_code;    // code to eval to get target
00248     Value*      index_code;     // code to eval to get index
00249 
00250 public:
00251                 IndexThunk(Value* index);
00252 
00253 #   define      is_indexthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_INDEX_THUNK_TAG)
00254     void        gc_trace();
00255     void        collect() { delete this; }
00256     ScripterExport void sprin1(CharStream* s);
00257 
00258     Value*      set_target(Value* targ) { target_code = targ; return this; }
00259     ScripterExport Value* eval();
00260     Value*      assign_vf(Value**arg_list, int count);
00261 };
00262 
00263 /* -------------------- RolloutControlThunk  ------------------- */
00264 
00265 class RolloutControlThunk : public Thunk
00266 {
00267 public:
00268     int     index;
00269     Rollout* rollout;
00270 
00271             RolloutControlThunk(Value* name, int control_index, Rollout* rollout);
00272     BOOL    _is_rolloutthunk() { DbgAssert(!is_sourcepositionwrapper(this)); return 1; }
00273 #   define  is_rolloutthunk(v) ((v)->_is_rolloutthunk())
00274 
00275     Value*  eval() { return rollout->controls[index]; }
00276 
00277     void ScripterExport gc_trace();
00278     void    collect() { delete this; }
00279     ScripterExport void sprin1(CharStream* s);
00280 
00281     Value*  assign_vf(Value**arg_list, int count);
00282 };
00283 
00284 /* -------------------- RolloutLocalThunk  ------------------- */
00285 
00286 class RolloutLocalThunk : public Thunk
00287 {
00288 public:
00289     int     index;
00290     Rollout* rollout;
00291 
00292             RolloutLocalThunk(Value* name, int control_index, Rollout* rollout);
00293     BOOL    _is_rolloutthunk() { DbgAssert(!is_sourcepositionwrapper(this)); return 1; }
00294 #   define  is_rolloutlocalthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_RO_LOCAL_THUNK_TAG)
00295 
00296     ScripterExport Value* eval();
00297 
00298     void    gc_trace();
00299     void    collect() { delete this; }
00300     ScripterExport void sprin1(CharStream* s);
00301 
00302     Value*  assign_vf(Value**arg_list, int count);
00303 };
00304 
00305 class ConstRolloutLocalThunk : public RolloutLocalThunk
00306 {
00307 public:
00308             ConstRolloutLocalThunk(Value* name, int control_index, Rollout* rollout) 
00309                 : RolloutLocalThunk(name, control_index, rollout) { }
00310 
00311     void    collect() { delete this; }
00312 
00313     Value*  assign_vf(Value**arg_list, int count) { throw AssignToConstError (this); return &undefined; }
00314 };
00315 
00316 /* -------------------- ToolLocalThunk  ------------------- */
00317 
00318 class ToolLocalThunk : public Thunk
00319 {
00320 public:
00321     int         index;
00322     MouseTool*  tool;
00323 
00324             ToolLocalThunk(Value* name, int iindex, MouseTool* tool);
00325 
00326     ScripterExport Value* eval();
00327 
00328 #   define  is_toollocalthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_TOOL_LOCAL_THUNK_TAG)
00329     void    gc_trace();
00330     void    collect() { delete this; }
00331     ScripterExport void sprin1(CharStream* s);
00332 
00333     Value*  assign_vf(Value**arg_list, int count);
00334 };
00335 
00336 /* -------------------- CodeBlockLocalThunk  ------------------- */
00337 
00338 class CodeBlock;
00339 
00340 class CodeBlockLocalThunk : public Thunk
00341 {
00342 public:
00343     int         index;
00344     CodeBlock*  block;
00345 
00346             CodeBlockLocalThunk(Value* name, int iindex, CodeBlock* block);
00347 
00348     ScripterExport Value* eval();
00349 
00350 #   define  is_codeblocklocalthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_CODEBLOCK_LOCAL_TAG)
00351     void    gc_trace();
00352     void    collect() { delete this; }
00353     ScripterExport void sprin1(CharStream* s);
00354 
00355     Value*  assign_vf(Value**arg_list, int count);
00356 };
00357 
00358 /* -------------------- RCMenuItemThunk  ------------------- */
00359 
00360 class RCMenuItemThunk : public Thunk
00361 {
00362 public:
00363     int         index;
00364     RCMenu*     rcmenu;
00365 
00366             RCMenuItemThunk(Value* name, int item_index, RCMenu* menu);
00367     BOOL    _is_rcmenuthunk() { DbgAssert(!is_sourcepositionwrapper(this)); return 1; }
00368 #   define  is_rcmenuitemthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_RCMENU_ITEM_THUNK_TAG)
00369 
00370     Value*  eval() { return rcmenu->items[index]; }
00371 
00372     void ScripterExport gc_trace();
00373     void    collect() { delete this; }
00374     ScripterExport void sprin1(CharStream* s);
00375 
00376     Value*  assign_vf(Value**arg_list, int count);
00377 };
00378 
00379 /* -------------------- RCMenuLocalThunk  ------------------- */
00380 
00381 class RCMenuLocalThunk : public Thunk
00382 {
00383 public:
00384     int         index;
00385     RCMenu*     rcmenu;
00386 
00387             RCMenuLocalThunk(Value* name, int iindex, RCMenu* menu);
00388     BOOL    _is_rcmenuthunk() { DbgAssert(!is_sourcepositionwrapper(this)); return 1; }
00389 #   define  is_rcmenulocalthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_RCMENU_LOCAL_THUNK_TAG)
00390 #   define  is_rcmenuthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_RCMENU_LOCAL_THUNK_TAG || (v)->tag == INTERNAL_RCMENU_ITEM_THUNK_TAG)
00391 
00392     ScripterExport Value* eval();
00393 
00394     void    gc_trace();
00395     void    collect() { delete this; }
00396     ScripterExport void sprin1(CharStream* s);
00397 
00398     Value*  assign_vf(Value**arg_list, int count);
00399 };
00400 
00401 /* -------------------- PluginLocalThunk  ------------------- */
00402 
00403 class PluginLocalThunk : public Thunk
00404 {
00405 public:
00406     int     index;    // access via current_plugin thread local
00407     BOOL    re_init;  // indicate whether this local needs re-initialization on a redefinition (say for local rollouts, fns, etc.)
00408 
00409             PluginLocalThunk(Value* name, int iindex, BOOL re_init = FALSE);
00410 #   define  is_pluginlocalthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_PLUGIN_LOCAL_THUNK_TAG)
00411 
00412     ScripterExport Value* eval();
00413 
00414     void    collect() { delete this; }
00415     ScripterExport void sprin1(CharStream* s);
00416 
00417     Value*  assign_vf(Value**arg_list, int count);
00418 };
00419 
00420 class ConstPluginLocalThunk : public PluginLocalThunk
00421 {
00422 public:
00423     ConstPluginLocalThunk(Value* name, int iindex, BOOL re_init = FALSE) : PluginLocalThunk(name, iindex, re_init) { }
00424     void    collect() { delete this; }
00425     Value*  assign_vf(Value**arg_list, int count) { throw AssignToConstError (this); return &undefined; }
00426 };
00427 #pragma warning(pop) // for C4100
00428 
00429 /* -------------------- PluginParamThunk  ------------------- */
00430 
00431 class PluginParamThunk : public Thunk
00432 {
00433 public:
00434             PluginParamThunk(Value* name);
00435 #   define  is_pluginparamthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_PLUGIN_PARAM_THUNK_TAG)
00436 
00437     ScripterExport Value* eval();
00438 
00439     void    collect() { delete this; }
00440     ScripterExport void sprin1(CharStream* s);
00441 
00442     Value*  assign_vf(Value**arg_list, int count);
00443 
00444     Value*  get_container_property(Value* prop, Value* cur_prop);
00445     Value*  set_container_property(Value* prop, Value* val, Value* cur_prop);
00446 };
00447 
00448 #define push_plugin(_pi)                                \
00449     MSPlugin* _save_cp = thread_local(current_plugin);  \
00450     thread_local(current_plugin) = _pi;
00451     
00452 #define pop_plugin()                                    \
00453     thread_local(current_plugin) = _save_cp;                
00454 
00455 #define push_struct(_struct)                                \
00456     Struct* _save_struct = thread_local(current_struct);    \
00457     thread_local(current_struct) = _struct;
00458 
00459 #define pop_struct()                                    \
00460     thread_local(current_struct) = _save_struct;                
00461 /* -------------------- StructMemberThunk  ------------------- */
00462 
00463 class StructMemberThunk : public Thunk
00464 {
00465 public:
00466     int     index;    // access via current_plugin thread local
00467 
00468     ScripterExport StructMemberThunk(Value* name, int iindex);
00469 
00470     ScripterExport Value* eval();
00471 
00472     void    collect() { delete this; }
00473     ScripterExport void sprin1(CharStream* s);
00474 
00475     Value*  assign_vf(Value**arg_list, int count);
00476 };
00477 
00478 /* -------------------- ThunkReference  ------------------- */
00479 // indirect thunk (eg, &foo)
00480 
00481 class ThunkReference : public Thunk
00482 {
00483 public:
00484     Thunk*  target;         // the target thunk
00485 
00486     ScripterExport ThunkReference(Thunk* target);
00487 #   define  is_thunkref(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_THUNK_REF_TAG)
00488 
00489     void    gc_trace();
00490     void    collect() { delete this; }
00491     void    sprin1(CharStream* s);
00492 
00493     Value*  eval();
00494 };
00495 
00496 class DerefThunk : public Thunk  // generated by a '*' prefix operator
00497 {
00498 public:
00499     Value*  target;    // the target to deref
00500 
00501             ScripterExport DerefThunk(Value* target);
00502 #   define  is_derefthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_THUNK_DEREF_TAG)
00503     void    gc_trace();
00504     void    collect() { delete this; }
00505     void    sprin1(CharStream* s) { s->printf(_M("*")); target->sprin1(s); }
00506 
00507     Value*  eval();
00508     Value*  assign_vf(Value**arg_list, int count);
00509 };
00510 
00511 /* -------------------- OwnerThunk  ------------------- */
00512 // used by wrap owner of Functions for use by debugger
00513 
00514 class OwnerThunk : public Thunk
00515 {
00516 public:
00517     Value*  cell;
00518 
00519     ScripterExport      OwnerThunk(Value* owner);
00520 #   define  is_ownerthunk(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_OWNER_THUNK_TAG)
00521 
00522     ScripterExport Value* eval();
00523 
00524     ScripterExport  void    gc_trace();
00525                     void    collect() { delete this; }
00526     ScripterExport  void    sprin1(CharStream* s);
00527 
00528     Value*  assign_vf(Value**arg_list, int count);
00529 
00530 };
00531