Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of .subst for strings in rakudo #221

Closed
p6rt opened this issue Aug 9, 2008 · 10 comments
Closed

Implementation of .subst for strings in rakudo #221

p6rt opened this issue Aug 9, 2008 · 10 comments

Comments

@p6rt
Copy link

p6rt commented Aug 9, 2008

Migrated from rt.perl.org#57756 (status was 'resolved')

Searchable as RT57756$

@p6rt
Copy link
Author

p6rt commented Aug 9, 2008

From @masak

Patch attached.

I've also fudged t/builtins/strings/subst.t in the Pugs repo, so that
it passes with this patch applied.

@p6rt
Copy link
Author

p6rt commented Aug 9, 2008

From @masak

subst.patch
Index: src/classes/Str.pir
===================================================================
--- src/classes/Str.pir	(revision 30136)
+++ src/classes/Str.pir	(working copy)
@@ -205,7 +205,85 @@
     .return(retv)
 .end
 
+=item subst
 
+ our Str method Str::subst ( Str $string: Str $substring, Str $replacement )
+ our Str method Str::subst ( Str $string: Code $regexp,   Str $replacement )
+
+Replaces the first occurrence of a given substring or a regular expression
+match with some other substring.
+
+Partial implementation. The :g modifier on regexps doesn't work, for example.
+
+=cut
+
+.sub subst :method :multi('Perl6Str','Perl6Str')
+    .param string substring
+    .param string replacement
+    .local int pos
+    .local int pos_after
+    .local pmc retv
+
+    retv = new 'Perl6Str'
+
+    $S0 = self
+    pos = index $S0, substring
+    if pos < 0 goto no_match
+
+    pos_after = pos
+    $I0 = length replacement
+    add pos_after, $I0
+
+    $S1 = substr $S0, 0, pos
+    $S2 = substr $S0, pos_after
+    concat retv, $S1
+    concat retv, replacement
+    concat retv, $S2
+
+    goto done
+
+  no_match:
+    retv = self
+
+  done:
+    .return(retv)
+.end
+
+.sub subst :method :lex :multi('Perl6Str','Sub','Perl6Str')
+    .param pmc regexp
+    .param string replacement
+    .local int pos
+    .local int pos_after
+    .local pmc retv
+    .local pmc match
+
+    retv = new 'Perl6Str'
+
+    new $P14, "Perl6Scalar"
+    .lex "$/", $P14
+
+    match = regexp.'ACCEPTS'(self)
+    unless match goto no_match
+    pos = match.'from'()
+    pos_after = match.'to'()
+
+    $S0 = self
+    $S1 = substr $S0, 0, pos
+    $S2 = substr $S0, pos_after
+    concat retv, $S1
+    concat retv, replacement
+    concat retv, $S2
+
+    goto done
+
+  no_match:
+    retv = self
+
+  done:
+    .return(retv)
+.end
+
+
 =item perl()
 
 Returns a Perl representation of the Str.

@p6rt
Copy link
Author

p6rt commented Aug 10, 2008

From @pmichaud

On Sat, Aug 09, 2008 at 10​:24​:20AM -0700, Carl Mäsak wrote​:

Patch attached.

I've also fudged t/builtins/strings/subst.t in the Pugs repo, so that
it passes with this patch applied.

Thanks! A couple of items​:

1. I suspect this method really belongs in src/builtins/any-str.pir
  instead of the C<Str> class, so that we can do replacements on
  the stringification of any invocant (not just C<Str> objects).

2. The :multi() is likely incorrect, even as a method of C<Str>.
  Any object should be usable as a pattern/replacement, not just
  C<Str> objects. For example, I think that these ought to
  be equivalent​:

  $foo.subst('3', '4')
  $foo.subst(<3>, <4>)
  $foo.subst(3, 4)

  I.e., the caller shouldn't have to be concerned about coercing
  the parameters to C<Str> objects in order to invoke the builtin
  C<subst> method.

Thanks again!

Pm

@p6rt
Copy link
Author

p6rt commented Aug 10, 2008

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Aug 10, 2008

From @masak

Patrick (>)​:

1. I suspect this method really belongs in src/builtins/any-str.pir
instead of the C<Str> class, so that we can do replacements on
the stringification of any invocant (not just C<Str> objects).

2. The :multi() is likely incorrect, even as a method of C<Str>.
Any object should be usable as a pattern/replacement, not just
C<Str> objects. For example, I think that these ought to
be equivalent​:

      $foo\.subst\('3', '4'\)
      $foo\.subst\(\<3>, \<4>\)
      $foo\.subst\(3, 4\)

I.e., the caller shouldn't have to be concerned about coercing
the parameters to C<Str> objects in order to invoke the builtin
C<subst> method.

I agree. I also like the new, more flexible behaviour much better​:

$ ./perl6 -e 'say (2 ** 5).subst(/3/, 4)'
42

New patch attached.

@p6rt
Copy link
Author

p6rt commented Aug 10, 2008

From @masak

