Skip to content
Permalink
Browse files

Merge pull request #675 from topazproject/tim/String#replace

Add String#replace
  • Loading branch information
alex committed May 11, 2013
2 parents b3cd7ae + 09647e2 commit 77ef2dc113c204d6e9f66e32d0edabd3941579b3
@@ -162,4 +162,12 @@ def strip
duplicate.strip!
duplicate
end

def replace(other)
raise RuntimeError.new("can't modify frozen #{self.class}") if frozen?
other = Topaz.convert_type(other, String, :to_str)
Topaz.infect(self, other)
clear
insert(0, other)
end
end
@@ -1,11 +1 @@
fails:String#replace returns self
fails:String#replace replaces the content of self with other
fails:String#replace taints self if other is tainted
fails:String#replace does not untaint self if other is untainted
fails:String#replace untrusts self if other is untrusted
fails:String#replace does not trust self if other is trusted
fails:String#replace replaces the encoding of self with that of other
fails:String#replace tries to convert other to string using to_str
fails:String#replace raises a TypeError if other can't be converted to string
fails:String#replace raises a RuntimeError on a frozen instance that is modified
fails:String#replace raises a RuntimeError on a frozen instance when self-replacing
@@ -100,9 +100,6 @@ def change_class(self, space, w_cls):
def copy_attrs(self, space, w_obj, w_target):
pass

def copy_flags(self, space, w_obj, w_target):
pass

def length(self):
return 0

@@ -151,9 +148,6 @@ def copy_attrs(self, space, w_obj, w_target):
self.prev.copy_attrs(space, w_obj, w_target)
w_target.set_instance_var(space, self.name, w_obj.storage[self.pos])

def copy_flags(self, space, w_obj, w_target):
self.prev.copy_flags(space, w_obj, w_target)


class FlagNode(StorageNode):
@jit.elidable
@@ -177,9 +171,3 @@ def change_class(self, space, w_cls):

def copy_attrs(self, space, w_obj, w_target):
self.prev.copy_attrs(space, w_obj, w_target)

def copy_flags(self, space, w_obj, w_target):
self.prev.copy_flags(space, w_obj, w_target)
if w_obj.storage[self.pos] is space.w_true:
# Only copy flags that are still set
w_target.set_flag(space, self.name)
@@ -262,8 +262,7 @@ def method_dup(self, space):
raise space.error(space.w_TypeError, "can't dup %s" % space.getclass(self).name)
w_dup = space.send(space.getnonsingletonclass(self), "allocate")
w_dup.copy_instance_vars(space, self)
w_dup.copy_flags(space, self)
w_dup.unset_flag(space, "frozen?")
space.infect(w_dup, self, freeze=False)
space.send(w_dup, "initialize_dup", [self])
return w_dup

@@ -275,7 +274,7 @@ def method_clone(self, space):
raise space.error(space.w_TypeError, "can't dup %s" % space.getclass(self).name)
w_dup = space.send(space.getnonsingletonclass(self), "allocate")
w_dup.copy_instance_vars(space, self)
w_dup.copy_flags(space, self)
space.infect(w_dup, self, freeze=True)
w_dup.copy_singletonclass(space, space.getsingletonclass(self))
space.send(w_dup, "initialize_clone", [self])
return w_dup
@@ -31,3 +31,8 @@ def method_convert_type(self, space, w_obj, w_type, method):
@moduledef.function("compare")
def method_compare(self, space, w_a, w_b, block=None):
return space.compare(w_a, w_b, block)

@moduledef.function("infect", taint="bool", untrust="bool", freeze="bool")
def method_infect(self, space, w_dest, w_src, taint=True, untrust=True, freeze=False):
space.infect(w_dest, w_src, taint=taint, untrust=untrust, freeze=freeze)
return self
@@ -181,8 +181,7 @@ def method_times(self, space, w_other):
if n < 0:
raise space.error(space.w_ArgumentError, "Count cannot be negative")
w_res = W_ArrayObject(space, self.items_w * n, space.getnonsingletonclass(self))
w_res.copy_flags(space, self)
w_res.unset_flag(space, "frozen?")
space.infect(w_res, self, freeze=False)
return w_res

@classdef.method("push")
@@ -249,13 +249,6 @@ def unset_flag(self, space, name):
def get_flag(self, space, name):
return self.flags.get(space, name) or space.w_false

def copy_flags(self, space, w_other):
assert isinstance(w_other, W_ModuleObject)
for key in w_other.flags:
w_value = w_other.flags.get(space, key)
if w_value is space.w_true:
self.set_flag(space, key)

def ancestors(self, include_singleton=True, include_self=True):
if include_self:
return [self] + self.included_modules
@@ -280,7 +280,3 @@ def unset_flag(self, space, name):
if idx != -1:
# Flags are by default unset, no need to add if unsetting
self.storage[idx] = space.w_false

def copy_flags(self, space, w_other):
assert isinstance(w_other, W_Object)
w_other.map.copy_flags(space, w_other, self)
@@ -713,6 +713,18 @@ def convert_type(self, w_obj, w_cls, method, raise_error=True):
else:
return w_res

def infect(self, w_dest, w_src, taint=True, untrust=True, freeze=False):
"""
By default copies tainted and untrusted state from src to dest.
Frozen state isn't copied by default, as this is the rarer case MRI.
"""
if taint and self.is_true(w_src.get_flag(self, "tainted?")):
w_dest.set_flag(self, "tainted?")
if untrust and self.is_true(w_src.get_flag(self, "untrusted?")):
w_dest.set_flag(self, "untrusted?")
if freeze and self.is_true(w_src.get_flag(self, "frozen?")):
w_dest.set_flag(self, "frozen?")

def any_to_s(self, w_obj):
return "#<%s:0x%x>" % (
self.obj_to_s(self.getnonsingletonclass(w_obj)),

0 comments on commit 77ef2dc

Please sign in to comment.
You can’t perform that action at this time.