codetree.h

Go to the documentation of this file.
00001 /*      <maxscript\compiler\codetree.h> - the CodeTree class - parser output
00002  *
00003  *      Copyright (c) John Wainwright, 1996
00004  *      
00005  *
00006  */
00007 
00008 #pragma once
00009 
00010 #include "..\ScripterExport.h"
00011 #include "..\kernel\value.h"
00012 // forward declarations
00013 class HashTable;
00014 
00015 /* ------------- debugging support classes -------------- */
00016 
00017 // SourcePositionWrapper wraps a piece of code in a source file
00018 // context.  Evaling this pushes the 'source_pos' and 'source_line' thread-locals,
00019 // evals the wrapped code & pops the thread-locals.
00020 
00021 class SourcePositionWrapper : public Value
00022 {
00023 public:
00024     Value*          code;
00025     unsigned int    pos;        // source stream pos
00026     unsigned int    line;       // source stream line number
00027     // Constructor
00028     SourcePositionWrapper(Value* icode, unsigned int pos = 0, unsigned int lineNumber = 0);
00029 
00030     void    gc_trace();
00031     void    collect();
00032     ScripterExport void sprin1(CharStream* s);
00033 
00034     Value* classOf_vf(Value** arg_list, int count) { DbgAssert(false); return code->classOf_vf(arg_list, count); }
00035     Value* superClassOf_vf(Value** arg_list, int count) { DbgAssert(false); return code->superClassOf_vf(arg_list, count); }
00036     Value* isKindOf_vf(Value** arg_list, int count) { DbgAssert(false); return code->isKindOf_vf(arg_list, count); }
00037     BOOL   is_kind_of(ValueMetaClass* c) { DbgAssert(false); return code->is_kind_of(c); }
00038 
00039     // polymorphic default type predicates - abstracted over by is_x(v) macros as needed
00040     BOOL    _is_collection()        { DbgAssert(false); return FALSE; }
00041     BOOL    _is_charstream()        { DbgAssert(false); return FALSE; }
00042     BOOL    _is_rolloutcontrol()    { DbgAssert(false); return FALSE; }
00043     BOOL    _is_rolloutthunk()      { DbgAssert(false); return FALSE; }
00044     BOOL    _is_function()          { DbgAssert(false); return code->_is_function(); }
00045     BOOL    _is_selection()         { DbgAssert(false); return FALSE; }
00046     BOOL    _is_thunk()             { DbgAssert(false); return code->_is_thunk(); }
00047     BOOL    _is_indirect_thunk()    { DbgAssert(false); return FALSE; }
00048 
00049     Thunk*  to_thunk()              { DbgAssert(false); return code->to_thunk(); }
00050 
00051     ScripterExport Value* eval();
00052     ScripterExport Value* apply(Value** arglist, int count, CallContext* cc=NULL);
00053     ScripterExport Value* apply_no_alloc_frame(Value** arglist, int count, CallContext* cc=NULL);
00054     ScripterExport Value* apply(value_vf vfn_ptr, Value** arglist, int count);
00055 };
00056 
00057 // SourceFileWrapper wraps a piece of code in a source file
00058 // context.  Evaling this pushes the 'source-file' thread-local,
00059 // evals the wrapped code & pops source-file.
00060 
00061 class SourceFileWrapper : public Value
00062 {
00063 public:
00064     Value*          file_name;
00065     Value*          code;
00066     MSZipPackage*   module;
00067     unsigned int    pos;        // source stream pos
00068     unsigned int    line;       // source stream line number
00069     DWORD           flags;
00070 
00071     // Constructor
00072     SourceFileWrapper(Value* file_name, Value* code, unsigned int ipos, unsigned int lineNumber, DWORD flags = 0);
00073 #define is_sourcefilewrapper(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_SOURCEFILEWRAPPER_TAG)
00074 
00075     void    gc_trace();
00076     void    collect();
00077     ScripterExport void sprin1(CharStream* s) { code->sprin1(s); }
00078     BOOL    _is_function() { DbgAssert(!is_sourcepositionwrapper(this)); return code->_is_function(); }
00079 
00080     Value* classOf_vf(Value** arg_list, int count) { return code->classOf_vf(arg_list, count); }
00081     Value* superClassOf_vf(Value** arg_list, int count) { return code->superClassOf_vf(arg_list, count); }
00082     Value* isKindOf_vf(Value** arg_list, int count) { return code->isKindOf_vf(arg_list, count); }
00083     BOOL      is_kind_of(ValueMetaClass* c) { return code->is_kind_of(c); }
00084     ScripterExport Value* eval();
00085     ScripterExport Value* eval_no_wrapper();
00086     ScripterExport Value* apply(Value** arglist, int count, CallContext* cc=NULL);
00087 };
00088 
00089 class CodeTree : public Value
00090 {
00091 public:
00092     Value*  fn;             // the function to apply
00093     short   count;          // number of arguments
00094     Value** arg_list;       // the argument list
00095     unsigned int pos;       // source stream pos
00096     unsigned int line;      // source streem line number
00097             CodeTree(CharStream* source, Value* codeFn, ...);
00098             ~CodeTree();
00099 
00100 #define is_codetree(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_CODE_TAG)
00101     void    gc_trace();
00102     void    collect();
00103     ScripterExport void sprin1(CharStream* s);
00104 
00105     ScripterExport Value* eval();
00106 
00107     Value*  add(Value* arg1, ...);
00108     Value*  append(Value* arg);
00109     Value*  put(int index, Value* arg);
00110 };
00111 
00112 /*  Maker class, a special CodeTree node that encodes runtime object 
00113  *               instantiation.  contains a reference to a maker
00114  *               static method on the class to be instantiated.  It is
00115  *               supplied an arg_list like any other codetree fn apply
00116  */
00117  
00118 class Maker : public Value
00119 {
00120     value_cf maker;         /* the maker class static fn                */
00121     short   count;          /* number of arguments                      */
00122     Value** arg_list;       /* the argument list                        */
00123 
00124 public:
00125             Maker(value_cf maker_fn, ...);
00126             Maker(Value** arg_list, int count, value_cf maker_fn);
00127             ~Maker();
00128 
00129 #define is_maker(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_MAKER_TAG)
00130     void    gc_trace();
00131     void    collect();
00132     ScripterExport void sprin1(CharStream* s);
00133 
00134     ScripterExport Value* eval();
00135 
00136     Value*  add(Value* arg1, ...);
00137     Value*  append(Value* arg);
00138 };
00139 
00140 // top-level code block, provides a storage for top-level locals
00141 // R4: CodeBlocks can now optionally be 'structured', made of on-handlers and local decls
00142 //     So it now supports call_handler() methods and property access to get at locals.
00143 //     If structured, there must at least be an 'on execute' handler which becomes the main
00144 //     executable body of the CodeBlock, and simple eval()'s on the codeblock turn into
00145 //     call_handler(n_execute...);
00146 //     Further, locals in a structured codeblock are now effectively static, as are 
00147 //     locals in rollups and plugins, they are initialized once the first time the block
00148 //     is used and have a lifetime corresponding to the lifetime of the codeblock.  The 
00149 //     per-execution-lifetime locals should be moved into the body of the 'on execute'
00150 //     handler.   -- JBW 2/29/00
00151 
00152 
00153 class CodeBlock : public Value
00154 {
00155 public:
00156     Value*      code;           // the code
00157     Value**     locals;         // local variable array 
00158     int         local_count;    // local variable count 
00159     HashTable*  local_scope;    // local name space         
00160     HashTable*  handlers;       // handler tables   
00161     BOOL        initialized;    // if locals in structured macroScript have been inited
00162     Name*       name;           // the macroscript name, used for debugger output   
00163 
00164                 CodeBlock();
00165                ~CodeBlock();
00166 #define is_codeblock(v) ((DbgVerify(!is_sourcepositionwrapper(v)), (v))->tag == INTERNAL_CODEBLOCK_TAG)
00167 
00168     void        init(Value* code, HashTable* local_scope);
00169     void        init_locals();
00170 
00171     void        collect();
00172     void        gc_trace();
00173     void        sprin1(CharStream* s);
00174 
00175     void        add_local();
00176     Value*      call_handler(Value* handler_or_name, Value** arg_list, int count);
00177     Value*      get_handler(Value* name);
00178 
00179     Value*      eval();
00180     Value*      get_property(Value** arg_list, int count);
00181     Value*      set_property(Value** arg_list, int count);
00182 
00183     // Used by debugger to dump locals and externals to standard out
00184     void        dump_local_vars_and_externals(int indentLevel);
00185 };
00186