Skip to content

Commit

Permalink
add an Immutable proxy builder. cleanup and streamline the decorator …
Browse files Browse the repository at this point in the history
…builder
  • Loading branch information
Whiteknight committed Mar 12, 2011
1 parent 9844036 commit 7a4244c
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 55 deletions.
3 changes: 2 additions & 1 deletion setup.winxed
Expand Up @@ -103,7 +103,8 @@ function main[main](argv) {
"proxy/builder/Array",
"proxy/builder/PMCKeyedHash",
"proxy/builder/StringKeyedHash",
"proxy/builder/Passthrough"
"proxy/builder/Passthrough",
"proxy/builder/Immutable"
);

// A testing library for writing and running unit tests.
Expand Down
56 changes: 12 additions & 44 deletions src/decorate/Builder.winxed
Expand Up @@ -2,69 +2,42 @@ namespace Rosella { namespace Decorator
{
class Builder : Rosella.Proxy.Builder
{
var immutable;

function BUILD(int immutable [optional], int has_i [opt_flag])
{
if (has_i && immutable)
self.immutable = 1;
else
self.immutable = 0;
}

function setup_proxy_class(var target_class, var proxy_class)
{
using Rosella.Proxy.add_proxy_class_private_attr;
using Rosella.Proxy.add_proxy_class_public_attr;

// This should transparently pass through all other vtables.
proxy_class.add_parent(target_class);

add_proxy_class_private_attr(proxy_class, "methods");
add_proxy_class_private_attr(proxy_class, "attributes");
add_proxy_class_private_attr(proxy_class, "target");
add_proxy_class_private_attr(proxy_class, "decorator_methods");
add_proxy_class_private_attr(proxy_class, "decorator_attributes");

using Rosella.Decorator.Builder.intercept_find_method;
proxy_class.add_vtable_override("find_method", intercept_find_method);

using Rosella.Decorator.Builder.intercept_get_attr_str;
proxy_class.add_vtable_override("get_attr_str", intercept_get_attr_str);

if (self.immutable) {
using Rosella.Decorator.Builder.intercept_immutable;
proxy_class.add_vtable_override("set_attr_str", intercept_immutable);
// TODO: For real immutability we should intercept set_string_native,
// set_integer_native, set_number_native, etc.
} else {
using Rosella.Decorator.Builder.intercept_set_attr_str;
proxy_class.add_vtable_override("set_attr_str", intercept_set_attr_str);
}
using Rosella.Decorator.Builder.intercept_set_attr_str;
proxy_class.add_vtable_override("set_attr_str", intercept_set_attr_str);
}

function intercept_find_method[nsentry](string name)
{
using Rosella.Proxy.get_proxy_private_attr;
var methods = get_proxy_private_attr(self, "methods");
var methods = get_proxy_private_attr(self, "decorator_methods");
if (exists methods[name])
return methods[name];
var target = get_proxy_private_attr(self, "target");
var method = find_method(target, name);
return function(var p [slurpy], var n [slurpy,named]) {
var me = null;
${ shift me, p };
return self.*method(p:[flat], n:[flat,named]);
};
var target_class = get_proxy_private_attr(self, "target_class");
return target_class.find_method(name);
}

function intercept_get_attr_str[nsentry](string name)
{
using Rosella.Proxy.get_proxy_private_attr;
if (name == "proxy")
return get_proxy_private_attr(self, "target");
var attrs = get_proxy_private_attr(self, "attributes");
return get_proxy_private_attr(self, "target_object");
var attrs = get_proxy_private_attr(self, "decorator_attributes");
if (exists attrs[name])
return attrs[name];
var target = get_proxy_private_attr(self, "target");
var target = get_proxy_private_attr(self, "target_object");
var value = null;
${ getattribute value, target, name };
return value;
Expand All @@ -73,18 +46,13 @@ namespace Rosella { namespace Decorator
function intercept_set_attr_str[nsentry](string name, var value)
{
using Rosella.Proxy.get_proxy_private_attr;
var attrs = get_proxy_private_attr(self, "attributes");
var attrs = get_proxy_private_attr(self, "decorator_attributes");
if (exists attrs[name])
attrs[name] = value;
else {
var target = get_proxy_private_attr(self, "target");
var target = get_proxy_private_attr(self, "target_object");
${ setattribute target, name, value };
}
}

function intercept_immutable[nsentry](var args [slurpy])
{
die("Cannot modify values of an immutable object");
}
}
}}
16 changes: 6 additions & 10 deletions src/decorate/Factory.winxed
Expand Up @@ -6,17 +6,14 @@ namespace Rosella { namespace Decorator
var methods;
var attributes;

function BUILD(var target_type, var methods, var attrs,
int is_immutable [optional,named], int has_is_i [opt_flag])
function BUILD(var target_type, var methods, var attrs)
{
using Rosella.build;
self.methods = methods;
self.attributes = attrs;
int immutable = 0;
if (has_is_i && is_immutable)
immutable = 1;
var builders = [
build(class Rosella.Decorator.Builder, immutable)
build(class Rosella.Proxy.Builder.Passthrough),
build(class Rosella.Decorator.Builder)
];
self.proxy_factory = build(class Rosella.Proxy.Factory, target_type, builders);
}
Expand All @@ -25,10 +22,9 @@ namespace Rosella { namespace Decorator
{
using Rosella.Proxy.set_proxy_private_attr;

var proxy = self.proxy_factory.create(null);
set_proxy_private_attr(proxy, "methods", self.methods);
set_proxy_private_attr(proxy, "attributes", self.attributes);
set_proxy_private_attr(proxy, "target", target);
var proxy = self.proxy_factory.create(null, target);
set_proxy_private_attr(proxy, "decorator_methods", self.methods);
set_proxy_private_attr(proxy, "decorator_attributes", self.attributes);
return proxy;
}

Expand Down
21 changes: 21 additions & 0 deletions src/proxy/builder/Immutable.winxed
@@ -0,0 +1,21 @@
namespace Rosella { namespace Proxy { namespace Builder
{
class Immutable : Rosella.Proxy.Builder
{
function setup_proxy_class(var target_class, var proxy_class)
{
using Rosella.Proxy.Builder.Immutable.intercept_immutable;
proxy_class.add_vtable_override("set_attr_str", intercept_immutable);
proxy_class.add_vtable_override("set_integer_native", intercept_immutable);
proxy_class.add_vtable_override("set_string_native", intercept_immutable);
proxy_class.add_vtable_override("set_number_native", intercept_immutable);
proxy_class.add_vtable_override("set_pmc", intercept_immutable);
proxy_class.add_vtable_override("assign_pmc", intercept_immutable);
}

function intercept_immutable[nsentry](var args [slurpy])
{
die("Cannot modify values of an immutable object");
}
}
}}}

0 comments on commit 7a4244c

Please sign in to comment.