StringConstructor(ObjectValue* string) :
        string(string),
        arguments(new FormalParameterList),
        prototype(new ObjectValue)
    {
        ObjectValue* function = static_cast<ObjectValue*>(getGlobal()->get("Function"));

        arguments->add(new Identifier("value"));
        prototype->put("constructor", string);
        prototype->setPrototype(function->getPrototype()->getPrototype());

        for (int i = 0; i < StringMethod::methodCount(); ++i)
        {
            ObjectValue* function = new ObjectValue;
            StringMethod* method = new StringMethod(function, i);
            function->setCode(method);
            prototype->put(method->name(), function);
        }

        string->setParameterList(arguments);
        string->setScope(getGlobal());
        string->put("prototype", prototype);
        string->setPrototype(function->getPrototype());

        for (int i = 0; i < StringConstructorMethod::methodCount(); ++i)
        {
            ObjectValue* function = new ObjectValue;
            StringConstructorMethod* method = new StringConstructorMethod(function, i);
            function->setCode(method);
            string->put(method->name(), function);
        }
    }
    CompletionType evaluate()
    {
        Value* value = getScopeChain()->get("iid");
        if (!value->isString())
        {
            throw getErrorInstance("TypeError");
        }

        const char* iid = value->toString().c_str();

        Reflect::Interface interface;
        try
        {
            interface = es::getInterface(iid);
        }
        catch (...)
        {
            throw getErrorInstance("TypeError");
        }

        // Construct Interface Object
        ObjectValue* object = new ObjectValue;
        object->setCode(new InterfaceConstructor(object, iid));
        object->setPrototype(prototype);
        return CompletionType(CompletionType::Return, object, "");
    }
    ErrorConstructor(ObjectValue* error, const char* name, ObjectValue* function) :
        name(new StringValue(name)),
        arguments(new FormalParameterList),
        prototype(new ErrorValue)
    {
        arguments->add(new Identifier("message"));
        prototype->put("name", this->name);
        prototype->put("constructor", error);
        if (strcmp(name, "Error") == 0)
        {
            prototype->setPrototype(function->getPrototype()->getPrototype());
            for (int i = 0; i < ErrorMethod::methodCount(); ++i)
            {
                ObjectValue* function = new ObjectValue;
                ErrorMethod* method = new ErrorMethod(function, i);
                function->setCode(method);
                prototype->put(method->name(), function);
            }
        }
        else
        {
            prototype->setPrototype(getGlobal()->get("Error")->get("prototype"));
        }

        error->setParameterList(arguments);
        error->setScope(global);
        error->put("prototype", prototype);
        error->setPrototype(function->getPrototype());
    }
ObjectValue* constructSystemObject(void* system)
{
    for (es::InterfaceData* data = es::interfaceData; data->iid; ++data)
    {
        // Construct Default Interface Object
        Reflect::Interface interface = es::getInterface(data->iid());
        PRINTF("%s\n", interface.getName().c_str());
        ObjectValue* object = new ObjectValue;
        object->setCode(new InterfaceConstructor(object, interface.getQualifiedName()));
        object->setPrototype(getGlobal()->get("InterfaceStore")->getPrototype());
        getGlobal()->put(interface.getName(), object);
    }

    System()->addRef();
    ObjectValue* object = new InterfacePointerValue(System());
    object->setPrototype(getGlobal()->get("CurrentProcess")->get("prototype"));
    return object;
}
ObjectValue* constructInterfaceObject()
{
    ObjectValue* object = new ObjectValue;
    object->setCode(new InterfaceStoreConstructor(object));
    return object;
}
    InterfaceConstructor(ObjectValue* object, std::string iid) :
        constructor(object),
        arguments(new FormalParameterList),
        prototype(new InterfacePrototypeValue),
        iid(iid)
    {
        arguments->add(new Identifier("object"));

        object->setParameterList(arguments);
        object->setScope(getGlobal());

        Reflect::Interface interface = es::getInterface(iid.c_str());
        // PRINTF("interface: %s\n", interface.getName().c_str());
        for (int i = 0; i < interface.getMethodCount(); ++i)
        {
            // Construct Method object
            Reflect::Method method(interface.getMethod(i));
            if (prototype->hasProperty(method.getName()))
            {
                if (method.isOperation())
                {
                    // XXX Currently overloaded functions are just ignored.
                }
                else
                {
                    AttributeValue* attribute = static_cast<AttributeValue*>(prototype->get(method.getName()));
                    if (method.isGetter())
                    {
                        attribute->addGetter(i);
                    }
                    else
                    {
                        attribute->addSetter(i);
                    }
                }
            }
            else
            {
                if (method.isOperation())
                {
                    ObjectValue* function = new ObjectValue;
                    function->setCode(new InterfaceMethodCode(function, iid.c_str(), i));
                    prototype->put(method.getName(), function);
#if 0
                    if (method.isIndexGetter())
                    {
                        AttributeGetterValue* getter = new AttributeGetterValue(iid, i);
                        prototype->setOpObject(InterfacePrototypeValue::IndexGetter, getter);
                    }
                    else if (method.isIndexSetter())
                    {
                        AttributeSetterValue* setter = new AttributeSetterValue(iid, i);
                        prototype->setOpObject(InterfacePrototypeValue::IndexSetter, setter);
                    }
                    else if (method.isNameGetter())
                    {
                        AttributeGetterValue* getter = new AttributeGetterValue(iid, i);
                        prototype->setOpObject(InterfacePrototypeValue::NameGetter, getter);
                    }
                    else if (method.isNameSetter())
                    {
                        AttributeSetterValue* setter = new AttributeSetterValue(iid, i);
                        prototype->setOpObject(InterfacePrototypeValue::NameSetter, setter);
                    }
#endif
                }
                else
                {
                    // method is an attribute
                    AttributeValue* attribute = new AttributeValue(iid.c_str());
                    if (method.isGetter())
                    {
                        attribute->addGetter(i);
                    }
                    else
                    {
                        attribute->addSetter(i);
                    }
                    prototype->put(method.getName(), attribute);
                }
            }
        }

        if (interface.getQualifiedSuperName() == "")
        {
            prototype->setPrototype(getGlobal()->get("InterfaceStore")->getPrototype()->getPrototype());
        }
        else
        {
            Reflect::Interface super = es::getInterface(interface.getQualifiedSuperName().c_str());
            prototype->setPrototype(getGlobal()->get(super.getName())->get("prototype"));
        }

        // Create Interface.prototype
        prototype->put("constructor", object);
        object->put("prototype", prototype);
    }
void constructGlobalObject()
{
    global = new ObjectValue;

    global->put("undefined", UndefinedValue::getInstance());
    global->put("NaN", new NumberValue(NAN));
    global->put("Infinity", new NumberValue(INFINITY));

    // Register function properties of the Global object
    for (int i = 0; i < GlobalMethod::methodCount(); ++i)
    {
        ObjectValue* function = new ObjectValue;
        GlobalMethod* method = new GlobalMethod(function, i);
        function->setCode(method);
        global->put(method->name(), function);
    }

    // Register Function
    ObjectValue* function = constructFunctionConstructor();
    global->put("Function", function);

    // Register Object
    ObjectValue* object = constructObjectConstructor();
    global->put("Object", object);

    function->getPrototype()->setPrototype(object->get("prototype"));

    // Register Error objects
    ObjectValue* error;

    error = new ObjectValue;
    error->setCode(new ErrorConstructor(error, "Error", function));
    global->put("Error", error);

    error = new ObjectValue;
    error->setCode(new ErrorConstructor(error, "EvalError", function));
    global->put("EvalError", error);

    error = new ObjectValue;
    error->setCode(new ErrorConstructor(error, "RangeError", function));
    global->put("RangeError", error);

    error = new ObjectValue;
    error->setCode(new ErrorConstructor(error, "ReferenceError", function));
    global->put("ReferenceError", error);

    error = new ObjectValue;
    error->setCode(new ErrorConstructor(error, "SyntaxError", function));
    global->put("SyntaxError", error);

    error = new ObjectValue;
    error->setCode(new ErrorConstructor(error, "TypeError", function));
    global->put("TypeError", error);

    error = new ObjectValue;
    error->setCode(new ErrorConstructor(error, "URIError", function));
    global->put("URIError", error);

    // Register String object
    ObjectValue* string = constructStringObject();
    global->put("String", string);

    // Register Math object
    ObjectValue* math = constructMathObject();
    global->put("Math", math);

    // Register Array object
    ObjectValue* array = constructArrayObject();
    global->put("Array", array);

    // Register Boolean object
    ObjectValue* boolean = constructBooleanObject();
    global->put("Boolean", boolean);

    // Register RegExp object
    ObjectValue* regexp = constructRegExpObject();
    global->put("RegExp", regexp);

    // Register Date object
    ObjectValue* date = constructDateObject();
    global->put("Date", date);

    // Register Interface Store object
    global->put("InterfaceStore", constructInterfaceObject());

    // Register System object
    global->put("System", constructSystemObject(0));

    // Register Number object
    global->put("Number", constructNumberObject());
}
ObjectValue* constructStringObject()
{
    ObjectValue* string = new ObjectValue;
    string->setCode(new StringConstructor(string));
    return string;
}