<commit_before>module Twostroke::Runtime
  Lib.register do |scope|
    obj = Types::StringObject.constructor_function
    scope.set_var "String", obj
    
    proto = Types::Object.new
    # String.prototype.toString
    proto.proto_put "toString", Types::Function.new(->(scope, this, args) {
        if this.is_a?(Types::StringObject)
          Types::String.new(this.string)
        else
          Lib.throw_type_error "String.prototype.toString is not generic"
        end
      }, nil, "toString", [])
    # String.prototype.valueOf
    proto.proto_put "valueOf", Types::Function.new(->(scope, this, args) { this.is_a?(Types::StringObject) ? Types::String.new(this.string) : Types.to_primitive(this) }, nil, "valueOf", [])
    # String.prototype.split
    proto.proto_put "split", Types::Function.new(->(scope, this, args) {
        sep = Types.to_string(args[0] || Types::Undefined.new).string
        str = Types.to_string(this).string
        Types::Array.new (if args[1]
            str.split sep, Types.to_uint32(args[1])
          else
            str.split sep
          end).map { |s| Types::String.new s }
      }, nil, "split", [])
    # String.prototype.length
    proto.define_own_property "length", get: ->(this) { Types::Number.new this.string.size }, writable: false, enumerable: false
    # String.prototype.replace
    proto.proto_put "replace", Types::Function.new(->(scope, this, args) {
        sobj = Types.to_string(this)
        s = sobj.string
        
        find = args[0] || Types::Undefined.new
        re = find.is_a?(Types::RegExp) ? find.regexp : Regexp.new(Regexp.escape Types.to_string(find).string)
        global = find.is_a?(Types::RegExp) && find.global
        
        replace = args[1] || Types::Undefined.new
        callback = replace.respond_to?(:call) ? replace : ->(*_) { replace }
        
        retn = ""
        offset = 0
        loop do
          md = re.match s, offset
          break unless md && (offset.zero? || global)
          retn << md.pre_match[offset..-1]
          retn << Types.to_string(callback.(scope, nil, [*md.to_a.map { |c| Types::String.new c }, Types::Number.new(md.begin 0), sobj])).string
          offset = md.end 0
        end
        
        retn << s[offset..-1]

        Types::String.new retn
      }, nil, "replace", [])
    # String.prototype.slice
    proto.proto_put "slice", Types::Function.new(->(scope, this, args) {
        sobj = Types.to_string(this)
        s = sobj.string
        if args[0].nil?
          sobj
        else
          start = Types.to_int32 args[0]
          if args[1]
            fin = Types.to_int32 args[1]
            Types::String.new s[start...fin]
          else
            Types::String.new s[start..-1]<commit_msg>substring<commit_after>module Twostroke::Runtime
  Lib.register do |scope|
    obj = Types::StringObject.constructor_function
    scope.set_var "String", obj
    
    proto = Types::Object.new
    # String.prototype.toString
    proto.proto_put "toString", Types::Function.new(->(scope, this, args) {
        if this.is_a?(Types::StringObject)
          Types::String.new(this.string)
        else
          Lib.throw_type_error "String.prototype.toString is not generic"
        end
      }, nil, "toString", [])
    # String.prototype.valueOf
    proto.proto_put "valueOf", Types::Function.new(->(scope, this, args) { this.is_a?(Types::StringObject) ? Types::String.new(this.string) : Types.to_primitive(this) }, nil, "valueOf", [])
    # String.prototype.split
    proto.proto_put "split", Types::Function.new(->(scope, this, args) {
        sep = Types.to_string(args[0] || Types::Undefined.new).string
        str = Types.to_string(this).string
        Types::Array.new (if args[1]
            str.split sep, Types.to_uint32(args[1])
          else
            str.split sep
          end).map { |s| Types::String.new s }
      }, nil, "split", [])
    # String.prototype.length
    proto.define_own_property "length", get: ->(this) { Types::Number.new this.string.size }, writable: false, enumerable: false
    # String.prototype.replace
    proto.proto_put "replace", Types::Function.new(->(scope, this, args) {
        sobj = Types.to_string(this)
        s = sobj.string
        
        find = args[0] || Types::Undefined.new
        re = find.is_a?(Types::RegExp) ? find.regexp : Regexp.new(Regexp.escape Types.to_string(find).string)
        global = find.is_a?(Types::RegExp) && find.global
        
        replace = args[1] || Types::Undefined.new
        callback = replace.respond_to?(:call) ? replace : ->(*_) { replace }
        
        retn = ""
        offset = 0
        loop do
          md = re.match s, offset
          break unless md && (offset.zero? || global)
          retn << md.pre_match[offset..-1]
          retn << Types.to_string(callback.(scope, nil, [*md.to_a.map { |c| Types::String.new c }, Types::Number.new(md.begin 0), sobj])).string
          offset = md.end 0
        end
        
        retn << s[offset..-1]

        Types::String.new retn
      }, nil, "replace", [])
    # String.prototype.substring
    proto.proto_put "substring", Types::Function.new(->(scope, this, args) {
        indexA = args[0] && Types.to_int32(args[0])
        indexB = args[1] && Types.to_int32(args[1])
        str = Types.to_string(this).string
        return Types::String.new(str) unless indexA
        return Types::String.new(str[indexA..-1] || "") unless indexB
        indexA, indexB = indexB, indexA if indexB < indexA
        Types::String.new(str[indexA...indexB] || "")
      }, nil, "substring", [])
    # String.prototype.slice
    proto.proto_put "slice", Types::Function.new(->(scope, this, args) {
        sobj = Types.to_string(this)
        s = sobj.string
        if args[0].nil?
          sobj
        else
          start = Types.to_int32 args[0]
          if args[1]
            fin = Types.to_int32 args[1]
            Types::String.new s[start...fin]
          else
            Types::String.new s[start..-1]
{'fraction_non_alphanumeric': 0.15142428785607195, 'fraction_numerical': 0.00849575212393803, 'mean_word_length': 2.3429844097995547, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3728434', 'n_tokens_mistral': 1917, 'n_tokens_neox': 1906, 'n_words': 369}