Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

ixlib_javascript.hh

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 //  Description      : Javascript interpreter
00003 // ----------------------------------------------------------------------------
00004 //  (c) Copyright 2000 by iXiONmedia, all rights reserved.
00005 // ----------------------------------------------------------------------------
00006 
00007 
00008 
00009 
00010 #ifndef IXLIB_JAVASCRIPT
00011 #define IXLIB_JAVASCRIPT
00012 
00013 
00014 
00015 
00016 #include <vector>
00017 #include <hash_map>
00018 #include <ixlib_string.hh>
00019 #include <ixlib_exbase.hh>
00020 #include <ixlib_garbage.hh>
00021 #include <ixlib_scanner.hh>
00022 
00023 
00024 
00025 
00026 // Error codes ----------------------------------------------------------------
00027 #define ECJS_UNTERMINATED_COMMENT               0
00028 #define ECJS_CANNOT_CONVERT                     1
00029 #define ECJS_INVALID_OPERATION                  2
00030 #define ECJS_UNEXPECTED                         3
00031 #define ECJS_UNEXPECTED_EOF                     4
00032 #define ECJS_CANNOT_MODIFY_RVALUE               5
00033 #define ECJS_UNKNOWN_IDENTIFIER                 6
00034 #define ECJS_UNKNOWN_OPERATOR                   7
00035 #define ECJS_INVALID_NON_LOCAL_EXIT             8
00036 #define ECJS_INVALID_NUMBER_OF_ARGUMENTS        9
00037 #define ECJS_INVALID_TOKEN                      10
00038 #define ECJS_CANNOT_REDECLARE                   11
00039 
00040 
00041 
00042 
00043 // helpful macros -------------------------------------------------------------
00044 #define IXLIB_JS_ASSERT_PARAMETERS(NAME,ARGMIN,ARGMAX) \
00045   if (parameters.size() < ARGMIN || parameters.size() > ARGMAX) \
00046     EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,NAME)
00047 
00048 #define IXLIB_JS_IF_METHOD(NAME,ARGMIN,ARGMAX) \
00049   if (identifier == NAME) \
00050     if (parameters.size() < ARGMIN || parameters.size() > ARGMAX) \
00051       EXJS_THROWINFO(ECJS_INVALID_NUMBER_OF_ARGUMENTS,NAME) \
00052     else
00053 
00054 #define IXLIB_JS_DECLARE_FUNCTION(NAME) \
00055   namespace { \
00056     class NAME : public value { \
00057       public: \
00058         value_type getType() const { \
00059           return VT_FUNCTION; \
00060           } \
00061         ixion::ref<ixion::javascript::value> call(context const &ctx,parameter_list const &parameters) const; \
00062       }; \
00063     } \
00064   ixion::ref<ixion::javascript::value> NAME::call(context const &ctx,parameter_list const &parameters) const
00065 
00066 #define IXLIB_JS_CONVERT_PARAMETERS_0 \
00067   
00068   
00069 
00070 
00071 // Exception throw macros -----------------------------------------------------
00072 #define EXJS_THROW(CODE)\
00073   EX_THROW(javascript,CODE)
00074 #define EXJS_THROWINFO(CODE,INFO)\
00075   EX_THROWINFO(javascript,CODE,INFO)
00076 #define EXJS_THROWINFOTOKEN(CODE,INFO,TOKEN)\
00077   EXJS_THROWINFOLINE(CODE,INFO,(TOKEN).Line)
00078 #define EXJS_THROWINFOLINE(CODE,INFO,LINE)\
00079   throw ixion::javascript_exception(CODE,LINE,INFO,__FILE__,__LINE__);
00080 
00081 
00082 
00083 
00084 namespace ixion {
00085   // javascript_exception -----------------------------------------------------
00086   struct javascript_exception : public base_exception {
00087     javascript_exception(TErrorCode error,char const *info = NULL,char *module = NULL,
00088       TIndex line = 0)
00089       : base_exception(error,info,module,line,"JS") {
00090       }
00091     javascript_exception(TErrorCode error, TIndex js_line = 0, char const *info = 0,char *module = NULL,
00092       TIndex line = 0);
00093     virtual char *getText() const;
00094     };
00095 
00096 
00097 
00098 
00099   // javascript ---------------------------------------------------------------
00123   namespace javascript {
00124     class context;
00125     class expression;
00126     
00127     class value {
00128       public:
00129         enum operator_id { 
00130           // unary, modifying
00131           OP_PRE_INCREMENT,OP_POST_INCREMENT,
00132           OP_PRE_DECREMENT,OP_POST_DECREMENT,
00133           // unary, non-modifying
00134           OP_UNARY_PLUS,OP_UNARY_MINUS,
00135           OP_LOG_NOT,OP_BIN_NOT,
00136           // binary, modifying
00137           OP_PLUS_ASSIGN,OP_MINUS_ASSIGN,
00138           OP_MUTLIPLY_ASSIGN,OP_DIVIDE_ASSIGN,OP_MODULO_ASSIGN,
00139           OP_BIT_AND_ASSIGN,OP_BIT_OR_ASSIGN,OP_BIT_XOR_ASSIGN,
00140           OP_LEFT_SHIFT_ASSIGN,OP_RIGHT_SHIFT_ASSIGN,
00141           // binary, non-modifying
00142           OP_PLUS,OP_MINUS,
00143           OP_MULTIPLY,OP_DIVIDE,OP_MODULO,
00144           OP_BIT_AND,OP_BIT_OR,OP_BIT_XOR,
00145           OP_LEFT_SHIFT,OP_RIGHT_SHIFT,
00146           OP_LOGICAL_OR,OP_LOGICAL_AND,
00147           OP_EQUAL,OP_NOT_EQUAL,OP_IDENTICAL,OP_NOT_IDENTICAL,
00148           OP_LESS_EQUAL,OP_GREATER_EQUAL,OP_LESS,OP_GREATER,
00149           // special
00150           OP_ASSIGN,
00151           };
00152         
00153         enum value_type {
00154           VT_UNDEFINED,VT_NULL,
00155           VT_INTEGER,VT_FLOATING_POINT,VT_STRING,
00156           VT_FUNCTION,VT_OBJECT,VT_BUILTIN,VT_HOST,
00157           VT_SCOPE,VT_BOUND_METHOD,VT_TYPE
00158           };
00159         typedef vector<ref<value> >     parameter_list;
00160 
00161         virtual ~value() {
00162           }
00163       
00164         virtual value_type getType() const = 0;
00165         virtual string toString() const;
00166         virtual int toInt() const;
00167         virtual double toFloat() const;
00168         virtual bool toBoolean() const;
00169         // toString is meant as a type conversion, whereas stringify
00170         // is for debuggers and the like
00171         virtual string stringify() const;
00172         
00173         // this operation is defined to eliminate any wrappers
00174         virtual ref<value> duplicate() const;
00175 
00176         virtual ref<value> lookup(string const &identifier);
00177         virtual ref<value> subscript(value const &index);
00178         virtual ref<value> call(context const &ctx,parameter_list const &parameters) const;
00179         virtual ref<value> construct(context const &ctx,parameter_list const &parameters) const;
00180         virtual ref<value> assign(ref<value> op2);
00181         
00182         virtual ref<value> operatorUnary(operator_id op) const;
00183         virtual ref<value> operatorBinary(operator_id op,expression const &op2,context const &ctx) const;
00184         virtual ref<value> operatorUnaryModifying(operator_id op);
00185         virtual ref<value> operatorBinaryModifying(operator_id op,expression const &op2,context const &ctx);
00186         
00187         static operator_id token2operator(scanner::token const &token,bool unary = false,bool prefix = false);
00188         static char *operator2string(operator_id op);
00189         static char *valueType2string(value_type vt);
00190       };
00191     
00192     // obviously, any value can have methods, but with this neat little
00193     // interface implementing methods has just become easier.
00194     class value_with_methods : public value {
00195       protected:
00196         class method : public value {
00197           protected:
00198             string                      Identifier;
00199             value_with_methods          *Parent;
00200             ref<value>                  ParentRef;
00201             
00202           public:
00203             value_type getType() const {
00204               return VT_BOUND_METHOD;
00205               }
00206 
00207             method(string const &identifier,value_with_methods *parent);
00208             ref<value> call(context const &ctx,parameter_list const &parameters) const;
00209           };
00210             
00211       public:
00212         ref<value> lookup(string const &identifier);
00213         virtual ref<value> callMethod(string const &identifier,context const &ctx,parameter_list const &parameters) = 0;
00214       };
00215 
00216     // obviously, any value can already represent a scope ("lookup" member!).
00217     // the list_scope class is an explicit scope that can "swallow" 
00218     // (=unite with) other scopes and keeps a list of registered members
00219     class list_scope : public value {
00220       protected:
00221         typedef hash_map<string,ref<value>,string_hash>         member_map;
00222         typedef vector<ref<value> >                             swallowed_list;
00223         
00224         member_map      MemberMap;
00225         swallowed_list  SwallowedList;
00226         
00227       public:
00228         value_type getType() const {
00229           return VT_SCOPE;
00230           }
00231 
00232         ref<value> lookup(string const &identifier);
00233 
00234         void unite(ref<value> scope);
00235         void separate(ref<value> scope);
00236         void clearScopes();
00237         
00238         bool hasMember(string const &name) const;
00239         void addMember(string const &name,ref<value> member);
00240         void removeMember(string const &name);
00241         void clearMembers();
00242         
00243         void clear();
00244       };
00245     
00246     class js_array : public value_with_methods {
00247       private:
00248         typedef value_with_methods      super;
00249         
00250       protected:
00251         typedef vector<ref<value> >     value_array;
00252         value_array                     Array;
00253   
00254       public:
00255         js_array() {
00256           }
00257         js_array(TSize size);
00258         js_array(value_array::const_iterator first,value_array::const_iterator last)
00259           : Array(first,last) {
00260           }
00261         js_array(js_array const &src)
00262           : Array(src.Array) {
00263           }
00264         
00265         value_type getType() const {
00266           return VT_BUILTIN;
00267           }
00268 
00269         string stringify() const;
00270         
00271         ref<value> duplicate() const;
00272   
00273         ref<value> lookup(string const &identifier);
00274         ref<value> subscript(value const &index);
00275         ref<value> callMethod(string const &identifier,javascript::context const &ctx,parameter_list const &parameters);
00276   
00277         TSize size() const {
00278           return Array.size();
00279           }
00280         void resize(TSize size);
00281         ref<value> &operator[](TIndex idx);
00282       };
00283 
00284     class expression {
00285       public:
00286         virtual ~expression() {
00287           }
00288         virtual ref<value> evaluate(context const &ctx) const = 0;
00289       };
00290     
00291     ref<value> makeUndefined();
00292     ref<value> makeNull();
00293     ref<value> makeValue(bool val);
00294     ref<value> makeConstant(bool val);
00295     ref<value> makeValue(signed long val);
00296     ref<value> makeConstant(signed long val);
00297     ref<value> makeValue(signed int val);
00298     ref<value> makeConstant(signed int val);
00299     ref<value> makeValue(unsigned long val);
00300     ref<value> makeConstant(unsigned long val);
00301     ref<value> makeValue(unsigned int val);
00302     ref<value> makeConstant(unsigned int val);
00303     ref<value> makeValue(double val);
00304     ref<value> makeConstant(double val);
00305     ref<value> makeValue(string const &val);
00306     ref<value> makeConstant(string const &val);
00307     ref<value> makeArray(TSize size = 0);
00308     ref<value> makeLValue(ref<value> target);
00309     ref<value> wrapConstant(ref<value> val);
00310     ref<expression> makeConstantExpression(ref<value> val);
00311 
00312     class interpreter {
00313       public:
00314         ref<list_scope,value>                   RootScope;
00315       
00316       public:
00317         interpreter();
00318         ~interpreter();
00319         
00320         ref<expression> parse(string const &str);
00321         ref<expression> parse(istream &istr);
00322         ref<value> execute(string const &str);
00323         ref<value> execute(istream &istr);
00324         ref<value> execute(ref<expression> expr);
00325     
00326       private:
00327         ref<value> evaluateCatchExits(ref<expression> expr);
00328       
00329         ref<expression> parseInstructionList(
00330           scanner::token_iterator &first,scanner::token_iterator const &last,bool scoped);
00331         ref<expression> parseSwitch(
00332           scanner::token_iterator &first,scanner::token_iterator const &last,string const &label);
00333         ref<expression> parseVariableDeclaration(
00334           scanner::token_iterator &first,scanner::token_iterator const &last);
00335         ref<expression> parseConstantDeclaration(
00336           scanner::token_iterator &first,scanner::token_iterator const &last);
00337         ref<expression> parseInstruction(
00338           scanner::token_iterator &first,scanner::token_iterator const &last);
00339         ref<expression> parseExpression(
00340           scanner::token_iterator &first,scanner::token_iterator const &last,
00341           int precedence = 0);
00342       };
00343 
00344     void addGlobal(interpreter &ip);
00345     void addMath(interpreter &ip);
00346     void addStandardLibrary(interpreter &ip);
00347     }
00348   }
00349 
00350 
00351 
00352 
00353 #endif

Generated at Tue Apr 17 18:29:43 2001 for ixlib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001