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

Generated on Wed Oct 31 17:12:24 2001 for ixlib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001