subst-any.patch
Index: src/builtins/any-str.pir
===================================================================
--- src/builtins/any-str.pir	(revision 30155)
+++ src/builtins/any-str.pir	(working copy)
@@ -325,6 +325,84 @@
     die "Must pass a List of Pairs for transliteration"
 .end
 
+=item subst
+ 
+ our Str method Str::subst ( Any $string: Any $substring, Any $replacement )
+ our Str method Str::subst ( Any $string: Code $regexp,   Any $replacement )
+
+Replaces the first occurrence of a given substring or a regular expression
+match with some other substring.
+
+Partial implementation. The :g modifier on regexps doesn't work, for example.
+
+=cut
+
+.sub subst :method :multi(_, _, _)
+    .param string substring
+    .param string replacement
+    .local int pos
+    .local int pos_after
+    .local pmc retv
+
+    retv = new 'Perl6Str'
+
+    $S0 = self
+    pos = index $S0, substring
+    if pos < 0 goto no_match
+
+    pos_after = pos
+    $I0 = length replacement
+    add pos_after, $I0
+
+    $S1 = substr $S0, 0, pos
+    $S2 = substr $S0, pos_after
+    concat retv, $S1
+    concat retv, replacement
+    concat retv, $S2
+
+    goto done
+
+  no_match:
+    retv = self
+
+  done:
+    .return(retv)
+.end
+
+.sub subst :method :lex :multi(_, 'Sub', _)
+    .param pmc regexp
+    .param string replacement
+    .local int pos
+    .local int pos_after
+    .local pmc retv
+    .local pmc match
+
+    retv = new 'Perl6Str'
+
+    new $P14, "Perl6Scalar"
+    .lex "$/", $P14
+
+    match = regexp.'ACCEPTS'(self)
+    unless match goto no_match
+    pos = match.'from'()
+    pos_after = match.'to'()
+
+    $S0 = self
+    $S1 = substr $S0, 0, pos
+    $S2 = substr $S0, pos_after
+    concat retv, $S1
+    concat retv, replacement
+    concat retv, $S2
+
+    goto done
+
+  no_match:
+    retv = self
+
+  done:
+    .return(retv)
+.end
+
 # Local Variables:
 #   mode: pir
 #   fill-column: 100

@p6rt
Copy link
Author

p6rt commented Aug 12, 2008

From @masak

Just tracked down a slight braino in the Str implementation of subst.
The new attached patch fixes this.

@p6rt
Copy link
Author

p6rt commented Aug 12, 2008

From @masak

subst-oops.patch
Index: src/builtins/any-str.pir
===================================================================
--- src/builtins/any-str.pir	(revision 30183)
+++ src/builtins/any-str.pir	(working copy)
@@ -325,6 +325,84 @@
     die "Must pass a List of Pairs for transliteration"
 .end
 
+=item subst
+ 
+ our Str method Str::subst ( Any $string: Any $substring, Any $replacement )
+ our Str method Str::subst ( Any $string: Code $regexp,   Any $replacement )
+
+Replaces the first occurrence of a given substring or a regular expression
+match with some other substring.
+
+Partial implementation. The :g modifier on regexps doesn't work, for example.
+
+=cut
+
+.sub subst :method :multi(_, _, _)
+    .param string substring
+    .param string replacement
+    .local int pos
+    .local int pos_after
+    .local pmc retv
+
+    retv = new 'Perl6Str'
+
+    $S0 = self
+    pos = index $S0, substring
+    if pos < 0 goto no_match
+
+    pos_after = pos
+    $I0 = length substring
+    add pos_after, $I0
+
+    $S1 = substr $S0, 0, pos
+    $S2 = substr $S0, pos_after
+    concat retv, $S1
+    concat retv, replacement
+    concat retv, $S2
+
+    goto done
+
+  no_match:
+    retv = self
+
+  done:
+    .return(retv)
+.end
+
+.sub subst :method :lex :multi(_, 'Sub', _)
+    .param pmc regexp
+    .param string replacement
+    .local int pos
+    .local int pos_after
+    .local pmc retv
+    .local pmc match
+
+    retv = new 'Perl6Str'
+
+    new $P14, "Perl6Scalar"
+    .lex "$/", $P14
+
+    match = regexp.'ACCEPTS'(self)
+    unless match goto no_match
+    pos = match.'from'()
+    pos_after = match.'to'()
+
+    $S0 = self
+    $S1 = substr $S0, 0, pos
+    $S2 = substr $S0, pos_after
+    concat retv, $S1
+    concat retv, replacement
+    concat retv, $S2
+
+    goto done
+
+  no_match:
+    retv = self
+
+  done:
+    .return(retv)
+.end
+
 # Local Variables:
 #   mode: pir
 #   fill-column: 100

@p6rt
Copy link
Author

p6rt commented Aug 23, 2008

From @moritz

Applied in r30467, thank you very much.

@p6rt
Copy link
Author

p6rt commented Aug 23, 2008

@moritz - Status changed from 'open' to 'resolved'

@p6rt p6rt closed this as completed Aug 23, 2008
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant