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 #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
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
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 ¶meters) const; \
00062 }; \
00063 } \
00064 ixion::ref<ixion::javascript::value> NAME::call(context const &ctx,parameter_list const ¶meters) const
00065
00066 #define IXLIB_JS_CONVERT_PARAMETERS_0 \
00067
00068
00069
00070
00071
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
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
00123 namespace javascript {
00124 class context;
00125 class expression;
00126
00127 class value {
00128 public:
00129 enum operator_id {
00130
00131 OP_PRE_INCREMENT,OP_POST_INCREMENT,
00132 OP_PRE_DECREMENT,OP_POST_DECREMENT,
00133
00134 OP_UNARY_PLUS,OP_UNARY_MINUS,
00135 OP_LOG_NOT,OP_BIN_NOT,
00136
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
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
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
00170
00171 virtual string stringify() const;
00172
00173
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 ¶meters) const;
00179 virtual ref<value> construct(context const &ctx,parameter_list const ¶meters) 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
00193
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 ¶meters) 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 ¶meters) = 0;
00214 };
00215
00216
00217
00218
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 ¶meters);
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