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
00046
00047
00048
00049
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 ¶meters); \
00068 }; \
00069 } \
00070 ixion::ref<ixion::javascript::value> NAME::call(parameter_list const ¶meters)
00071
00072 #define IXLIB_JS_CONVERT_PARAMETERS_0 \
00073
00074
00075
00076
00077
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
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
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
00169 OP_PRE_INCREMENT,OP_POST_INCREMENT,
00170 OP_PRE_DECREMENT,OP_POST_DECREMENT,
00171
00172 OP_UNARY_PLUS,OP_UNARY_MINUS,
00173 OP_LOG_NOT,OP_BIN_NOT,
00174
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
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
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
00208
00209 virtual std::string stringify() const;
00210
00211
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 ¶meters);
00217 virtual ref<value> callAsMethod(ref<value> instance,parameter_list const ¶meters);
00218 virtual ref<value> construct(parameter_list const ¶meters);
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
00233
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 ¶meters);
00248 };
00249
00250 public:
00251 ref<value> lookup(std::string const &identifier);
00252 virtual ref<value> callMethod(std::string const &identifier,parameter_list const ¶meters) = 0;
00253 };
00254
00255
00256
00257
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 ¶meters);
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