The attribute `TextField::is_password` toggles hiding the content of the field using platform specific services. So on Android, not only is the text hidden but it also notifies the soft keyboard to behave accordingly.
In the future, we could add alternative modes for email entry and more.
Pull-Request: #1978
Reviewed-by: Jean Privat <jean@pryen.org>
var str = file.to_path.read_all
var parser = new MarkdownProcessor
+parser.no_location = true
for i in [1..n] do
print parser.process(str)
end
# Create a directory (and all intermediate directories if needed)
#
+ # The optional `mode` parameter specifies the permissions of the directory,
+ # the default value is `0o777`.
+ #
# Return an error object in case of error.
#
# assert "/etc/".mkdir != null
- fun mkdir: nullable Error
+ fun mkdir(mode: nullable Int): nullable Error
do
+ mode = mode or else 0o777
+
var dirs = self.split_with("/")
var path = new FlatBuffer
if dirs.is_empty then return null
if d.is_empty then continue
path.append(d)
path.add('/')
- var res = path.to_s.to_cstring.file_mkdir
+ var res = path.to_s.to_cstring.file_mkdir(mode)
if not res and error == null then
error = new IOError("Cannot create directory `{path}`: {sys.errno.strerror}")
end
return stat_element;
`}
- private fun file_mkdir: Bool `{ return !mkdir(self, 0777); `}
+ private fun file_mkdir(mode: Int): Bool `{ return !mkdir(self, mode); `}
private fun rmdir: Bool `{ return !rmdir(self); `}
#
# assert 3.is_prime
# assert not 1.is_prime
- # assert not 12.is_prime
+ # assert not 15.is_prime
fun is_prime: Bool
do
if self == 2 then
else if self <= 1 or self.is_even then
return false
end
- for i in [3..self.sqrt[ do
+ for i in [3..self.sqrt] do
if self % i == 0 then return false
end
return true
b.append("\\\\")
else if c.code_point < 32 then
b.add('\\')
- var oct = c.code_point.to_base(8, false)
+ var oct = c.code_point.to_base(8)
# Force 3 octal digits since it is the
# maximum allowed in the C specification
if oct.length == 1 then
b.add('\\')
b.add(c)
else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' or c == '=' then
- b.append("?{c.code_point.to_base(16, false)}")
+ b.append("?{c.code_point.to_base(16)}")
else
b.add(c)
end
# Returns a string describing error number
fun strerror: String do return strerror_ext.to_s
- # Fill `s` with the digits in base `base` of `self` (and with the '-' sign if 'signed' and negative).
+ # Fill `s` with the digits in base `base` of `self` (and with the '-' sign if negative).
# assume < to_c max const of char
- private fun fill_buffer(s: Buffer, base: Int, signed: Bool)
+ private fun fill_buffer(s: Buffer, base: Int)
do
var n: Int
# Sign
snprintf(nstr, strlen, "%ld", self);
`}
- # return displayable int in base base and signed
- fun to_base(base: Int, signed: Bool): String is abstract
+ # String representation of `self` in the given `base`
+ #
+ # ~~~
+ # assert 15.to_base(10) == "15"
+ # assert 15.to_base(16) == "f"
+ # assert 15.to_base(2) == "1111"
+ # assert (-10).to_base(3) == "-101"
+ # ~~~
+ fun to_base(base: Int): String
+ do
+ var l = digit_count(base)
+ var s = new Buffer
+ s.enlarge(l)
+ for x in [0..l[ do s.add(' ')
+ fill_buffer(s, base)
+ return s.to_s
+ end
+
# return displayable int in hexadecimal
#
# assert 1.to_hex == "1"
# assert (-255).to_hex == "-ff"
- fun to_hex: String do return to_base(16,false)
+ fun to_hex: String do return to_base(16)
end
redef class Float
# assert [1, 2, 3].join(":") == "1:2:3"
# assert [1..3].join(":") == "1:2:3"
# assert [1..3].join == "123"
- fun join(separator: nullable Text): String
+ #
+ # if `last_separator` is given, then it is used to separate the last element.
+ #
+ # assert [1, 2, 3, 4].join(", ", " and ") == "1, 2, 3 and 4"
+ fun join(separator: nullable Text, last_separator: nullable Text): String
do
if is_empty then return ""
var e = i.item
if e != null then s.append(e.to_s)
+ if last_separator == null then last_separator = separator
+
# Concat other items
i.next
while i.is_ok do
- if separator != null then s.append(separator)
e = i.item
- if e != null then s.append(e.to_s)
i.next
+ if i.is_ok then
+ if separator != null then s.append(separator)
+ else
+ if last_separator != null then s.append(last_separator)
+ end
+ if e != null then s.append(e.to_s)
end
return s.to_s
end
fun char_to_byte_index(index: Int): Int do
var dpos = index - _position
var b = _bytepos
+ var its = _items
- if dpos == 0 then return b
if dpos == 1 then
- b += _items.length_of_char_at(b)
+ if its[b] & 0x80u8 == 0x00u8 then
+ b += 1
+ else
+ b += its.length_of_char_at(b)
+ end
_bytepos = b
_position = index
return b
end
if dpos == -1 then
- b = _items.find_beginning_of_char_at(b - 1)
+ b = its.find_beginning_of_char_at(b - 1)
_bytepos = b
_position = index
return b
end
+ if dpos == 0 then return b
var ln = _length
var pos = _position
var delta_end = (ln - 1) - index
var delta_cache = (pos - index).abs
var min = delta_begin
- var its = _items
if delta_cache < min then min = delta_cache
if delta_end < min then min = delta_end
end
redef fun [](index) do
- assert index >= 0 and index < _length
+ var len = _length
+
+ # Statistically:
+ # * ~70% want the next char
+ # * ~23% want the previous
+ # * ~7% want the same char
+ #
+ # So it makes sense to shortcut early. And early is here.
+ var dpos = index - _position
+ var b = _bytepos
+ if dpos == 1 and index < len - 1 then
+ var its = _items
+ var c = its[b]
+ if c & 0x80u8 == 0x00u8 then
+ # We want the next, and current is easy.
+ # So next is easy to find!
+ b += 1
+ _position = index
+ _bytepos = b
+ # The rest will be done by `dpos==0` bellow.
+ dpos = 0
+ end
+ else if dpos == -1 and index > 1 then
+ var its = _items
+ var c = its[b-1]
+ if c & 0x80u8 == 0x00u8 then
+ # We want the previous, and it is easy.
+ b -= 1
+ dpos = 0
+ _position = index
+ _bytepos = b
+ return c.ascii
+ end
+ end
+ if dpos == 0 then
+ # We know what we want (+0 or +1) just get it now!
+ var its = _items
+ var c = its[b]
+ if c & 0x80u8 == 0x00u8 then return c.ascii
+ return items.char_at(b)
+ end
+
+ assert index >= 0 and index < len
return fetch_char_at(index)
end
#
# Very unsafe, make sure to have room for this char prior to calling this function.
private fun set_char_at(pos: Int, c: Char) do
+ if c.code_point < 128 then
+ self[pos] = c.code_point.to_b
+ return
+ end
var ln = c.u8char_len
native_set_char(pos, c, ln)
end
end
redef class Int
- redef fun to_base(base, signed)
- do
- var l = digit_count(base)
- var s = new FlatBuffer.from(" " * l)
- fill_buffer(s, base, signed)
- return s.to_s
- end
-
# return displayable int in base 10 and signed
#
# assert 1.to_s == "1"
# ~~~
var ext_mode = true
+ # Disable attaching MDLocation to Tokens
+ #
+ # Locations are useful for some tools but they may
+ # cause an important time and space overhead.
+ #
+ # Default = `false`
+ var no_location = false is writable
+
init do self.emitter = new MarkdownEmitter(self)
# Process the mardown `input` string and return the processed output.
c2 = ' '
end
- var loc = new MDLocation(
- current_loc.line_start,
- current_loc.column_start + pos,
- current_loc.line_start,
- current_loc.column_start + pos)
+ var loc
+ if no_location then
+ loc = null
+ else
+ loc = new MDLocation(
+ current_loc.line_start,
+ current_loc.column_start + pos,
+ current_loc.line_start,
+ current_loc.column_start + pos)
+ end
if c == '*' then
if c1 == '*' then
end
# Append `c` to current buffer.
- fun addc(c: Char) do add c.to_s
+ fun addc(c: Char) do
+ current_buffer.add c
+ end
# Append a "\n" line break.
- fun addn do add "\n"
+ fun addn do addc '\n'
end
# A Link Reference.
abstract class Token
# Location of `self` in the original input.
- var location: MDLocation
+ var location: nullable MDLocation
# Position of `self` in input independant from lines.
var pos: Int
if c == '\\' and pos + 1 < length then
pos = escape(out, self[pos + 1], pos)
else
- var end_reached = false
- for n in nend do
- if c == n then
- end_reached = true
- break
- end
- end
- if end_reached then break
+ for n in nend do if c == n then break label
out.add c
end
pos += 1
- end
+ end label
if pos == length then return -1
return pos
end
redef fun token_at(input, pos) do
var token = super
if token isa TokenNone then return token
- var res = "{token.class_name} at {token.location}"
+ var res = "{token.class_name} at {token.location or else "?"}"
var exp = test_stack.shift
print ""
print "EXP {exp}"
return r
end
- redef fun join(sep)
+ redef fun join(sep, last_sep)
do
mutex.lock
- var r = real_collection.join(sep)
+ var r = real_collection.join(sep, last_sep)
mutex.unlock
return r
end
else if node isa AClassdef then
# Automatic free init is always inlined since it is empty or contains only attribtes assigments
return true
+ else if node == null then
+ return true
else
abort
end
v.assign(v.frame.returnvar.as(not null), res)
else if mpropdef == mwritepropdef then
assert arguments.length == 2
- v.write_attribute(self.mpropdef.mproperty, arguments.first, arguments[1])
+ var recv = arguments.first
+ var arg = arguments[1]
+ if is_optional then
+ var value = v.new_var(self.mpropdef.static_mtype.as(not null))
+ v.add("if ({arg} == NULL) \{")
+ v.assign(value, evaluate_expr(v, recv))
+ v.add("\} else \{")
+ v.assign(value, arg)
+ v.add("\}")
+ arg = value
+ end
+ v.write_attribute(self.mpropdef.mproperty, arguments.first, arg)
if is_lazy then
var ret = self.mtype
var useiset = not ret.is_c_primitive and not ret isa MNullableType
#
# In nitni files, declare internal function as extern
- var full_friendly_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind})"
+ var full_friendly_csignature = "int {v.compiler.mainmodule.c_name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind})"
ccu.header_decl.add("extern {full_friendly_csignature};\n")
# In nitni files, #define friendly as extern
- ccu.header_decl.add("#define {check_cname} {v.compiler.mainmodule.name}___{check_cname}\n")
+ ccu.header_decl.add "#ifndef {check_cname}\n"
+ ccu.header_decl.add "#define {check_cname} {v.compiler.mainmodule.c_name}___{check_cname}\n"
+ ccu.header_decl.add "#endif\n"
if compile_implementation_too then
# Internally, implement internal function
var nitni_visitor = v.compiler.new_visitor
nitni_visitor.frame = v.frame
- var full_internal_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
+ var full_internal_csignature = "int {v.compiler.mainmodule.c_name }___{from.mangled_cname}_is_a_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
nitni_visitor.add_decl("/* nitni check for {from} to {to} */")
nitni_visitor.add_decl("{full_internal_csignature} \{")
# special checks
if from == to.as_nullable then
# format A_is_null
- ccu.header_decl.add("#define {from.mangled_cname}_is_null !{from.mangled_cname}_is_a_{to.mangled_cname}\n")
+ ccu.header_decl.add "#ifndef {from.mangled_cname}_is_null\n"
+ ccu.header_decl.add "#define {from.mangled_cname}_is_null !{from.mangled_cname}_is_a_{to.mangled_cname}\n"
+ ccu.header_decl.add "#endif\n"
end
#
#
# In nitni files, declare internal function as extern
- full_friendly_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind})"
+ full_friendly_csignature = "{to.cname_blind} {v.compiler.mainmodule.c_name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind})"
ccu.header_decl.add("extern {full_friendly_csignature};\n")
# In nitni files, #define friendly as extern
- ccu.header_decl.add("#define {cast_cname} {v.compiler.mainmodule.name}___{cast_cname}\n")
+ ccu.header_decl.add "#ifndef {cast_cname}\n"
+ ccu.header_decl.add "#define {cast_cname} {v.compiler.mainmodule.c_name}___{cast_cname}\n"
+ ccu.header_decl.add "#endif\n"
if compile_implementation_too then
# Internally, implement internal function
var nitni_visitor = v.compiler.new_visitor
nitni_visitor.frame = v.frame
- var full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
+ var full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.c_name }___{from.mangled_cname}_as_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
nitni_visitor.add_decl("/* nitni cast for {from} to {to} */")
nitni_visitor.add_decl("{full_internal_csignature} \{")
# special casts
if from.as_nullable == to then
# format A_as_nullable
- ccu.header_decl.add("#define {from.mangled_cname}_as_nullable {from.mangled_cname}_as_{to.mangled_cname}\n")
+ ccu.header_decl.add "#ifndef {from.mangled_cname}_as_nullable\n"
+ ccu.header_decl.add "#define {from.mangled_cname}_as_nullable {from.mangled_cname}_as_{to.mangled_cname}\n"
+ ccu.header_decl.add "#endif\n"
end
if from == to.as_nullable then
# format A_as_nullable
- ccu.header_decl.add("#define {to.mangled_cname}_as_not_nullable {from.mangled_cname}_as_{to.mangled_cname}\n")
+ ccu.header_decl.add "#ifndef {to.mangled_cname}_as_not_nullable\n"
+ ccu.header_decl.add "#define {to.mangled_cname}_as_not_nullable {from.mangled_cname}_as_{to.mangled_cname}\n"
+ ccu.header_decl.add "#endif\n"
end
end
end
else if c == '`' then
b.append("'")
else if c.code_point < 32 then
- b.append("\\{c.code_point.to_base(8, false)}")
+ b.append("\\{c.code_point.to_base(8)}")
else
b.add(c)
end
noinit
readonly
writable
+optional
autoinit
noautoinit
lateinit
import nitni
import ffi
import naive_interpreter
+import debugger_socket # To linearize `ToolContext::init`
+
+redef class ToolContext
+
+ # --compile-dir
+ var opt_compile_dir = new OptionString("Directory used to generate temporary files", "--compile-dir")
+
+ init do option_context.add_option opt_compile_dir
+end
redef class AMethPropdef
# Does this method definition use the FFI and is it supported by the interpreter?
end
redef class NaiveInterpreter
+ redef fun start(mainmodule)
+ do
+ super
+
+ # Delete temporary files
+ var compile_dir = compile_dir
+ if compile_dir.file_exists then compile_dir.rmdir
+ end
+
# Where to store generated C and extracted code
- #
- # TODO make customizable and delete when execution completes
- private var compile_dir = "nit_compile"
+ private var compile_dir: String is lazy do
+ # Prioritize the user supplied directory
+ var opt = modelbuilder.toolcontext.opt_compile_dir.value
+ if opt != null then return opt
+ return "/tmp/niti_ffi_{process_id}"
+ end
+
+ # Identifier for this process, unique between running interpreters
+ private fun process_id: Int `{ return getpid(); `}
# Path of the compiled foreign code library
#
var compile_dir = v.compile_dir
var foreign_code_lib_path = v.foreign_code_lib_path(mmodule)
- if not compile_dir.file_exists then compile_dir.mkdir
+ if not compile_dir.file_exists then compile_dir.mkdir(0o700)
# Compile the common FFI part
ensure_compile_ffi_wrapper
return evaluate_expr(v, recv, f)
else if mpropdef == mwritepropdef then
assert args.length == 2
- v.write_attribute(attr, recv, args[1])
+ var arg = args[1]
+ if is_optional and arg.mtype isa MNullType then
+ var f = v.new_frame(self, mpropdef, args)
+ arg = evaluate_expr(v, recv, f)
+ end
+ v.write_attribute(attr, recv, arg)
return null
else
abort
mreadpropdef.mproperty.is_autoinit = true
continue
end
- if npropdef.has_value then continue
- var paramname = mreadpropdef.mproperty.name
- var ret_type = msignature.return_mtype
- if ret_type == null then return
- var mparameter = new MParameter(paramname, ret_type, false)
- mparameters.add(mparameter)
+ if npropdef.has_value and not npropdef.is_optional then continue
var msetter = npropdef.mwritepropdef
if msetter == null then
# No setter, it is a readonly attribute, so just add it
+ var paramname = mreadpropdef.mproperty.name
+ var ret_type = msignature.return_mtype
+ if ret_type == null then return
+ var mparameter = new MParameter(paramname, ret_type, false)
+ mparameters.add(mparameter)
+
initializers.add(npropdef.mpropdef.mproperty)
npropdef.mpropdef.mproperty.is_autoinit = true
else
# Add the setter to the list
+ mparameters.add_all msetter.msignature.mparameters
initializers.add(msetter.mproperty)
msetter.mproperty.is_autoinit = true
end
# Is the node tagged lazy?
var is_lazy = false
+ # Is the node tagged optional?
+ var is_optional = false
+
# Has the node a default value?
# Could be through `n_expr` or `n_block`
var has_value = false
self.mlazypropdef = mlazypropdef
end
+ var atoptional = self.get_single_annotation("optional", modelbuilder)
+ if atoptional != null then
+ if not has_value then
+ modelbuilder.error(atoptional, "Error: `optional` attributes need a default value.")
+ end
+ is_optional = true
+ end
+
var atreadonly = self.get_single_annotation("readonly", modelbuilder)
if atreadonly != null then
if not has_value then
var mwritepropdef = self.mwritepropdef
if mwritepropdef != null then
+ var mwritetype = mtype
+ if is_optional then
+ mwritetype = mwritetype.as_nullable
+ end
var name: String
name = n_id2.text
- var mparameter = new MParameter(name, mtype, false)
+ var mparameter = new MParameter(name, mwritetype, false)
var msignature = new MSignature([mparameter], null)
mwritepropdef.msignature = msignature
end
redef class MMethod
# Build a C function name for the FFI implementation (uses friendly naming).
- # * On a specific static receiver mype `recv_mtype`
+ # * On a specific static receiver type `recv_mtype`
# * In referene to the module `from_module` (used for type resolving and as a possible prefix)
# * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
# * With a specified length indicating whether it uses the sort name or the long name with
if suffix != null then cname = "{cname}{suffix}"
- if length.long then cname = "{from_mmodule.name}___{cname}"
+ if length.long then cname = "{from_mmodule.c_name}___{cname}"
return cname
end
# Build a C function signature for the FFI implementation (uses friendly naming).
- # * On a specific static receiver mype `recv_mtype`
+ # * On a specific static receiver type `recv_mtype`
# * In referene to the module `from_module` (used for type resolving and as a possible prefix)
# * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
# * With a specified length indicating whether it uses the sort name or the long name with
end
# Build a C function call for the FFI implementation (uses friendly naming).
- # * On a specific static receiver mype `recv_mtype`
+ # * On a specific static receiver type `recv_mtype`
# * In referene to the module `from_module` (used for type resolving and as a possible prefix)
# * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
# * With a specified length indicating whether it uses the sort name or the long name with
end
return null # forward error
end
- self.error(nexpr, "Error: expected an expression.")
+ var more_message = null
+ var p = nexpr.parent
+ if p != null then more_message = p.bad_expr_message(nexpr)
+ if more_message == null then more_message = "" else more_message = " " + more_message
+ self.error(nexpr, "Error: expected an expression{more_message}.")
return null
end
redef class ANode
private fun accept_post_typing(v: TypeVisitor) do end
+
+ # An additional information message to explain the role of a child expression.
+ #
+ # The point of the method is to allow some kind of double dispatch so the parent
+ # choose how to describe its children.
+ private fun bad_expr_message(child: AExpr): nullable String do return null
end
redef class AAttrPropdef
# The property invoked by the send.
var callsite: nullable CallSite
+ redef fun bad_expr_message(child)
+ do
+ if child == self.n_expr then
+ return "to be the receiver of `{self.property_name}`"
+ end
+ return null
+ end
+
redef fun accept_typing(v)
do
var nrecv = self.n_expr
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+ var i: Int = 99 is optional
+
+ var o: Object = 999 is optional
+end
+
+var a = new A
+a.i.output
+a.o.output
+
+a.i = 1
+a.o = 10
+a.i.output
+a.o.output
+
+a.i = null
+a.o = null
+a.i.output
+a.o.output
+
+a = new A(2)
+a.i.output
+a.o.output
+
+a = new A(3, true)
+a.i.output
+a.o.output
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import core::kernel
+
+redef class Int
+ fun a: Int do return 10*self+self.abs
+end
+
+fun foo(a: Int): Int do
+ a.output
+ return a
+end
+fun bar(a: Int) do a.output
+
+foo 1.a
+foo(1.a)
+foo (1).a
+foo(1).a
+foo((1).a)
+
+'\n'.output
+
+bar 1.a
+bar(1.a)
+#alt1#bar (1).a
+#alt1#bar(1).a
+bar((1).a)
--- /dev/null
+99
+999
+1
+10
+99
+999
+2
+999
+3
+true
-alt/base_meth_call_alt1.nit:36,1--6: Error: expected an expression.
+alt/base_meth_call_alt1.nit:36,1--6: Error: expected an expression to be the receiver of `output`.
--- /dev/null
+11
+11
+1
+1
+11
+
+11
+11
+11
--- /dev/null
+alt/error_arg_alt1.nit:37,1--7: Error: expected an expression to be the receiver of `a`.
+alt/error_arg_alt1.nit:38,1--6: Error: expected an expression to be the receiver of `a`.
-RopeBuffer = 0
Calls to length, by type:
- FlatString = 23 (cache misses 5, 21.73%)
+ FlatString = 18 (cache misses 5, 27.77%)
Indexed accesses, by type:
- FlatString = 13
+ FlatString = 8
Calls to bytelen for each type:
FlatString = 61
Calls to position for each type:
- FlatString = 27
+ FlatString = 17
Calls to bytepos for each type:
- FlatString = 14
-Calls to first_byte on FlatString 216
+ FlatString = 9
+Calls to first_byte on FlatString 191
Calls to last_byte on FlatString 19
FlatStrings allocated with length 78 (86.813%)
Length of travel for index distribution:
-* null = 16 => occurences 80.0%, cumulative 80.0%
-* 1 = 14 => occurences 35.0%, cumulative 75.0%
+* null = 11 => occurences 73.333%, cumulative 73.333%
+* 1 = 8 => occurences 27.586%, cumulative 65.517%
Byte length of the FlatStrings created:
* null = 6 => occurences 4.444%, cumulative 4.444%
-* 1 = 21 => occurences 14.094%, cumulative 18.121%
-* 2 = 33 => occurences 20.245%, cumulative 36.81%
+* 1 = 24 => occurences 16.107%, cumulative 20.134%
+* 2 = 30 => occurences 18.405%, cumulative 36.81%
* 3 = 29 => occurences 16.292%, cumulative 50.0%
-* 4 = 9 => occurences 4.663%, cumulative 50.777%
-* 5 = 20 => occurences 9.615%, cumulative 56.731%
-* 6 = 21 => occurences 9.417%, cumulative 62.332%
+* 4 = 5 => occurences 2.591%, cumulative 48.705%
+* 5 = 20 => occurences 9.615%, cumulative 54.808%
+* 6 = 25 => occurences 11.211%, cumulative 62.332%
* 9 = 1 => occurences 0.42%, cumulative 58.824%
* 10 = 9 => occurences 3.557%, cumulative 58.893%
* 11 = 2 => occurences 0.746%, cumulative 56.343%
* 12 = 1 => occurences 0.355%, cumulative 53.901%
* 13 = 1 => occurences 0.339%, cumulative 51.864%
* 14 = 1 => occurences 0.325%, cumulative 50.0%
-* 15 = 5 => occurences 1.558%, cumulative 49.533%
-* 16 = 7 => occurences 2.083%, cumulative 49.405%
+* 15 = 7 => occurences 2.181%, cumulative 50.156%
+* 16 = 5 => occurences 1.488%, cumulative 49.405%
* 17 = 1 => occurences 0.285%, cumulative 47.578%
* 25 = 2 => occurences 0.549%, cumulative 46.429%
* 26 = 1 => occurences 0.265%, cumulative 44.974%
* 40 = 1 => occurences 0.207%, cumulative 37.19%
* 43 = 1 => occurences 0.201%, cumulative 36.419%
* 46 = 1 => occurences 0.196%, cumulative 35.686%
-* 48 = 1 => occurences 0.191%, cumulative 34.99%
-* 51 = 21 => occurences 3.918%, cumulative 38.06%
+* 51 = 20 => occurences 3.824%, cumulative 38.623%
+* 55 = 1 => occurences 0.186%, cumulative 37.732%
-RopeBuffer = 0
Calls to length, by type:
- FlatString = 23 (cache misses 5, 21.73%)
+ FlatString = 18 (cache misses 5, 27.77%)
Indexed accesses, by type:
- FlatString = 13
+ FlatString = 8
Calls to bytelen for each type:
FlatString = 61
Calls to position for each type:
- FlatString = 27
+ FlatString = 17
Calls to bytepos for each type:
- FlatString = 14
-Calls to first_byte on FlatString 216
+ FlatString = 9
+Calls to first_byte on FlatString 191
Calls to last_byte on FlatString 19
FlatStrings allocated with length 78 (86.813%)
Length of travel for index distribution:
-* 0 = 16 => occurences 80.0%, cumulative 80.0%
-* 1 = 14 => occurences 35.0%, cumulative 75.0%
+* 0 = 11 => occurences 73.333%, cumulative 73.333%
+* 1 = 8 => occurences 27.586%, cumulative 65.517%
Byte length of the FlatStrings created:
* 0 = 6 => occurences 4.478%, cumulative 4.478%
-* 1 = 21 => occurences 14.189%, cumulative 18.243%
-* 2 = 33 => occurences 20.37%, cumulative 37.037%
+* 1 = 24 => occurences 16.216%, cumulative 20.27%
+* 2 = 30 => occurences 18.519%, cumulative 37.037%
* 3 = 29 => occurences 16.384%, cumulative 50.282%
-* 4 = 7 => occurences 3.646%, cumulative 50.0%
-* 5 = 20 => occurences 9.662%, cumulative 56.039%
-* 6 = 21 => occurences 9.459%, cumulative 61.712%
-* 9 = 1 => occurences 0.422%, cumulative 58.228%
-* 10 = 9 => occurences 3.571%, cumulative 58.333%
-* 11 = 2 => occurences 0.749%, cumulative 55.805%
-* 12 = 1 => occurences 0.356%, cumulative 53.381%
-* 13 = 1 => occurences 0.34%, cumulative 51.361%
-* 14 = 1 => occurences 0.326%, cumulative 49.511%
-* 15 = 5 => occurences 1.563%, cumulative 49.063%
-* 16 = 7 => occurences 2.09%, cumulative 48.955%
-* 17 = 1 => occurences 0.286%, cumulative 47.143%
-* 25 = 2 => occurences 0.551%, cumulative 46.006%
-* 26 = 1 => occurences 0.265%, cumulative 44.562%
-* 31 = 2 => occurences 0.513%, cumulative 43.59%
-* 32 = 1 => occurences 0.248%, cumulative 42.327%
-* 33 = 1 => occurences 0.24%, cumulative 41.247%
-* 34 = 2 => occurences 0.465%, cumulative 40.465%
-* 35 = 1 => occurences 0.225%, cumulative 39.414%
-* 37 = 1 => occurences 0.219%, cumulative 38.512%
-* 39 = 1 => occurences 0.213%, cumulative 37.66%
-* 40 = 1 => occurences 0.207%, cumulative 36.853%
-* 43 = 1 => occurences 0.202%, cumulative 36.089%
-* 46 = 1 => occurences 0.196%, cumulative 35.363%
-* 48 = 3 => occurences 0.575%, cumulative 35.057%
+* 4 = 3 => occurences 1.563%, cumulative 47.917%
+* 5 = 20 => occurences 9.662%, cumulative 54.106%
+* 6 = 26 => occurences 11.712%, cumulative 62.162%
+* 9 = 1 => occurences 0.422%, cumulative 58.65%
+* 10 = 9 => occurences 3.571%, cumulative 58.73%
+* 11 = 2 => occurences 0.749%, cumulative 56.18%
+* 12 = 1 => occurences 0.356%, cumulative 53.737%
+* 13 = 1 => occurences 0.34%, cumulative 51.701%
+* 14 = 1 => occurences 0.326%, cumulative 49.837%
+* 15 = 7 => occurences 2.188%, cumulative 50.0%
+* 16 = 5 => occurences 1.493%, cumulative 49.254%
+* 17 = 1 => occurences 0.286%, cumulative 47.429%
+* 25 = 2 => occurences 0.551%, cumulative 46.281%
+* 26 = 1 => occurences 0.265%, cumulative 44.828%
+* 31 = 2 => occurences 0.513%, cumulative 43.846%
+* 32 = 1 => occurences 0.248%, cumulative 42.574%
+* 33 = 1 => occurences 0.24%, cumulative 41.487%
+* 34 = 2 => occurences 0.465%, cumulative 40.698%
+* 35 = 1 => occurences 0.225%, cumulative 39.64%
+* 37 = 1 => occurences 0.219%, cumulative 38.731%
+* 39 = 1 => occurences 0.213%, cumulative 37.872%
+* 40 = 1 => occurences 0.207%, cumulative 37.06%
+* 43 = 1 => occurences 0.202%, cumulative 36.29%
+* 46 = 1 => occurences 0.196%, cumulative 35.56%
+* 51 = 14 => occurences 2.682%, cumulative 37.356%
+* 52 = 5 => occurences 0.931%, cumulative 37.244%