// ---------------------------------------------------------------------------- // Description : Javascript interpreter // ---------------------------------------------------------------------------- // (c) Copyright 2000 by iXiONmedia, all rights reserved. // ---------------------------------------------------------------------------- #ifndef IXLIB_JS_INTERNALS #define IXLIB_JS_INTERNALS #include using namespace std; namespace ixion { namespace javascript { struct code_location { TIndex Line; code_location(scanner::token &tok); explicit code_location(TIndex line); string stringify() const; }; struct return_exception { ref ReturnValue; code_location Location; return_exception(ref retval,code_location const &loc) : ReturnValue(retval),Location(loc) { } }; struct break_exception { bool HasLabel; string Label; code_location Location; break_exception(bool has_label,string const &label,code_location const &loc) : HasLabel(has_label),Label(label),Location(loc) { } }; struct continue_exception { bool HasLabel; string Label; code_location Location; continue_exception(bool has_label,string const &label,code_location const &loc) : HasLabel(has_label),Label(label),Location(loc) { } }; // values ----------------------------------------------------------------- class null : public value { private: typedef value super; public: value_type getType() const; bool toBoolean() const; ref duplicate(); }; class const_floating_point : public value_with_methods { private: typedef value_with_methods super; protected: double Value; public: const_floating_point(double value); value_type getType() const; int toInt() const; double toFloat() const; bool toBoolean() const; string toString() const; ref duplicate(); ref callMethod(string const &identifier,parameter_list const ¶meters); ref operatorUnary(operator_id op) const; ref operatorBinary(operator_id op,ref op2) const; }; class floating_point : public const_floating_point { private: typedef const_floating_point super; public: floating_point(double value); ref operatorUnaryModifying(operator_id op); ref operatorBinaryModifying(operator_id op,ref op2); }; class const_integer : public value_with_methods { private: typedef value_with_methods super; protected: long Value; public: const_integer(long value); value_type getType() const; int toInt() const; double toFloat() const; bool toBoolean() const; string toString() const; ref duplicate(); ref callMethod(string const &identifier,parameter_list const ¶meters); ref operatorUnary(operator_id op) const; ref operatorBinary(operator_id op,ref op2) const; }; class integer : public const_integer { private: typedef const_integer super; public: integer(long value); ref operatorUnaryModifying(operator_id op); ref operatorBinaryModifying(operator_id op,ref op2); }; class js_string : public value_with_methods { private: typedef value_with_methods super; protected: string Value; public: js_string(string const &value); value_type getType() const; string toString() const; bool toBoolean() const; string stringify() const; ref duplicate(); ref lookup(string const &identifier); ref callMethod(string const &identifier,parameter_list const ¶meters); ref operatorBinary(operator_id op,ref op2) const; ref operatorBinaryModifying(operator_id op,ref op2); }; class lvalue : public value { protected: ref Reference; public: lvalue(ref ref); value_type getType() const; string toString() const; int toInt() const; double toFloat() const; bool toBoolean() const; string stringify() const; ref eliminateWrappers(); ref duplicate(); ref lookup(string const &identifier); ref subscript(value const &index); ref call(parameter_list const ¶meters); ref callAsMethod(ref instance,parameter_list const ¶meters); ref construct(parameter_list const ¶meters); ref assign(ref op2); ref operatorUnary(operator_id op) const; ref operatorBinary(operator_id op,ref op2) const; ref operatorBinaryShortcut(operator_id op,expression const &op2,context const &ctx) const; ref operatorUnaryModifying(operator_id op); ref operatorBinaryModifying(operator_id op,ref op2); }; class constant_wrapper : public value { protected: ref Constant; public: constant_wrapper(ref val); value_type getType() const; string toString() const; int toInt() const; double toFloat() const; bool toBoolean() const; string stringify() const; ref eliminateWrappers(); ref duplicate(); ref lookup(string const &identifier); ref subscript(value const &index); ref call(parameter_list const ¶meters) const; ref callAsMethod(ref instance,parameter_list const ¶meters); ref construct(parameter_list const ¶meters); ref assign(ref value); ref operatorUnary(operator_id op) const; ref operatorBinary(operator_id op,ref op2) const; ref operatorBinaryShortcut(operator_id op,expression const &op2,context const &ctx) const; ref operatorUnaryModifying(operator_id op); ref operatorBinaryModifying(operator_id op,ref op2); }; class callable_with_parameters : public value { public: typedef vector parameter_name_list; protected: parameter_name_list ParameterNameList; public: callable_with_parameters(parameter_name_list const &pnames); void addParametersTo(list_scope &scope,parameter_list const ¶meters) const; static ref evaluateBody(expression &body,context const &ctx); }; class function : public callable_with_parameters { typedef callable_with_parameters super; ref Body; ref LexicalScope; public: function(parameter_name_list const &pnames,ref body,ref lex_scope); value_type getType() const{ return VT_FUNCTION; } ref duplicate(); ref call(parameter_list const ¶meters); }; class method : public callable_with_parameters { typedef callable_with_parameters super; ref Body; ref LexicalScope; public: method(parameter_name_list const &pnames,ref body,ref lex_scope); value_type getType() const{ return VT_FUNCTION; } ref duplicate(); ref callAsMethod(ref instance,parameter_list const ¶meters); }; class constructor : public callable_with_parameters { typedef callable_with_parameters super; ref Body; ref LexicalScope; public: constructor(parameter_name_list const &pnames,ref body,ref lex_scope); value_type getType() const{ return VT_FUNCTION; } ref duplicate(); ref callAsMethod(ref instance,parameter_list const ¶meters); }; class js_class : public value { class super_instance_during_construction : public value { // this object constructs the superclass // a) if it is called, by calling the super constructor // with the aprropriate parameters // b) implicitly with no super constructor arguments, // if the super object is referenced explicitly ref SuperClass; ref SuperClassInstance; public: super_instance_during_construction(ref super_class); value_type getType() const { return VT_OBJECT; } ref call(parameter_list const ¶meters); ref lookup(string const &identifier); ref getSuperClassInstance(); }; typedef vector > declaration_list; ref LexicalScope; ref SuperClass; ref Constructor; ref StaticMethodScope; ref MethodScope; ref StaticVariableScope; declaration_list VariableList; public: js_class(ref lex_scope,ref super_class,ref constructor, ref static_method_scope,ref method_scope, ref static_variable_scope,declaration_list const &variable_list); value_type getType() const { return VT_TYPE; } ref duplicate(); ref lookup(string const &identifier); ref lookupLocal(string const &identifier); ref construct(parameter_list const ¶meters); }; class js_class_instance : public value { class bound_method : public value { ref Instance; ref Method; public: bound_method(ref instance,ref method); value_type getType() const { return VT_BOUND_METHOD; } ref call(parameter_list const ¶meters); }; ref SuperClassInstance; ref Class; ref MethodScope; ref VariableScope; public: js_class_instance(ref cls,ref method_scope, ref variable_scope); void setSuperClassInstance(ref super_class_instance); value_type getType() const { return VT_OBJECT; } ref duplicate(); ref lookup(string const &identifier); }; class js_array_constructor : public value { public: value_type getType() const { return VT_TYPE; } ref duplicate(); ref construct(parameter_list const ¶meters); }; // expressions ---------------------------------------------------------- class expression { code_location Location; public: expression(code_location const &loc); virtual ~expression(); virtual ref evaluate(context const &ctx) const = 0; code_location const &getCodeLocation() const { return Location; } }; class constant : public expression { ref Value; public: constant(ref val,code_location const &loc); ref evaluate(context const &ctx) const; }; class unary_operator : public expression { value::operator_id Operator; ref Operand; public: unary_operator(value::operator_id opt,ref opn,code_location const &loc); ref evaluate(context const &ctx) const; }; class modifying_unary_operator : public expression { value::operator_id Operator; ref Operand; public: modifying_unary_operator(value::operator_id opt,ref opn,code_location const &loc); ref evaluate(context const &ctx) const; }; class binary_operator : public expression { value::operator_id Operator; ref Operand1; ref Operand2; public: binary_operator(value::operator_id opt,ref opn1,ref opn2,code_location const &loc); ref evaluate(context const &ctx) const; }; class binary_shortcut_operator : public expression { value::operator_id Operator; ref Operand1; ref Operand2; public: binary_shortcut_operator(value::operator_id opt,ref opn1,ref opn2,code_location const &loc); ref evaluate(context const &ctx) const; }; class modifying_binary_operator : public expression { value::operator_id Operator; ref Operand1; ref Operand2; public: modifying_binary_operator(value::operator_id opt,ref opn1,ref opn2,code_location const &loc); ref evaluate(context const &ctx) const; }; class ternary_operator : public expression { ref Operand1; ref Operand2; ref Operand3; public: ternary_operator(ref opn1,ref opn2,ref opn3,code_location const &loc); ref evaluate(context const &ctx) const; }; class subscript_operation : public expression { ref Operand1; ref Operand2; public: subscript_operation(ref opn1,ref opn2,code_location const &loc); ref evaluate(context const &ctx) const; }; class lookup_operation : public expression { ref Operand; string Identifier; public: lookup_operation(string const &id,code_location const &loc); lookup_operation(ref opn,string const &id,code_location const &loc); ref evaluate(context const &ctx) const; }; class assignment : public expression { ref Operand1; ref Operand2; public: assignment(ref opn1,ref opn2,code_location const &loc); ref evaluate(context const &ctx) const; }; class basic_call : public expression { public: typedef vector > parameter_expression_list; typedef vector > parameter_value_list; private: parameter_expression_list ParameterExpressionList; public: basic_call(parameter_expression_list const &pexps,code_location const &loc); void makeParameterValueList(context const &ctx,parameter_value_list &pvalues) const; }; class function_call : public basic_call { typedef basic_call super; ref Function; public: function_call(ref fun,parameter_expression_list const &pexps,code_location const &loc); ref evaluate(context const &ctx) const; }; class construction : public basic_call { typedef basic_call super; ref Class; public: construction(ref cls,parameter_expression_list const &pexps,code_location const &loc); ref evaluate(context const &ctx) const; }; // declarations ----------------------------------------------------------- class variable_declaration : public expression { protected: string Identifier; ref DefaultValue; public: variable_declaration(string const &id,ref def_value,code_location const &loc); ref evaluate(context const &ctx) const; }; class constant_declaration : public expression { protected: string Identifier; ref DefaultValue; public: constant_declaration(string const &id,ref def_value,code_location const &loc); ref evaluate(context const &ctx) const; }; class function_declaration : public expression { public: typedef function::parameter_name_list parameter_name_list; private: string Identifier; parameter_name_list ParameterNameList; ref Body; public: function_declaration(string const &id,parameter_name_list const &pnames, ref body,code_location const &loc); ref evaluate(context const &ctx) const; }; class method_declaration : public expression { public: typedef method::parameter_name_list parameter_name_list; private: string Identifier; parameter_name_list ParameterNameList; ref Body; public: method_declaration(string const &id,parameter_name_list const &pnames, ref body,code_location const &loc); ref evaluate(context const &ctx) const; }; class constructor_declaration : public expression { public: typedef method::parameter_name_list parameter_name_list; private: parameter_name_list ParameterNameList; ref Body; public: constructor_declaration(parameter_name_list const &pnames, ref body,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_class_declaration : public expression { typedef vector > declaration_list; string Identifier; ref SuperClass; ref ConstructorDeclaration; declaration_list StaticMethodList; declaration_list MethodList; declaration_list StaticVariableList; declaration_list VariableList; public: js_class_declaration(string const &id,ref superclass, code_location const &loc); ref evaluate(context const &ctx) const; void setConstructor(ref decl); void addStaticMethod(ref decl); void addMethod(ref decl); void addStaticVariable(ref decl); void addVariable(ref decl); }; // instructions --------------------------------------------------------- class instruction_list : public expression { typedef vector > expression_list; expression_list ExpressionList; public: instruction_list(code_location const &loc) : expression(loc) { } ref evaluate(context const &ctx) const; void add(ref expr); }; class scoped_instruction_list : public instruction_list { public: scoped_instruction_list(code_location const &loc) : instruction_list(loc) { } ref evaluate(context const &ctx) const; }; class js_if : public expression { ref Conditional; ref IfExpression; ref IfNotExpression; public: js_if(ref cond,ref ifex,ref ifnotex,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_while : public expression { ref Conditional; ref LoopExpression; bool HasLabel; string Label; public: js_while(ref cond,ref loopex,code_location const &loc); js_while(ref cond,ref loopex,string const &Label,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_do_while : public expression { ref Conditional; ref LoopExpression; bool HasLabel; string Label; public: js_do_while(ref cond,ref loopex,code_location const &loc); js_do_while(ref cond,ref loopex,string const &Label,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_for : public expression { ref Initialization; ref Conditional; ref Update; ref LoopExpression; bool HasLabel; string Label; public: js_for(ref init,ref cond,ref update,ref loop,code_location const &loc); js_for(ref init,ref cond,ref update,ref loop,string const &label,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_for_in : public expression { ref Iterator; ref Array; ref LoopExpression; bool HasLabel; string Label; public: js_for_in(ref iter,ref array,ref loop,code_location const &loc); js_for_in(ref iter,ref array,ref loop,string const &label,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_return : public expression { ref ReturnValue; public: js_return(ref retval,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_break : public expression { bool HasLabel; string Label; public: js_break(code_location const &loc); js_break(string const &label,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_continue : public expression { bool HasLabel; string Label; public: js_continue(code_location const &loc); js_continue(string const &label,code_location const &loc); ref evaluate(context const &ctx) const; }; class break_label : public expression { string Label; ref Expression; public: break_label(string const &label,ref expr,code_location const &loc); ref evaluate(context const &ctx) const; }; class js_switch : public expression { bool HasLabel; string Label; ref Discriminant; struct case_label { ref DiscriminantValue; ref Expression; }; typedef vector case_list; case_list CaseList; public: js_switch(ref discriminant,code_location const &loc); js_switch(ref discriminant,string const &label,code_location const &loc); ref evaluate(context const &ctx) const; void addCase(ref dvalue,ref expr); }; } } #endif