00001
00002
00003
00004
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
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
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 ¶meters); \
00069 }; \
00070 } \
00071 ixion::ref<ixion::javascript::value> NAME::call(parameter_list const ¶meters)
00072
00073 #define IXLIB_JS_CONVERT_PARAMETERS_0 \
00074
00075
00076
00077
00078
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
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
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
00178 OP_PRE_INCREMENT,OP_POST_INCREMENT,
00179 OP_PRE_DECREMENT,OP_POST_DECREMENT,
00180
00181 OP_UNARY_PLUS,OP_UNARY_MINUS,
00182 OP_LOG_NOT,OP_BIN_NOT,
00183
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
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
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
00217
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 ¶meters);
00226 virtual ref<value> callAsMethod(ref<value> instance,parameter_list const ¶meters);
00227 virtual ref<value> construct(parameter_list const ¶meters);
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
00242
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 ¶meters);
00257 };
00258
00259 public:
00260 ref<value> lookup(std::string const &identifier);
00261 virtual ref<value> callMethod(std::string const &identifier,parameter_list const ¶meters) = 0;
00262 };
00263
00264
00265
00266
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 ¶meters);
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