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

Generated at Fri Jun 29 18:49:16 2001 for ixlib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001