Use CallSite to resolve and type some implicit services.
Subsequent phases will like them!
Currenlty: all the AFor and ARange services are converted and tools updated.
TODO: Array and SuperString
Pull-Request: #370
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
fun clanit(i: Int): String
do
- var s = new Buffer
+ var s = new FlatBuffer
s.append("{classes.first}[" * i)
s.append("Root")
s.append("]" * i)
fun clajava(i: Int): String
do
- var s = new Buffer
+ var s = new FlatBuffer
s.append("{classes.first}<" * i)
s.append("Root")
s.append(">" * i)
fun clacpp(i: Int): String
do
- var s = new Buffer
+ var s = new FlatBuffer
s.append("{classes.first}<" * i)
s.append("Root")
s.append("*>" * i)
fun clae(i: Int): String
do
- var s = new Buffer
+ var s = new FlatBuffer
s.append("{classes.first}[" * i)
s.append("ROOT")
s.append("]" * i)
# Dump of the concrete grammar and the transformations
fun pretty: String
do
- var res = new Buffer
+ var res = new FlatBuffer
for p in prods do
if p.spe != null then
res.append("{p.name} \{-> {p.spe.name}\}=\n")
redef fun to_s
do
- var b = new Buffer
+ var b = new FlatBuffer
b.append("{alt.prod.name}::{alt.name}=")
for i in [0..alt.elems.length[
do
fun str
do
- var b = new Buffer
+ var b = new FlatBuffer
b.add('\'')
while iter.is_ok do
var c = iter.item
fun id(c: Char)
do
- var b = new Buffer
+ var b = new FlatBuffer
b.add c
while iter.is_ok do
c = iter.item
fun kw(c: Char)
do
- var b = new Buffer
+ var b = new FlatBuffer
b.add c
while iter.is_ok do
c = iter.item
var steps = length / 4
var result_length = steps*3
- var padding_begin = padding.search_index_in( self, 0 )
+ var padding_begin = self.search(padding)
var padding_count : Int
- if padding_begin == -1 then
+ if padding_begin == null then
padding_count = 0
else
- padding_count = length - padding_begin
+ padding_count = length - padding_begin.from
steps -= 1
result_length -= padding_count
end
# Binding of C libCurl which allow us to interact with network.
module curl_c is pkgconfig("libcurl")
-import pipeline
-
in "C header" `{
#include <stdio.h>
#include <stdlib.h>
print "Collection item must be strings."
end
var primList = new CURLSList.with_str(self.first)
- for s in self.skip_head(1) do primList.append(s)
+ var is_first = true
+ for s in self do
+ if not is_first then primList.append(s)
+ is_first = false
+ end
return primList
end
end
super Jsonable
end
+redef class String
+ super Jsonable
+end
+
# Can b converted to a Json object
redef class Map[ K, V ]
super Jsonable
# A pretty print for this help
fun pretty(off: Int): String
do
- var text = new Buffer.from(" ")
+ var text = new FlatBuffer.from(" ")
text.append(_names.join(", "))
text.append(" ")
var rest = off - text.length
# Pipelined filters and operations on iterators.
#
-# This module enhance `Collection`s with some methods that enable a
+# This module enhance `Iterator`s with some methods that enable a
# pipeline-like programing that offers the manupulation of
# collections trough connected filters with reasonable memory constraints.
-#
-# The filters methods return a view bounded on the original collection.
-# Filters can be chained to build complex virtual collections.
-#
-# FIXME: Fix vocabulary (lazy/view/filter)
-# FIXME: Maybe the name of the method should indicate that the method is 'lazy' (or is a filter).
module pipeline
-redef interface Collection[E]
+redef interface Iterator[E]
# Filter: sort with `default_comparator`.
# SEE: `sort_with` for details
# REQUIRE: self isa Iterator[Comparable]
#
- # assert [1,3,2].sort_filter.to_a == [1,2,3]
- fun sort_filter: Collection[E]
+ # assert [1,3,2].iterator.sort.to_a == [1,2,3]
+ fun sort: Iterator[E]
do
- assert self isa Collection[Comparable]
+ assert self isa Iterator[Comparable]
var a = self.to_a
default_comparator.sort(a)
- return a
+ return a.iterator
end
# Filter: sort with a given `comparator`.
# Important: require O(n) memory.
- fun sort_with(comparator: Comparator[E]): Collection[E]
+ fun sort_with(comparator: Comparator[E]): Iterator[E]
do
var a = self.to_a
comparator.sort(a)
- return a
+ return a.iterator
end
# Filter: reject duplicates.
# Important: rely on `==` and `hash`
# Important: require O(m) in memory, where m is the total number of uniq items.
#
- # assert [1,2,1,1,1,3,2].uniq.to_a == [1,2,3]
+ # assert [1,2,1,1,1,3,2].iterator.uniq.to_a == [1,2,3]
#
# REQUIRE: self isa Iterator[Object]
- fun uniq: Collection[E]
+ fun uniq: Iterator[E]
do
- assert self isa Collection[Object]
+ assert self isa Iterator[Object]
return new PipeUniq[E](self)
end
#
# Important: rely on `==`.
#
- # assert [1,2,1,1,1,3,2].seq_uniq.to_a == [1,2,1,3,2]
- fun seq_uniq: Collection[E]
+ # assert [1,2,1,1,1,3,2].iterator.seq_uniq.to_a == [1,2,1,3,2]
+ fun seq_uniq: Iterator[E]
do
return new PipeSeqUniq[E](self)
end
- # The view of two combined collections.
+ # Combine two iterators.
+ #
+ # When the first iterator is terminated, the second is started.
#
- # assert ([1..20[ + [20..40[).to_a == ([1..40[).to_a
- fun +(other: Collection[E]): Collection[E]
+ # assert ([1..20[.iterator + [20..40[.iterator).to_a == ([1..40[).to_a
+ fun +(other: Iterator[E]): Iterator[E]
do
return new PipeJoin[E](self, other)
end
# Alternate each item with `e`.
#
- # assert [1,2,3].alternate(0).to_a == [1,0,2,0,3]
- fun alternate(e: E): Collection[E]
+ # assert [1,2,3].iterator.alternate(0).to_a == [1,0,2,0,3]
+ fun alternate(e: E): Iterator[E]
do
return new PipeAlternate[E](self, e)
end
# Filter: reject a given `item`.
#
- # assert [1,1,2,1,3].skip(1).to_a == [2,3]
- fun skip(item: E): Collection[E]
+ # assert [1,1,2,1,3].iterator.skip(1).to_a == [2,3]
+ fun skip(item: E): Iterator[E]
do
return new PipeSkip[E](self, item)
end
# Filter: keep only the first `length` items.
#
- # assert [1,2,3,4,5].head(2).to_a == [1,2]
- fun head(length: Int): Collection[E]
+ # This filter does not always consume `self'.
+ #
+ # var i = [1,2,3,4,5].iterator
+ # assert i.head(2).to_a == [1,2]
+ # i.to_a == [3,4,5]
+ fun head(length: Int): Iterator[E]
do
return new PipeHead[E](self, length)
end
# Filter: reject the first `length` items.
#
- # assert [1,2,3,4,5].skip_head(2).to_a == [3,4,5]
+ # assert [1,2,3,4,5].iterator.skip_head(2).to_a == [3,4,5]
#
# ENSURE: self == return
- fun skip_head(length: Int): Collection[E]
+ fun skip_head(length: Int): Iterator[E]
do
- return new PipeSkipHead[E](self, length)
+ while length > 0 and self.is_ok do
+ length -= 1
+ self.next
+ end
+ return self
end
# Filter: keep only the last `length` items.
#
- # assert [1,2,3,4,5].tail(2).to_a == [4,5]
+ # assert [1,2,3,4,5].iterator.tail(2).to_a == [4,5]
#
# Important: require O(length) in memory
- fun tail(length: Int): Collection[E]
+ fun tail(length: Int): Iterator[E]
do
- return new PipeTail[E](self, length)
+ var lasts = new List[E]
+ while self.is_ok do
+ while lasts.length >= length do lasts.shift
+ lasts.push(self.item)
+ self.next
+ end
+ return lasts.iterator
end
# Filter: reject the last `length` items.
#
- # assert [1,2,3,4,5].skip_tail(2).to_a == [1,2,3]
+ # assert [1,2,3,4,5].iterator.skip_tail(2).to_a == [1,2,3]
#
# Important: require O(length) in memory
- fun skip_tail(length: Int): Collection[E]
+ fun skip_tail(length: Int): Iterator[E]
do
return new PipeSkipTail[E](self, length)
end
+
+ # Filter: reject items that does not meet some criteria.
+ #
+ # class IsEvenFunction
+ # super Function[Int, Bool]
+ # redef fun apply(i) do return i % 2 == 0
+ # end
+ # assert [1,2,3,4,8].iterator.select(new IsEvenFunction).to_a == [2,4,8]
+ fun select(predicate: Function[E, Bool]): Iterator[E]
+ do
+ return new PipeSelect[E](self, predicate)
+ end
end
-### Specific private collection and iterator classes
+# Interface that reify a function.
+# Concrete subclasses must implements the `apply` method.
+#
+# This interface helps to manipulate function-like objects.
+#
+# The main usage it as a transformation; that takes an argument and produce a result.
+# See `map` for example.
+#
+# Another usage is as a predicate, with `Function[E, Bool]`.
+# See `Iterator::select` for example.
+#
+# Function with more than one argument can be reified with some uncurification.
+# Eg. `Function[ARG1, Function[ARG2, RES]]`.
+#
+# NOTE: Nit is not a functionnal language, this class is a very basic way to
+# simulate the reification of a simple function.
+interface Function[FROM, TO]
+ # How an element is mapped to another one.
+ fun apply(e: FROM): TO is abstract
-private class PipeUniq[E]
- super Collection[E]
- var source: Collection[E]
- redef fun iterator do return new PipeUniqIterator[E](source.iterator)
+ # Filter: produce an iterator which each element is transformed.
+ #
+ # var i = [1,2,3].iterator
+ # assert fun_to_s.map(i).to_a == ["1", "2", "3"]
+ #
+ # Note: because there is no generic method in Nit (yet?),
+ # there is no way to have a better API.
+ # eg. with the Iterator as receiver and the function as argument.
+ # (see `Iterator::select`)
+ fun map(i: Iterator[FROM]): Iterator[TO]
+ do
+ return new PipeMap[FROM, TO](i, self)
+ end
end
-private class PipeUniqIterator[E]
+private class FunctionToS
+ super Function[Object, String]
+ redef fun apply(e) do return e.to_s
+end
+
+### Specific private iterator classes
+
+private class PipeUniq[E]
super Iterator[E]
var source: Iterator[E]
end
private class PipeSeqUniq[E]
- super Collection[E]
- var source: Collection[E]
- redef fun iterator do return new PipeSeqUniqIterator[E](source.iterator)
-end
-
-private class PipeSeqUniqIterator[E]
super Iterator[E]
var source: Iterator[E]
end
private class PipeJoin[E]
- super Collection[E]
- var source1: Collection[E]
- var source2: Collection[E]
- redef fun iterator do return new PipeJoinIterator[E](source1.iterator, source2.iterator)
-end
-
-private class PipeJoinIterator[E]
super Iterator[E]
var source1: Iterator[E]
var source2: Iterator[E]
end
private class PipeAlternate[E]
- super Collection[E]
- var source: Collection[E]
- var odd_item: E
- redef fun iterator do return new PipeAlternateIterator[E](source.iterator, odd_item)
-end
-
-private class PipeAlternateIterator[E]
super Iterator[E]
var source: Iterator[E]
end
private class PipeSkip[E]
- super Collection[E]
- var source: Collection[E]
- var skip_item: E
- redef fun iterator do return new PipeSkipIterator[E](source.iterator, skip_item)
-end
-
-private class PipeSkipIterator[E]
- super Collection[E]
super Iterator[E]
var source: Iterator[E]
end
private class PipeHead[E]
- super Collection[E]
- var source: Collection[E]
- var pipe_length: Int
- redef fun iterator do return new PipeHeadIterator[E](source.iterator, pipe_length)
-end
-
-private class PipeHeadIterator[E]
super Iterator[E]
var source: Iterator[E]
end
end
-private class PipeSkipHead[E]
- super Collection[E]
- var source: Collection[E]
- var pipe_length: Int
- redef fun iterator
- do
- var res = source.iterator
- var length = pipe_length
- while length > 0 and res.is_ok do
- length -= 1
- res.next
- end
- return res
- end
-end
-
-private class PipeTail[E]
- super Collection[E]
- var source: Collection[E]
- var pipe_length: Int
- redef fun iterator
- do
- var lasts = new List[E]
- var res = source.iterator
- var length = pipe_length
- while res.is_ok do
- while lasts.length >= length do lasts.shift
- lasts.push(res.item)
- res.next
- end
- return lasts.iterator
- end
-end
-
private class PipeSkipTail[E]
- super Collection[E]
- var source: Collection[E]
- var pipe_length: Int
- redef fun iterator do return new PipeSkipTailIterator[E](source.iterator, pipe_length)
-end
-
-private class PipeSkipTailIterator[E]
super Iterator[E]
var source: Iterator[E]
source.next
end
end
+
+private class PipeSelect[E]
+ super Iterator[E]
+
+ var source: Iterator[E]
+
+ var predicate: Function[E, Bool]
+
+ init(source: Iterator[E], predicate: Function[E, Bool])
+ do
+ self.source = source
+ self.predicate = predicate
+
+ do_skip
+ end
+
+ fun do_skip
+ do
+ while source.is_ok and not predicate.apply(source.item) do source.next
+ end
+
+ redef fun is_ok do return source.is_ok
+
+ redef fun item do return source.item
+
+ redef fun next
+ do
+ source.next
+ do_skip
+ end
+end
+
+private class PipeMap[E, F]
+ super Iterator[F]
+
+ var source: Iterator[E]
+ var function: Function[E, F]
+
+ var item_cache: nullable F = null
+ var item_cached = false
+
+ redef fun is_ok do return source.is_ok
+
+ redef fun item do
+ if item_cached then return item_cache
+ item_cache = function.apply(source.item)
+ item_cached = true
+ return item_cache
+ end
+
+ redef fun next do
+ source.next
+ item_cached = false
+ end
+end
+
+# Stateless singleton that reify to the `to_s` method.
+#
+# assert fun_to_s.apply(5) == "5"
+fun fun_to_s: Function[Object, String] do return once new FunctionToS
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Copyright 2014 Lucas Bajolet <r4pass@hotmail.com>
+#
+# 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.
+
+# Provides methods to compute the SHA1 hash of a String
+module sha1
+
+in "C Header" `{
+
+ /* This code is public-domain - it is based on libcrypt
+ * placed in the public domain by Wei Dai and other contributors.
+ */
+
+ #include <stdint.h>
+ #include <string.h>
+
+ #define HASH_LENGTH 20
+ #define BLOCK_LENGTH 64
+
+ union _buffer {
+ uint8_t b[BLOCK_LENGTH];
+ uint32_t w[BLOCK_LENGTH/4];
+ };
+
+ union _state {
+ uint8_t b[HASH_LENGTH];
+ uint32_t w[HASH_LENGTH/4];
+ };
+
+ typedef struct sha1nfo {
+ union _buffer buffer;
+ uint8_t bufferOffset;
+ union _state state;
+ uint32_t byteCount;
+ uint8_t keyBuffer[BLOCK_LENGTH];
+ uint8_t innerHash[HASH_LENGTH];
+ } sha1nfo;
+
+ /**
+ */
+ void sha1_init(sha1nfo *s);
+ /**
+ */
+ void sha1_writebyte(sha1nfo *s, uint8_t data);
+ /**
+ */
+ void sha1_write(sha1nfo *s, const char *data, size_t len);
+ /**
+ */
+ uint8_t* sha1_result(sha1nfo *s);
+ /**
+ */
+ void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength);
+ /**
+ */
+ uint8_t* sha1_resultHmac(sha1nfo *s);
+`}
+
+`{
+ #define SHA1_K0 0x5a827999
+ #define SHA1_K20 0x6ed9eba1
+ #define SHA1_K40 0x8f1bbcdc
+ #define SHA1_K60 0xca62c1d6
+
+ const uint8_t sha1InitState[] = {
+ 0x01,0x23,0x45,0x67, // H0
+ 0x89,0xab,0xcd,0xef, // H1
+ 0xfe,0xdc,0xba,0x98, // H2
+ 0x76,0x54,0x32,0x10, // H3
+ 0xf0,0xe1,0xd2,0xc3 // H4
+ };
+
+ void sha1_init(sha1nfo *s) {
+ memcpy(s->state.b,sha1InitState,HASH_LENGTH);
+ s->byteCount = 0;
+ s->bufferOffset = 0;
+ }
+
+ uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
+ return ((number << bits) | (number >> (32-bits)));
+ }
+
+ void sha1_hashBlock(sha1nfo *s) {
+ uint8_t i;
+ uint32_t a,b,c,d,e,t;
+
+ a=s->state.w[0];
+ b=s->state.w[1];
+ c=s->state.w[2];
+ d=s->state.w[3];
+ e=s->state.w[4];
+ for (i=0; i<80; i++) {
+ if (i>=16) {
+ t = s->buffer.w[(i+13)&15] ^ s->buffer.w[(i+8)&15] ^ s->buffer.w[(i+2)&15] ^ s->buffer.w[i&15];
+ s->buffer.w[i&15] = sha1_rol32(t,1);
+ }
+ if (i<20) {
+ t = (d ^ (b & (c ^ d))) + SHA1_K0;
+ } else if (i<40) {
+ t = (b ^ c ^ d) + SHA1_K20;
+ } else if (i<60) {
+ t = ((b & c) | (d & (b | c))) + SHA1_K40;
+ } else {
+ t = (b ^ c ^ d) + SHA1_K60;
+ }
+ t+=sha1_rol32(a,5) + e + s->buffer.w[i&15];
+ e=d;
+ d=c;
+ c=sha1_rol32(b,30);
+ b=a;
+ a=t;
+ }
+ s->state.w[0] += a;
+ s->state.w[1] += b;
+ s->state.w[2] += c;
+ s->state.w[3] += d;
+ s->state.w[4] += e;
+ }
+
+ void sha1_addUncounted(sha1nfo *s, uint8_t data) {
+ s->buffer.b[s->bufferOffset ^ 3] = data;
+ s->bufferOffset++;
+ if (s->bufferOffset == BLOCK_LENGTH) {
+ sha1_hashBlock(s);
+ s->bufferOffset = 0;
+ }
+ }
+
+ void sha1_writebyte(sha1nfo *s, uint8_t data) {
+ ++s->byteCount;
+ sha1_addUncounted(s, data);
+ }
+
+ void sha1_write(sha1nfo *s, const char *data, size_t len) {
+ for (;len--;) sha1_writebyte(s, (uint8_t) *data++);
+ }
+
+ void sha1_pad(sha1nfo *s) {
+ // Implement SHA-1 padding (fips180-2 §5.1.1)
+
+ // Pad with 0x80 followed by 0x00 until the end of the block
+ sha1_addUncounted(s, 0x80);
+ while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00);
+
+ // Append length in the last 8 bytes
+ sha1_addUncounted(s, 0); // We're only using 32 bit lengths
+ sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
+ sha1_addUncounted(s, 0); // So zero pad the top bits
+ sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
+ sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
+ sha1_addUncounted(s, s->byteCount >> 13); // byte.
+ sha1_addUncounted(s, s->byteCount >> 5);
+ sha1_addUncounted(s, s->byteCount << 3);
+ }
+
+ uint8_t* sha1_result(sha1nfo *s) {
+ int i;
+ // Pad to complete the last block
+ sha1_pad(s);
+
+ // Swap byte order back
+ for (i=0; i<5; i++) {
+ uint32_t a,b;
+ a=s->state.w[i];
+ b=a<<24;
+ b|=(a<<8) & 0x00ff0000;
+ b|=(a>>8) & 0x0000ff00;
+ b|=a>>24;
+ s->state.w[i]=b;
+ }
+
+ // Return pointer to hash (20 characters)
+ return s->state.b;
+ }
+
+ #define HMAC_IPAD 0x36
+ #define HMAC_OPAD 0x5c
+
+ void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength) {
+ uint8_t i;
+ memset(s->keyBuffer, 0, BLOCK_LENGTH);
+ if (keyLength > BLOCK_LENGTH) {
+ // Hash long keys
+ sha1_init(s);
+ for (;keyLength--;) sha1_writebyte(s, *key++);
+ memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH);
+ } else {
+ // Block length keys are used as is
+ memcpy(s->keyBuffer, key, keyLength);
+ }
+ // Start inner hash
+ sha1_init(s);
+ for (i=0; i<BLOCK_LENGTH; i++) {
+ sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD);
+ }
+ }
+
+ uint8_t* sha1_resultHmac(sha1nfo *s) {
+ uint8_t i;
+ // Complete inner hash
+ memcpy(s->innerHash,sha1_result(s),HASH_LENGTH);
+ // Calculate outer hash
+ sha1_init(s);
+ for (i=0; i<BLOCK_LENGTH; i++) sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD);
+ for (i=0; i<HASH_LENGTH; i++) sha1_writebyte(s, s->innerHash[i]);
+ return sha1_result(s);
+ }
+`}
+
+redef class String
+
+ # Computes the SHA1 of the receiver
+ #
+ # Returns a digest of 20 bytes as a String,
+ # note that all the characters are not necessarily ASCII.
+ # If you want the hex string version of the digest, use
+ # sha1_to_s.
+ #
+ # import base64
+ # assert "The quick brown fox jumps over the lazy dog".sha1.encode_base64 == "L9ThxnotKPzthJ7hu3bnORuT6xI="
+ fun sha1: String import String.to_cstring, String.length, NativeString.to_s_with_length `{
+ uint32_t a;
+ sha1nfo s;
+
+ sha1_init(&s);
+ sha1_write(&s, String_to_cstring(recv), String_length(recv));
+ uint8_t* digest = sha1_result(&s);
+
+ char* digested = malloc(21);
+
+ memcpy(digested, digest, 20);
+
+ digested[20] = '\0';
+
+ return NativeString_to_s_with_length(digested, 20);
+ `}
+
+ # Computes the SHA1 of the receiver.
+ #
+ # Returns a 40 char String containing the Hexadecimal
+ # Digest in its Char form.
+ #
+ # assert "The quick brown fox jumps over the lazy dog".sha1_to_s == "2FD4E1C67A2D28FCED849EE1BB76E7391B93EB12"
+ fun sha1_to_s: String import String.to_cstring, String.length, NativeString.to_s_with_length `{
+ uint32_t a;
+ sha1nfo s;
+
+ sha1_init(&s);
+ sha1_write(&s, String_to_cstring(recv), String_length(recv));
+ uint8_t* digest = sha1_result(&s);
+
+ char* ret_str = malloc(41);
+ char* hexmap = "0123456789ABCDEF";
+
+ int i;
+ for(i=0;i<20;i++){
+ uint8_t q = digest[i];
+ ret_str[i*2] = hexmap[q >> 4];
+ ret_str[(i*2)+1] = hexmap[q & 0x0F];
+ }
+ ret_str[40] = '\0';
+
+ return NativeString_to_s_with_length(ret_str, 40);
+ `}
+
+end
+
# Internal code to handle execution
protected init execute(command: String, arguments: nullable Array[String], pipeflags: Int)
do
- var args = new Buffer
+ var args = new FlatBuffer
var l = 1 # Number of elements in args
args.append(command)
if arguments != null then
redef fun fill_buffer
do
- var nb = _file.io_read(_buffer._items, _buffer._capacity)
+ var nb = _file.io_read(_buffer.items, _buffer.capacity)
if nb <= 0 then
_end_reached = true
nb = 0
end
- _buffer._length = nb
+ _buffer.length = nb
_buffer_pos = 0
end
# assert "".basename("") == ""
fun basename(ext: String): String
do
- var l = _length - 1 # Index of the last char
+ var l = length - 1 # Index of the last char
while l > 0 and self.chars[l] == '/' do l -= 1 # remove all trailing `/`
if l == 0 then return "/"
var pos = last_index_of_from('/', l)
# assert "".dirname == "."
fun dirname: String
do
- var l = _length - 1 # Index of the last char
+ var l = length - 1 # Index of the last char
while l > 0 and self.chars[l] == '/' do l -= 1 # remove all trailing `/`
var pos = last_index_of_from('/', l)
if pos > 0 then
fun mkdir
do
var dirs = self.split_with("/")
- var path = new Buffer
+ var path = new FlatBuffer
if dirs.is_empty then return
if dirs[0].is_empty then
# it was a starting /
end
# Initializes a new Rope with a text embedded in directly
- init with_string(str: AbstractString) do
+ init with_string(str: String) do
self.parent_node = new ConcatNode
parent_node.as(ConcatNode).right_child = new LeafNode(str)
parent_node.as(ConcatNode).update_data
end
# Stores a flat version of self in cache
- private fun flatten: String
+ private fun flatten: FlatString
do
var native_final_str = calloc_string(length + 1)
var iter = new DFSRopeLeafIterator(self)
while iter.is_ok do
- iter.item.value._items.copy_to(native_final_str, iter.item.value.length, 0, offset)
+ iter.item.value.as(FlatString).items.copy_to(native_final_str, iter.item.value.length, 0, offset)
offset += iter.item.value.length
iter.next
end
# Compares the current Rope to another object (either another rope or a String)
redef fun == (other)
do
- if other == null or not (other isa Rope or other isa AbstractString) then return false
+ if other == null or not (other isa Rope or other isa FlatText) then return false
var self_iter = new RopeCharIterator(self)
if other isa Rope then
if self.length != other.length then return false
self_iter.next
other_iterator.next
end
- else if other isa AbstractString then
+ else if other isa FlatText then
var pos = 0
if self.length != other.length then return false
while self_iter.is_ok do
############################################################################
# Appends a new Collection[Char] at the end of the current rope
- fun append(str: Collection[Char]): BufferRope
+ fun append(str: String): BufferRope
do
- if str isa AbstractString then
- var last_node = parent_node
+ var last_node = parent_node
- while last_node isa ConcatNode and last_node.right_child != null do
- last_node = last_node.right_child.as(not null)
- end
-
- if last_node isa ConcatNode then
- last_node.right_child = new LeafNode(str.to_s)
- else if last_node isa LeafNode then
- var last_node_parent = last_node.parent
- var new_concat = new ConcatNode
- last_node_parent.right_child = new_concat
- new_concat.left_child = last_node
- new_concat.right_child = new LeafNode(str.to_s)
- last_node = new_concat
- else
- print "Fatal Error, please report to the developers for more insight."
- abort
- end
+ while last_node isa ConcatNode and last_node.right_child != null do
+ last_node = last_node.right_child.as(not null)
+ end
- balance_from_node(last_node)
+ if last_node isa ConcatNode then
+ last_node.right_child = new LeafNode(str.to_s)
+ else if last_node isa LeafNode then
+ var last_node_parent = last_node.parent
+ var new_concat = new ConcatNode
+ last_node_parent.right_child = new_concat
+ new_concat.left_child = last_node
+ new_concat.right_child = new LeafNode(str.to_s)
+ last_node = new_concat
else
- var buf = new Buffer.with_capacity(str.length)
- for i in str do
- buf.add(i)
- end
- append(buf)
+ print "Fatal Error, please report to the developers for more insight."
+ abort
end
- if not is_dirty then is_dirty = true
+ balance_from_node(last_node)
+
+ is_dirty = true
return self
end
# Variatic function to append several collections of Chars
- fun append_multi(strs: Collection[Char]...): BufferRope
+ fun append_multi(strs: String...): BufferRope
do
for i in strs do
append(i)
end
# Adds a new Collection[Char] at the beginning of the rope
- fun prepend(str: Collection[Char]): BufferRope
+ fun prepend(str: String): BufferRope
do
- if str isa AbstractString then
- var curr_node = parent_node
-
- while curr_node isa ConcatNode and curr_node.left_child != null do
- curr_node = curr_node.left_child.as(not null)
- end
+ var curr_node = parent_node
- if curr_node isa ConcatNode then
- curr_node.left_child = new LeafNode(str.to_s)
- else if curr_node isa LeafNode then
- var parent = curr_node.parent
- var new_concat = new ConcatNode
- var new_leaf = new LeafNode(str.to_s)
- new_concat.left_child = new_leaf
- new_concat.right_child = curr_node
- parent.left_child = new_concat
- curr_node = new_concat
- else
- print "Fatal Error"
- abort
- end
+ while curr_node isa ConcatNode and curr_node.left_child != null do
+ curr_node = curr_node.left_child.as(not null)
+ end
- balance_from_node(curr_node)
+ if curr_node isa ConcatNode then
+ curr_node.left_child = new LeafNode(str.to_s)
+ else if curr_node isa LeafNode then
+ var parent = curr_node.parent
+ var new_concat = new ConcatNode
+ var new_leaf = new LeafNode(str.to_s)
+ new_concat.left_child = new_leaf
+ new_concat.right_child = curr_node
+ parent.left_child = new_concat
+ curr_node = new_concat
else
- var buf = new Buffer.with_capacity(str.length)
- for i in str do
- buf.add(i)
- end
- prepend(buf.to_s)
+ print "Fatal Error"
+ abort
end
- if not is_dirty then is_dirty = true
+ balance_from_node(curr_node)
+
+ is_dirty = true
return self
end
# Variatic function to prepend several collections of Chars
- fun prepend_multi(strs: Collection[Char]...): BufferRope
+ fun prepend_multi(strs: String...): BufferRope
do
for i in strs do
prepend(i)
# Encapsulated string in the leaf node
private var _value: String
- init(val: AbstractString)
+ init(val: String)
do
self._value = val.to_s
self.length = val.length
# Read at most i bytes
fun read(i: Int): String
do
- var s = new Buffer.with_capacity(i)
+ var s = new FlatBuffer.with_capacity(i)
while i > 0 and not eof do
var c = read_char
if c >= 0 then
fun read_line: String
do
assert not eof
- var s = new Buffer
+ var s = new FlatBuffer
append_line_to(s)
return s.to_s
end
# Read all the stream until the eof.
fun read_all: String
do
- var s = new Buffer
+ var s = new FlatBuffer
while not eof do
var c = read_char
if c >= 0 then s.add(c.ascii)
redef fun read(i)
do
- var s = new Buffer.with_capacity(i)
+ var s = new FlatBuffer.with_capacity(i)
var j = _buffer_pos
var k = _buffer.length
while i > 0 do
redef fun read_all
do
- var s = new Buffer
+ var s = new FlatBuffer
while not eof do
var j = _buffer_pos
var k = _buffer.length
redef fun eof do return _buffer_pos >= _buffer.length and end_reached
# The buffer
- var _buffer: nullable Buffer = null
+ var _buffer: nullable FlatBuffer = null
# The current position in the buffer
var _buffer_pos: Int = 0
# Allocate a `_buffer` for a given `capacity`.
protected fun prepare_buffer(capacity: Int)
do
- _buffer = new Buffer.with_capacity(capacity)
+ _buffer = new FlatBuffer.with_capacity(capacity)
_buffer_pos = 0 # need to read
end
end
# String #
###############################################################################
-# Common subclass for String and Buffer
-abstract class AbstractString
- super AbstractArrayRead[Char]
+# High-level abstraction for all text representations
+abstract class Text
+ super Comparable
+ super StringCapable
- readable private var _items: NativeString
+ redef type OTHER: Text
- fun chars: StringCharView is abstract
+ # Type of the view on self (.chars)
+ type SELFVIEW: StringCharView
- # Access a character at `index` in the string.
- #
- # assert "abcd"[2] == 'c'
- redef fun [](index) do return _items[index]
+ # Type of self (used for factorization of several methods, ex : substring_from, empty...)
+ type SELFTYPE: Text
+
+ var hash_cache: nullable Int = null
+
+ # Gets a view on the chars of the Text object
+ fun chars: SELFVIEW is abstract
+
+ # Number of characters contained in self.
+ fun length: Int is abstract
# Create a substring.
#
# A `from` index < 0 will be replaced by 0.
# Unless a `count` value is > 0 at the same time.
# In this case, `from += count` and `count -= from`.
- fun substring(from: Int, count: Int): String
+ fun substring(from: Int, count: Int): SELFTYPE is abstract
+
+ # Concatenates `o` to `self`
+ fun +(o: Text): SELFTYPE is abstract
+
+ # Auto-concatenates self `i` times
+ fun *(i: Int): SELFTYPE is abstract
+
+ # Is the current Text empty (== "")
+ # assert "".is_empty
+ # assert not "foo".is_empty
+ fun is_empty: Bool do return self.length == 0
+
+ # Returns an empty Text of the right type
+ fun empty: SELFTYPE is abstract
+
+ # Gets the first char of the Text
+ #
+ # DEPRECATED : Use self.chars.first instead
+ fun first: Char do return self.chars[0]
+
+ # Access a character at `index` in the string.
+ #
+ # assert "abcd"[2] == 'c'
+ #
+ # DEPRECATED : Use self.chars.[] instead
+ fun [](index: Int): Char do return self.chars[index]
+
+ # Gets the index of the first occurence of 'c'
+ #
+ # Returns -1 if not found
+ #
+ # DEPRECATED : Use self.chars.index_of instead
+ fun index_of(c: Char): Int
do
- assert count >= 0
- count += from
- if from < 0 then from = 0
- if count > length then count = length
- if from < count then
- var r = new Buffer.with_capacity(count - from)
- while from < count do
- r.chars.push(_items[from])
- from += 1
- end
- return r.to_s
- else
- return ""
+ return index_of_from(c, 0)
+ end
+
+ # Gets the last char of self
+ #
+ # DEPRECATED : Use self.chars.last instead
+ fun last: Char do return self.chars[length-1]
+
+ # Gets the index of the first occurence of ´c´ starting from ´pos´
+ #
+ # Returns -1 if not found
+ #
+ # DEPRECATED : Use self.chars.index_of_from instead
+ fun index_of_from(c: Char, pos: Int): Int
+ do
+ var iter = self.chars.iterator_from(pos)
+ while iter.is_ok do
+ if iter.item == c then return iter.index
end
+ return -1
end
+ # Gets the last index of char ´c´
+ #
+ # Returns -1 if not found
+ #
+ # DEPRECATED : Use self.chars.last_index_of instead
+ fun last_index_of(c: Char): Int
+ do
+ return last_index_of_from(c, length - 1)
+ end
+
+ # Return a null terminated char *
+ fun to_cstring: NativeString do return flatten.to_cstring
+
+ # The index of the last occurrence of an element starting from pos (in reverse order).
+ # Example :
+ # assert "/etc/bin/test/test.nit".last_index_of_from('/', length-1) == 13
+ # assert "/etc/bin/test/test.nit".last_index_of_from('/', 12) == 8
+ #
+ # Returns -1 if not found
+ #
+ # DEPRECATED : Use self.chars.last_index_of_from instead
+ fun last_index_of_from(item: Char, pos: Int): Int
+ do
+ var iter = self.chars.reverse_iterator_from(pos)
+ while iter.is_ok do
+ if iter.item == item then return iter.index
+ iter.next
+ end
+ return -1
+ end
+
+ # Gets an iterator on the chars of self
+ #
+ # DEPRECATED : Use self.chars.iterator instead
+ fun iterator: Iterator[Char]
+ do
+ return self.chars.iterator
+ end
+
+ # Is 'c' contained in self ?
+ #
+ # DEPRECATED : Use self.chars.has instead
+ fun has(c: Char): Bool
+ do
+ return self.chars.has(c)
+ end
+
+ # Gets an Array containing the chars of self
+ #
+ # DEPRECATED : Use self.chars.to_a instead
+ fun to_a: Array[Char] do return chars.to_a
+
# Create a substring from `self` beginning at the `from` position
#
# assert "abcd".substring_from(1) == "bcd"
# assert "abcd".substring_from(2) == "cd"
#
# As with substring, a `from` index < 0 will be replaced by 0
- fun substring_from(from: Int): String
+ fun substring_from(from: Int): SELFTYPE
do
- assert from < length
+ if from > self.length then return empty
+ if from < 0 then from = 0
return substring(from, length - from)
end
+ # Returns a reversed version of self
+ fun reversed: SELFTYPE is abstract
+
# Does self have a substring `str` starting from position `pos`?
#
# assert "abcd".has_substring("bc",1) == true
# assert "abcd".has_substring("bc",2) == false
fun has_substring(str: String, pos: Int): Bool
do
- var itsindex = str.length - 1
- var myindex = pos + itsindex
- var myitems = _items
- var itsitems = str._items
- if myindex > length or itsindex > myindex then return false
- var its_index_from = str._index_from
- itsindex += its_index_from
- while itsindex >= its_index_from do
- if myitems[myindex] != itsitems[itsindex] then return false
- myindex -= 1
- itsindex -= 1
+ var myiter = self.chars.iterator_from(pos)
+ var itsiter = str.iterator
+ while myiter.is_ok and itsiter.is_ok do
+ if myiter.item != itsiter.item then return false
+ myiter.next
+ itsiter.next
end
+ if itsiter.is_ok then return false
return true
end
# A upper case version of `self`
#
# assert "Hello World!".to_upper == "HELLO WORLD!"
- fun to_upper: String
- do
- var s = new Buffer.with_capacity(length)
- for i in self.chars do s.add(i.to_upper)
- return s.to_s
- end
+ fun to_upper: SELFTYPE is abstract
# A lower case version of `self`
#
# assert "Hello World!".to_lower == "hello world!"
- fun to_lower : String
+ fun to_lower : SELFTYPE is abstract
+
+ # Removes the whitespaces at the beginning of self
+ fun l_trim: SELFTYPE
do
- var s = new Buffer.with_capacity(length)
- for i in self.chars do s.add(i.to_lower)
- return s.to_s
+ var iter = self.chars.iterator
+ while iter.is_ok do
+ if iter.item.ascii > 32 then break
+ iter.next
+ end
+ if iter.index == length then return self.empty
+ return self.substring_from(iter.index)
+ end
+
+ # Removes the whitespaces at the end of self
+ fun r_trim: SELFTYPE
+ do
+ var iter = self.chars.reverse_iterator
+ while iter.is_ok do
+ if iter.item.ascii > 32 then break
+ iter.next
+ end
+ if iter.index == length then return self.empty
+ return self.substring(0, iter.index + 1)
end
# Trims trailing and preceding white spaces
#
# assert " Hello World ! ".trim == "Hello World !"
# assert "\na\nb\tc\t".trim == "a\nb\tc"
- fun trim: String
- do
- if self.length == 0 then return self.to_s
- # find position of the first non white space char (ascii < 32) from the start of the string
- var start_pos = 0
- while self.chars[start_pos].ascii <= 32 do
- start_pos += 1
- if start_pos == length then return ""
- end
- # find position of the first non white space char from the end of the string
- var end_pos = length - 1
- while self.chars[end_pos].ascii <= 32 do
- end_pos -= 1
- if end_pos == start_pos then return self.chars[start_pos].to_s
- end
- return self.substring(start_pos, end_pos - start_pos + 1)
- end
-
- redef fun output
- do
- var i = 0
- while i < length do
- _items[i].output
- i += 1
- end
- end
+ fun trim: SELFTYPE do return (self.l_trim).r_trim
# Mangle a string to be a unique string only made of alphanumeric characters
fun to_cmangle: String
do
- var res = new Buffer
+ var res = new FlatBuffer
var underscore = false
for c in self.chars do
if (c >= 'a' and c <= 'z') or (c >='A' and c <= 'Z') then
# assert "\n\"'\\".escape_to_c == "\\n\\\"\\'\\\\"
fun escape_to_c: String
do
- var b = new Buffer
+ var b = new FlatBuffer
for c in self.chars do
if c == '\n' then
b.append("\\n")
# assert "ab|\{\}".escape_more_to_c("|\{\}") == "ab\\|\\\{\\\}"
fun escape_more_to_c(chars: String): String
do
- var b = new Buffer
+ var b = new FlatBuffer
for c in escape_to_c do
- if chars.has(c) then
+ if chars.chars.has(c) then
b.add('\\')
end
b.add(c)
# assert u[0].ascii == 10 # (the ASCII value of the "new line" character)
fun unescape_nit: String
do
- var res = new Buffer.with_capacity(self.length)
+ var res = new FlatBuffer.with_capacity(self.length)
var was_slash = false
for c in self do
if not was_slash then
end
return res.to_s
end
+
+ redef fun ==(o)
+ do
+ if o == null then return false
+ if not o isa Text then return false
+ if self.is_same_instance(o) then return true
+ if self.length != o.length then return false
+ return self.chars == o.chars
+ end
+
+ redef fun <(o)
+ do
+ return self.chars < o.chars
+ end
+
+ # Flat representation of self
+ fun flatten: FlatText is abstract
+
+ redef fun hash
+ do
+ if hash_cache == null then
+ # djb2 hash algorithm
+ var h = 5381
+ var i = length - 1
+
+ for char in self.chars do
+ h = (h * 32) + h + char.ascii
+ i -= 1
+ end
+
+ hash_cache = h
+ end
+ return hash_cache.as(not null)
+ end
+
+end
+
+# All kinds of array-based text representations.
+abstract class FlatText
+ super Text
+
+ private var items: NativeString
+
+ # Real items, used as cache for to_cstring is called
+ private var real_items: nullable NativeString = null
+
+ redef var length: Int
+
+ init do end
+
+ redef fun output
+ do
+ var i = 0
+ while i < length do
+ items[i].output
+ i += 1
+ end
+ end
+
+ redef fun flatten do return self
end
# Abstract class for the SequenceRead compatible
# views on String and Buffer objects
abstract class StringCharView
super SequenceRead[Char]
+ super Comparable
+
+ type SELFTYPE: Text
- type SELFTYPE: AbstractString
+ redef type OTHER: StringCharView
private var target: SELFTYPE
redef fun length do return target.length
+ redef fun iterator: IndexedIterator[Char] do return self.iterator_from(0)
+
+ # Gets a new Iterator starting at position `pos`
+ #
+ # Ex :
+ # var iter = "abcd".iterator_from(2)
+ # while iter.is_ok do
+ # printn iter.item
+ # iter.next
+ # end
+ #
+ # Outputs : cd
+ fun iterator_from(pos: Int): IndexedIterator[Char] is abstract
+
+ # Gets an iterator starting at the end and going backwards
+ #
+ # Ex :
+ # var reviter = "now step live...".reverse_iterator
+ # while reviter.is_ok do
+ # printn reviter.item
+ # reviter.next
+ # end
+ #
+ # Outputs : ...evil pets won
+ fun reverse_iterator: IndexedIterator[Char] do return self.reverse_iterator_from(self.length - 1)
+
+ # Gets an iterator on the chars of self starting from `pos`
+ #
+ # Ex :
+ # var iter = "abcd".reverse_iterator_from(1)
+ # while iter.is_ok do
+ # printn iter.item
+ # iter.next
+ # end
+ #
+ # Outputs : ba
+ fun reverse_iterator_from(pos: Int): IndexedIterator[Char] is abstract
+
redef fun has(c: Char): Bool
do
for i in self do
return false
end
+ redef fun ==(other)
+ do
+ if other == null then return false
+ if not other isa StringCharView then return false
+ var other_chars = other.iterator
+ for i in self do
+ if i != other_chars.item then return false
+ other_chars.next
+ end
+ return true
+ end
+
+ redef fun <(other)
+ do
+ var self_chars = self.iterator
+ var other_chars = other.iterator
+
+ while self_chars.is_ok and other_chars.is_ok do
+ if self_chars.item < other_chars.item then return true
+ if self_chars.item > other_chars.item then return false
+ self_chars.next
+ other_chars.next
+ end
+
+ if self_chars.is_ok then
+ return false
+ else
+ return true
+ end
+ end
end
# View on Buffer objects, extends Sequence
end
+abstract class String
+ super Text
+
+ redef type SELFTYPE: String
+
+ redef fun to_s do return self
+
+end
+
# Immutable strings of characters.
-class String
- super Comparable
- super AbstractString
- super StringCapable
+class FlatString
+ super FlatText
+ super String
- redef type OTHER: String
+ redef type SELFTYPE: FlatString
# Index in _items of the start of the string
- readable var _index_from: Int
+ private var index_from: Int
# Indes in _items of the last item of the string
- readable var _index_to: Int
+ private var index_to: Int
- redef var chars: StringCharView = new FlatStringCharView(self)
+ redef var chars: SELFVIEW = new FlatStringCharView(self)
################################################
# AbstractString specific methods #
assert index >= 0
# Check that the index (+ index_from) is not larger than indexTo
# In other terms, if the index is valid
- assert (index + _index_from) <= _index_to
- return _items[index + _index_from]
+ assert (index + index_from) <= index_to
+ return items[index + index_from]
+ end
+
+ redef fun reversed
+ do
+ var native = calloc_string(self.length + 1)
+ var reviter = chars.reverse_iterator
+ var pos = 0
+ while reviter.is_ok do
+ native[pos] = reviter.item
+ pos += 1
+ reviter.next
+ end
+ return native.to_s_with_length(self.length)
end
- redef fun substring(from: Int, count: Int): String
+ redef fun substring(from, count)
do
assert count >= 0
from = 0
end
- var realFrom = _index_from + from
+ var realFrom = index_from + from
- if (realFrom + count) > _index_to then return new String.with_infos(_items, _index_to - realFrom + 1, realFrom, _index_to)
+ if (realFrom + count) > index_to then return new FlatString.with_infos(items, index_to - realFrom + 1, realFrom, index_to)
- if count == 0 then return ""
+ if count == 0 then return empty
var to = realFrom + count - 1
- return new String.with_infos(_items, to - realFrom + 1, realFrom, to)
+ return new FlatString.with_infos(items, to - realFrom + 1, realFrom, to)
end
- redef fun substring_from(from: Int): String
- do
- if from > _length then return ""
- if from < 0 then from = 0
- return substring(from, _length)
- end
-
- redef fun has_substring(str: String, pos: Int): Bool
- do
- var itsindex = str._length - 1
-
- var myindex = pos + itsindex
- var myitems = _items
-
- var itsitems = str._items
-
- if myindex > _length or itsindex > myindex then return false
-
- var itsindexfrom = str.index_from
- itsindex += itsindexfrom
- myindex += index_from
-
- while itsindex >= itsindexfrom do
- if myitems[myindex] != itsitems[itsindex] then return false
- myindex -= 1
- itsindex -= 1
- end
+ redef fun empty do return "".as(FlatString)
- return true
- end
-
- redef fun to_upper: String
+ redef fun to_upper
do
- var outstr = calloc_string(self._length + 1)
+ var outstr = calloc_string(self.length + 1)
var out_index = 0
- var myitems = self._items
- var index_from = self._index_from
- var max = self._index_to
+ var myitems = self.items
+ var index_from = self.index_from
+ var max = self.index_to
while index_from <= max do
outstr[out_index] = myitems[index_from].to_upper
outstr[self.length] = '\0'
- return outstr.to_s_with_length(self._length)
+ return outstr.to_s_with_length(self.length)
end
- redef fun to_lower : String
+ redef fun to_lower
do
- var outstr = calloc_string(self._length + 1)
+ var outstr = calloc_string(self.length + 1)
var out_index = 0
- var myitems = self._items
- var index_from = self._index_from
- var max = self._index_to
+ var myitems = self.items
+ var index_from = self.index_from
+ var max = self.index_to
while index_from <= max do
outstr[out_index] = myitems[index_from].to_lower
outstr[self.length] = '\0'
- return outstr.to_s_with_length(self._length)
- end
-
- redef fun trim: String
- do
- if self._length == 0 then return self
- # find position of the first non white space char (ascii < 32) from the start of the string
- var start_pos = self._index_from
- while _items[start_pos].ascii <= 32 do
- start_pos += 1
- if start_pos == _index_to + 1 then return ""
- end
- # find position of the first non white space char from the end of the string
- var end_pos = _index_to
- while _items[end_pos].ascii <= 32 do
- end_pos -= 1
- if end_pos == start_pos then return _items[start_pos].to_s
- end
- start_pos -= index_from
- end_pos -= index_from
- return self.substring(start_pos, end_pos - start_pos + 1)
+ return outstr.to_s_with_length(self.length)
end
redef fun output
do
- var i = self._index_from
- var imax = self._index_to
+ var i = self.index_from
+ var imax = self.index_to
while i <= imax do
- _items[i].output
+ items[i].output
i += 1
end
end
private init with_infos(items: NativeString, len: Int, from: Int, to: Int)
do
- self._items = items
- _length = len
- _index_from = from
- _index_to = to
+ self.items = items
+ length = len
+ index_from = from
+ index_to = to
end
# Return a null terminated char *
- fun to_cstring: NativeString
+ redef fun to_cstring: NativeString
do
- if _index_from > 0 or _index_to != items.cstring_length - 1 then
- var newItems = calloc_string(_length + 1)
- self.items.copy_to(newItems, _length, _index_from, 0)
+ if real_items != null then return real_items.as(not null)
+ if index_from > 0 or index_to != items.cstring_length - 1 then
+ var newItems = calloc_string(length + 1)
+ self.items.copy_to(newItems, length, index_from, 0)
newItems[length] = '\0'
+ self.real_items = newItems
return newItems
end
- return _items
+ return items
end
redef fun ==(other)
do
- if not other isa String then return false
+ if not other isa FlatString then return super
if self.object_id == other.object_id then return true
- var my_length = _length
+ var my_length = length
- if other._length != my_length then return false
+ if other.length != my_length then return false
- var my_index = _index_from
- var its_index = other._index_from
+ var my_index = index_from
+ var its_index = other.index_from
var last_iteration = my_index + my_length
- var itsitems = other._items
- var myitems = self._items
+ var itsitems = other.items
+ var myitems = self.items
while my_index < last_iteration do
if myitems[my_index] != itsitems[its_index] then return false
# assert ("aa" < "b") == true
redef fun <(other)
do
+ if not other isa FlatString then return super
+
if self.object_id == other.object_id then return false
var my_curr_char : Char
var its_curr_char : Char
- var curr_id_self = self._index_from
- var curr_id_other = other._index_from
+ var curr_id_self = self.index_from
+ var curr_id_other = other.index_from
- var my_items = self._items
- var its_items = other._items
+ var my_items = self.items
+ var its_items = other.items
- var my_length = self._length
- var its_length = other._length
+ var my_length = self.length
+ var its_length = other.length
var max_iterations = curr_id_self + my_length
# The concatenation of `self` with `s`
#
# assert "hello " + "world!" == "hello world!"
- fun +(s: String): String
+ redef fun +(s)
do
- var my_length = self._length
- var its_length = s._length
+ var my_length = self.length
+ var its_length = s.length
var total_length = my_length + its_length
var target_string = calloc_string(my_length + its_length + 1)
- self._items.copy_to(target_string, my_length, _index_from, 0)
- s._items.copy_to(target_string, its_length, s._index_from, my_length)
+ self.items.copy_to(target_string, my_length, index_from, 0)
+ if s isa FlatString then
+ s.items.copy_to(target_string, its_length, s.index_from, my_length)
+ else if s isa FlatBuffer then
+ s.items.copy_to(target_string, its_length, 0, my_length)
+ else
+ var curr_pos = my_length
+ for i in s.chars do
+ target_string[curr_pos] = i
+ curr_pos += 1
+ end
+ end
target_string[total_length] = '\0'
return target_string.to_s_with_length(total_length)
end
- # `i` repetitions of `self`
- #
# assert "abc"*3 == "abcabcabc"
# assert "abc"*1 == "abc"
# assert "abc"*0 == ""
- fun *(i: Int): String
+ redef fun *(i)
do
assert i >= 0
- var my_length = self._length
+ var my_length = self.length
var final_length = my_length * i
- var my_items = self._items
+ var my_items = self.items
var target_string = calloc_string((final_length) + 1)
return target_string.to_s_with_length(final_length)
end
- redef fun to_s do return self
-
redef fun hash
do
- # djb2 hash algorythm
- var h = 5381
- var i = _length - 1
+ if hash_cache == null then
+ # djb2 hash algorythm
+ var h = 5381
+ var i = length - 1
+
+ var myitems = items
+ var strStart = index_from
- var myitems = _items
- var strStart = _index_from
+ i += strStart
- i += strStart
+ while i >= strStart do
+ h = (h * 32) + h + self.items[i].ascii
+ i -= 1
+ end
- while i >= strStart do
- h = (h * 32) + h + self._items[i].ascii
- i -= 1
+ hash_cache = h
end
- return h
+ return hash_cache.as(not null)
end
end
+private class FlatStringReverseIterator
+ super IndexedIterator[Char]
+
+ var target: FlatString
+
+ var target_items: NativeString
+
+ var curr_pos: Int
+
+ init with_pos(tgt: FlatString, pos: Int)
+ do
+ target = tgt
+ target_items = tgt.items
+ curr_pos = pos + tgt.index_from
+ end
+
+ redef fun is_ok do return curr_pos >= 0
+
+ redef fun item do return target_items[curr_pos]
+
+ redef fun next do curr_pos -= 1
+
+ redef fun index do return curr_pos - target.index_from
+
+end
+
private class FlatStringIterator
super IndexedIterator[Char]
- var target: String
+ var target: FlatString
var target_items: NativeString
var curr_pos: Int
- init with_pos(tgt: String, pos: Int)
+ init with_pos(tgt: FlatString, pos: Int)
do
target = tgt
target_items = tgt.items
private class FlatStringCharView
super StringCharView
- redef type SELFTYPE: String
+ redef type SELFTYPE: FlatString
redef fun [](index)
do
# Check that the index (+ index_from) is not larger than indexTo
# In other terms, if the index is valid
assert index >= 0
- assert (index + target._index_from) <= target._index_to
- return target._items[index + target._index_from]
+ assert (index + target.index_from) <= target.index_to
+ return target.items[index + target.index_from]
end
- redef fun iterator: IndexedIterator[Char] do return new FlatStringIterator.with_pos(target, 0)
+ redef fun iterator_from(start) do return new FlatStringIterator.with_pos(target, start)
+
+ redef fun reverse_iterator_from(start) do return new FlatStringReverseIterator.with_pos(target, start)
+
+end
+
+abstract class Buffer
+ super Text
+
+ redef type SELFVIEW: BufferCharView
+ redef type SELFTYPE: Buffer
+
+ var is_dirty = true
+
+ # Modifies the char contained at pos `index`
+ #
+ # DEPRECATED : Use self.chars.[]= instead
+ fun []=(index: Int, item: Char) is abstract
+
+ # Adds a char `c` at the end of self
+ #
+ # DEPRECATED : Use self.chars.add instead
+ fun add(c: Char) is abstract
+
+ # Clears the buffer
+ fun clear is abstract
+
+ # Enlarges the subsequent array containing the chars of self
+ fun enlarge(cap: Int) is abstract
+
+ # Adds the content of text `s` at the end of self
+ fun append(s: Text) is abstract
+
+ redef fun hash
+ do
+ if is_dirty then hash_cache = null
+ return super
+ end
end
# Mutable strings of characters.
-class Buffer
- super AbstractString
- super Comparable
- super StringCapable
- super AbstractArray[Char]
+class FlatBuffer
+ super FlatText
+ super Buffer
+
+ redef type SELFTYPE: FlatBuffer
- redef type OTHER: String
+ redef var chars: SELFVIEW = new FlatBufferCharView(self)
- redef var chars: BufferCharView = new FlatBufferCharView(self)
+ var capacity: Int
redef fun []=(index, item)
do
+ is_dirty = true
if index == length then
add(item)
return
end
assert index >= 0 and index < length
- _items[index] = item
+ items[index] = item
end
redef fun add(c)
do
- if _capacity <= length then enlarge(length + 5)
- _items[length] = c
- _length += 1
+ is_dirty = true
+ if capacity <= length then enlarge(length + 5)
+ items[length] = c
+ length += 1
+ end
+
+ redef fun clear do
+ is_dirty = true
+ length = 0
end
+ redef fun empty do return new FlatBuffer
+
redef fun enlarge(cap)
do
- var c = _capacity
+ is_dirty = true
+ var c = capacity
if cap <= c then return
while c <= cap do c = c * 2 + 2
var a = calloc_string(c+1)
- _items.copy_to(a, length, 0, 0)
- _items = a
- _capacity = c
+ items.copy_to(a, length, 0, 0)
+ items = a
+ capacity = c
+ items.copy_to(a, length, 0, 0)
end
- redef fun append(s)
+ redef fun to_s: String
+ do
+ return to_cstring.to_s_with_length(length)
+ end
+
+ redef fun to_cstring
do
- if s isa String then
- var sl = s.length
- if _capacity < _length + sl then enlarge(_length + sl)
- s.items.copy_to(_items, sl, s._index_from, _length)
- _length += sl
+ if is_dirty then
+ var new_native = calloc_string(length + 1)
+ new_native[length] = '\0'
+ items.copy_to(new_native, length, 0, 0)
+ real_items = new_native
+ is_dirty = false
+ end
+ return real_items.as(not null)
+ end
+
+ # Create a new empty string.
+ init do with_capacity(5)
+
+ init from(s: Text)
+ do
+ capacity = s.length + 1
+ length = s.length
+ items = calloc_string(capacity)
+ if s isa FlatString then
+ s.items.copy_to(items, length, s.index_from, 0)
+ else if s isa FlatBuffer then
+ s.items.copy_to(items, length, 0, 0)
else
- super
+ var curr_pos = 0
+ for i in s.chars do
+ items[curr_pos] = i
+ curr_pos += 1
+ end
end
end
- redef fun to_s: String
+ # Create a new empty string with a given capacity.
+ init with_capacity(cap: Int)
do
- var l = length
- var a = calloc_string(l+1)
- _items.copy_to(a, l, 0, 0)
+ assert cap >= 0
+ # _items = new NativeString.calloc(cap)
+ items = calloc_string(cap+1)
+ capacity = cap
+ length = 0
+ end
- # Ensure the afterlast byte is '\0' to nul-terminated char *
- a[length] = '\0'
+ redef fun append(s)
+ do
+ is_dirty = true
+ var sl = s.length
+ if capacity < length + sl then enlarge(length + sl)
+ if s isa FlatString then
+ s.items.copy_to(items, sl, s.index_from, length)
+ else if s isa FlatBuffer then
+ s.items.copy_to(items, sl, 0, length)
+ else
+ var curr_pos = self.length
+ for i in s.chars do
+ items[curr_pos] = i
+ curr_pos += 1
+ end
+ end
+ length += sl
+ end
- return a.to_s_with_length(length)
+ # Copies the content of self in `dest`
+ fun copy(start: Int, len: Int, dest: Buffer, new_start: Int)
+ do
+ var self_chars = self.chars
+ var dest_chars = dest.chars
+ for i in [0..len-1] do
+ dest_chars[new_start+i] = self_chars[start+i]
+ end
end
- redef fun <(s)
+ redef fun substring(from, count)
do
- var i = 0
- var l1 = length
- var l2 = s.length
- while i < l1 and i < l2 do
- var c1 = self.chars[i].ascii
- var c2 = s.chars[i].ascii
- if c1 < c2 then
- return true
- else if c2 < c1 then
- return false
+ assert count >= 0
+ count += from
+ if from < 0 then from = 0
+ if count > length then count = length
+ if from < count then
+ var r = new FlatBuffer.with_capacity(count - from)
+ while from < count do
+ r.chars.push(items[from])
+ from += 1
end
- i += 1
- end
- if l1 < l2 then
- return true
+ return r
else
- return false
+ return new FlatBuffer
end
end
- # Create a new empty string.
- init
+ redef fun reversed
do
- with_capacity(5)
+ var new_buf = new FlatBuffer.with_capacity(self.length)
+ var reviter = self.chars.reverse_iterator
+ while reviter.is_ok do
+ new_buf.add(reviter.item)
+ reviter.next
+ end
+ return new_buf
end
- init from(s: String)
+ redef fun +(other)
do
- _capacity = s.length + 1
- _length = s.length
- _items = calloc_string(_capacity)
- s.items.copy_to(_items, _length, s._index_from, 0)
+ var new_buf = new FlatBuffer.with_capacity(self.length + other.length)
+ new_buf.append(self)
+ new_buf.append(other)
+ return new_buf
end
- # Create a new empty string with a given capacity.
- init with_capacity(cap: Int)
+ redef fun *(repeats)
do
- assert cap >= 0
- # _items = new NativeString.calloc(cap)
- _items = calloc_string(cap+1)
- _capacity = cap
- _length = 0
+ var new_buf = new FlatBuffer.with_capacity(self.length * repeats)
+ for i in [0..repeats[ do
+ new_buf.append(self)
+ end
+ return new_buf
end
+end
- redef fun ==(o)
+private class FlatBufferReverseIterator
+ super IndexedIterator[Char]
+
+ var target: FlatBuffer
+
+ var target_items: NativeString
+
+ var curr_pos: Int
+
+ init with_pos(tgt: FlatBuffer, pos: Int)
do
- if not o isa Buffer then return false
- var l = length
- if o.length != l then return false
- var i = 0
- var it = _items
- var oit = o._items
- while i < l do
- if it[i] != oit[i] then return false
- i += 1
- end
- return true
+ target = tgt
+ target_items = tgt.items
+ curr_pos = pos
end
- readable private var _capacity: Int
+ redef fun index do return curr_pos
+
+ redef fun is_ok do return curr_pos >= 0
+
+ redef fun item do return target_items[curr_pos]
+
+ redef fun next do curr_pos -= 1
+
end
private class FlatBufferCharView
super BufferCharView
super StringCapable
- redef type SELFTYPE: Buffer
+ redef type SELFTYPE: FlatBuffer
- redef fun [](index) do return target._items[index]
+ redef fun [](index) do return target.items[index]
redef fun []=(index, item)
do
add(item)
return
end
- target._items[index] = item
+ target.items[index] = item
end
redef fun push(c)
if target.capacity < s.length then enlarge(s_length + target.length)
end
- redef fun iterator: IndexedIterator[Char] do return new FlatBufferIterator.with_pos(target, 0)
+ redef fun iterator_from(pos) do return new FlatBufferIterator.with_pos(target, pos)
+
+ redef fun reverse_iterator_from(pos) do return new FlatBufferReverseIterator.with_pos(target, pos)
end
private class FlatBufferIterator
super IndexedIterator[Char]
- var target: Buffer
+ var target: FlatBuffer
var target_items: NativeString
var curr_pos: Int
- init with_pos(tgt: Buffer, pos: Int)
+ init with_pos(tgt: FlatBuffer, pos: Int)
do
target = tgt
target_items = tgt.items
fun to_base(base: Int, signed: Bool): String
do
var l = digit_count(base)
- var s = new Buffer.from(" " * l)
+ var s = new FlatBuffer.from(" " * l)
fill_buffer(s, base, signed)
return s.to_s
end
# assert 'x'.to_s == "x"
redef fun to_s
do
- var s = new Buffer.with_capacity(1)
+ var s = new FlatBuffer.with_capacity(1)
s.chars[0] = self
return s.to_s
end
# Concatenate elements.
redef fun to_s
do
- var s = new Buffer
+ var s = new FlatBuffer
for e in self do if e != null then s.append(e.to_s)
return s.to_s
end
do
if is_empty then return ""
- var s = new Buffer # Result
+ var s = new FlatBuffer # Result
# Concat first item
var i = iterator
# Fast implementation
redef fun to_s
do
- var s = new Buffer
+ var s = new FlatBuffer
var i = 0
var l = length
while i < l do
do
if is_empty then return ""
- var s = new Buffer # Result
+ var s = new FlatBuffer # Result
# Concat first item
var i = iterator
return to_s_with_length(cstring_length)
end
- fun to_s_with_length(length: Int): String
+ fun to_s_with_length(length: Int): FlatString
do
assert length >= 0
- return new String.with_infos(self, length, 0, length - 1)
+ return new FlatString.with_infos(self, length, 0, length - 1)
end
- fun to_s_with_copy: String
+ fun to_s_with_copy: FlatString
do
var length = cstring_length
var new_self = calloc_string(length + 1)
copy_to(new_self, length, 0, 0)
- return new String.with_infos(new_self, length, 0, length - 1)
+ return new FlatString.with_infos(new_self, length, 0, length - 1)
end
end
# Search all `self` occurrences into `s`.
#
# assert 'l'.search_all_in("hello world").length == 3
- # assert 'z'.search_all_in("hello world"),length == 0
+ # assert 'z'.search_all_in("hello world").length == 0
#
# Note: Is used by `String::search_all`.
- fun search_all_in(s: String): Array[Match]
+ protected fun search_all_in(s: String): Array[Match]
do
var res = new Array[Match] # Result
var match = search_in(s, 0)
# assert 'z'.split_in("hello world").join("|") == "hello world"
#
# Note: is used by `String::split`
- fun split_in(s: String): Array[Match]
+ protected fun split_in(s: String): Array[Match]
do
var res = new Array[Match] # Result
var i = 0 # Cursor
if args != null then
n_args.n_exprs.add_all(args)
end
- callsite = new CallSite(self, mtype, true, mmethod, mmethod.intro, mmethod.intro.msignature.as(not null), false)
+ callsite = new CallSite(self, mtype, mmethod.intro.mclassdef.mmodule, mtype, true, mmethod, mmethod.intro, mmethod.intro.msignature.as(not null), false)
self.mtype = mtype
end
end
self.n_args.n_exprs.add_all(args)
end
var mtype = recv.mtype.as(not null)
- callsite = new CallSite(self, mtype, true, mmethod, mmethod.intro, mmethod.intro.msignature.as(not null), false)
+ callsite = new CallSite(self, mtype, mmethod.intro.mclassdef.mmodule, mmethod.intro.mclassdef.bound_mtype, true, mmethod, mmethod.intro, mmethod.intro.msignature.as(not null), false)
self.mtype = t
self.is_typed = true
end
var msignature = candidatedef.msignature
msignature = msignature.resolve_for(recvtype, anchor, mmodule, true)
- var callsite = new CallSite(self, recvtype, true, candidate, candidatedef, msignature, false)
+ var callsite = new CallSite(self, recvtype, mmodule, anchor, true, candidate, candidatedef, msignature, false)
auto_super_inits.add(callsite)
end
if auto_super_inits.is_empty then
do
super
+ var base_cname = "null_{mtype.mangled_cname}"
+ var full_cname = "NIT_NULL___{base_cname}"
+
# In nitni files, declare internal function as extern
- var full_friendly_csignature = "{cname} {v.compiler.mainmodule.name}___null_{mtype.mangled_cname}()"
+ var full_friendly_csignature = "{cname_blind} {full_cname}()"
ccu.header_decl.add("extern {full_friendly_csignature};\n")
# In nitni files, #define friendly as extern
- var base_cname = "null_{mtype.mangled_cname}"
- ccu.header_decl.add("#define {base_cname} {v.compiler.mainmodule.name}___{base_cname}\n")
+ ccu.header_decl.add("#define {base_cname} {full_cname}\n")
+
+ # FIXME: This is ugly an broke the separate compilation principle
+ # The real function MUST be compiled only once, #define pragma only protect the compiler, not the loader
+ # However, I am not sure of the right approach here (eg. week refs are ugly)
+ if is_already_compiled then return
+ is_already_compiled = true
# Internally, implement internal function
var nitni_visitor = v.compiler.new_visitor
nitni_visitor.frame = v.frame
- var full_internal_csignature = "{cname_blind} {v.compiler.mainmodule.name}___null_{mtype.mangled_cname}()"
- nitni_visitor.add("#ifndef NIT_NULL_null_{mtype.mangled_cname}")
- nitni_visitor.add("#define NIT_NULL_null_{mtype.mangled_cname}")
+ var full_internal_csignature = "{cname_blind} {full_cname}()"
nitni_visitor.add("{full_internal_csignature} \{")
nitni_visitor.add("struct nitni_instance* ret_for_c;")
nitni_visitor.add("ret_for_c = malloc(sizeof(struct nitni_instance));")
nitni_visitor.add("ret_for_c->value = NULL;")
nitni_visitor.add("return ret_for_c;")
nitni_visitor.add("\}")
- nitni_visitor.add("#endif")
end
+
+ private var is_already_compiled = false # FIXME to remove, show above
end
redef class MExplicitCall
message_sorter.sort(messages)
for m in messages do
- if "Warning".search_in(m.text, 0) == null then had_error = true
+ if m.text.search("Warning") == null then had_error = true
stderr.write("{m.to_color_string}\n")
end
end
else if command == "nit" then
printn "$~> "
command = gets
- var nit_buf = new Buffer
+ var nit_buf = new FlatBuffer
while not command == ":q" do
nit_buf.append(command)
nit_buf.append("\n")
# Gets all the identifiers of an instruction (uses the rules of Nit as of Mar 05 2013)
#
- fun get_identifiers_in_current_instruction(instruction: AbstractString): Array[String]
+ fun get_identifiers_in_current_instruction(instruction: Text): Array[String]
do
var result_array = new Array[String]
- var instruction_buffer = new Buffer
+ var instruction_buffer = new FlatBuffer
var trigger_char_escape = false
var trigger_string_escape = false
# Takes a function call or declaration and strips all but the arguments
#
- fun get_function_arguments(function: AbstractString): String
+ fun get_function_arguments(function: Text): String
do
- var buf = new Buffer
+ var buf = new FlatBuffer
var trigger_copy = false
for i in function.chars do
fun get_real_variable_name(name: String): String
do
var explode_string = name.split_with(".")
- var final_string = new Buffer
+ var final_string = new FlatBuffer
for i in explode_string do
var alias_resolved = get_variable_name_by_alias(i)
if alias_resolved != null then
# Returns an array containing their content
fun remove_braces(braces: String): nullable Array[String]
do
- var buffer = new Buffer
+ var buffer = new FlatBuffer
var result_array = new Array[String]
var frame = new Frame(v, mmethoddef, recv, arguments)
v.frame = frame
- var sig = new Buffer
- var comment = new Buffer
+ var sig = new FlatBuffer
+ var comment = new FlatBuffer
var ret = mmethoddef.msignature.return_mtype
if ret != null then
ret = v.resolve_for(ret, selfvar)
lmid = ""
lend = ""
end
- var indent = new Buffer
+ var indent = new FlatBuffer
for j in [line_start..line_start+l.column_start-1[ do
if string.chars[j] == '\t' then
indent.add '\t'
# Create a dot file representing the class hierarchy of a model.
fun generate_class_hierarchy(toolcontext: ToolContext, mmodule: MModule)
do
- var buf = new Buffer
+ var buf = new FlatBuffer
buf.append("digraph \{\n")
buf.append("node [shape=box];\n")
buf.append("rankdir=BT;\n")
# For a simple user of the model, the classdef hierarchy is not really usefull, it is more an internal thing.
fun generate_classdef_hierarchy(toolcontext: ToolContext, model: Model)
do
- var buf = new Buffer
+ var buf = new FlatBuffer
buf.append("digraph \{\n")
buf.append("node [shape=box];\n")
buf.append("rankdir=BT;\n")
# The generated file contains the description of each entity of the model
fun generate_model_hyperdoc(toolcontext: ToolContext, model: Model)
do
- var buf = new Buffer
+ var buf = new FlatBuffer
buf.append("<html>\n<body>\n")
buf.append("<h1>Model</h1>\n")
gmetrics.to_console(1, not toolcontext.opt_nocolors.value)
if csv then gmetrics.to_csv.save("{out}/complexity.csv")
+ callsite_info(analysis)
+
# dump type and method infos
if csv then
analysis.live_types_to_csv.save("{out}/rta_types.csv")
analysis.live_methods_to_tree.write_to_file("{out}/rta_methods.dat")
end
end
+
+ fun callsite_info(rta: RapidTypeAnalysis)
+ do
+ print toolcontext.format_h2("\n ## Callsites")
+ print "* {rta.live_callsites.length} live callsites"
+
+ var csep = new Counter[MPropDef]
+ var cglo = new Counter[MPropDef]
+ var morphisme = new Counter[Int]
+ for cs in rta.live_callsites do
+ csep.inc(cs.mpropdef)
+ var targets = rta.live_targets(cs)
+ for d in targets do
+ cglo.inc(d)
+ end
+ morphisme.inc(targets.length)
+ end
+
+ print toolcontext.format_h3("MMethodDef locally designated (by number of CallSites)")
+ csep.print_summary
+ csep.print_elements(5)
+
+ print toolcontext.format_h3("MMethodDef possibly invoked at runtime (by number of CallSites)")
+ cglo.print_summary
+ cglo.print_elements(5)
+ end
end
# Summary metrics
redef fun to_s
do
- var b = new Buffer
+ var b = new FlatBuffer
if not mparameters.is_empty then
b.append("(")
for i in [0..mparameters.length[ do
end
end
-fun intrude_visibility: MVisibility do return once new MVisibility("intrude", 4)
+fun intrude_visibility: MVisibility do return once new MVisibility("intrude", 5)
fun public_visibility: MVisibility do return once new MVisibility("public", 4)
fun protected_visibility: MVisibility do return once new MVisibility("protected", 3)
fun private_visibility: MVisibility do return once new MVisibility("private", 2)
-fun none_visibility: MVisibility do return once new MVisibility("none", 2)
+fun none_visibility: MVisibility do return once new MVisibility("none", 1)
# Option --only-parse
var opt_only_parse: OptionBool = new OptionBool("Only proceed to parse step of loaders", "--only-parse")
+ # Option --ignore-visibility
+ var opt_ignore_visibility: OptionBool = new OptionBool("Do not check, and produce errors, on visibility issues.", "--ignore-visibility")
+
redef init
do
super
- option_context.add_option(opt_path, opt_only_parse, opt_only_metamodel)
+ option_context.add_option(opt_path, opt_only_parse, opt_only_metamodel, opt_ignore_visibility)
end
fun modelbuilder: ModelBuilder do return modelbuilder_real.as(not null)
mainmodule.set_imported_mmodules(mmodules)
end
for phase in phases_list do
+ if phase.disabled then continue
phase.process_mainmodule(mainmodule, mmodules)
end
end
# Return a new native string initialized with `txt`
fun native_string_instance(txt: String): Instance
do
- var val = new Buffer.from(txt)
+ var val = new FlatBuffer.from(txt)
val.add('\0')
var ic = self.mainmodule.get_primitive_class("NativeString")
return new PrimitiveInstance[Buffer](ic.mclass_type, val)
# Return a stack stace. One line per function
fun stack_trace: String
do
- var b = new Buffer
+ var b = new FlatBuffer
b.append(",---- Stack trace -- - - -\n")
for f in frames do
b.append("| {f.mpropdef} ({f.current_node.location})\n")
return null
else if pname == "copy_to" then
# sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
- var destval = args[1].val.as(Buffer)
+ var destval = args[1].val.as(FlatBuffer)
var lenval = args[2].to_i
var fromval = args[3].to_i
var toval = args[4].to_i
if toval + lenval >= destval.length then
debug("Illegal access on {destval} for element {toval}+{lenval}/{destval.length}")
end
- recvval.copy(fromval, lenval, destval, toval)
+ recvval.as(FlatBuffer).copy(fromval, lenval, destval, toval)
return null
else if pname == "atoi" then
return v.int_instance(recvval.to_i)
var recvval = args.first.val
if pname == "io_write" then
var a1 = args[1].val.as(Buffer)
- recvval.as(OStream).write(a1.substring(0, args[2].to_i))
+ recvval.as(OStream).write(a1.substring(0, args[2].to_i).to_s)
return args[2]
else if pname == "io_read" then
var str = recvval.as(IStream).read(args[2].to_i)
var a1 = args[1].val.as(Buffer)
- new Buffer.from(str).copy(0, str.length, a1, 0)
+ new FlatBuffer.from(str).copy(0, str.length, a1.as(FlatBuffer), 0)
return v.int_instance(str.length)
else if pname == "io_close" then
recvval.as(IOS).close
var connection: nullable Socket = null
# Used to store data that has been read from the connection
- var buf: Buffer = new Buffer
+ var buf: Buffer = new FlatBuffer
var buf_pos: Int = 0
# Checks if data is available for reading
# Blocking if the buffer is empty
redef fun read_all
do
- var loc_buf = new Buffer
+ var loc_buf = new FlatBuffer
if connection.ready_to_read(0) then buf.append(connection.read)
for i in [buf_pos .. buf.length-1] do loc_buf.add(buf.chars[i])
buf.clear
# If the buffer is empty, the read_line call is blocking
redef fun read_line
do
- var line_buf = new Buffer
+ var line_buf = new FlatBuffer
if connection.ready_to_read(0) then buf.append(connection.read)
var has_found_eol: Bool = false
loop
fun read_command: String
do
- var buff = new Buffer
+ var buff = new FlatBuffer
while debugger_connection.ready_to_read(40) do buff.append(debugger_connection.read)
return buff.to_s
end
end
end
# build graph
- var op = new Buffer
+ var op = new FlatBuffer
op.append("digraph dep \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
for mmodule in poset do
op.append("\"{mmodule.name}\"[URL=\"{mmodule.url}\"];\n")
end
end
# build graph
- var op = new Buffer
+ var op = new FlatBuffer
var name = "dep_{mmodule.name}"
op.append("digraph {name} \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
for mmodule in poset do
end
cla.add_all(pe.greaters)
- var op = new Buffer
+ var op = new FlatBuffer
var name = "dep_{mclass.name}"
op.append("digraph {name} \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
for c in cla do
# module_owner_name.html
private fun url: String do
if url_cache == null then
- var res = new Buffer
+ var res = new FlatBuffer
res.append("module_")
var mowner = public_owner
if mowner != null then
# MOD_owner_name
private fun anchor: String do
if anchor_cache == null then
- var res = new Buffer
+ var res = new FlatBuffer
res.append("MOD_")
var mowner = public_owner
if mowner != null then
# <a href="url" title="short_comment">html_name</a>
private fun html_link(page: NitdocPage) do
if html_link_cache == null then
- var res = new Buffer
+ var res = new FlatBuffer
if page.ctx.mbuilder.mmodule2nmodule.has_key(self) then
res.append("<a href='{url}' title='{page.ctx.mbuilder.mmodule2nmodule[self].short_comment}'>{html_name}</a>")
else
# <a href="url" title="short_comment">html_name(signature)</a>
private fun html_link(page: NitdocPage) do
if html_link_cache == null then
- var res = new Buffer
+ var res = new FlatBuffer
res.append("<a href='{url}'")
if page.ctx.mbuilder.mclassdef2nclassdef.has_key(intro) then
var nclass = page.ctx.mbuilder.mclassdef2nclassdef[intro]
# <a href="url" title="short_comment">html_name</a>
private fun html_short_link(page: NitdocPage) do
if html_short_link_cache == null then
- var res = new Buffer
+ var res = new FlatBuffer
res.append("<a href='{url}'")
if page.ctx.mbuilder.mclassdef2nclassdef.has_key(intro) then
var nclass = page.ctx.mbuilder.mclassdef2nclassdef[intro]
# <a href="url" title="short_comment">html_name</a>
private fun html_link_anchor(page: NitdocPage) do
if html_link_anchor_cache == null then
- var res = new Buffer
+ var res = new FlatBuffer
res.append("<a href='#{anchor}'")
if page.ctx.mbuilder.mclassdef2nclassdef.has_key(intro) then
var nclass = page.ctx.mbuilder.mclassdef2nclassdef[intro]
# <a href="url" title="short_comment">html_name</a>
private fun html_link(page: NitdocPage) do
if html_link_cache == null then
- var res = new Buffer
+ var res = new FlatBuffer
if page.ctx.mbuilder.mpropdef2npropdef.has_key(self) then
var nprop = page.ctx.mbuilder.mpropdef2npropdef[self]
res.append("<a href=\"{url}\" title=\"{nprop.short_comment}\">{mproperty.html_name}</a>")
end
private fun untyped_signature(page: NitdocPage): String do
- var res = new Buffer
+ var res = new FlatBuffer
if not mparameters.is_empty then
res.append("(")
for i in [0..mparameters.length[ do
end
private fun full_comment: String do
- var res = new Buffer
+ var res = new FlatBuffer
for t in n_comment do
var text = t.text
text = text.substring_from(1)
end
f.close
- var cmd = "../bin/nitg --no-color '{file}' -I . >'{file}.out1' 2>&1 </dev/null -o '{file}.bin'"
+ var cmd = "../bin/nitg --ignore-visibility --no-color '{file}' -I . >'{file}.out1' 2>&1 </dev/null -o '{file}.bin'"
var res = sys.system(cmd)
var res2 = 0
if res == 0 then
end
private class Pager
- var content = new Buffer
+ var content = new FlatBuffer
var indent = 0
fun add(text: String) do
add_indent
# return the generic signature of the class
# [E, F]
private fun signature: String do
- var res = new Buffer
+ var res = new FlatBuffer
if arity > 0 then
res.append("[")
for i in [0..intro.parameter_names.length[ do
# class name is displayed with colors depending on visibility
# abstract interface Foo[E]
private fun prototype: String do
- var res = new Buffer
+ var res = new FlatBuffer
res.append("{kind} ")
if visibility.to_s == "public" then res.append("{name}{signature}".bold.green)
if visibility.to_s == "private" then res.append("{name}{signature}".bold.red)
end
fun to_console: String do
- var res = new Buffer
+ var res = new FlatBuffer
if not is_intro then res.append("redef ")
res.append(mclass.prototype)
return res.to_s
redef class MMethodDef
redef fun to_console do
- var res = new Buffer
+ var res = new FlatBuffer
if not is_intro then res.append("redef ")
if not mproperty.is_init then res.append("fun ")
res.append(mproperty.to_console.bold)
redef class MVirtualTypeDef
redef fun to_console do
- var res = new Buffer
+ var res = new FlatBuffer
res.append("type ")
res.append(mproperty.to_console.bold)
res.append(": {bound.to_console}")
redef class MAttributeDef
redef fun to_console do
- var res = new Buffer
+ var res = new FlatBuffer
res.append("var ")
res.append(mproperty.to_console.bold)
res.append(": {static_mtype.to_console}")
redef class MSignature
redef fun to_console do
- var res = new Buffer
+ var res = new FlatBuffer
if not mparameters.is_empty then
res.append("(")
for i in [0..mparameters.length[ do
redef class MParameter
fun to_console: String do
- var res = new Buffer
+ var res = new FlatBuffer
res.append("{name}: {mtype.to_console}")
if is_vararg then res.append("...")
return res.to_s
redef class MGenericType
redef fun to_console do
- var res = new Buffer
+ var res = new FlatBuffer
res.append("{mclass.name}[")
for i in [0..arguments.length[ do
res.append(arguments[i].to_console)
private fun escape: String
do
- var b = new Buffer
+ var b = new FlatBuffer
for c in self.chars do
if c == '\n' then
b.append("\\n")
# it is often simpler to use the constructor in `Phase`
var phases = new POSet[Phase]
+ # --disable-phase
+ var opt_disable_phase = new OptionArray("DEBUG: Disable a specific phase; use `list` to get the list.", "--disable-phase")
+
+ redef init
+ do
+ super
+
+ option_context.add_option(opt_disable_phase)
+ end
+
+ redef fun process_options(args)
+ do
+ super
+
+ for v in opt_disable_phase.value do
+ if v == "list" then
+ for p in phases_list do
+ var deps = p.in_hierarchy.direct_greaters
+ if deps.is_empty then
+ print p
+ else
+ print "{p} (dep: {deps.join(", ")})"
+ end
+ end
+ exit 0
+ end
+
+ var found = false
+ for p in phases do
+ if v != p.to_s then continue
+ found = true
+ p.disabled = true
+ end
+ if not found then fatal_error(null, "Error: no phase named `{v}`. Use `list` to list all phases.")
+ end
+ end
+
fun phases_list: Sequence[Phase]
do
var phases = self.phases.to_a
var phases = phases_list
for phase in phases do
- self.info(" registered phases: {phase.class_name}", 2)
+ self.info(" registered phases: {phase}", 2)
end
for nmodule in nmodules do
self.info("Semantic analysis module {nmodule.location.file.filename}", 2)
for phase in phases do
- self.info(" phase: {phase.class_name}", 3)
+ if phase.disabled then continue
+ self.info(" phase: {phase}", 3)
assert phase.toolcontext == self
var errcount = self.error_count
phase.process_nmodule(nmodule)
end
errcount = self.error_count
for nclassdef in nmodule.n_classdefs do
- self.info(" phase: {phase.class_name} for {nclassdef.location}", 3)
+ self.info(" phase: {phase} for {nclassdef.location}", 3)
assert phase.toolcontext == self
phase.process_nclassdef(nclassdef)
for npropdef in nclassdef.n_propdefs do
end
end
+ # By default, the name is the lowercased prefix of the classname
+ redef fun to_s do return class_name.strip_extension("Phase").to_lower
+
+ # Is the phase globally disabled?
+ # A disabled phase is not called automatically called by `ToolContext::run_phases` and cie.
+ var disabled = false
+
# Specific actions to execute on the whole tree of a module
# @toimplement
fun process_nmodule(nmodule: AModule) do end
import csv # for live_types_to_csv
import ordered_tree # for live_methods_to_tree
+private import more_collections
+
redef class ModelBuilder
fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis
do
# Live methods.
var live_methods = new HashSet[MMethod]
+ # Live callsites.
+ var live_callsites = new HashSet[CallSite]
+
+ private var live_targets_cache = new HashMap2[MType, MProperty, Set[MMethodDef]]
+
+ # The live targets of a specific callsite.
+ fun live_targets(callsite: CallSite): Set[MMethodDef]
+ do
+ var mtype = callsite.recv
+ var anchor = callsite.anchor
+ if anchor != null then mtype = mtype.anchor_to(callsite.mmodule, anchor)
+ if mtype isa MNullableType then mtype = mtype.mtype
+ assert mtype isa MClassType
+ mtype = mtype.mclass.intro.bound_mtype
+ var mproperty = callsite.mproperty
+ var res = live_targets_cache[mtype, mproperty]
+ if res != null then return res
+ res = new ArraySet[MMethodDef]
+ live_targets_cache[mtype, mproperty] = res
+
+ for c in live_classes do
+ var tc = c.intro.bound_mtype
+ if not tc.is_subtype(mainmodule, null, mtype) then continue
+ var d = mproperty.lookup_first_definition(mainmodule, tc)
+ res.add d
+ end
+
+ return res
+ end
+
# Live call-to-super.
var live_super_sends = new HashSet[MMethodDef]
fun add_cast_type(mtype: MType) do analysis.add_cast(mtype)
- fun add_callsite(callsite: nullable CallSite) do if callsite != null then analysis.add_send(callsite.recv, callsite.mproperty)
+ fun add_callsite(callsite: nullable CallSite) do if callsite != null then
+ analysis.add_send(callsite.recv, callsite.mproperty)
+ analysis.live_callsites.add(callsite)
+ end
end
###
res = self.new_var(ret)
end
- var s = new Buffer
- var ss = new Buffer
+ var s = new FlatBuffer
+ var ss = new FlatBuffer
var recv = arguments.first
s.append("val*")
var msignature = mmethoddef.msignature.resolve_for(mmethoddef.mclassdef.bound_mtype, mmethoddef.mclassdef.bound_mtype, mmethoddef.mclassdef.mmodule, true)
- var sig = new Buffer
- var comment = new Buffer
+ var sig = new FlatBuffer
+ var comment = new FlatBuffer
var ret = msignature.return_mtype
if ret != null then
sig.append("{ret.ctype} ")
var frame = new Frame(v, mmethoddef, recv, arguments)
v.frame = frame
- var sig = new Buffer
- var comment = new Buffer
+ var sig = new FlatBuffer
+ var comment = new FlatBuffer
# Because the function is virtual, the signature must match the one of the original class
var intromclassdef = self.mmethoddef.mproperty.intro.mclassdef
end
assert mproperty isa MMethod
- if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility then
- self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self. {mproperty.intro_mclassdef.mmodule.visibility_for(self.mmodule)}")
+ if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility and not modelbuilder.toolcontext.opt_ignore_visibility.value then
+ self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self.")
return null
end
end
end
- var callsite = new CallSite(node, recvtype, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
+ var callsite = new CallSite(node, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
return callsite
end
# The assiciated node for location
var node: ANode
- # The statis type of the receiver
+ # The static type of the receiver (possibly unresolved)
var recv: MType
+ # The module where the callsite is present
+ var mmodule: MModule
+
+ # The anchor to use with `recv` or `msignature`
+ var anchor: nullable MClassType
+
# Is the receiver self?
# If "for_self", virtual types of the signature are keeped
# If "not_for_self", virtual type are erased
end
var msignature = v.resolve_signature_for(superprop, recvtype, true)
- var callsite = new CallSite(self, recvtype, true, superprop.mproperty, superprop, msignature, false)
+ var callsite = new CallSite(self, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
self.callsite = callsite
var args = self.n_args.to_a
# This file is part of NIT ( http://www.nitlanguage.org ).
#
-# Copyright 2008 Jean Privat <jean@pryen.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
import kernel
-class A
+import base_prot0
+
+redef class A
fun pub do 0.output
protected fun pro do 1.output
private fun pri do 2.output
a.pub
a.pro
a.pri
+ 3.output
end
init do end
end
--- /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
+end
# This file is part of NIT ( http://www.nitlanguage.org ).
#
-# Copyright 2008 Jean Privat <jean@pryen.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
# See the License for the specific language governing permissions and
# limitations under the License.
+import base_prot0
private import base_prot
-class A2
+class B
super A
- fun o
- do
+ redef fun pub do 10.output
+ redef fun pro do 11.output
+ #alt1#redef fun pri do 12.output
+ fun o do
pub
pro
- #alt1#pri
+ #alt2#pri
end
- init do end
end
class O2
fun o
do
- var a = new A
+ var a = new B
a.pub
- #alt2#a.pro
- #alt3#a.pri
-
- var a2 = new A2
- a2.o
- a2.pub
- #alt4#a2.pro
- #alt5#a2.pri
+ #alt3#a.pro
+ #alt4#a.pri
+ 13.output
end
init do end
end
# This file is part of NIT ( http://www.nitlanguage.org ).
#
-# Copyright 2008 Jean Privat <jean@pryen.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
# See the License for the specific language governing permissions and
# limitations under the License.
+import base_prot0
private import base_prot2
-intrude import base_prot
+
+class C
+ super A
+ #alt5#redef fun pub do 20.output
+ #alt6#redef fun pro do 21.output
+ #alt1#redef fun pri do 22.output
+ fun o do
+ #alt7#pub
+ #alt8#pro
+ #alt2#pri
+ end
+end
class O3
fun o
do
- var a = new A
- a.pub
- a.pro
- a.pri
+ var a = new C
+ #alt9#a.pub
+ #alt3#a.pro
+ #alt4#a.pri
+ 23.output
end
init do end
end
(new O3).o
-
assert 1.0.object_id.to_s.is_numeric
# Check NativeString.object_id
-assert "Test"._items.object_id.to_s.is_numeric
+assert "Test".as(FlatString).items.object_id.to_s.is_numeric
var s = "*"
var i = 0
while i < n do
- var s2 = new Buffer.from("Je dis «")
+ var s2 = new FlatBuffer.from("Je dis «")
s2.append(s)
s2.append("» et redis «")
s2.append(s)
s = s2.to_s
i = i + 1
end
-print("Je dis «Je dis".search_all_in(s).length)
+print(s.search_all("Je dis «Je dis").length)
i = 0
var j = 0
while j >= 0 do
- j = "Je dis «Je dis".search_index_in(s, j)
- if j >= 0 then
- i = i + 1
- j = j + 1
- end
+ var r = s.search_from("Je dis «Je dis", j)
+ if r == null then break
+ i = i + 1
+ j = r.from + 1
end
print(i)
do
# Les variables sont déclarées par "var", leur portée va de leur
# déclaration jusqu'au "end" correspondant
- var s = new Buffer # Là où on calcule le résultat
+ var s = new FlatBuffer # Là où on calcule le résultat
# Les chaînes littérales sont déclarées avec des guillemets
s.append("*** Entrepôt ") # On initialise "s"
# puis on concatène des chaînes à "s"
# Si une expression est passée comme valeur initiale d'une
# variable, le type statique de la variable est implicitement
# celui de l'expression.
- var s = new Buffer
+ var s = new FlatBuffer
s.append("* Rayon : ")
# Ici, le type statique de s est implicitement String
redef fun to_s: String
do
- var s = new Buffer
+ var s = new FlatBuffer
s.append(to_s_head)
# Les boucles en NIT sont des structures puissantes, toutefois
# la manipulation des itérateurs peut être facilité par la
fun first_word(s: String): String
do
- var result = new Buffer
+ var result = new FlatBuffer
var i = 0
while i < s.length and s.chars[i] != ' ' do
result.add(s.chars[i])
# Second way: Build a string and display it.
# Pro: Eiffel way (rigourous).
# Con: Eiffel way (heavy).
-var s = new Buffer.from("The value of a is: ")
+var s = new FlatBuffer.from("The value of a is: ")
s.append(a.to_s)
s.append(".\n")
printn(s)
alt/base_attr3_alt2.nit:49,3--10: Error: Method 'a1=' doesn't exists in A.
+alt/base_attr3_alt2.nit:50,3--6: Error: Method 'a2' is protected and can only acceded by self.
alt/base_attr3_alt2.nit:51,3--10: Error: Method 'a2=' doesn't exists in A.
alt/base_attr3_alt2.nit:52,3--6: Error: Method 'a3' doesn't exists in A.
alt/base_attr3_alt2.nit:53,3--10: Error: Method 'a3=' doesn't exists in A.
+alt/base_attr3_alt2.nit:56,3--6: Error: Method 'a5' is protected and can only acceded by self.
alt/base_attr3_alt2.nit:58,3--6: Error: Method 'a6' doesn't exists in A.
+alt/base_attr3_alt2.nit:61,3--10: Error: Method 'a7=' is protected and can only acceded by self.
+alt/base_attr3_alt2.nit:62,3--6: Error: Method 'a8' is protected and can only acceded by self.
+alt/base_attr3_alt2.nit:63,3--10: Error: Method 'a8=' is protected and can only acceded by self.
alt/base_attr3_alt2.nit:64,3--6: Error: Method 'a9' doesn't exists in A.
+alt/base_attr3_alt2.nit:65,3--10: Error: Method 'a9=' is protected and can only acceded by self.
alt/base_attr3_alt2.nit:67,3--11: Error: Method 'a10=' doesn't exists in A.
+alt/base_attr3_alt2.nit:68,3--7: Error: Method 'a11' is protected and can only acceded by self.
alt/base_attr3_alt2.nit:69,3--11: Error: Method 'a11=' doesn't exists in A.
alt/base_attr3_alt2.nit:70,3--7: Error: Method 'a12' doesn't exists in A.
alt/base_attr3_alt2.nit:71,3--11: Error: Method 'a12=' doesn't exists in A.
alt/base_attr3_alt3.nit:80,2--9: Error: Method 'a1=' doesn't exists in A.
+alt/base_attr3_alt3.nit:81,2--5: Error: Method 'a2' is protected and can only acceded by self.
alt/base_attr3_alt3.nit:82,2--9: Error: Method 'a2=' doesn't exists in A.
alt/base_attr3_alt3.nit:83,2--5: Error: Method 'a3' doesn't exists in A.
alt/base_attr3_alt3.nit:84,2--9: Error: Method 'a3=' doesn't exists in A.
+alt/base_attr3_alt3.nit:87,2--5: Error: Method 'a5' is protected and can only acceded by self.
alt/base_attr3_alt3.nit:89,2--5: Error: Method 'a6' doesn't exists in A.
+alt/base_attr3_alt3.nit:92,2--9: Error: Method 'a7=' is protected and can only acceded by self.
+alt/base_attr3_alt3.nit:93,2--5: Error: Method 'a8' is protected and can only acceded by self.
+alt/base_attr3_alt3.nit:94,2--9: Error: Method 'a8=' is protected and can only acceded by self.
alt/base_attr3_alt3.nit:95,2--5: Error: Method 'a9' doesn't exists in A.
+alt/base_attr3_alt3.nit:96,2--9: Error: Method 'a9=' is protected and can only acceded by self.
alt/base_attr3_alt3.nit:98,2--10: Error: Method 'a10=' doesn't exists in A.
+alt/base_attr3_alt3.nit:99,2--6: Error: Method 'a11' is protected and can only acceded by self.
alt/base_attr3_alt3.nit:100,2--10: Error: Method 'a11=' doesn't exists in A.
alt/base_attr3_alt3.nit:101,2--6: Error: Method 'a12' doesn't exists in A.
alt/base_attr3_alt3.nit:102,2--10: Error: Method 'a12=' doesn't exists in A.
alt/base_attr3_alt4.nit:110,2--9: Error: Method 'a1=' doesn't exists in B.
+alt/base_attr3_alt4.nit:111,2--5: Error: Method 'a2' is protected and can only acceded by self.
alt/base_attr3_alt4.nit:112,2--9: Error: Method 'a2=' doesn't exists in B.
alt/base_attr3_alt4.nit:113,2--5: Error: Method 'a3' doesn't exists in B.
alt/base_attr3_alt4.nit:114,2--9: Error: Method 'a3=' doesn't exists in B.
+alt/base_attr3_alt4.nit:117,2--5: Error: Method 'a5' is protected and can only acceded by self.
alt/base_attr3_alt4.nit:119,2--5: Error: Method 'a6' doesn't exists in B.
+alt/base_attr3_alt4.nit:122,2--9: Error: Method 'a7=' is protected and can only acceded by self.
+alt/base_attr3_alt4.nit:123,2--5: Error: Method 'a8' is protected and can only acceded by self.
+alt/base_attr3_alt4.nit:124,2--9: Error: Method 'a8=' is protected and can only acceded by self.
alt/base_attr3_alt4.nit:125,2--5: Error: Method 'a9' doesn't exists in B.
+alt/base_attr3_alt4.nit:126,2--9: Error: Method 'a9=' is protected and can only acceded by self.
alt/base_attr3_alt4.nit:128,2--10: Error: Method 'a10=' doesn't exists in B.
+alt/base_attr3_alt4.nit:129,2--6: Error: Method 'a11' is protected and can only acceded by self.
alt/base_attr3_alt4.nit:130,2--10: Error: Method 'a11=' doesn't exists in B.
alt/base_attr3_alt4.nit:131,2--6: Error: Method 'a12' doesn't exists in B.
alt/base_attr3_alt4.nit:132,2--10: Error: Method 'a12=' doesn't exists in B.
-String
+FlatString
Int
Test
Test
-alt/base_prot2_alt1.nit:25,3--5: Error: Method or variable 'pri' unknown in A2.
+alt/base_prot2_alt1.nit:22,12--14: Error: No property B::pri is inherited. Remove the redef keyword to define a new property.
-alt/base_prot2_alt2.nit:35,3--7: Error: Method 'pro' is protected and can only acceded by self. none
+alt/base_prot2_alt2.nit:26,3--5: Error: Method or variable 'pri' unknown in B.
-alt/base_prot2_alt3.nit:36,3--7: Error: Method 'pri' doesn't exists in A.
+alt/base_prot2_alt3.nit:35,3--7: Error: Method 'pro' is protected and can only acceded by self.
-alt/base_prot2_alt4.nit:41,3--8: Error: Method 'pro' is protected and can only acceded by self. none
+alt/base_prot2_alt4.nit:36,3--7: Error: Method 'pri' doesn't exists in B.
--- /dev/null
+alt/base_prot3_alt1.nit:22,12--14: Error: No property C::pri is inherited. Remove the redef keyword to define a new property.
--- /dev/null
+alt/base_prot3_alt2.nit:26,3--5: Error: Method or variable 'pri' unknown in C.
--- /dev/null
+alt/base_prot3_alt3.nit:35,3--7: Error: Method 'pro' doesn't exists in C.
--- /dev/null
+alt/base_prot3_alt4.nit:36,3--7: Error: Method 'pri' doesn't exists in C.
--- /dev/null
+alt/base_prot3_alt5.nit:20,12--14: Error: No property C::pub is inherited. Remove the redef keyword to define a new property.
--- /dev/null
+alt/base_prot3_alt6.nit:21,12--14: Error: No property C::pro is inherited. Remove the redef keyword to define a new property.
--- /dev/null
+alt/base_prot3_alt7.nit:24,3--5: Error: Method or variable 'pub' unknown in C.
--- /dev/null
+alt/base_prot3_alt8.nit:25,3--5: Error: Method or variable 'pro' unknown in C.
--- /dev/null
+alt/base_prot3_alt9.nit:34,3--7: Error: Method 'pub' doesn't exists in C.
-String
+FlatString
Int
Test
Test
std: 0.926
cnbip: number of introduced properties
avg: 2.0
- max: C (7)
+ max: C (5)
min: Bool (0)
- std: 2.42
+ std: 1.69
cnbrp: number of redefined properties
avg: 0.0
max: Object (0)
std: 0.866
cnbip: number of introduced properties
avg: 2.0
- max: C (7)
+ max: C (5)
min: Bool (0)
- std: 2.291
+ std: 1.62
cnbrp: number of redefined properties
avg: 0.0
max: Object (0)
std: 0.866
cnbip: number of introduced properties
avg: 2.0
- max: C (7)
+ max: C (5)
min: Bool (0)
- std: 2.291
+ std: 1.62
cnbrp: number of redefined properties
avg: 0.0
max: Object (0)
max: Sys (0)
min: Sys (0)
std: 0.0
+
+ ## Callsites
+* 22 live callsites
+MMethodDef locally designated (by number of CallSites)
+ population: 13
+ minimum value: 1
+ maximum value: 10
+ total value: 22
+ average value: 1.69
+ distribution:
+ <=1: sub-population=12 (92.30%); cumulated value=12 (54.54%)
+ <=16: sub-population=1 (7.69%); cumulated value=10 (45.45%)
+ list:
+ base_simple3#Int#output: 10 (45.45%)
+ base_simple3#B#val: 1 (4.54%)
+ base_simple3#B#val=: 1 (4.54%)
+ base_simple3#C#val2: 1 (4.54%)
+ base_simple3#C#val1: 1 (4.54%)
+ ...
+ base_simple3#A#init: 1 (4.54%)
+ base_simple3#Object#baz: 1 (4.54%)
+ base_simple3#Object#bar: 1 (4.54%)
+ base_simple3#Object#foo: 1 (4.54%)
+ base_simple3#C#init: 1 (4.54%)
+MMethodDef possibly invoked at runtime (by number of CallSites)
+ population: 13
+ minimum value: 1
+ maximum value: 10
+ total value: 22
+ average value: 1.69
+ distribution:
+ <=1: sub-population=12 (92.30%); cumulated value=12 (54.54%)
+ <=16: sub-population=1 (7.69%); cumulated value=10 (45.45%)
+ list:
+ base_simple3#Int#output: 10 (45.45%)
+ base_simple3#B#val: 1 (4.54%)
+ base_simple3#B#val=: 1 (4.54%)
+ base_simple3#C#val2: 1 (4.54%)
+ base_simple3#C#val1: 1 (4.54%)
+ ...
+ base_simple3#A#init: 1 (4.54%)
+ base_simple3#Object#baz: 1 (4.54%)
+ base_simple3#Object#bar: 1 (4.54%)
+ base_simple3#Object#foo: 1 (4.54%)
+ base_simple3#C#init: 1 (4.54%)
class_hierarchy.dot
classdef_hierarchy.dot
inheritance/
1111223
123
12132
-1007
-1020101010302
+123451211132
+102030405
232
12
-9991000
-9991000
-12
+345
+345
+45
+123
3
* [1, 2[ = " "
* [8, 9[ = " "
splits:
-* [0, 1[ = "A"
-* [2, 8[ = "simple"
-* [9, 16[ = "example"
+* "A"
+* "simple"
+* "example"
join: A, simple, example
string: "A simple example" ; pattern: "ple"
searches:
* [5, 8[ = "ple"
* [13, 16[ = "ple"
splits:
-* [0, 5[ = "A sim"
-* [8, 13[ = " exam"
-* [16, 16[ = ""
+* "A sim"
+* " exam"
+* ""
join: A sim, exam,
string: "A simple example" ; pattern: "ple"
searches:
* [5, 8[ = "ple"
* [13, 16[ = "ple"
splits:
-* [0, 5[ = "A sim"
-* [8, 13[ = " exam"
-* [16, 16[ = ""
+* "A sim"
+* " exam"
+* ""
join: A sim, exam,
fun nsieve(n: Int): Int
do
var count = 0
- var array = new Buffer.with_capacity(n)
+ var array = new FlatBuffer.with_capacity(n)
for i in [0..n[ do
array.chars[i] = 'o'
end
module string_ffi_ref_test
+intrude import string
+import file
+
class StringTest
var copied_str: nullable String
referenced_str = null
end
- fun get_c_string import String.items, NativeString.to_s, NativeString.to_s_with_copy, StringTest.ref_test, StringTest.copy_test `{
+ fun get_c_string import FlatString.items, NativeString.to_s, NativeString.to_s_with_copy, StringTest.ref_test, StringTest.copy_test `{
char* string = "This is a test string";
- String ref_string = NativeString_to_s(string);
+ FlatString ref_string = NativeString_to_s(string);
StringTest_ref_test(recv, ref_string);
- String copy_string = NativeString_to_s_with_copy(string);
+ FlatString copy_string = NativeString_to_s_with_copy(string);
StringTest_copy_test(recv, copy_string);
- int same_refs = String_items(copy_string) == String_items(ref_string);
+ int same_refs = FlatString_items(copy_string) == FlatString_items(ref_string);
printf("Do the strings have the same NativeString reference ? ");
var subtrim = trimtest.substring(2,15)
-var buffertrimtest = new Buffer.from(trimtest)
+var buffertrimtest = new FlatBuffer.from(trimtest)
print "resulttrim = {buffertrimtest.trim}"
var emptytrim = " \t "
-var bufferemptytest = new Buffer.from(emptytrim)
+var bufferemptytest = new FlatBuffer.from(emptytrim)
print "emptytrim = {emptytrim.trim}"
var onelettertrim = " \n d \n\t "
-var oneletterbuftest = new Buffer.from(onelettertrim)
+var oneletterbuftest = new FlatBuffer.from(onelettertrim)
print "onelettertrim = {onelettertrim.trim}"
var twolettertrim = " \n hg \n\t "
-var twoletterbuftest = new Buffer.from(twolettertrim)
+var twoletterbuftest = new FlatBuffer.from(twolettertrim)
print "twolettertrim = {twolettertrim.trim}"
var firstlettertrim = "d "
-var firstlettertrimbuf = new Buffer.from(firstlettertrim)
+var firstlettertrimbuf = new FlatBuffer.from(firstlettertrim)
print "firstlettertrimtest = {firstlettertrim.trim}"
var lastlettertrim = " d"
-var lastlettertrimbuf = new Buffer.from(lastlettertrim)
+var lastlettertrimbuf = new FlatBuffer.from(lastlettertrim)
print "lastlettertrimtest = {lastlettertrim.trim}"
var a2: Object = "Bonjour"
print(not a2 isa Int)
print(a2 isa String)
-print(a2 isa AbstractArrayRead[Char])
+print(a2 isa Text)
print(not a2 isa Iterator[Int])
print(not a2 isa Discrete)
print(a2 isa Object)
import pipeline
-var a1 = [1..1000]
+var a1 = [1,2,3,4,5]
var a2 = [1,2,1,1,1,3,2]
-print a2.sort_filter.to_a
-print a2.uniq.to_a
-print a2.seq_uniq.to_a
+print a2.iterator.sort.to_a
+print a2.iterator.uniq.to_a
+print a2.iterator.seq_uniq.to_a
##
-print((a1 + a2).length)
+print((a1.iterator + a2.iterator).to_a)
-print a2.alternate(0).to_a
+print a1.iterator.alternate(0).to_a
-print a2.skip(1).to_a
+print a2.iterator.skip(1).to_a
##
-print a1.head(2).to_a
-print a1.skip_head(998).to_a
-print a1.tail(2).to_a
-print a1.skip_tail(998).to_a
+var i = a1.iterator
+print i.head(2).to_a
+print i.to_a
-print a1.skip_head(1).head(3).skip_tail(1).tail(1).to_a
+print a1.iterator.skip_head(2).to_a
+print a1.iterator.tail(2).to_a
+print a1.iterator.skip_tail(2).to_a
+
+print a1.iterator.skip_head(1).head(3).skip_tail(1).tail(1).to_a
#False
print "21,52,210.52".is_numeric
-var buf = new Buffer
+var buf = new FlatBuffer
buf.append("45.3")
var s = "Bonjour !\n"
-var r = new Buffer.with_capacity(50)
-var r2 = new Buffer
+var r = new FlatBuffer.with_capacity(50)
+var r2 = new FlatBuffer
var i = 0
while i < 5000 do
print("* [{m.from}, {m.after}[ = \"{m}\"")
end
print("splits:")
- for m in p.split_in(s) do
- print("* [{m.from}, {m.after}[ = \"{m}\"")
+ for m in s.split(p) do
+ print("* \"{m}\"")
end
- print("join: {s.split_with(p).join(", ")}")
+ print("join: {s.split(p).join(", ")}")
end
search_and_split("A simple example", ' ')