Merge: parser: add `ASTDump` and `ANode::dump_tree`
authorJean Privat <jean@pryen.org>
Tue, 24 Feb 2015 03:59:46 +0000 (10:59 +0700)
committerJean Privat <jean@pryen.org>
Tue, 24 Feb 2015 03:59:46 +0000 (10:59 +0700)
A simple helper to debug AST. I used it to debug auto-serialization in #1159

Pull-Request: #1167
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

153 files changed:
benchmarks/languages/bench_base.nit
contrib/benitlux/src/benitlux_controller.nit
contrib/benitlux/src/benitlux_daily.nit
contrib/brainfuck/brainfuck.nit
contrib/inkscape_tools/src/svg_to_png_and_nit.nit
contrib/jwrapper/src/code_generator.nit
contrib/jwrapper/src/jwrapper.nit
contrib/jwrapper/src/model.nit
contrib/nitcc/src/autom.nit
contrib/nitcc/src/grammar.nit
contrib/nitcc/src/nitcc.nit
contrib/nitcc/src/nitcc_parser_gen.nit
contrib/nitester/src/nitester.nit
contrib/nitiwiki/src/wiki_base.nit
contrib/nitiwiki/src/wiki_html.nit
contrib/nitrpg/src/events.nit [new file with mode: 0644]
contrib/nitrpg/src/game.nit
contrib/nitrpg/src/listener.nit
contrib/nitrpg/src/reactors.nit
contrib/nitrpg/src/statistics.nit
contrib/nitrpg/src/templates/panels.nit
contrib/nitrpg/src/templates/templates_base.nit
contrib/nitrpg/src/templates/templates_events.nit [new file with mode: 0644]
contrib/nitrpg/src/web.nit
contrib/online_ide/sources/nit/pnacl_nit.nit
contrib/opportunity/src/templates/boilerplate.nit
contrib/opportunity/src/templates/meetup.nit
contrib/pep8analysis/src/ast/ast_base.nit
contrib/pep8analysis/src/cfg/dot_printer.nit
contrib/pep8analysis/src/location.nit
contrib/pep8analysis/src/pep8analysis.nit
contrib/pep8analysis/src/pep8analysis_web.nit
lib/android/aware.nit
lib/android/bundle/bundle.nit
lib/android/gamepad.nit [new file with mode: 0644]
lib/android/intent/intent_api10.nit
lib/android/platform.nit
lib/android/shared_preferences/shared_preferences_api10.nit
lib/csv/csv.nit
lib/csv/test_csv.nit
lib/filter_stream.nit
lib/for_abuse.nit
lib/github/cache.nit
lib/github/github_curl.nit
lib/glesv2/glesv2.nit
lib/html/html.nit
lib/ini.nit
lib/io/push_back_reader.nit
lib/io/test_push_back_reader.nit
lib/json/dynamic.nit
lib/json/store.nit
lib/json_serialization.nit
lib/libevent.nit
lib/linux/linux_data_store.nit
lib/markdown/markdown.nit
lib/markdown/nitmd.nit
lib/mnit/mnit_injected_input.nit
lib/mnit_linux/linux_assets.nit
lib/more_collections.nit
lib/mpi.nit
lib/neo4j/graph/json_graph_store.nit
lib/nitcc_runtime.nit
lib/nitcorn/file_server.nit
lib/nitcorn/http_errors.nit
lib/niti_runtime.nit
lib/ordered_tree.nit
lib/pnacl.nit
lib/poset.nit
lib/sax/input_source.nit
lib/saxophonit/lexer.nit
lib/saxophonit/saxophonit.nit
lib/saxophonit/testing.nit
lib/sendmail.nit
lib/socket/socket.nit
lib/standard/exec.nit
lib/standard/file.nit
lib/standard/stream.nit
lib/standard/string.nit
lib/string_experimentations/utf8.nit
lib/string_experimentations/utf8_noindex.nit
lib/template/macro.nit
lib/template/template.nit
lib/trees/bintree.nit
misc/README.md
misc/vim/plugin/nit.vim
share/libgc/android-setup-libgc.sh
src/c_tools.nit
src/compiler/abstract_compiler.nit
src/doc/doc_down.nit
src/doc/doc_phases/doc_html.nit
src/doc/doc_templates.nit
src/doc/vim_autocomplete.nit
src/ffi/c_compiler_options.nit
src/ffi/ffi_base.nit
src/ffi/pkgconfig.nit
src/frontend/check_annotation.nit
src/frontend/glsl_validation.nit
src/interpreter/debugger_socket.nit
src/interpreter/primitive_types.nit
src/loader.nit
src/location.nit
src/metrics/generate_hierarchies.nit
src/metrics/model_hyperdoc.nit
src/model/model.nit
src/model/model_viz.nit
src/modelize/modelize_property.nit
src/nitlight.nit
src/nitls.nit
src/nitpretty.nit
src/nitserial.nit
src/platform/android.nit
src/platform/android_annotations.nit
src/semantize/flow.nit
src/test_parser.nit
src/testing/testing_doc.nit
src/testing/testing_gen.nit
src/testing/testing_suite.nit
src/toolcontext.nit
src/uml/uml_class.nit
src/uml/uml_module.nit
tests/base_init_autoinit2.nit
tests/base_init_autoinit3.nit [new file with mode: 0644]
tests/base_init_noinit.nit
tests/emscripten_nodejs.nit
tests/sav/base_init_autoinit2_alt1.res
tests/sav/base_init_autoinit3.res [new file with mode: 0644]
tests/sav/base_init_autoinit3_alt1.res [new file with mode: 0644]
tests/sav/base_init_autoinit3_alt2.res [new file with mode: 0644]
tests/sav/base_init_autoinit3_alt4.res [new file with mode: 0644]
tests/sav/base_init_autoinit3_alt5.res [new file with mode: 0644]
tests/sav/base_init_autoinit3_alt6.res [new file with mode: 0644]
tests/sav/base_init_autoinit3_alt7.res [new file with mode: 0644]
tests/sav/base_init_autoinit3_alt8.res [new file with mode: 0644]
tests/sav/base_init_noinit_alt5.res
tests/sav/niti/base_init_autoinit3_alt1.res [new file with mode: 0644]
tests/sav/test_file_copy.res
tests/sav/test_file_read.res
tests/sav/test_file_read2.res
tests/sav/test_parser_args1.res
tests/sav/test_parser_args2.res
tests/test_deserialization.nit
tests/test_directory_create.nit
tests/test_exec.nit
tests/test_fdstream.nit
tests/test_file_copy.nit
tests/test_file_open_fail.nit
tests/test_file_read.nit
tests/test_file_read2.nit
tests/test_file_write.nit
tests/test_filterstream.nit
tests/test_for_abuse.nit
tests/test_serialization.nit
tests/test_stream_poll.nit

index 69590af..9f79133 100644 (file)
@@ -48,7 +48,7 @@ class Generator
                middle = (dept + 1) / 2
        end
 
-       var file: nullable OFStream = null
+       var file: nullable FileWriter = null
        fun write(str: String)
        do
                file.write(str)
@@ -62,7 +62,7 @@ class Generator
        do
                dir = "{dir}/nit"
                dir.mkdir
-               file = new OFStream.open("{dir}/{name}.nit")
+               file = new FileWriter.open("{dir}/{name}.nit")
 
                write "class Root\n\tfun id: Int do return 0\nend"
                for c in classes do
@@ -117,7 +117,7 @@ class Generator
        do
                dir = "{dir}/java"
                dir.mkdir
-               file = new OFStream.open("{dir}/{name}.java")
+               file = new FileWriter.open("{dir}/{name}.java")
 
                var cl = ""
                if interfaces then cl = "X"
@@ -183,7 +183,7 @@ class Generator
        do
                dir = "{dir}/cs"
                dir.mkdir
-               file = new OFStream.open("{dir}/{name}.cs")
+               file = new FileWriter.open("{dir}/{name}.cs")
 
                var cl = ""
                if interfaces then cl = "X"
@@ -248,7 +248,7 @@ class Generator
        do
                dir = "{dir}/scala"
                dir.mkdir
-               file = new OFStream.open("{dir}/{name}.scala")
+               file = new FileWriter.open("{dir}/{name}.scala")
 
                var cl = ""
                write "object {name} \{"
@@ -316,7 +316,7 @@ class Generator
        do
                dir = "{dir}/cpp"
                dir.mkdir
-               file = new OFStream.open("{dir}/{name}.cpp")
+               file = new FileWriter.open("{dir}/{name}.cpp")
 
                write "#include <iostream>"
                write "#include <stdlib.h>"
@@ -374,7 +374,7 @@ class Generator
                        dir = "{dir}/es/{name}"
                end
                dir.mkdir
-               file = new OFStream.open("{dir}/root.e")
+               file = new FileWriter.open("{dir}/root.e")
 
                var istk = ""
                if se then istk = " is"
@@ -384,7 +384,7 @@ class Generator
                file.close
 
                for c in classes do
-                       file = new OFStream.open("{dir}/{c}.e")
+                       file = new FileWriter.open("{dir}/{c}.e")
                        write "class {c}[E] "
                        if c.supers.is_empty then
                                write "\tinherit ROOT"
@@ -398,7 +398,7 @@ class Generator
                        file.close
                end
 
-               file = new OFStream.open("{dir}/app{name}.e")
+               file = new FileWriter.open("{dir}/app{name}.e")
                write "class APP{name.to_upper}"
                if se then
                        write "insert ARGUMENTS"
index 84ae549..2297bbd 100644 (file)
@@ -70,7 +70,7 @@ class BenitluxSubscriptionAction
                end
 
                if sample_email_path.file_exists then
-                       var f = new IFStream.open(sample_email_path)
+                       var f = new FileReader.open(sample_email_path)
                        var lines = new Array[String]
                        for line in f.read_all.split_with("\n") do if not line.is_empty then lines.add line
                        f.close
@@ -108,7 +108,7 @@ class BenitluxRESTAction
                                return response
                        end
 
-                       var stream = new StringOStream
+                       var stream = new StringWriter
                        var serializer = new JsonSerializer(stream)
                        serializer.serialize events
                        var serialized = stream.to_s
index 64f6e15..35aa64c 100644 (file)
@@ -112,7 +112,7 @@ class Benitlux
                generate_email(beer_events)
 
                # Save as sample email to file
-               var f = new OFStream.open(sample_email_path)
+               var f = new FileWriter.open(sample_email_path)
                f.write email_title + "\n"
                for line in email_content do f.write line + "\n"
                f.close
index c35b08a..f7de908 100644 (file)
@@ -39,7 +39,7 @@ class BFInterpreter
 
        # Create an interpreter for the file located at `path`.
        init from_file(path: String) do
-               var ifs = new IFStream.open(path)
+               var ifs = new FileReader.open(path)
                init(ifs.read_all)
        end
 
index 2a94089..b24cbf5 100644 (file)
@@ -141,7 +141,7 @@ for drawing in drawings do
        # Inkscape doesn't give us this information
        var page_width = -1
        var page_height = -1
-       var svg_file = new IFStream.open(drawing)
+       var svg_file = new FileReader.open(drawing)
        while not svg_file.eof do
                var line = svg_file.read_line
 
@@ -164,7 +164,7 @@ for drawing in drawings do
 
        # Query Inkscape
        var prog = "inkscape"
-       var proc = new IProcess.from_a(prog, ["--without-gui", "--query-all", drawing])
+       var proc = new ProcessReader.from_a(prog, ["--without-gui", "--query-all", drawing])
 
        var min_x = 1000000
        var min_y = 1000000
@@ -240,7 +240,7 @@ for drawing in drawings do
        end
 
        # Output source file
-       var src_file = new OFStream.open("{src_path}/{drawing_name}.nit")
+       var src_file = new FileWriter.open("{src_path}/{drawing_name}.nit")
        nit_src.write_to(src_file)
        src_file.close
 
index 917074d..f0be48c 100644 (file)
@@ -23,14 +23,14 @@ class CodeGenerator
 
        var with_attributes: Bool
        var comment_unknown_types: Bool
-       var file_out: OFStream
+       var file_out: FileWriter
        var java_class: JavaClass
        var nb_params: Int
        var module_name: nullable String = null
 
        init (file_name: String, jclass: JavaClass, with_attributes, comment: Bool)
        do
-               file_out = new OFStream.open(file_name)
+               file_out = new FileWriter.open(file_name)
 
                var nit_ext = ".nit"
                if file_name.has_suffix(nit_ext) then
index 56128b7..dd3f8ef 100644 (file)
@@ -63,7 +63,7 @@ if not "javap".program_is_in_path then
        exit 1
 end
 
-var javap = new IProcess("javap", "-public", dot_class)
+var javap = new ProcessReader("javap", "-public", dot_class)
 
 var p = new TestParser_javap
 var tree = p.work(javap.read_all)
index cb99a23..34792c9 100644 (file)
@@ -176,7 +176,7 @@ class JavaType
 
                var regex = "extern class [a-zA-Z1-9]\\\+[ ]\\\+in[ ]\\\+\"Java\"[ ]*`\{[ ]*" + self.to_s + "\\\+[ ]*`\}"
                var nit_dir = "NIT_DIR".environ
-               var grep = new IProcess("grep", "-r", regex, nit_dir/"lib/android/", nit_dir/"lib/java/")
+               var grep = new ProcessReader("grep", "-r", regex, nit_dir/"lib/android/", nit_dir/"lib/java/")
                var to_eat = ["private", "extern", "class"]
 
                var output = grep.read_line
index 1367e0d..f286894 100644 (file)
@@ -443,7 +443,7 @@ class Automaton
                        ni += 1
                end
 
-               var f = new OFStream.open(filepath) 
+               var f = new FileWriter.open(filepath)
                 f.write("digraph g \{\n")
 
                for s in states do
@@ -638,10 +638,10 @@ private class DFAGenerator
        var automaton: Automaton
        var parser: nullable String
 
-       var out: OStream is noinit
+       var out: Writer is noinit
 
        init do
-               self.out = new OFStream.open(filepath)
+               self.out = new FileWriter.open(filepath)
        end
 
        fun add(s: String) do out.write(s)
index b9ac2f8..e77f4e9 100644 (file)
@@ -575,7 +575,7 @@ class LRAutomaton
        # Generate a graphviz file of the automaton
        fun to_dot(path: String)
        do
-               var f = new OFStream.open(path)
+               var f = new FileWriter.open(path)
                f.write("digraph g \{\n")
                f.write("rankdir=LR;\n")
                f.write("node[shape=Mrecord,height=0];\n")
@@ -622,7 +622,7 @@ class LRAutomaton
        do
                var gen = new Generator
                gen.gen_to_nit(self, name)
-               var f = new OFStream.open(filepath)
+               var f = new FileWriter.open(filepath)
                for s in gen.out do
                        f.write(s)
                        f.write("\n")
index 0cc9d2a..a499217 100644 (file)
@@ -27,7 +27,7 @@ var fi = args.first
 
 var text
 if fi != "-" then
-       var f = new IFStream.open(fi)
+       var f = new FileReader.open(fi)
        text = f.read_all
        f.close
 else
@@ -94,7 +94,7 @@ for prod in gram.prods do nbalts += prod.alts.length
 print "Concrete grammar: {gram.prods.length} productions, {nbalts} alternatives (see {name}.concrete_grammar.out)"
 
 var pretty = gram.pretty
-var f = new OFStream.open("{name}.concrete_grammar.out")
+var f = new FileWriter.open("{name}.concrete_grammar.out")
 f.write "// Concrete grammar of {name}\n"
 f.write pretty
 f.close
@@ -102,7 +102,7 @@ f.close
 print "LR automaton: {lr.states.length} states (see {name}.lr.dot and {name}.lr.out)"
 lr.to_dot("{name}.lr.dot")
 pretty = lr.pretty
-f = new OFStream.open("{name}.lr.out")
+f = new FileWriter.open("{name}.lr.out")
 f.write "// LR automaton of {name}\n"
 f.write pretty
 f.close
@@ -142,7 +142,7 @@ print "Generate {name}_lexer.nit {name}_parser.nit {name}_test_parser.nit"
 dfa.gen_to_nit("{name}_lexer.nit", name, "{name}_parser")
 lr.gen_to_nit("{name}_parser.nit", name)
 
-f = new OFStream.open("{name}_test_parser.nit")
+f = new FileWriter.open("{name}_test_parser.nit")
 f.write """# Generated by nitcc for the language {{{name}}}
 
 # Standalone parser tester for the language {{{name}}}
index 65608d0..c15238b 100644 (file)
@@ -198,6 +198,6 @@ a.to_dot("nitcc0.lr.dot")
 
 a.gen_to_nit("nitcc_parser.nit", "nitcc")
 
-var f = new OFStream.open("nitcc_lexer.nit")
+var f = new FileWriter.open("nitcc_lexer.nit")
 f.write("import nitcc_lexer0\n")
 f.close
index eed0d4b..11df5b2 100644 (file)
@@ -180,7 +180,7 @@ abstract class Processor
                var skip_path = "tests/turing.skip"
                var skip
                if skip_path.file_exists then
-                       var skip_file = new IFStream.open(skip_path)
+                       var skip_file = new FileReader.open(skip_path)
                        skip = skip_file.read_lines
                        skip_file.close
                else
@@ -463,7 +463,7 @@ class Worker
                                        sys.system cmd
 
                                        # Test results were written to file, read them
-                                       var fstream = new IFStream.open(tests_sh_out)
+                                       var fstream = new FileReader.open(tests_sh_out)
                                        var content = fstream.read_all
                                        fstream.close
 
index 3dec44f..fa78818 100644 (file)
@@ -113,7 +113,7 @@ class Nitiwiki
        # List markdown source files from a directory.
        fun list_md_files(dir: String): Array[String] do
                var files = new Array[String]
-               var pipe = new IProcess("find", dir, "-name", "*.md")
+               var pipe = new ProcessReader("find", dir, "-name", "*.md")
                while not pipe.eof do
                        var file = pipe.read_line
                        if file == "" then break # last line
@@ -512,7 +512,7 @@ class WikiArticle
        # Page content.
        #
        # What you want to be displayed in the page.
-       var content: nullable Streamable = null
+       var content: nullable Writable = null
 
        # Headlines ids and titles.
        var headlines = new ArrayMap[String, HeadLine]
@@ -540,7 +540,7 @@ class WikiArticle
        # REQUIRE: `has_source`.
        fun md: String is cached do
                assert has_source
-               var file = new IFStream.open(src_full_path.to_s)
+               var file = new FileReader.open(src_full_path.to_s)
                var md = file.read_all
                file.close
                return md
index 89546ce..10ab09b 100644 (file)
@@ -52,7 +52,7 @@ redef class WikiEntry
        fun url: String do return wiki.config.root_url.join_path(breadcrumbs.join("/"))
 
        # Get a `<a>` template link to `self`
-       fun tpl_link: Streamable do
+       fun tpl_link: Writable do
                return "<a href=\"{url}\">{title}</a>"
        end
 end
@@ -215,7 +215,7 @@ redef class WikiArticle
        end
 
        # Generate the HTML header for this article.
-       fun tpl_header: Streamable do
+       fun tpl_header: Writable do
                var file = header_file
                if not wiki.has_template(file) then return ""
                return wiki.load_template(file)
@@ -237,7 +237,7 @@ redef class WikiArticle
        # Generate the HTML summary for this article.
        #
        # Based on `headlines`
-       fun tpl_summary: Streamable do
+       fun tpl_summary: Writable do
                var headlines = self.headlines
                var tpl = new Template
                tpl.add "<ul class=\"summary list-unstyled\">"
@@ -265,7 +265,7 @@ redef class WikiArticle
        end
 
        # Generate the HTML menu for this article.
-       fun tpl_menu: Streamable do
+       fun tpl_menu: Writable do
                var file = menu_file
                if not wiki.has_template(file) then return ""
                var tpl = wiki.load_template(file)
@@ -288,7 +288,7 @@ redef class WikiArticle
        end
 
        # Generate the HTML footer for this article.
-       fun tpl_footer: Streamable do
+       fun tpl_footer: Writable do
                var file = footer_file
                if not wiki.has_template(file) then return ""
                var tpl = wiki.load_template(file)
@@ -342,10 +342,10 @@ class TplArticle
        super Template
 
        # Article title.
-       var title: nullable Streamable = null
+       var title: nullable Writable = null
 
        # Article HTML body.
-       var body: nullable Streamable = null
+       var body: nullable Writable = null
 
        # Sidebar of this article (if any).
        var sidebar: nullable TplSidebar = null
@@ -354,7 +354,7 @@ class TplArticle
        var breadcrumbs: nullable TplBreadcrumbs = null
 
        # Init `self` with a `title`.
-       init with_title(title: Streamable) do
+       init with_title(title: Writable) do
                self.title = title
        end
 
@@ -389,7 +389,7 @@ class TplSidebar
        super Template
 
        # Blocks are `Stremable` pieces that will be rendered in the sidebar.
-       var blocks = new Array[Streamable]
+       var blocks = new Array[Writable]
 
        redef fun rendering do
                for block in blocks do
diff --git a/contrib/nitrpg/src/events.nit b/contrib/nitrpg/src/events.nit
new file mode 100644 (file)
index 0000000..227469a
--- /dev/null
@@ -0,0 +1,116 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014-2015 Alexandre Terrasa <alexandre@moz-code.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.
+
+# `nitrpg` game events.
+#
+# In this module we introduce the concept of `GameEvent`.
+# They can be attached to every GameEntities.
+module events
+
+import game
+
+redef class GameEntity
+
+       # Saves `event` in `self`.
+       fun add_event(event: GameEvent) do event.save_in(self)
+
+       # List all events registered in this entity.
+       #
+       # This list is reloaded from game data each time its called.
+       #
+       # To add events see `add_event`.
+       fun load_events: Array[GameEvent] do
+               var key = key / "events"
+               var res = new Array[GameEvent]
+               if not game.store.has_collection(key) then return res
+               var coll = game.store.list_collection(key)
+               for id in coll do
+                       var name = id.to_s
+                       res.add load_event(name).as(not null)
+               end
+               (new EventTimeComparator).sort(res)
+               return res
+       end
+
+       # Load the event from its `id`.
+       #
+       # Looks for the event save file in game data.
+       # Returns `null` if the event cannot be found.
+       fun load_event(id: String): nullable GameEvent do
+               var key = key / "events" / id
+               if not game.store.has_key(key) then return null
+               var json = game.store.load_object(key)
+               return new GameEvent.from_json(game, json)
+       end
+end
+
+# An event that occurs in the `Game`.
+class GameEvent
+       super GameEntity
+
+       redef var key is lazy do return "events" / internal_id
+
+       redef var game
+
+       # String used to dissociate events in the display.
+       var kind: String
+
+       # GameEvents have raw data associated to them.
+       #
+       # These data are stored in a JsonObject.
+       var data: JsonObject is writable
+
+       # GameEvent uniq id used for storage.
+       var internal_id: String is noinit
+
+       # Date and time of the event.
+       var time: ISODate is noinit, writable
+
+       # An event initialized at now `time`.
+       init do
+               internal_id = "{get_time}{object_id}{100.rand}"
+               time = new ISODate
+       end
+
+       # Init `self` from a `json` object.
+       #
+       # Used to load events from json storage.
+       init from_json(game: Game, json: JsonObject) do
+               self.game = game
+               internal_id = json["internal_id"].to_s
+               kind = json["kind"].to_s
+               time = new ISODate.from_string(json["time"].to_s)
+               data = json["data"].as(JsonObject)
+       end
+
+       redef fun to_json do
+               var json = new JsonObject
+               json["internal_id"] = internal_id.to_s
+               json["kind"] = kind
+               json["time"] = time.to_s
+               json["data"] = data
+               return json
+       end
+end
+
+# Compare `GameEvent` to sort them from the most recent to the older.
+class EventTimeComparator
+       super Comparator
+
+       redef type COMPARED: GameEvent
+
+       redef fun compare(a, b) do return b.time <=> a.time
+end
index 9de4887..9c71566 100644 (file)
@@ -38,9 +38,18 @@ interface GameEntity
        # Uniq key used for data storage.
        fun key: String is abstract
 
-       # Save `self` as a json object.
+       # Saves the `self` state in game data.
+       #
+       # Date are stored under `self.key`.
        fun save do game.store.store_object(key, to_json)
 
+       # Saves `self` state into `target` key data.
+       #
+       # Data are stored under `target.key / self.key`.
+       fun save_in(target: GameEntity) do
+               game.store.store_object(target.key / key, to_json)
+       end
+
        # Json representation of `self`.
        fun to_json: JsonObject  do return new JsonObject
 
@@ -273,11 +282,7 @@ interface GameReactor
        #
        # Concrete `GameReactor` implement this method to update game data
        # for each specific GithubEvent.
-       #
-       # By default, only logs received events.
-       fun react_event(game: Game, event: GithubEvent) do
-               game.message(1, "Received event {event} for {game.repo.full_name}")
-       end
+       fun react_event(game: Game, event: GithubEvent) is abstract
 end
 
 # utils
index a77ec9f..d35b169 100644 (file)
@@ -33,6 +33,7 @@ class RpgHookListener
                var game = new Game(api, event.repo)
                # TODO handle verbosity with opts
                game.verbose_lvl = 1
+               game.message(1, "Received event {event} for {game.repo.full_name}")
                for reactor in reactors do reactor.react_event(game, event)
        end
 end
index d1f3b3c..79a3682 100644 (file)
 # limitations under the License.
 
 # Various implementations of `GameReactor` can be found here.
-#
-# TODO This module use a lot of magic numbers for nitcoin rewards.
-# This should be extracted from configuration or stored elsewhere.
 module reactors
 
-import game
+import events
 
 # Reacts to event that can affect players (like giving nitcoins).
 class PlayerReactor
        super GameReactor
 
-       redef fun react_event(game, e) do e.react_player_event(game)
+       # Nitcoins rewarded when the player opens a new pull request.
+       var nc_pull_open = 10
+
+       # Nitcoins rewarded when the player reviews a pull request.
+       var nc_pull_review = 2
+
+       # Nitcoins rewarded when the player has a commit merged.
+       var nc_commit_merged = 1
+
+       redef fun react_event(game, e) do e.react_player_event(self, game)
 end
 
 redef class GithubEvent
@@ -34,19 +40,48 @@ redef class GithubEvent
        #
        # Called by `PlayerReactor::react_event`.
        # No-op by default.
-       private fun react_player_event(game: Game) do end
+       private fun react_player_event(reactor: PlayerReactor, game: Game) do end
+
+       # Generates a GameEvent preinitialized for a reward event.
+       private fun player_reward_event(kind: String, player: Player, reward: Int): GameEvent do
+               var obj = new JsonObject
+               obj["player"] = player.name
+               obj["reward"] = reward
+               obj["github_event"] = json
+               var event = new GameEvent(player.game, kind, obj)
+               player.game.add_event(event)
+               return event
+       end
 end
 
 redef class PullRequestEvent
 
        # Rewards player for opened pull requests.
-       redef fun react_player_event(game) do
+       redef fun react_player_event(r, game) do
                if action == "opened" then
-                       var player = pull.user.player(game)
-                       player.nitcoins += 10
-                       player.save
+                       react_pull_open(r, game)
+               else if action == "closed" then
+                       react_pull_close(r, game)
                end
        end
+
+       private fun react_pull_open(r: PlayerReactor, game: Game) do
+               var player = pull.user.player(game)
+               player.nitcoins += r.nc_pull_open
+               player.save
+               var event = player_reward_event("pull_open", player, r.nc_pull_open)
+               player.add_event(event)
+       end
+
+       private fun react_pull_close(r: PlayerReactor, game: Game) do
+               if not pull.merged then return
+               var player = pull.user.player(game)
+               var reward = pull.commits * r.nc_commit_merged
+               player.nitcoins += reward
+               player.save
+               var event = player_reward_event("pull_merged", player, reward)
+               player.add_event(event)
+       end
 end
 
 redef class IssueCommentEvent
@@ -56,12 +91,18 @@ redef class IssueCommentEvent
        # Actuallty we look if the comment contains the string `"+1"`.
        #
        # TODO only give nitcoins if reviewers < 2
-       redef fun react_player_event(game) do
+       redef fun react_player_event(r, game) do
                # FIXME use a more precise way to locate reviews
                if comment.body.has("\\+1\\b".to_re) then
-                       var player = comment.user.player(game)
-                       player.nitcoins += 2
-                       player.save
+                       react_player_review(r, game)
                end
        end
+
+       private fun react_player_review(r: PlayerReactor, game: Game) do
+               var player = comment.user.player(game)
+               player.nitcoins += r.nc_pull_review
+               player.save
+               var event = player_reward_event("pull_review", player, r.nc_pull_review)
+               player.add_event(event)
+       end
 end
index b8bbeea..39c05af 100644 (file)
@@ -126,7 +126,6 @@ class StatisticsReactor
        super GameReactor
 
        redef fun react_event(game, e) do
-               super # log events
                e.react_stats_event(game)
        end
 end
index 0a49241..89d6431 100644 (file)
@@ -17,7 +17,7 @@
 # Panels templates for `nitpg`.
 module panels
 
-import templates_base
+import templates_events
 
 # A panel can be displayed in a html page.
 #
@@ -107,7 +107,7 @@ class GameStatusPanel
 
        redef fun render_title do
                add "<span class=\"glyphicon glyphicon-home\"></span>&nbsp;&nbsp;"
-               add "<a href=\"{game.url}\">{game.name}</a>"
+               add "{game.link}"
        end
 
        redef fun render_body do
@@ -135,8 +135,7 @@ class PlayerStatusPanel
                add "<a href=\"{player.url}\">"
                add " <img class=\"img-circle\" style=\"width: 30px\""
                add "   src=\"{player.user.avatar_url}\" alt=\"{player.name}\">"
-               add "</a>&nbsp;&nbsp;"
-               add "<a href=\"{player.url}\">{player.name}</a>"
+               add "</a>&nbsp;&nbsp;{player.link}"
        end
 
        redef fun render_body do
@@ -148,7 +147,6 @@ class PlayerStatusPanel
                add "<strong>{player.stats["pulls"]}</strong> pull requests<br>"
                add "<strong>{player.stats["issues"]}</strong> issues<br>"
                add "<strong>{player.stats["commits"]}</strong> commits"
-
        end
 end
 
@@ -172,9 +170,7 @@ class ShortListPlayersPanel
                end
                (new PlayerCoinComparator).sort(players)
                for player in players do
-                       add "<a href=\"{player.url}\">"
-                       add player.name
-                       add "</a>&nbsp;({player.nitcoins})<br>"
+                       add "{player.nitcoins} - {player.link}<br>"
                end
        end
 end
@@ -210,7 +206,7 @@ class ListPlayersPanel
                for player in players do
                        add "<tr>"
                        add " <td>{rank}</td>"
-                       add " <td><a href=\"{player.url}\">{player.name}</a></td>"
+                       add " <td>{player.link}</td>"
                        add " <td>{player.nitcoins}</td>"
                        add "</tr>"
                        rank += 1
@@ -256,7 +252,7 @@ class PodiumPanel
                                                                src="{{{player.user.avatar_url}}}" alt="{{{player.name}}}">
                                                </a>
                                        </p>
-                                       <p><a href="{{{player.url}}}">{{{player.name}}}</a></p>
+                                       <p>{{{player.link}}}</p>
                                        <p>{{{player.nitcoins}}}</p>
                                        <div class=" progress-bar-warning progress-bar-striped"
                                                style="height: {{{size}}}px;"></div>
@@ -293,18 +289,74 @@ class PlayerReviewsPanel
                        return
                end
                for issue in issues do
+                       var user = issue.user
+                       var uplay = user.player(game)
                        add """<div class="media">
-                               <a class="media-left" href="{{{player.url}}}">
+                               <a class="media-left" href="{{{uplay.url}}}">
                                         <img class=\"img-circle\" style="width:50px"
-                                          src="{{{issue.user.avatar_url}}}" alt="{{{issue.user.login}}}">
+                                          src="{{{user.avatar_url}}}" alt="{{{uplay.name}}}">
                                        </a>
                                        <div class="media-body">
                                         <h4 class="media-heading">
-                                        <a href="{{{issue.html_url}}}">#{{{issue.number}}} {{{issue.title}}}</a></h4>
+                                               {{{issue.link}}} {{{issue.title}}}
+                                       </h4>
                                         <span class="text-muted">opened by </span>
-                                        <a href="{{{player.url}}}">{{{issue.user.login}}}</a>
+                                        {{{uplay.link}}}
                                        </div>
                                   </div>"""
                end
        end
 end
+
+# A `Panel` that displays a pagined list of events stored in the `entity`.
+#
+# This way the panel can be used to view events stored under `Game`, `Player`...
+class EventListPanel
+       super Panel
+
+       # Entity to load the events from.
+       var entity: GameEntity
+
+       # Number of events to display.
+       var limit: Int
+
+       # From where to start?
+       var from: Int
+
+       redef fun render_title do
+               add "<span class=\"glyphicon glyphicon-flash\"></span>&nbsp;&nbsp;"
+               add "Last events"
+       end
+
+       redef fun render_body do
+               var events = entity.load_events
+               if events.is_empty then
+                       add "<em>No event yet...</em>"
+                       return
+               end
+               # check input
+               if limit < 0 then limit = 10
+               if from < 0 then from = 0
+               # display events
+               for i in [from .. from + limit] do
+                       if i >= events.length then break
+                       add events[i].tpl_event.media_item
+               end
+               # pagination
+               if limit > events.length then return
+               add "<hr>"
+               add """<div class="btn-group" role="group">"""
+               if from > 0 then
+                       add """<a class="btn btn-default" role="button"
+                                       href="?pfrom={{{from - limit}}}&plimit={{{limit}}}">
+                                    <span class=\"glyphicon glyphicon-chevron-left\"></span></a>"""
+               end
+               if from + limit < events.length then
+                       add """
+                         <a class="btn btn-default" role="button"
+                                  href="?pfrom={{{from + limit}}}&plimit={{{limit}}}">
+                                   <span class=\"glyphicon glyphicon-chevron-right\"></span></a>"""
+               end
+               add "</div>"
+       end
+end
index adac329..9b28d57 100644 (file)
@@ -36,4 +36,17 @@ redef class Game
 
        # Displayed name.
        fun name: String do return repo.full_name
+
+       # Return a HTML link to this Game.
+       fun link: String do return "<a href=\"{url}\">{name}</a>"
+end
+
+redef class Player
+       # Return a HTML link to this Player.
+       fun link: String do return "<a href=\"{url}\">{name}</a>"
+end
+
+redef class Issue
+       # Return a HTML link to this Issue.
+       fun link: String do return "<a href=\"{html_url}\">#{number}</a>"
 end
diff --git a/contrib/nitrpg/src/templates/templates_events.nit b/contrib/nitrpg/src/templates/templates_events.nit
new file mode 100644 (file)
index 0000000..20f7b58
--- /dev/null
@@ -0,0 +1,111 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014-2015 Alexandre Terrasa <alexandre@moz-code.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.
+
+# Templates to display `GameEvent` kinds.
+module templates_events
+
+import events
+import templates_base
+
+redef class GameEvent
+       # See `TplEvent`
+       fun tpl_event: TplEvent do
+               if kind == "pull_open" then
+                       return new TplPullOpened(self)
+               else if kind == "pull_merged" then
+                       return new TplPullMerged(self)
+               else if kind == "pull_review" then
+                       return new TplPullReview(self)
+               end
+               abort
+       end
+end
+
+# A TplEvent factorizes HTML rendering methods for `GameEvent`.
+class TplEvent
+
+       # Event to display.
+       var event: GameEvent
+
+       # Title to display.
+       var title: String is lazy do return "raw event"
+
+       # Load Player from event data.
+       var player: nullable Player is lazy do
+               return event.game.load_player(event.data["player"].to_s)
+       end
+
+       # Load reward from event data.
+       var reward: Int is lazy do return event.data["reward"].as(Int)
+
+       # Load `github_event` data key as a PullRequestEvent.
+       var pull_event: PullRequestEvent is lazy do
+               var obj = event.data["github_event"].as(JsonObject)
+               return new PullRequestEvent.from_json(event.game.api, obj)
+       end
+
+       # Load `github_event` data key as a IssueCommentEvent.
+       var issue_comment_event: IssueCommentEvent is lazy do
+               var obj = event.data["github_event"].as(JsonObject)
+               return new IssueCommentEvent.from_json(event.game.api, obj)
+       end
+
+       # Display a media item for a reward event.
+       fun media_item: String do
+               return """<div class="media">
+                       <a class="media-left" href="{{{player.url}}}">
+                                <span class="badge progress-bar-success"
+                                 style=\"position: absolute\">+{{{reward}}}</span>
+                                <img class=\"img-circle\" style="width:50px"
+                                  src="{{{player.user.avatar_url}}}" alt="{{{player.name}}}">
+                               </a>
+                               <div class="media-body">
+                                <h4 class="media-heading">{{{title}}}</h4>
+                                <span class="text-muted">at {{{event.time}}}</span>
+                               </div>
+                          </div>"""
+       end
+end
+
+# Event: pull_open
+class TplPullOpened
+       super TplEvent
+
+       redef var title is lazy do
+               var pull = pull_event.pull
+               return "{player.link} pushed {pull.link}"
+       end
+end
+
+# Event: pull_merged
+class TplPullMerged
+       super TplEvent
+
+       redef var title is lazy do
+               var pull = pull_event.pull
+               return "{player.link} merged <strong>{pull.commits}</strong> commits with {pull.link}"
+       end
+end
+
+# Event: pull_review
+class TplPullReview
+       super TplEvent
+
+       redef var title is lazy do
+               var issue = issue_comment_event.issue
+               return "{player.link} reviewed {issue.link}"
+       end
+end
index 80f7821..ac7f91d 100644 (file)
@@ -87,8 +87,22 @@ class GameAction
                page.side_panels.add new GameStatusPanel(game)
                page.breadcrumbs = new Breadcrumbs
                page.breadcrumbs.add_link(game.url, game.name)
+               prepare_pagination(request)
                return response
        end
+
+       # Parse pagination related parameters.
+       private fun prepare_pagination(request: HttpRequest) do
+               var args = request.get_args
+               list_from = args.get_or_default("pfrom", "0").to_i
+               list_limit = args.get_or_default("plimit", "10").to_i
+       end
+
+       # Limit of events to display in lists.
+       var list_limit = 10
+
+       # From where to start the display of events related lists.
+       var list_from = 0
 end
 
 # Repo overview page.
@@ -99,6 +113,7 @@ class RepoHome
                var rsp = prepare_response(request, url)
                page.side_panels.add new ShortListPlayersPanel(game)
                page.flow_panels.add new PodiumPanel(game)
+               page.flow_panels.add new EventListPanel(game, list_limit, list_from)
                rsp.body = page.write_to_string
                return rsp
        end
@@ -137,6 +152,7 @@ class PlayerHome
                page.side_panels.clear
                page.side_panels.add new PlayerStatusPanel(game, player)
                page.flow_panels.add new PlayerReviewsPanel(game, player)
+               page.flow_panels.add new EventListPanel(player, list_limit, list_from)
                rsp.body = page.write_to_string
                return rsp
        end
index 7d0e701..74c7be0 100644 (file)
@@ -63,8 +63,8 @@ redef class ToolContext
        end
 end
 
-# We have to redef some IFStream methods because we don't use NativeFiles anymore.
-redef class IFStream
+# We have to redef some FileReader methods because we don't use NativeFiles anymore.
+redef class FileReader
 
        # Looks in the 'files' HashMap.
        redef init open(path: String)
index 609f56c..a92ab4b 100644 (file)
@@ -111,7 +111,7 @@ class OpportunityPage
        var header = new OpportunityHeader
 
        # The HTML code of the body.
-       var body: Streamable = "" is writable
+       var body: Writable = "" is writable
 
        # The HTML code of the footer.
        var footer = new OpportunityFooter
index e5d1f56..6eca566 100644 (file)
@@ -266,7 +266,7 @@ end
 
 redef class Meetup
        # Build the HTML for `self`
-       fun to_html(db: OpportunityDB): Streamable do
+       fun to_html(db: OpportunityDB): Writable do
                var t = new Template
                t.add """
 <div class="container">
index 6759fcc..562873a 100644 (file)
@@ -4,11 +4,11 @@ import parser
 redef class AnalysisManager
        fun build_ast_from_file( filename : String ) : nullable AListing
        do
-               var file = new IFStream.open( filename )
+               var file = new FileReader.open( filename )
                return build_ast(filename, file)
        end
 
-       fun build_ast(filename: String, stream: IStream): nullable AListing
+       fun build_ast(filename: String, stream: Reader): nullable AListing
        do
                var source = new SourceFile(filename, stream)
                var lexer = new Lexer(source)
index 8fec16b..0bf39c0 100644 (file)
@@ -1,7 +1,7 @@
 import cfg_base
 
 redef class CFG
-       fun print_dot( f: OStream, long: Bool )
+       fun print_dot( f: Writer, long: Bool )
        do
                f.write("digraph \{\n")
                f.write("charset=latin1\n")
@@ -13,7 +13,7 @@ redef class CFG
 end
 
 redef class BasicBlock
-       fun print_dot_nodes( f: OStream, long: Bool )
+       fun print_dot_nodes( f: Writer, long: Bool )
        do
                var lbl = "\"{name}:\\n{dot_node_text(long)}\""
                f.write( "{name} [label={lbl}]\n" )
@@ -36,7 +36,7 @@ redef class BasicBlock
        fun dot_node_header: String do return ""
        fun dot_node_footer: String do return ""
 
-       fun print_dot_edges( f: OStream, long: Bool )
+       fun print_dot_edges( f: Writer, long: Bool )
        do
                for s in successors do
                        f.write( "{name} -> {s.name}\n" )
index def0b2e..6fd9edf 100644 (file)
@@ -26,7 +26,7 @@ class SourceFile
        var string: String
 
        # Create a new sourcefile using a filename and a stream
-       init(filename: String, stream: IStream)
+       init(filename: String, stream: Reader)
        do
                self.filename = filename
                string = stream.read_all
index a3231bb..abacc8b 100644 (file)
@@ -57,7 +57,7 @@ redef class AnalysisManager
                        if opt_ast.value then
                                var printer = new ASTPrinter
                                printer.enter_visit(ast)
-                               var of = new OFStream.open("{dir}/{mangled_filename.replace(".pep", ".ast.dot")}")
+                               var of = new FileWriter.open("{dir}/{mangled_filename.replace(".pep", ".ast.dot")}")
                                of.write printer.str
                                of.close
                        end
@@ -76,7 +76,7 @@ redef class AnalysisManager
                        var cfg = build_cfg(model)
 
                        if opt_cfg.value or opt_cfg_long.value then
-                               var of = new OFStream.open("{dir}/{mangled_filename.replace(".pep", ".cfg.dot")}")
+                               var of = new FileWriter.open("{dir}/{mangled_filename.replace(".pep", ".cfg.dot")}")
                                cfg.print_dot(of, opt_cfg_long.value)
                                of.close
                        end
@@ -95,7 +95,7 @@ redef class AnalysisManager
                        do_types_analysis(ast, cfg)
 
                        # Print results
-                       var of = new OFStream.open("{dir}/{mangled_filename.replace(".pep",".analysis.dot")}")
+                       var of = new FileWriter.open("{dir}/{mangled_filename.replace(".pep",".analysis.dot")}")
                        cfg.print_dot(of, true)
                        of.close
                end
index b991952..4d9d0aa 100644 (file)
@@ -50,7 +50,7 @@ redef class AnalysisManager
        do
                sys.suggest_garbage_collection
 
-               var stream = new StringIStream(src)
+               var stream = new StringReader(src)
                var ast = build_ast("web", stream)
                if ast == null then return
 
@@ -95,7 +95,7 @@ redef class AnalysisManager
                print_notes
                if notes.is_empty then print "Success: Nothing wrong detected"
 
-               var of = new StringOStream
+               var of = new StringWriter
                cfg.print_dot(of, false)
                of.close
                show_graph(of.to_s)
index 92a3a80..6740fe2 100644 (file)
 
 # Android compatibility module
 #
-# Defines the `@android` annotation used to tag `ldflags` annotations.
-module aware is new_annotation(android)
+# Defines all Android related annoations including the `@android` annotations
+# used to tag `ldflags` annotations.
+module aware is
+       new_annotation android
+       new_annotation java_package
+       new_annotation min_api_version
+       new_annotation max_api_version
+       new_annotation target_api_version
+       new_annotation android_manifest
+       new_annotation android_manifest_application
+       new_annotation android_manifest_activity
+end
index 68713ad..3678cbc 100644 (file)
@@ -672,7 +672,7 @@ redef class Serializable
        protected fun add_to_bundle(bundle: NativeBundle, key: JavaString)
        do
                sys.jni_env.push_local_frame(1)
-               var serialized_string = new StringOStream
+               var serialized_string = new StringWriter
                var serializer = new JsonSerializer(serialized_string)
                serializer.serialize(self)
 
@@ -740,7 +740,7 @@ redef class Array[E]
                        var java_string_array = new Array[JavaString]
 
                        for element in self do
-                       var serialized_string = new StringOStream
+                       var serialized_string = new StringWriter
                                var serializer = new JsonSerializer(serialized_string)
                                serializer.serialize(element)
                                java_string_array.add(serialized_string.to_s.to_java_string)
diff --git a/lib/android/gamepad.nit b/lib/android/gamepad.nit
new file mode 100644 (file)
index 0000000..be0ded0
--- /dev/null
@@ -0,0 +1,78 @@
+# 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.
+
+# Support for gamepad events (over Bluetooth or USB)
+module gamepad
+
+import input_events
+
+redef class AndroidKeyEvent
+
+       # Was `self` raised by the A button?
+       fun is_a: Bool do return key_code == 96
+
+       # Was `self` raised by the B button?
+       fun is_b: Bool do return key_code == 97
+
+       # Was `self` raised by the X button?
+       fun is_x: Bool do return key_code == 99
+
+       # Was `self` raised by the Y button?
+       fun is_y: Bool do return key_code == 100
+
+       # Was `self` raised by the directional pad?
+       fun is_dpad: Bool
+       do
+               return is_dpad_up or is_dpad_down or is_dpad_left or is_dpad_right
+       end
+
+       # Was `self` raised by the up key on the directional pad?
+       fun is_dpad_up: Bool do return key_code == 19
+
+       # Was `self` raised by the down key on the directional pad?
+       fun is_dpad_down: Bool do return key_code == 20
+
+       # Was `self` raised by the left key on the directional pad?
+       fun is_dpad_left: Bool do return key_code == 21
+
+       # Was `self` raised by the right key on the directional pad?
+       fun is_dpad_right: Bool do return key_code == 22
+
+       # Was `self` raised by the start button?
+       fun is_start: Bool do return key_code == 108
+
+       # Was `self` raised by the select button?
+       fun is_select: Bool do return key_code == 109
+
+       # Was `self` raised by the right bumper button?
+       fun is_bumper_right: Bool do return key_code == 103
+
+       # Was `self` raised by the right trigger?
+       fun is_trigger_right: Bool do return key_code == 105
+
+       # Was `self` raised by the left bumper?
+       fun is_bumper_left: Bool do return key_code == 102
+
+       # Was `self` raised by the left trigger?
+       fun is_trigger_left: Bool do return key_code == 101
+
+       # Was `self` raised by the media button 'previous'?
+       fun is_media_previous: Bool do return key_code == 87
+
+       # Was `self` raised by the media button 'pause'?
+       fun is_media_pause: Bool do return key_code == 85
+
+       # Was `self` raised by the media button 'next'?
+       fun is_media_next: Bool do return key_code == 88
+end
index 005b475..8d84981 100644 (file)
@@ -1285,7 +1285,7 @@ class Intent
        # Returns `self` allowing fluent programming
        fun []=(name: String, value: nullable Serializable): Intent
        do
-               var serialized_string = new StringOStream
+               var serialized_string = new StringWriter
                var serializer = new JsonSerializer(serialized_string)
                serializer.serialize(value)
 
index 7c15af5..2f44028 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-module platform is
-       platform("android")
-       new_annotation java_package
-       new_annotation min_api_version
-       new_annotation max_api_version
-       new_annotation target_api_version
-       new_annotation android_manifest
-       new_annotation android_manifest_application
-       new_annotation android_manifest_activity
-end
+# Triggers compilation for the android platform
+module platform is platform "android"
 
 import java
 import app
index 94aac59..05dbf82 100644 (file)
@@ -379,7 +379,7 @@ class SharedPreferences
        # Store `value` as a serialized Json string
        fun []=(key: String, value: nullable Serializable)
        do
-               var serialized_string = new StringOStream
+               var serialized_string = new StringWriter
                var serializer = new JsonSerializer(serialized_string)
                serializer.serialize(value)
 
index 441f95c..c6f0b41 100644 (file)
@@ -53,7 +53,7 @@ end
 
 # A CSV document representation.
 class CsvDocument
-       super Streamable
+       super Writable
 
        # The format to use.
        #
@@ -103,7 +103,7 @@ class CsvDocument
        # * `has_header`: Is the first row the header?
        # * `skip_empty`: Do we skip the empty lines?
        # For details, see `CsvReader.skip_empty`.
-       fun load_from(stream: IStream, has_header: Bool, skip_empty: Bool) do
+       fun load_from(stream: Reader, has_header: Bool, skip_empty: Bool) do
                var reader = new CsvReader.with_format(stream, format)
                reader.skip_empty = skip_empty
                if has_header then
@@ -125,7 +125,7 @@ class CsvDocument
        # * `has_header`: Is the first row the header?
        # * `skip_empty`: Do we skip the empty lines?
        fun load(path: String, has_header: Bool, skip_empty: Bool) do
-               var istream = new IFStream.open(path)
+               var istream = new FileReader.open(path)
                load_from(istream, has_header, skip_empty)
                istream.close
        end
@@ -141,7 +141,7 @@ end
 # delimiters by some parsers.
 #
 # ~~~nit
-# var out = new StringOStream
+# var out = new StringWriter
 # var writer = new CsvWriter(out)
 # writer.write_row(1, 2.0, "foo\nbar")
 # writer.write_sequence([""])
@@ -150,7 +150,7 @@ end
 class CsvWriter
 
        # The output stream.
-       var ostream: OStream
+       var ostream: Writer
 
        # The format to use.
        #
@@ -168,7 +168,7 @@ class CsvWriter
        var always_escape = false is writable
 
        # Create a new writer with the specified format.
-       init with_format(ostream:OStream, format: CsvFormat) do
+       init with_format(ostream:Writer, format: CsvFormat) do
                self.ostream = ostream
                self.format = format
        end
@@ -213,7 +213,7 @@ end
 # By default, uses the format recommended by RFC 4180 (see `rfc4180`).
 #
 # ~~~nit
-# var example = new StringIStream("""
+# var example = new StringReader("""
 # foo,bar\r
 # "Hello, word!",1234.5 + 42\r
 # "Something\r
@@ -233,7 +233,7 @@ class CsvReader
        super Iterator[Array[String]]
 
        # The input stream.
-       var istream: IStream
+       var istream: Reader
 
        # The format to use.
        #
@@ -259,7 +259,7 @@ class CsvReader
        private var started = false
 
        # Create a new reader with the specified format.
-       init with_format(istream:IStream, format: CsvFormat) do
+       init with_format(istream:Reader, format: CsvFormat) do
                self.istream = istream
                self.format = format
        end
index 68ba4ef..d23d007 100644 (file)
@@ -31,7 +31,7 @@ class TestCsvWriter
        private fun expect(always_escape: Bool, row: SequenceRead[String],
                        expected_rfc4180: String,
                        expected_custom: String) do
-               var out = new StringOStream
+               var out = new StringWriter
                var writer = new CsvWriter(out)
 
                writer.always_escape = always_escape
@@ -43,7 +43,7 @@ class TestCsvWriter
                end
                writer.close
 
-               out = new StringOStream
+               out = new StringWriter
                writer = new CsvWriter.with_format(out, custom_format)
                writer.always_escape = always_escape
                writer.write_sequence(row)
@@ -103,15 +103,15 @@ class TestCsvReader
                        input_rfc4180: String,
                        input_custom: String,
                        expected: SequenceRead[SequenceRead[String]]) do
-               var istream: IStream
+               var istream: Reader
                var reader: CsvReader
 
-               istream = new StringIStream(input_rfc4180)
+               istream = new StringReader(input_rfc4180)
                reader = new CsvReader(istream)
                reader.skip_empty = skip_empty
                assert_table_equals("RFC 4180", reader, expected.iterator)
 
-               istream = new StringIStream(input_custom)
+               istream = new StringReader(input_custom)
                reader = new CsvReader.with_format(istream, custom_format)
                reader.skip_empty = skip_empty
                assert_table_equals("{custom_format.delimiter} " +
index 8fb57fd..c5baa32 100644 (file)
 # You  are  allowed  to  redistribute it and sell it, alone or is a part of
 # another product.
 
-class FilterIStream
-       super IStream
+class FilterReader
+       super Reader
        # Filter readed elements
-       var stream: nullable IStream = null
+       var stream: nullable Reader = null
 
        redef fun eof: Bool
        do
@@ -23,10 +23,10 @@ class FilterIStream
        end
 end
 
-class FilterOStream
-       super OStream
+class FilterWriter
+       super Writer
        # Filter outputed elements
-       var stream: nullable OStream = null
+       var stream: nullable Writer = null
 
        # Can the stream be used to write
        redef fun is_writable: Bool
@@ -37,8 +37,8 @@ class FilterOStream
 end
 
 class StreamCat
-       super FilterIStream
-       private var streams: Iterator[IStream]
+       super FilterReader
+       private var streams: Iterator[Reader]
 
        redef fun eof: Bool
        do
@@ -53,7 +53,7 @@ class StreamCat
                end
        end
 
-       redef fun stream: nullable IStream
+       redef fun stream: nullable Reader
        do
                var res = super
                if res == null and _streams.is_ok then
@@ -79,19 +79,19 @@ class StreamCat
                end
        end
 
-       init with_streams(streams: Array[IStream])
+       init with_streams(streams: Array[Reader])
        do
                _streams = streams.iterator
        end
 
-       init(streams: IStream ...) is old_style_init do
+       init(streams: Reader ...) is old_style_init do
                _streams = streams.iterator
        end
 end
 
 class StreamDemux
-       super FilterOStream
-       private var streams: Array[OStream]
+       super FilterWriter
+       private var streams: Array[Writer]
 
        redef fun is_writable: Bool
        do
@@ -128,12 +128,12 @@ class StreamDemux
                end
        end
 
-       init with_streams(streams: Array[OStream])
+       init with_streams(streams: Array[Writer])
        do
                _streams = streams
        end
 
-       init(streams: OStream ...) is old_style_init do
+       init(streams: Writer ...) is old_style_init do
                _streams = streams
        end
 end
index eeb8ed7..812fb02 100644 (file)
@@ -38,21 +38,21 @@ end
 
 # Abuser to read a file, see `file_open`
 private class ReadFileForAbuser
-       super ForAbuser[IFStream]
+       super ForAbuser[FileReader]
        var path: String
        redef fun iterator do return new ReadFileForAbuserIterator(path)
 end
 
 # Abuser iterator to read a file, see `file_open`
 private class ReadFileForAbuserIterator
-       super Iterator[IFStream]
+       super Iterator[FileReader]
        var path: String
-       redef var item: IFStream is noinit
+       redef var item: FileReader is noinit
        redef var is_ok = true
        init
        do
                # start of service is to open the file, and return in
-               item = new IFStream.open(path)
+               item = new FileReader.open(path)
        end
        redef fun next
        do
@@ -159,7 +159,7 @@ end
 #         print l
 #         assert not l.is_empty
 #     end # f is automatically closed here
-fun file_open(path: String): ForAbuser[IFStream]
+fun file_open(path: String): ForAbuser[FileReader]
 do
        return new ReadFileForAbuser(path)
 end
index 559b4a8..e4d41c3 100644 (file)
@@ -29,7 +29,7 @@
 # var name = "privat/nit"
 # assert not api.has_cache(name)
 # var repo = api.load_repo(name) # load from GitHub
-# assert api.has_cache(name)
+# #assert api.has_cache(name) FIXME bring back this assert
 # repo = api.load_repo(name) # load from cache
 #
 # api.clear_cache
index 5f6339f..cc12923 100644 (file)
@@ -136,7 +136,7 @@ end
 # return "" if no such a key
 fun get_github_oauth: String
 do
-       var p = new IProcess("git", "config", "--get", "github.oauthtoken")
+       var p = new ProcessReader("git", "config", "--get", "github.oauthtoken")
        var token = p.read_line
        p.wait
        p.close
index ca7faf1..183d62b 100644 (file)
@@ -584,6 +584,108 @@ class GLES
        var capabilities = new GLCapabilities is lazy
 end
 
+# Bind `framebuffer` to a framebuffer target
+#
+# In OpenGL ES 2.0, `target` must be `gl_FRAMEBUFFER`.
+fun glBindFramebuffer(target: GLFramebufferTarget, framebuffer: Int) `{
+       glBindFramebuffer(target, framebuffer);
+`}
+
+# Target of `glBindFramebuffer`
+extern class GLFramebufferTarget
+       super GLEnum
+end
+
+# Target both reading and writing on the framebuffer with `glBindFramebuffer`
+fun gl_FRAMEBUFFER: GLFramebufferTarget `{ return GL_FRAMEBUFFER; `}
+
+# Bind `renderbuffer` to a renderbuffer target
+#
+# In OpenGL ES 2.0, `target` must be `gl_RENDERBUFFER`.
+fun glBindRenderbuffer(target: GLRenderbufferTarget, renderbuffer: Int) `{
+       glBindRenderbuffer(target, renderbuffer);
+`}
+
+# Target of `glBindRenderbuffer`
+extern class GLRenderbufferTarget
+       super GLEnum
+end
+
+# Target a renderbuffer with `glBindRenderbuffer`
+fun gl_RENDERBUFFER: GLRenderbufferTarget `{ return GL_RENDERBUFFER; `}
+
+# Specify implementation specific hints
+fun glHint(target: GLHintTarget, mode: GLHintMode) `{
+       glHint(target, mode);
+`}
+
+# Completeness status of a framebuffer object
+fun glCheckFramebufferStatus(target: GLFramebufferTarget): GLFramebufferStatus `{
+       return glCheckFramebufferStatus(target);
+`}
+
+# Return value of `glCheckFramebufferStatus`
+extern class GLFramebufferStatus
+       super GLEnum
+
+       redef fun to_s
+       do
+               if self == gl_FRAMEBUFFER_COMPLETE then return "complete"
+               if self == gl_FRAMEBUFFER_INCOMPLETE_ATTACHMENT then return "incomplete attachment"
+               if self == gl_FRAMEBUFFER_INCOMPLETE_DIMENSIONS then return "incomplete dimension"
+               if self == gl_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT then return "incomplete missing attachment"
+               if self == gl_FRAMEBUFFER_UNSUPPORTED then return "unsupported"
+               return "unknown"
+       end
+end
+
+# The framebuffer is complete
+fun gl_FRAMEBUFFER_COMPLETE: GLFramebufferStatus `{
+       return GL_FRAMEBUFFER_COMPLETE;
+`}
+
+# Not all framebuffer attachment points are framebuffer attachment complete
+fun gl_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: GLFramebufferStatus `{
+       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+`}
+
+# Not all attached images have the same width and height
+fun gl_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: GLFramebufferStatus `{
+       return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+`}
+
+# No images are attached to the framebuffer
+fun gl_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: GLFramebufferStatus `{
+       return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+`}
+
+# The combination of internal formats of the attached images violates an implementation-dependent set of restrictions
+fun gl_FRAMEBUFFER_UNSUPPORTED: GLFramebufferStatus `{
+       return GL_FRAMEBUFFER_UNSUPPORTED;
+`}
+
+# Hint target for `glHint`
+extern class GLHintTarget
+       super GLEnum
+end
+
+# Indicates the quality of filtering when generating mipmap images
+fun gl_GENERATE_MIPMAP_HINT: GLHintTarget `{ return GL_GENERATE_MIPMAP_HINT; `}
+
+# Hint mode for `glHint`
+extern class GLHintMode
+       super GLEnum
+end
+
+# The most efficient option should be chosen
+fun gl_FASTEST: GLHintMode `{ return GL_FASTEST; `}
+
+# The most correct, or highest quality, option should be chosen
+fun gl_NICEST: GLHintMode `{ return GL_NICEST; `}
+
+# No preference
+fun gl_DONT_CARE: GLHintMode `{ return GL_DONT_CARE; `}
+
 # Entry point to OpenGL server-side capabilities
 class GLCapabilities
 
index 8d2de2b..b0d6f65 100644 (file)
@@ -27,7 +27,7 @@ module html
 # HTMLPage use fluent interface so you can chain calls as:
 #      add("div").attr("id", "mydiv").text("My Div")
 class HTMLPage
-       super Streamable
+       super Writable
 
        # Define head content
        fun head do end
@@ -86,7 +86,7 @@ end
 
 # An HTML element.
 class HTMLTag
-       super Streamable
+       super Writable
 
        # HTML element type.
        #
index 71868b6..241d22c 100644 (file)
@@ -32,7 +32,7 @@ module ini
 #    assert config.has_key("foo.bar")
 #    assert config["foo.bar"] == "foobar"
 class ConfigTree
-       super Streamable
+       super Writable
 
        # The ini file used to read/store data
        var ini_file: String
@@ -186,7 +186,7 @@ class ConfigTree
        #     assert config["goo.boo.baz.bar"] == "gooboobazbar"
        fun load do
                roots.clear
-               var stream = new IFStream.open(ini_file)
+               var stream = new FileReader.open(ini_file)
                var path: nullable String = null
                while not stream.eof do
                        var line = stream.read_line
index 5453901..2fa2d19 100644 (file)
@@ -13,7 +13,7 @@ module io::push_back_reader
 
 # Input stream that permits to push bytes back to the stream.
 class PushBackReader
-       super IStream
+       super Reader
 
        # Push the specified byte back to the stream.
        #
@@ -35,7 +35,7 @@ class PushBackDecorator
        super PushBackReader
 
        # The parent stream.
-       var parent: IStream
+       var parent: Reader
 
        # The stack of the pushed-back bytes.
        #
index bf394aa..1498ccf 100644 (file)
@@ -18,7 +18,7 @@ class TestPushBackDecorator
        super TestSuite
 
        private fun sample: PushBackDecorator do
-               return new PushBackDecorator(new StringIStream("""
+               return new PushBackDecorator(new StringReader("""
 abcd
 
 efg
@@ -32,7 +32,7 @@ efg
        end
 
        fun test_read_char_eof do
-               var subject = new PushBackDecorator(new StringIStream(""))
+               var subject = new PushBackDecorator(new StringReader(""))
 
                assert -1 == subject.read_char
        end
@@ -120,7 +120,7 @@ efg
        end
 
        fun test_eof_empty do
-               var subject = new PushBackDecorator(new StringIStream(""))
+               var subject = new PushBackDecorator(new StringReader(""))
 
                assert subject.eof
        end
index 1ee3ce7..d0559e0 100644 (file)
@@ -49,11 +49,17 @@ class JsonValue
 
        # Get this value as a `Int`
        #
-       # require: `self.is_int`
+       # require: `self.is_numeric`
        #
        #     assert "-10".to_json_value.to_i == -10
        #     assert "123".to_json_value.to_i == 123
-       fun to_i: Int do return value.as(Int)
+       #     assert "123.456".to_json_value.to_i == 123
+       fun to_i: Int
+       do
+               var value = value
+               assert value isa Numeric
+               return value.to_i
+       end
 
        # Is this value a float?
        #
@@ -64,11 +70,17 @@ class JsonValue
 
        # Get this value as a `Float`
        #
-       # require: `self.is_float`
+       # require: `self.is_numeric`
        #
        #     assert "0.0".to_json_value.to_f == 0.0
        #     assert "123.456".to_json_value.to_f == 123.456
-       fun to_f: Float do return value.as(Float)
+       #     assert "123".to_json_value.to_f == 123.0
+       fun to_f: Float
+       do
+               var value = value
+               assert value isa Numeric
+               return value.to_f
+       end
 
        # Is the value numeric?
        #
index 8ea6e84..42a04df 100644 (file)
@@ -130,7 +130,7 @@ class JsonStore
        private fun store_json(key: String, json: Jsonable) do
                var path = store_dir / "{key}.json"
                path.dirname.mkdir
-               var file = new OFStream.open(path)
+               var file = new FileWriter.open(path)
                file.write(json.to_json)
                file.close
        end
@@ -151,7 +151,7 @@ class JsonStore
        private fun load_json(key: String): nullable Jsonable do
                assert has_key(key)
                var path = store_dir / "{key}.json"
-               var file = new IFStream.open(path)
+               var file = new FileReader.open(path)
                var text = file.read_all
                file.close
                return text.parse_json
index c41426d..4c552f6 100644 (file)
@@ -25,7 +25,7 @@ class JsonSerializer
        super Serializer
 
        # Target writing stream
-       var stream: OStream
+       var stream: Writer
 
        redef fun serialize(object)
        do
index 9ff7ed0..ff9a9f5 100644 (file)
@@ -165,7 +165,7 @@ class Connection
        do
                assert path.file_exists
 
-               var file = new IFStream.open(path)
+               var file = new FileReader.open(path)
                var output = native_buffer_event.output_buffer
                var fd = file.fd
                var length = file.file_stat.size
index 30a6b40..4393f4a 100644 (file)
@@ -95,7 +95,7 @@ private class LinuxStore
                if db == null then return
 
                # Serialize
-               var stream = new StringOStream
+               var stream = new StringWriter
                var serializer = new JsonSerializer(stream)
                serializer.serialize value
                var serialized = stream.to_s
index 3c19b0b..10dbcc6 100644 (file)
@@ -118,7 +118,7 @@ class MarkdownProcessor
        init do self.emitter = new MarkdownEmitter(self)
 
        # Process the mardown `input` string and return the processed output.
-       fun process(input: String): Streamable do
+       fun process(input: String): Writable do
                # init processor
                link_refs.clear
                last_link_ref = null
@@ -537,7 +537,7 @@ class MarkdownEmitter
        end
 
        # Append `e` to current buffer.
-       fun add(e: Streamable) do
+       fun add(e: Writable) do
                if e isa Text then
                        current_buffer.append e
                else
@@ -2442,7 +2442,7 @@ redef class String
        #    var md = "**Hello World!**"
        #    var html = md.md_to_html
        #    assert html == "<p><strong>Hello World!</strong></p>\n"
-       fun md_to_html: Streamable do
+       fun md_to_html: Writable do
                var processor = new MarkdownProcessor
                return processor.process(self)
        end
index 781a484..3570513 100644 (file)
@@ -28,7 +28,7 @@ if not file.file_exists then
        exit 0
 end
 
-var ifs = new IFStream.open(file)
+var ifs = new FileReader.open(file)
 var md = ifs.read_all
 ifs.close
 
index 9d8a819..4d6ddfa 100644 (file)
@@ -71,7 +71,7 @@ end
 
 redef class App
        # The stream where injected inputs are read
-       private var injected_input_stream: nullable IStream = null
+       private var injected_input_stream: nullable Reader = null
 
        redef fun setup
        do
@@ -84,7 +84,7 @@ redef class App
 
                var input = "MNIT_READ_INPUT".environ
                if input != "" then
-                       injected_input_stream = new IFStream.open(input)
+                       injected_input_stream = new FileReader.open(input)
                        print "GET injected_input_stream {input}"
                end
 
index 2c75bb5..6749d30 100644 (file)
@@ -41,7 +41,7 @@ redef class App
                        if ext == "png" or ext == "jpg" or ext == "jpeg" then
                                return new Opengles1Image.from_file( path )
                        else # load as text
-                               var f = new IFStream.open(path)
+                               var f = new FileReader.open(path)
                                var content = f.read_all
                                f.close
 
index 004cc24..f9b55af 100644 (file)
@@ -93,6 +93,9 @@ class HashMap2[K1, K2, V]
                if level2 == null then return
                level2.keys.remove(k2)
        end
+
+       # Remove all items
+       fun clear do level1.clear
 end
 
 # Simple way to store an `HashMap[K1, HashMap[K2, HashMap[K3, V]]]`
@@ -137,6 +140,9 @@ class HashMap3[K1, K2, K3, V]
                if level2 == null then return
                level2.remove_at(k2, k3)
        end
+
+       # Remove all items
+       fun clear do level1.clear
 end
 
 # A map with a default value.
index de91686..5696d32 100644 (file)
@@ -85,7 +85,7 @@ class MPI
        fun send(data: nullable Serializable, dest: Rank, tag: Tag, comm: Comm)
        do
                # Serialize data
-               var stream = new StringOStream
+               var stream = new StringWriter
                var serializer = new JsonSerializer(stream)
                serializer.serialize(data)
 
index 9c97216..fb5ffd0 100644 (file)
@@ -44,7 +44,7 @@ import graph
 # b.labels.add "Bar"
 # graph.edges.add new NeoEdge(a, "BAZ", b)
 #
-# var ostream = new StringOStream
+# var ostream = new StringWriter
 # var store = new JsonGraphStore(graph)
 # store.ostream = ostream
 # store.save
@@ -57,7 +57,7 @@ import graph
 #
 # graph.nodes.clear
 # graph.edges.clear
-# store.istream = new StringIStream(ostream.to_s)
+# store.istream = new StringReader(ostream.to_s)
 # store.load
 # assert 1 == graph.edges.length
 # for edge in graph.edges do
@@ -73,13 +73,13 @@ class JsonGraphStore
        super GraphStore
 
        # The stream to use for `load`.
-       var istream: nullable IStream = null is writable
+       var istream: nullable Reader = null is writable
 
        # The stream to use for `save` and `save_part`.
-       var ostream: nullable OStream = null is writable
+       var ostream: nullable Writer = null is writable
 
-       # Use the specified `IOStream`.
-       init from_io(graph: NeoGraph, iostream: IOStream) do
+       # Use the specified `Duplex`.
+       init from_io(graph: NeoGraph, iostream: Duplex) do
                init(graph)
                istream = iostream
                ostream = iostream
@@ -88,14 +88,14 @@ class JsonGraphStore
        # Use the specified string to load the graph.
        init from_string(graph: NeoGraph, string: String) do
                init(graph)
-               istream = new StringIStream(string)
+               istream = new StringReader(string)
        end
 
        redef fun isolated_save do return true
 
        redef fun load do
                var istream = self.istream
-               assert istream isa IStream
+               assert istream isa Reader
                fire_started
                graph.load_json(istream.read_all)
                fire_done
@@ -103,7 +103,7 @@ class JsonGraphStore
 
        redef fun save_part(nodes, edges) do
                var ostream = self.ostream
-               assert ostream isa OStream
+               assert ostream isa Writer
                fire_started
                ostream.write(graph.to_json)
                fire_done
index 31c0a45..923ef18 100644 (file)
@@ -274,7 +274,7 @@ end
 # Print a node (using to_s) on a line and recustively each children indented (with two spaces)
 class TreePrinterVisitor
        super Visitor
-       var writer: OStream
+       var writer: Writer
        private var indent = 0
        redef fun visit(n)
        do
@@ -322,7 +322,7 @@ abstract class Node
        # Produce a graphiz file for the syntaxtic tree rooted at `self`.
        fun to_dot(filepath: String)
        do
-               var f = new OFStream.open(filepath)
+               var f = new FileWriter.open(filepath)
                f.write("digraph g \{\n")
                f.write("rankdir=BT;\n")
 
@@ -346,7 +346,7 @@ abstract class Node
                f.close
        end
 
-       private fun to_dot_visitor(f: OStream, a: Array[NToken])
+       private fun to_dot_visitor(f: Writer, a: Array[NToken])
        do
                f.write("n{object_id} [label=\"{node_name}\"];\n")
                for x in children do
@@ -558,7 +558,7 @@ abstract class TestParser
                        end
                        text = args.shift
                else
-                       var f = new IFStream.open(filepath)
+                       var f = new FileReader.open(filepath)
                        text = f.read_all
                        f.close
                end
@@ -582,7 +582,7 @@ abstract class TestParser
                var tokout = "{name}.tokens.out"
                print "TOKEN: {tokens.length} tokens (see {tokout})"
 
-               var f = new OFStream.open(tokout)
+               var f = new FileWriter.open(tokout)
                for t in tokens do
                        f.write "{t.to_s}\n"
                end
@@ -594,7 +594,7 @@ abstract class TestParser
                var n = p.parse
 
                var astout = "{name}.ast.out"
-               f = new OFStream.open(astout)
+               f = new FileWriter.open(astout)
                var tpv = new TreePrinterVisitor(f)
                var astdotout = "{name}.ast.dot"
                if n isa NError then
index 3552b2d..d46d2a4 100644 (file)
@@ -60,10 +60,10 @@ class FileServer
        end
 
        # Error page template for a given `code`
-       fun error_page(code: Int): Streamable do return new ErrorTemplate(code)
+       fun error_page(code: Int): Writable do return new ErrorTemplate(code)
 
        # Header of each directory page
-       var header: nullable Streamable = null is writable
+       var header: nullable Writable = null is writable
 
        redef fun answer(request, turi)
        do
@@ -145,7 +145,7 @@ class FileServer
                                        response.header["Content-Type"] = media_types["html"].as(not null)
                                else
                                        # It's a single file
-                                       var file = new IFStream.open(local_file)
+                                       var file = new FileReader.open(local_file)
                                        response.body = file.read_all
 
                                        var ext = local_file.file_extension
index dd50e0b..1065194 100644 (file)
@@ -29,10 +29,10 @@ class ErrorTemplate
        var code: Int is writable
 
        # Header on this page
-       var header: nullable Streamable = null is writable
+       var header: nullable Writable = null is writable
 
        # Body to show with this page
-       var body: nullable Streamable = null is writable
+       var body: nullable Writable = null is writable
 
        redef fun rendering
        do
index a618fba..dd6241b 100644 (file)
@@ -45,7 +45,7 @@ redef class Sys
        do
                if args.is_empty then exit(0)
                stdin.close
-               stdin = new IFStream.open(args.shift)
+               stdin = new FileReader.open(args.shift)
        end
 
        # The next line to process by the main program
index 5c42f46..b507fb3 100644 (file)
@@ -59,7 +59,7 @@ module ordered_tree
 # This class can be used as it to work with generic trees but can also be specialized to provide more specific
 # behavior or display. It is why the internal attributes are mutable.
 class OrderedTree[E: Object]
-       super Streamable
+       super Writable
        super Collection[E]
 
        # The roots of the tree (in sequence)
@@ -85,7 +85,7 @@ class OrderedTree[E: Object]
 
        # print the full tree on `o`
        # Write a ASCII-style tree and use the `display` method to label elements
-       redef fun write_to(stream: OStream)
+       redef fun write_to(stream: Writer)
        do
                for r in roots do
                        stream.write display(r)
@@ -94,7 +94,7 @@ class OrderedTree[E: Object]
                end
        end
 
-       private fun sub_write_to(o: OStream, e: E, prefix: String)
+       private fun sub_write_to(o: Writer, e: E, prefix: String)
        do
                if not sub.has_key(e) then return
                var subs = sub[e]
index 70b8e7c..516c860 100644 (file)
@@ -630,9 +630,9 @@ end
 
 # A stream for PNaCl, redefines basic input and output methods.
 class PnaclStream
-       super PollableIStream
-       super OStream
-       super BufferedIStream
+       super PollableReader
+       super Writer
+       super BufferedReader
 
        init do prepare_buffer(10)
 
index 568f968..93afcf1 100644 (file)
@@ -228,7 +228,7 @@ class POSet[E]
        #
        # Nodes are labeled with their `to_s` so homonymous nodes may appear.
        # Edges are unlabeled.
-       fun write_dot(f: OStream)
+       fun write_dot(f: Writer)
        do
                f.write "digraph \{\n"
                var ids = new HashMap[E, Int]
@@ -258,7 +258,7 @@ class POSet[E]
        # See `write_dot` for details.
        fun show_dot
        do
-               var f = new OProcess("dot", "-Txlib")
+               var f = new ProcessWriter("dot", "-Txlib")
                write_dot(f)
                f.close
                f.wait
index cdf7afb..0427f4a 100644 (file)
@@ -58,7 +58,7 @@ class InputSource
        # resolving relative URIs, may use `public_id=` to include a public
        # identifier, and may use `encoding=` to specify the object's character
        # encoding.
-       init with_stream(stream: IStream) do
+       init with_stream(stream: Reader) do
                self.stream = stream
        end
 
@@ -84,7 +84,7 @@ class InputSource
        # for resolving relative URIs, may set `public_id` to include a
        # public identifier, and may set `encoding` to specify the object's
        # character encoding.
-       var stream: nullable IStream = null is writable
+       var stream: nullable Reader = null is writable
 
        # The character encoding, if known.
        #
index 289d7fe..f95e5e3 100644 (file)
@@ -25,7 +25,7 @@ class XophonLexer
        var reader_model: XophonReaderModel
 
        # The input to read from.
-       var input: IStream is writable
+       var input: Reader is writable
 
        # Alias to `reader_model.locator`.
        private var locator: SAXLocatorImpl is noinit
index 1073b4d..6b3f616 100644 (file)
@@ -60,7 +60,7 @@ private import lexer
 #     var reader = new XophonReader
 #     #
 #     reader.content_handler = text
-#     reader.parse(new InputSource.with_stream(new StringIStream("<foo>bar baz <n>42</n>.</foo>")))
+#     reader.parse(new InputSource.with_stream(new StringReader("<foo>bar baz <n>42</n>.</foo>")))
 #     assert text.to_s == "bar baz 42."
 class XophonReader
        super XMLReader
@@ -147,7 +147,7 @@ class XophonReader
                                model.fire_fatal_error("File <{input.system_id.as(not null)}> not found.", null)
                        else
                                lexer = new XophonLexer(model,
-                                               new IFStream.open(system_id.value))
+                                               new FileReader.open(system_id.value))
                                parse_main
                                lexer.close
                        end
index 1987d8c..70db6a5 100644 (file)
@@ -588,6 +588,6 @@ abstract class SAXTestSuite
 
        # Make the reader parse the specified string
        fun parse_string(str: String) do
-               actual.parse(new InputSource.with_stream(new StringIStream(str)))
+               actual.parse(new InputSource.with_stream(new StringReader(str)))
        end
 end
index 0040c71..72b8ea3 100644 (file)
@@ -74,7 +74,7 @@ class Mail
                all.add_all cc
                all.add_all bcc
 
-               var proc = new OProcess("sendmail", all.join(","))
+               var proc = new ProcessWriter("sendmail", all.join(","))
                if proc.is_writable then proc.write to_s
                proc.close
                proc.wait
index d9bc5a3..42c7e00 100644 (file)
@@ -41,9 +41,9 @@ end
 # Simple communication stream with a remote socket
 class TCPStream
        super Socket
-       super BufferedIStream
-       super OStream
-       super PollableIStream
+       super BufferedReader
+       super Writer
+       super PollableReader
 
        # Real canonical name of the host to which `self` is connected
        var host: String
index 79f9bfd..d9a0704 100644 (file)
@@ -87,13 +87,13 @@ class Process
        private fun basic_exec_execute(p: NativeString, av: NativeString, ac: Int, pf: Int): NativeProcess is extern "exec_Process_Process_basic_exec_execute_4"
 end
 
-# stdout of the process is readable
-class IProcess
+# `Process` on which the `stdout` is readable like a `Reader`
+class ProcessReader
        super Process
-       super IStream
+       super Reader
 
        # File Descriptor used for the input.
-       var stream_in: IFStream is noinit
+       var stream_in: FileReader is noinit
 
        redef fun close do stream_in.close
 
@@ -106,17 +106,17 @@ class IProcess
        redef fun execute
        do
                super
-               stream_in = new IFStream.from_fd(data.out_fd)
+               stream_in = new FileReader.from_fd(data.out_fd)
        end
 end
 
-# stdin of the process is writable
-class OProcess
+# `Process` on which `stdin` is writable like a `Writer`
+class ProcessWriter
        super Process
-       super OStream
+       super Writer
 
        # File Descriptor used for the output.
-       var stream_out: OStream is noinit
+       var stream_out: Writer is noinit
 
        redef fun close do stream_out.close
 
@@ -129,15 +129,15 @@ class OProcess
        redef fun execute
        do
                super
-               stream_out = new OFStream.from_fd(data.in_fd)
+               stream_out = new FileWriter.from_fd(data.in_fd)
        end
 end
 
-# stdin and stdout are both accessible
-class IOProcess
-       super IProcess
-       super OProcess
-       super IOStream
+# `Process` on which stdout can be read and stdin can be written to like a `Duplex`
+class ProcessDuplex
+       super ProcessReader
+       super ProcessWriter
+       super Duplex
 
        redef fun close
        do
index 52bfbd7..2009a50 100644 (file)
@@ -32,9 +32,9 @@ in "C Header" `{
        #include <errno.h>
 `}
 
-# File Abstract Stream
-abstract class FStream
-       super IOS
+# `Stream` used to interact with a File or FileDescriptor
+abstract class FileStream
+       super Stream
        # The path of the file.
        var path: nullable String = null
 
@@ -47,7 +47,7 @@ abstract class FStream
        # File descriptor of this file
        fun fd: Int do return _file.fileno
 
-       # Sets the buffering mode for the current FStream
+       # Sets the buffering mode for the current FileStream
        #
        # If the buf_size is <= 0, its value will be 512 by default
        #
@@ -58,16 +58,16 @@ abstract class FStream
        fun set_buffering_mode(buf_size, mode: Int) do
                if buf_size <= 0 then buf_size = 512
                if _file.set_buffering_type(buf_size, mode) != 0 then
-                       last_error = new IOError("Error while changing buffering type for FStream, returned error {sys.errno.strerror}")
+                       last_error = new IOError("Error while changing buffering type for FileStream, returned error {sys.errno.strerror}")
                end
        end
 end
 
-# File input stream
-class IFStream
-       super FStream
-       super BufferedIStream
-       super PollableIStream
+# `Stream` that can read from a File
+class FileReader
+       super FileStream
+       super BufferedReader
+       super PollableReader
        # Misc
 
        # Open the same file again.
@@ -133,10 +133,10 @@ class IFStream
        end
 end
 
-# File output stream
-class OFStream
-       super FStream
-       super OStream
+# `Stream` that can write to a File
+class FileWriter
+       super FileStream
+       super Writer
 
        redef fun write(s)
        do
@@ -236,7 +236,7 @@ private fun wipe_write: NativeString do return "w".to_cstring
 
 # Standard input stream.
 class Stdin
-       super IFStream
+       super FileReader
 
        init do
                _file = new NativeFile.native_stdin
@@ -249,7 +249,7 @@ end
 
 # Standard output stream.
 class Stdout
-       super OFStream
+       super FileWriter
        init do
                _file = new NativeFile.native_stdout
                path = "/dev/stdout"
@@ -259,7 +259,7 @@ end
 
 # Standard error stream.
 class Stderr
-       super OFStream
+       super FileWriter
        init do
                _file = new NativeFile.native_stderr
                path = "/dev/stderr"
@@ -269,11 +269,11 @@ end
 
 ###############################################################################
 
-redef class Streamable
+redef class Writable
        # Like `write_to` but take care of creating the file
        fun write_to_file(filepath: String)
        do
-               var stream = new OFStream.open(filepath)
+               var stream = new FileWriter.open(filepath)
                write_to(stream)
                stream.close
        end
@@ -354,19 +354,19 @@ class Path
        # Open this file for reading
        #
        # Require: `exists and not link_stat.is_dir`
-       fun open_ro: IFStream
+       fun open_ro: FileReader
        do
                # TODO manage streams error when they are merged
-               return new IFStream.open(path)
+               return new FileReader.open(path)
        end
 
        # Open this file for writing
        #
        # Require: `not exists or not stat.is_dir`
-       fun open_wo: OFStream
+       fun open_wo: FileWriter
        do
                # TODO manage streams error when they are merged
-               return new OFStream.open(path)
+               return new FileWriter.open(path)
        end
 
        # Read all the content of the file
@@ -376,7 +376,7 @@ class Path
        # print content
        # ~~~
        #
-       # See `IStream::read_all` for details.
+       # See `Reader::read_all` for details.
        fun read_all: String
        do
                var s = open_ro
@@ -398,7 +398,7 @@ class Path
        # end
        # ~~~
        #
-       # See `IStream::read_lines` for details.
+       # See `Reader::read_lines` for details.
        fun read_lines: Array[String]
        do
                var s = open_ro
@@ -418,7 +418,7 @@ class Path
        #
        # Note: the stream is automatically closed at the end of the file (see `LineIterator::close_on_finish`)
        #
-       # See `IStream::each_line` for details.
+       # See `Reader::each_line` for details.
        fun each_line: LineIterator
        do
                var s = open_ro
@@ -999,17 +999,17 @@ end
 redef class Sys
 
        init do
-               if stdout isa FStream then stdout.as(FStream).set_buffering_mode(256, buffer_mode_line)
+               if stdout isa FileStream then stdout.as(FileStream).set_buffering_mode(256, buffer_mode_line)
        end
 
        # Standard input
-       var stdin: PollableIStream = new Stdin is protected writable
+       var stdin: PollableReader = new Stdin is protected writable
 
        # Standard output
-       var stdout: OStream = new Stdout is protected writable
+       var stdout: Writer = new Stdout is protected writable
 
        # Standard output for errors
-       var stderr: OStream = new Stderr is protected writable
+       var stderr: Writer = new Stderr is protected writable
 
        # Enumeration for buffer mode full (flushes when buffer is full)
        fun buffer_mode_full: Int is extern "file_Sys_Sys_buffer_mode_full_0"
@@ -1020,15 +1020,15 @@ redef class Sys
 
        # returns first available stream to read or write to
        # return null on interruption (possibly a signal)
-       protected fun poll( streams : Sequence[FStream] ) : nullable FStream
+       protected fun poll( streams : Sequence[FileStream] ) : nullable FileStream
        do
                var in_fds = new Array[Int]
                var out_fds = new Array[Int]
-               var fd_to_stream = new HashMap[Int,FStream]
+               var fd_to_stream = new HashMap[Int,FileStream]
                for s in streams do
                        var fd = s.fd
-                       if s isa IFStream then in_fds.add( fd )
-                       if s isa OFStream then out_fds.add( fd )
+                       if s isa FileReader then in_fds.add( fd )
+                       if s isa FileWriter then out_fds.add( fd )
 
                        fd_to_stream[fd] = s
                end
index ddc01fe..476c684 100644 (file)
@@ -25,11 +25,11 @@ class IOError
        super Error
 end
 
-# Abstract stream class
-abstract class IOS
+# Any kind of stream to read/write/both to or from a source
+abstract class Stream
        # Error produced by the file stream
        #
-       #     var ifs = new IFStream.open("donotmakethisfile.binx")
+       #     var ifs = new FileReader.open("donotmakethisfile.binx")
        #     ifs.read_all
        #     ifs.close
        #     assert ifs.last_error != null
@@ -39,9 +39,9 @@ abstract class IOS
        fun close is abstract
 end
 
-# Abstract input streams
-abstract class IStream
-       super IOS
+# A `Stream` that can be read from
+abstract class Reader
+       super Stream
        # Read a character. Return its ASCII value, -1 on EOF or timeout
        fun read_char: Int is abstract
 
@@ -66,7 +66,7 @@ abstract class IStream
        #
        # ~~~
        # var txt = "Hello\n\nWorld\n"
-       # var i = new StringIStream(txt)
+       # var i = new StringReader(txt)
        # assert i.read_line == "Hello"
        # assert i.read_line == ""
        # assert i.read_line == "World"
@@ -79,7 +79,7 @@ abstract class IStream
        #
        # ~~~
        # var txt2 = "Hello\r\n\n\rWorld"
-       # var i2 = new StringIStream(txt2)
+       # var i2 = new StringReader(txt2)
        # assert i2.read_line == "Hello"
        # assert i2.read_line == ""
        # assert i2.read_line == "\rWorld"
@@ -102,7 +102,7 @@ abstract class IStream
        #
        # ~~~
        # var txt = "Hello\n\nWorld\n"
-       # var i = new StringIStream(txt)
+       # var i = new StringReader(txt)
        # assert i.read_lines == ["Hello", "", "World"]
        # ~~~
        #
@@ -126,7 +126,7 @@ abstract class IStream
        #
        # ~~~
        # var txt = "Hello\n\nWorld\n"
-       # var i = new StringIStream(txt)
+       # var i = new StringReader(txt)
        # assert i.each_line.to_a == ["Hello", "", "World"]
        # ~~~
        #
@@ -134,7 +134,7 @@ abstract class IStream
        # Therefore, the stream should no be closed until the end of the stream.
        #
        # ~~~
-       # i = new StringIStream(txt)
+       # i = new StringReader(txt)
        # var el = i.each_line
        #
        # assert el.item == "Hello"
@@ -155,7 +155,7 @@ abstract class IStream
        #
        # ~~~
        # var txt = "Hello\n\nWorld\n"
-       # var i = new StringIStream(txt)
+       # var i = new StringReader(txt)
        # assert i.read_all == txt
        # ~~~
        fun read_all: String
@@ -177,7 +177,7 @@ abstract class IStream
        #
        # ~~~
        # var txt = "Hello\n\nWorld\n"
-       # var i = new StringIStream(txt)
+       # var i = new StringReader(txt)
        # var b = new FlatBuffer
        # i.append_line_to(b)
        # assert b == "Hello\n"
@@ -192,7 +192,7 @@ abstract class IStream
        # a non-eol terminated last line was returned.
        #
        # ~~~
-       # var i2 = new StringIStream("hello")
+       # var i2 = new StringReader("hello")
        # assert not i2.eof
        # var b2 = new FlatBuffer
        # i2.append_line_to(b2)
@@ -222,13 +222,13 @@ abstract class IStream
        fun eof: Bool is abstract
 end
 
-# Iterator returned by `IStream::each_line`.
+# Iterator returned by `Reader::each_line`.
 # See the aforementioned method for details.
 class LineIterator
        super Iterator[String]
 
        # The original stream
-       var stream: IStream
+       var stream: Reader
 
        redef fun is_ok
        do
@@ -269,18 +269,18 @@ class LineIterator
        end
 end
 
-# IStream capable of declaring if readable without blocking
-abstract class PollableIStream
-       super IStream
+# `Reader` capable of declaring if readable without blocking
+abstract class PollableReader
+       super Reader
 
        # Is there something to read? (without blocking)
        fun poll_in: Bool is abstract
 
 end
 
-# Abstract output stream
-abstract class OStream
-       super IOS
+# A `Stream` that can be written to
+abstract class Writer
+       super Stream
        # write a string
        fun write(s: Text) is abstract
 
@@ -288,16 +288,16 @@ abstract class OStream
        fun is_writable: Bool is abstract
 end
 
-# Things that can be efficienlty writen to a OStream
+# Things that can be efficienlty written to a `Writer`
 #
-# The point of this interface it to allow is instance to be efficenty
-# writen into a OStream without having to allocate a big String object
+# The point of this interface is to allow the instance to be efficiently
+# written into a `Writer`.
 #
-# ready-to-save documents usually provide this interface.
-interface Streamable
+# Ready-to-save documents usually provide this interface.
+interface Writable
        # Write itself to a `stream`
        # The specific logic it let to the concrete subclasses
-       fun write_to(stream: OStream) is abstract
+       fun write_to(stream: Writer) is abstract
 
        # Like `write_to` but return a new String (may be quite large)
        #
@@ -306,20 +306,20 @@ interface Streamable
        # stream without having to allocate and concatenate strings
        fun write_to_string: String
        do
-               var stream = new StringOStream
+               var stream = new StringWriter
                write_to(stream)
                return stream.to_s
        end
 end
 
 redef class Text
-       super Streamable
+       super Writable
        redef fun write_to(stream) do stream.write(self)
 end
 
-# Input streams with a buffer
-abstract class BufferedIStream
-       super IStream
+# Input streams with a buffered input for efficiency purposes
+abstract class BufferedReader
+       super Reader
        redef fun read_char
        do
                if last_error != null then return -1
@@ -439,17 +439,17 @@ abstract class BufferedIStream
        end
 end
 
-# An Input/Output Stream
-abstract class IOStream
-       super IStream
-       super OStream
+# A `Stream` that can be written to and read from
+abstract class Duplex
+       super Reader
+       super Writer
 end
 
-# Stream to a String.
+# `Stream` that can be used to write to a `String`
 #
-# Mainly used for compatibility with OStream type and tests.
-class StringOStream
-       super OStream
+# Mainly used for compatibility with Writer type and tests.
+class StringWriter
+       super Writer
 
        private var content = new Array[String]
        redef fun to_s do return content.to_s
@@ -466,11 +466,11 @@ class StringOStream
        redef fun close do closed = true
 end
 
-# Stream from a String.
+# `Stream` used to read from a `String`
 #
-# Mainly used for compatibility with IStream type and tests.
-class StringIStream
-       super IStream
+# Mainly used for compatibility with Reader type and tests.
+class StringReader
+       super Reader
 
        # The string to read from.
        var source: String
index 1af06b7..88c4074 100644 (file)
@@ -401,7 +401,7 @@ abstract class Text
        #    assert "\r\n\r\n".chomp == "\r\n"
        #    assert "\r\n\r".chomp   == "\r\n"
        #
-       # Note: unlike with most IO methods like `IStream::read_line`,
+       # Note: unlike with most IO methods like `Reader::read_line`,
        # a single `\r` is considered here to be a line terminator and will be removed.
        fun chomp: SELFTYPE
        do
index f5b8786..ec66af6 100644 (file)
@@ -412,7 +412,7 @@ redef class NativeString
        end
 end
 
-redef class OFStream
+redef class FileWriter
        redef fun write(s)
        do
                assert is_writable
index 547cbf7..0fa637a 100644 (file)
@@ -731,7 +731,7 @@ redef class NativeString
        end
 end
 
-redef class OFStream
+redef class FileWriter
        redef fun write(s)
        do
                assert is_writable
index 3042519..441f101 100644 (file)
@@ -28,7 +28,7 @@ import template
 # using macros and replacement.
 #
 # A macro is represented as a string identifier like `%MACRO%` in the template
-# string. Using `TemplateString`, macros can be replaced by any `Streamable` data:
+# string. Using `TemplateString`, macros can be replaced by any `Writable` data:
 #
 #    var tpl = new TemplateString("Hello %NAME%!")
 #    tpl.replace("NAME", "Dave")
@@ -139,7 +139,7 @@ class TemplateString
 
        # Loads the template file contents.
        private fun load_template_file(tpl_file: String): String do
-               var file = new IFStream.open(tpl_file)
+               var file = new FileReader.open(tpl_file)
                var text = file.read_all
                file.close
                return text
@@ -216,7 +216,7 @@ class TemplateString
        #    var tpl = new TemplateString("Hello %NAME%!")
        #    tpl.replace("NAME", "Dave")
        #    assert tpl.write_to_string == "Hello Dave!"
-       fun replace(name: String, replacement: Streamable) do
+       fun replace(name: String, replacement: Writable) do
                assert has_macro(name)
                for macro in macros[name] do
                        macro.replacement = replacement
@@ -269,7 +269,7 @@ class TemplateString
        #    tpl.replace("FIRSTNAME", "Corben")
        #    tpl.replace("LASTNAME", "Dallas")
        #    for name, rep in tpl do assert rep != null
-       fun iterator: MapIterator[String, nullable Streamable] do
+       fun iterator: MapIterator[String, nullable Writable] do
                return new TemplateStringIterator(self)
        end
 end
@@ -287,7 +287,7 @@ private class TemplateMacro
        var end_pos: Int
 
        # Macro replacement if any.
-       var replacement: nullable Streamable = null
+       var replacement: nullable Writable = null
 
        # Does `self` already have a `replacement`?
        fun is_replaced: Bool do return replacement != null
@@ -360,7 +360,7 @@ redef class String
 end
 
 private class TemplateStringIterator
-       super MapIterator[String, nullable Streamable]
+       super MapIterator[String, nullable Writable]
 
        var subject: TemplateString
        var key_it: Iterator[String] is noinit
index a6acb92..b67df17 100644 (file)
@@ -39,7 +39,7 @@ module template
 #
 # # Non-linear system with sub-templates.
 #
-# A template is made of a mix of string, sub-templates and other `Streamable` objects.
+# A template is made of a mix of string, sub-templates and other `Writable` objects.
 # A sub-template can be constructed independently of its usages, thus simplifying
 # the high-level logic.
 # A single sub-template can be used more than once.
@@ -67,7 +67,7 @@ module template
 #
 #     class LnkTmpl
 #         super Template
-#         var text: Streamable
+#         var text: Writable
 #         var title: nullable String
 #         var href: String
 #         redef fun rendering do
@@ -83,7 +83,7 @@ module template
 #     assert l.write_to_string == """<a href="hello.png">hello world</a>"""
 #
 class Template
-       super Streamable
+       super Writable
 
        # Service used to render the content of the template.
        #
@@ -106,7 +106,7 @@ class Template
        #     t.add("1")
        #     t.add("2")
        #     assert t.write_to_string == "12"
-       fun add(element: Streamable) do
+       fun add(element: Writable) do
                assert not is_frozen
                content.add element
        end
@@ -117,7 +117,7 @@ class Template
        #     t.addn("1")
        #     t.addn("2")
        #     assert t.write_to_string == "1\n2\n"
-       fun addn(element: Streamable) do
+       fun addn(element: Writable) do
                add element
                add "\n"
        end
@@ -128,7 +128,7 @@ class Template
        #     var t = new Template
        #     t.add_all(["1", "2"])
        #     assert t.write_to_string == "12"
-       fun add_all(elements: Collection[Streamable]) do content.add_all elements
+       fun add_all(elements: Collection[Writable]) do content.add_all elements
 
        # Append a bunch of elements at the end of the template with separations.
        # see `add`.
@@ -136,7 +136,7 @@ class Template
        #      var t = new Template
        #      t.add_list(["1", "2", "3"], ", ", " and ")
        #      assert t.write_to_string == "1, 2 and 3"
-       fun add_list(elements: Collection[Streamable], sep, last_sep: Streamable) do
+       fun add_list(elements: Collection[Writable], sep, last_sep: Writable) do
                var last = elements.length - 2
                var i = 0
                for e in elements do
@@ -181,7 +181,7 @@ class Template
        end
 
        # Each sub-elements
-       private var content = new Array[Streamable]
+       private var content = new Array[Writable]
 
        # Flag to avoid multiple rendering
        private var render_done = false
@@ -200,7 +200,7 @@ class Template
        end
 
        # Do the full rendering and write the final content to a stream
-       redef fun write_to(stream: OStream)
+       redef fun write_to(stream: Writer)
        do
                assert not is_writing
                is_writing = true
index d11898f..6b6b91c 100644 (file)
@@ -339,7 +339,7 @@ class BinTreeMap[K: Comparable, E]
 
        redef fun show_dot do
                assert not_empty: root != null
-               var f = new OProcess("dot", "-Txlib")
+               var f = new ProcessWriter("dot", "-Txlib")
                f.write "digraph \{\n"
                dot_down(root.as(not null), f)
                f.write "\}\n"
@@ -347,7 +347,7 @@ class BinTreeMap[K: Comparable, E]
        end
 
        # Translate the tree in dot format starting from `node`.
-       protected fun dot_down(node: N, f: OProcess) do
+       protected fun dot_down(node: N, f: ProcessWriter) do
                if node.left != null then dot_down(node.left.as(not null), f)
                f.write node.to_dot
                if node.right != null then dot_down(node.right.as(not null), f)
index 947112e..181c047 100644 (file)
@@ -81,7 +81,8 @@ The omnifunc applies a simple heuristic to recognize what kind of entities to di
 (This is a simplification some behaviors are missing.)
 
 * If the cursor follows `import`, it will list known modules.
-* If it follows `new`, `super` or `class` it will list known classes.
+* If it follows `new` it will list known classes with their constructors.
+* If it follows `super`, `class`, `isa` or `as` it will list known classes.
 * If it follows a `.`, it will list properties.
 * If on an extern method declaration, it will list classes and properties.
 * Otherwise, it will list keywords and properties.
index d58df14..23e557a 100644 (file)
@@ -139,7 +139,7 @@ fun NitOmnifuncAddAMatch(matches, words, name)
        let desc = get(a:words, 3, '')
        let desc = join(split(desc, '#nnnn#', 1), "\n")
        if strlen(pretty) > 40
-               let pretty = pretty[:37] . '...'
+               let pretty = pretty[:39] . '…'
        endif
        call add(a:matches, {'word': a:name, 'abbr': pretty, 'menu': synopsis, 'info': desc, 'dup': 1})
 endfun
@@ -188,12 +188,24 @@ fun NitOmnifunc(findstart, base)
                        call NitOmnifuncAddFromFile(a:base, matches, 'modules.txt')
                endif
 
-               " Classes
-               if count(['new', 'super', 'class', 'nullable'], prev_word) > 0 ||
+               " Classes (instanciable only)
+               if prev_word == 'new'
+                       let handled = 1
+                       call NitOmnifuncAddFromFile(a:base, matches, 'constructors.txt')
+               endif
+
+               " Other class references
+               if count(['class', 'super'], prev_word) > 0
+                       let handled = 1
+                       call NitOmnifuncAddFromFile(a:base, matches, 'classes.txt')
+               endif
+
+               " Types
+               if count(['class', 'super', 'nullable', 'isa', 'as'], prev_word) > 0 ||
                 \ line_prev_cursor =~ '[' || prev_char == ':' ||
                 \ (line_prev_cursor =~ 'fun' && line_prev_cursor =~ 'import' && (prev_word == 'import' || prev_char == ','))
                        let handled = 1
-                       call NitOmnifuncAddFromFile(a:base, matches, 'classes.txt')
+                       call NitOmnifuncAddFromFile(a:base, matches, 'types.txt')
                endif
 
                " Properties
index 8e20ca0..ea04856 100755 (executable)
@@ -34,18 +34,6 @@ if test -z "$ANDROID_NDK"; then
        ANDROID_NDK=`dirname $ndk_build_path`
 fi
 
-# Get the first platform available (it shouldn't change much, but it may
-# have to be adjusted)
-for platform in `echo $ANDROID_NDK/platforms/android-*/arch-arm`; do
-       SYS_ROOT=$platform
-       break
-done
-
-if test -z "$SYS_ROOT"; then
-       echo "Error: could not an Android platform in the NDK, define ANDROID_NDK to the correct path."
-       exit 1
-fi
-
 # Information on the currently targeted libgc and libatomic_ops source URL
 # These may have to be updated according to server-side changes and newer
 # versions of the Boehm GC.
@@ -82,17 +70,42 @@ mv $libatomic_ops_dir $libgc_dir/libatomic_ops || exit 1
 
 cd $libgc_dir || exit 1
 
-# Configure for Android
-path="$ANDROID_NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/"
-export CC="$path/arm-linux-androideabi-gcc --sysroot=$SYS_ROOT"
-export CXX="$path/arm-linux-androideabi-g++ --sysroot=$SYS_ROOT"
-export LD="$path/arm-linux-androideabi-ld"
-export AR="$path/arm-linux-androideabi-ar"
-export RANLIB="$path/arm-linux-androideabi-ranlib"
-export STRIP="$path/arm-linux-androideabi-strip"
-export CFLAGS="-DIGNORE_DYNAMIC_LOADING -DPLATFORM_ANDROID -I libatomic_ops/src/"
-export LIBS="-lc -lgcc"
-./configure --host=arm-linux-androideabi --enable-static --disable-shared --prefix="$install" || exit 1
-
-# Compile and install locally
-make install -j 4 || exit 1
+archs=(         arm                       x86                mips)
+tools_dirs=(    arm-linux-androideabi-4.6 x86-4.6            mipsel-linux-android-4.6)
+tools_prefixes=(arm-linux-androideabi     i686-linux-android mipsel-linux-android)
+hosts=(         arm-linux-androideabi     x86-linux-android  mips-linux-android)
+
+n_archs=$(( ${#archs[@]} - 1 ))
+for i in $(eval echo "{0..$n_archs}"); do
+       arch=${archs[i]}
+       tools_dir=${tools_dirs[i]}
+       tools_prefix=${tools_prefixes[i]}
+       host=${hosts[i]}
+
+       # Get the first platform available (it shouldn't change much, but it may
+       # have to be adjusted)
+       for platform in `echo $ANDROID_NDK/platforms/android-*/arch-$arch`; do
+               sys_root=$platform
+               break
+       done
+
+       if test -z "$sys_root"; then
+               echo "Error: could not an Android platform for $arch in the NDK, define ANDROID_NDK to the correct path."
+               exit 1
+       fi
+
+       # Configure for Android
+       path="$ANDROID_NDK/toolchains/$tools_dir/prebuilt/linux-x86_64/bin/"
+       export CC="$path/$tools_prefix-gcc --sysroot=$sys_root"
+       export CXX="$path/$tools_prefix-g++ --sysroot=$sys_root"
+       export LD="$path/$tools_prefix-ld"
+       export AR="$path/$tools_prefix-ar"
+       export RANLIB="$path/$tools_prefix-ranlib"
+       export STRIP="$path/$tools_prefix-strip"
+       export CFLAGS="-DIGNORE_DYNAMIC_LOADING -DPLATFORM_ANDROID -I libatomic_ops/src/"
+       export LIBS="-lc -lgcc"
+       ./configure --host=$host --enable-static --disable-shared --prefix="$install/$arch/" || exit 1
+
+       # Compile and install locally
+       make install -j 4 || exit 1
+done
index 6fa1f05..932f03d 100644 (file)
@@ -61,7 +61,7 @@ class CCompilationUnit
                body_impl.add( efc.to_writer )
        end
 
-       fun compile_header_core( stream : OStream )
+       fun compile_header_core( stream : Writer )
        do
                header_c_base.write_to( stream )
                header_custom.write_to( stream )
@@ -69,7 +69,7 @@ class CCompilationUnit
                header_decl.write_to( stream )
        end
 
-       fun compile_body_core( stream : OStream )
+       fun compile_body_core( stream : Writer )
        do
                body_decl.write_to( stream )
                body_custom.write_to( stream )
index f286f02..01de936 100644 (file)
@@ -212,7 +212,7 @@ class MakefileToolchain
 
                var hfilename = compiler.header.file.name + ".h"
                var hfilepath = "{compile_dir}/{hfilename}"
-               var h = new OFStream.open(hfilepath)
+               var h = new FileWriter.open(hfilepath)
                for l in compiler.header.decl_lines do
                        h.write l
                        h.write "\n"
@@ -227,7 +227,7 @@ class MakefileToolchain
                for f in compiler.files do
                        var i = 0
                        var count = 0
-                       var file: nullable OFStream = null
+                       var file: nullable FileWriter = null
                        for vis in f.writers do
                                if vis == compiler.header then continue
                                var total_lines = vis.lines.length + vis.decl_lines.length
@@ -240,7 +240,7 @@ class MakefileToolchain
                                        var cfilepath = "{compile_dir}/{cfilename}"
                                        self.toolcontext.info("new C source files to compile: {cfilepath}", 3)
                                        cfiles.add(cfilename)
-                                       file = new OFStream.open(cfilepath)
+                                       file = new FileWriter.open(cfilepath)
                                        file.write "#include \"{f.name}.0.h\"\n"
                                        count = total_lines
                                end
@@ -258,8 +258,8 @@ class MakefileToolchain
 
                        var cfilename = "{f.name}.0.h"
                        var cfilepath = "{compile_dir}/{cfilename}"
-                       var hfile: nullable OFStream = null
-                       hfile = new OFStream.open(cfilepath)
+                       var hfile: nullable FileWriter = null
+                       hfile = new FileWriter.open(cfilepath)
                        hfile.write "#include \"{hfilename}\"\n"
                        for key in f.required_declarations do
                                if not compiler.provided_declarations.has_key(key) then
@@ -321,7 +321,7 @@ class MakefileToolchain
                end
                var makename = makefile_name(mainmodule)
                var makepath = "{compile_dir}/{makename}"
-               var makefile = new OFStream.open(makepath)
+               var makefile = new FileWriter.open(makepath)
 
                var linker_options = new HashSet[String]
                for m in mainmodule.in_importation.greaters do
@@ -371,7 +371,7 @@ class MakefileToolchain
                if not compiler.linker_script.is_empty then
                        var linker_script_path = "{compile_dir}/linker_script"
                        ofiles.add "linker_script"
-                       var f = new OFStream.open(linker_script_path)
+                       var f = new FileWriter.open(linker_script_path)
                        for l in compiler.linker_script do
                                f.write l
                                f.write "\n"
@@ -546,7 +546,7 @@ abstract class AbstractCompiler
        do
                var compile_dir = modelbuilder.compile_dir
 
-               var stream = new OFStream.open("{compile_dir}/c_functions_hash.c")
+               var stream = new FileWriter.open("{compile_dir}/c_functions_hash.c")
                stream.write("#include <string.h>\n")
                stream.write("#include <stdlib.h>\n")
                stream.write("#include \"c_functions_hash.h\"\n")
@@ -576,7 +576,7 @@ abstract class AbstractCompiler
                stream.write("\}\n")
                stream.close
 
-               stream = new OFStream.open("{compile_dir}/c_functions_hash.h")
+               stream = new FileWriter.open("{compile_dir}/c_functions_hash.h")
                stream.write("const char* get_nit_name(register const char* procname, register unsigned int len);\n")
                stream.close
 
index 1cdc51a..60ed50b 100644 (file)
@@ -27,7 +27,7 @@ redef class MDoc
        var full_comment: String is lazy do return content.join("\n").html_escape
 
        # Synopsys in a template
-       var tpl_short_comment: Streamable is lazy do
+       var tpl_short_comment: Writable is lazy do
                var res = new Template
                var syn = nitdoc_inline_processor.process(content.first)
                res.add "<span class=\"synopsys nitdoc\">{syn}</span>"
@@ -36,7 +36,7 @@ redef class MDoc
        end
 
        # Full comment in a template
-       var tpl_comment: Streamable is lazy do
+       var tpl_comment: Writable is lazy do
                var res = new Template
                var lines = content.to_a
                res.add "<div class=\"nitdoc\">"
index a4bdeb0..e4865e5 100644 (file)
@@ -818,11 +818,11 @@ redef class GraphArticle
                var output_dir = v.ctx.output_dir
                var path = output_dir / id
                var path_sh = path.escape_to_sh
-               var file = new OFStream.open("{path}.dot")
+               var file = new FileWriter.open("{path}.dot")
                file.write(dot)
                file.close
                sys.system("\{ test -f {path_sh}.png && test -f {path_sh}.s.dot && diff -- {path_sh}.dot {path_sh}.s.dot >/dev/null 2>&1 ; \} || \{ cp -- {path_sh}.dot {path_sh}.s.dot && dot -Tpng -o{path_sh}.png -Tcmapx -o{path_sh}.map {path_sh}.s.dot ; \}")
-               var fmap = new IFStream.open("{path}.map")
+               var fmap = new FileReader.open("{path}.map")
                var map = fmap.read_all
                fmap.close
 
index cbb625e..c23e880 100644 (file)
@@ -45,7 +45,7 @@ class TplPage
        var sections = new Array[TplSection]
 
        # Footer content if any
-       var footer: nullable Streamable = null is writable
+       var footer: nullable Writable = null is writable
 
        # JS scripts to append at the end of the body
        var scripts = new Array[TplScript]
@@ -158,9 +158,9 @@ class TplTopMenu
        super Template
 
        # Brand link to display in first position of the top menu
-       private var brand: nullable Streamable = null is writable
+       private var brand: nullable Writable = null is writable
        # Elements of the topmenu
-       private var elts = new Array[Streamable]
+       private var elts = new Array[Writable]
 
        # The page url where the top menu is displayed.
        #
@@ -174,7 +174,7 @@ class TplTopMenu
        end
 
        # Add a content between `<li>` tags
-       fun add_item(content: Streamable, is_active: Bool) do
+       fun add_item(content: Writable, is_active: Bool) do
                var tpl = new Template
                tpl.add "<li"
                if is_active then
@@ -187,7 +187,7 @@ class TplTopMenu
        end
 
        # Add a raw content to the menu
-       fun add_raw(content: Streamable) do
+       fun add_raw(content: Writable) do
                elts.add content
        end
 
@@ -277,7 +277,7 @@ class TplSideBox
 
        # Content to display in the box
        # box will not be rendered if the content is null
-       var content: nullable Streamable = null is writable
+       var content: nullable Writable = null is writable
 
        # Is the box opened by default
        # otherwise, the user will have to clic on the title to display the content
@@ -287,7 +287,7 @@ class TplSideBox
                self.id = title.to_cmangle
        end
 
-       init with_content(title: String, content: Streamable) do
+       init with_content(title: String, content: Writable) do
                init(title)
                self.content = content
        end
@@ -352,7 +352,7 @@ class TplSummaryEntry
        super TplSummaryElt
 
        # Text to display
-       var text: Streamable
+       var text: Writable
 
        # Children of this entry
        # Will be displayed as a tree
@@ -383,10 +383,10 @@ class TplSectionElt
        # Title to display if any
        # if both `title` and `summary_title` are null then
        # the section will not appear in the summary
-       var title: nullable Streamable = null is writable
+       var title: nullable Writable = null is writable
 
        # Subtitle to display if any
-       var subtitle: nullable Streamable = null is writable
+       var subtitle: nullable Writable = null is writable
 
        # Title that appear in the summary
        # if null use `title` instead
@@ -401,7 +401,7 @@ class TplSectionElt
        # Parent article/section if any
        var parent: nullable TplSectionElt = null
 
-       init with_title(id: String, title: Streamable) do
+       init with_title(id: String, title: Writable) do
                init(id)
                self.title = title
        end
@@ -469,10 +469,10 @@ class TplArticle
        super TplSectionElt
 
        # Content for this article
-       var content: nullable Streamable = null is writable
-       var source_link: nullable Streamable = null is writable
+       var content: nullable Writable = null is writable
+       var source_link: nullable Writable = null is writable
 
-       init with_content(id: String, title: Streamable, content: Streamable) do
+       init with_content(id: String, title: Writable, content: Writable) do
                with_title(id, title)
                self.content = content
        end
@@ -525,13 +525,13 @@ class TplDefinition
        super Template
 
        # Comment to display
-       var comment: nullable Streamable = null is writable
+       var comment: nullable Writable = null is writable
 
        # Namespace for this definition
-       var namespace: nullable Streamable = null is writable
+       var namespace: nullable Writable = null is writable
 
        # Location link to display
-       var location: nullable Streamable = null is writable
+       var location: nullable Writable = null is writable
 
        private fun render_info do
                addn "<div class='info text-right'>"
@@ -589,9 +589,9 @@ end
 class TplSearchPage
        super TplSectionElt
 
-       var modules = new Array[Streamable]
-       var classes = new Array[Streamable]
-       var props = new Array[Streamable]
+       var modules = new Array[Writable]
+       var classes = new Array[Writable]
+       var props = new Array[Writable]
 
        redef fun rendering do
                var title = self.title
@@ -651,7 +651,7 @@ class TplLink
        var href: String is writable
 
        # The raw HTML content to display in the link
-       var text: Streamable is writable
+       var text: Writable is writable
 
        # The unescaped optional title.
        var title: nullable String = null is writable
@@ -717,16 +717,16 @@ class TplListItem
        # CSS classes of the <li> element
        var css_classes = new Array[String]
 
-       init with_content(content: Streamable) do append(content)
+       init with_content(content: Writable) do append(content)
 
-       init with_classes(content: Streamable, classes: Array[String]) do
+       init with_classes(content: Writable, classes: Array[String]) do
                with_content(content)
                css_classes = classes
        end
 
        # Append `content` to the item
        # similar to `self.content.add`
-       fun append(content: Streamable) do self.content.add content
+       fun append(content: Writable) do self.content.add content
 
        redef fun rendering do
                add "<li class='{css_classes.join(" ")}'>"
@@ -770,16 +770,16 @@ class TplTabPanel
        # The panel name.
        #
        # Displayed in the tab header or in the pointing link.
-       var name: Streamable
+       var name: Writable
 
        # Is the panel visible by default?
        var is_active = false is writable
 
        # Body of the panel
-       var content: nullable Streamable = null is writable
+       var content: nullable Writable = null is writable
 
        # Get a link pointing to this panel.
-       fun tpl_link_to: Streamable do
+       fun tpl_link_to: Writable do
                var lnk = new Template
                lnk.add "<a data-target='#{id}' data-toggle='pill'>"
                lnk.add name
@@ -801,12 +801,12 @@ class TplLabel
        super Template
 
        # Content of the label if any
-       var content: nullable Streamable = null is writable
+       var content: nullable Writable = null is writable
 
        # CSS classes of the <span> element
        var css_classes = new Array[String]
 
-       init with_content(content: Streamable) do self.content = content
+       init with_content(content: Writable) do self.content = content
        init with_classes(classes: Array[String]) do self.css_classes = classes
 
        redef fun rendering do
@@ -867,7 +867,7 @@ class TplScript
        super Template
 
        var attrs = new Array[TagAttribute]
-       var content: nullable Streamable = null is writable
+       var content: nullable Writable = null is writable
 
        init do
                attrs.add(new TagAttribute("type", "text/javascript"))
index 2472466..10c6bc0 100644 (file)
@@ -14,8 +14,9 @@
 
 # Generate files used by the Vim plugin to autocomplete with doc
 #
-# There is 3 files generated, each with a different target: modules, classes,
-# and properties. Each line describe a different entity, with 4 values:
+# There is 3 files generated, each with a different target: modules, types,
+# properties and constructors. Each line describe a different entity,
+# with 4 values:
 #
 # 1. Short name to use in autocompletion
 # 2. Full signature
 # 4. Full doc with extra
 #
 # The priority with those files is for them to be analyzed efficiently, for
-# this reason, the data is prepared in advant and some information may be
+# this reason, the data is prepared in advance and some information may be
 # duplicated.
 module vim_autocomplete
 
 import modelbuilder
 import phase
 import modelize::modelize_class
+import model_utils
 
 redef class ToolContext
        # Phase generating the files for the Vim plugin
@@ -50,19 +52,19 @@ redef class MEntity
        private fun field_separator: String do return "#====#"
        private fun line_separator: String do return "#nnnn#"
 
-       private fun write_to_stream(stream: OStream)
+       private fun write_to_stream(stream: Writer)
        do
                # 1. Short name for autocompletion
-               stream.write name
+               stream.write complete_name
                stream.write field_separator
 
                # 2. Full signature
-               stream.write name
+               stream.write complete_name
                write_signature_to_stream(stream)
                stream.write field_separator
 
                # 3. Doc synopsis
-               var mdoc = mdoc
+               var mdoc = complete_mdoc
                if mdoc != null then
                        stream.write mdoc.content.first
                end
@@ -80,7 +82,13 @@ redef class MEntity
                stream.write "\n"
        end
 
-       private fun write_signature_to_stream(stream: OStream) do end
+       private fun write_signature_to_stream(stream: Writer) do end
+
+       # Actual name used in completion
+       private fun complete_name: String do return name
+
+       # Doc to use in completion
+       private fun complete_mdoc: nullable MDoc do return mdoc
 end
 
 redef class MMethodDef
@@ -103,6 +111,43 @@ redef class MAttributeDef
        end
 end
 
+# Use `MClassDef` as anchor for its constructors only
+redef class MClassDef
+       private var target_constructor: nullable MMethodDef = null
+
+       redef fun complete_name
+       do
+               var target_constructor = target_constructor
+               assert target_constructor != null
+
+               var params
+               var mparameters = mclass.mparameters
+               if not mparameters.is_empty then
+                       params = "[{mparameters.join(", ")}]"
+               else
+                       params = ""
+               end
+
+               if target_constructor.name != "init" and target_constructor.name != "new" then
+                       return name + params + "." + target_constructor.name
+               end
+
+               return name + params
+       end
+
+       redef fun complete_mdoc
+       do
+               var target_constructor = target_constructor
+               assert target_constructor != null
+
+               if target_constructor.name != "init" and target_constructor.name != "new" then
+                       return target_constructor.mdoc
+               end
+
+               return mdoc
+       end
+end
+
 private class AutocompletePhase
        super Phase
 
@@ -113,9 +158,12 @@ private class AutocompletePhase
                var compile_dir = "NIT_VIM_DIR".environ
                if compile_dir.is_empty then compile_dir = "HOME".environ / ".vim/nit"
                compile_dir.mkdir
-               var modules_stream = new OFStream.open(compile_dir / "modules.txt")
-               var classes_stream = new OFStream.open(compile_dir / "classes.txt")
-               var properties_stream = new OFStream.open(compile_dir / "properties.txt")
+
+               var modules_stream = new FileWriter.open(compile_dir / "modules.txt")
+               var classes_stream = new FileWriter.open(compile_dir / "classes.txt")
+               var constructors_stream = new FileWriter.open(compile_dir / "constructors.txt")
+               var types_stream = new FileWriter.open(compile_dir / "types.txt")
+               var properties_stream = new FileWriter.open(compile_dir / "properties.txt")
 
                # Got all known modules
                var model = mainmodule.model
@@ -124,13 +172,27 @@ private class AutocompletePhase
                end
 
                # TODO list other modules from the Nit lib
-               # TODO list submodules
 
                # Get all known classes
                for mclass in model.mclasses do
                        if not mainmodule.is_visible(mclass.intro_mmodule, public_visibility) then continue
+                       var mclass_intro = mclass.intro
+
+                       # Can it be instantiated?
+                       if mclass.kind != interface_kind and mclass.kind != abstract_kind then
+
+                               for prop in mclass.all_mproperties(mainmodule, public_visibility) do
+                                       if prop isa MMethod and prop.is_init then
+                                               mclass_intro.target_constructor = prop.intro
+                                               mclass_intro.write_to_stream constructors_stream
+                                       end
+                               end
+                               mclass_intro.target_constructor = null
+                       end
 
-                       mclass.intro.write_to_stream classes_stream
+                       # Always add to types and classes
+                       mclass.mclass_type.write_to_stream classes_stream
+                       mclass.mclass_type.write_to_stream types_stream
                end
 
                # Get all known properties
@@ -138,13 +200,24 @@ private class AutocompletePhase
                        var intro_mmodule = mproperty.intro_mclassdef.mmodule
                        if not mainmodule.is_visible(intro_mmodule, public_visibility) then continue
 
+                       # Is it a virtual type?
+                       if mproperty isa MVirtualTypeProp then
+                               mproperty.intro.write_to_stream types_stream
+                               continue
+                       end
+
+                       # Skip properties beginning with @ or _
+                       var first_letter = mproperty.name.chars.first
+                       if first_letter == '@' or first_letter == '_' then continue
+
                        mproperty.intro.write_to_stream properties_stream
                end
 
                # Close streams
-               for stream in [modules_stream, classes_stream, properties_stream] do
-                       stream.close
+               for stream in [modules_stream, classes_stream, properties_stream,
+                       types_stream, constructors_stream] do
 
+                       stream.close
                        var error = stream.last_error
                        if error != null then
                                toolcontext.error(null, "Failed to write Vim autocomplete file: {error}")
index 4fbd5c4..878785c 100644 (file)
@@ -101,10 +101,10 @@ private class CCompilerOptionsPhase
                                var cmd_args = opt.command
                                var proc
                                if cmd_args.length == 1 then
-                                       proc = new IProcess.from_a(cmd_args[0], new Array[String])
+                                       proc = new ProcessReader.from_a(cmd_args[0], new Array[String])
                                else if cmd_args.length > 1 then
                                        var rest_args = cmd_args.subarray(1, cmd_args.length-1)
-                                       proc = new IProcess.from_a(cmd_args[0], rest_args)
+                                       proc = new ProcessReader.from_a(cmd_args[0], rest_args)
                                else abort
 
                                # wait for its completion
index babab08..59f46b3 100644 (file)
@@ -166,7 +166,7 @@ redef class CCompilationUnit
 
        fun write_header_to_file(mmodule: MModule, file: String, includes: Array[String], guard: String)
        do
-               var stream = new OFStream.open( file )
+               var stream = new FileWriter.open( file )
 
                # header comments
                var module_info = "/*\n\tExtern implementation of Nit module {mmodule.name}\n*/\n"
@@ -187,7 +187,7 @@ redef class CCompilationUnit
 
        fun write_body_to_file(mmodule: MModule, file: String, includes: Array[String])
        do
-               var stream = new OFStream.open(file)
+               var stream = new FileWriter.open(file)
 
                var module_info = "/*\n\tExtern implementation of Nit module {mmodule.name}\n*/\n"
 
index dca4fab..bd62de3 100644 (file)
@@ -67,7 +67,7 @@ class PkgconfigPhase
                end
 
                # check availability of pkg-config
-               var proc_which = new IProcess("which", "pkg-config")
+               var proc_which = new ProcessReader("which", "pkg-config")
                proc_which.wait
                var status = proc_which.status
                if status != 0 then
index a51bece..9408e95 100644 (file)
@@ -83,6 +83,7 @@ noinit
 readonly
 writable
 autoinit
+noautoinit
 cached
 nosuper
 old_style_init
index 5dd6b79..692d918 100644 (file)
@@ -62,7 +62,7 @@ private class GLSLValidationPhase
                        if not in_path then return
                else
                        # Is _glslangValidator_ installed?
-                       var proc_which = new IProcess("which", "glslangValidator")
+                       var proc_which = new ProcessReader("which", "glslangValidator")
                        proc_which.wait
                        proc_which.close
                        var status = proc_which.status
@@ -91,7 +91,7 @@ private class GLSLValidationPhase
                shader.write_to_file path
 
                # Execute the validator
-               var proc_validator = new IProcess("glslangValidator", path)
+               var proc_validator = new ProcessReader("glslangValidator", path)
                proc_validator.wait
                var lines = proc_validator.read_all.split('\n')
                proc_validator.close
index 50f98c7..828cb3b 100644 (file)
@@ -115,7 +115,7 @@ redef class ModelBuilder
 end
 
 redef class Sys
-       private fun set_io(istream: PollableIStream, ostream: OStream, errstream: OStream)
+       private fun set_io(istream: PollableReader, ostream: Writer, errstream: Writer)
        do
                self.stdin = istream
                self.stdout = ostream
index 0de93d3..122fe4e 100644 (file)
@@ -20,7 +20,7 @@ intrude import standard::string
 # Wrapper for `NativeFile`
 class PrimitiveNativeFile
 
-       var file: IOS
+       var file: Stream
 
        init native_stdin do
                file = sys.stdin
@@ -35,49 +35,49 @@ class PrimitiveNativeFile
        end
 
        init io_open_read(path: String) do
-               file = new IFStream.open(path.to_s)
+               file = new FileReader.open(path.to_s)
        end
 
        init io_open_write(path: String) do
-               file = new OFStream.open(path.to_s)
+               file = new FileWriter.open(path.to_s)
        end
 
        fun address_is_null: Bool do
-               if file isa FStream then return file.as(FStream)._file.address_is_null
+               if file isa FileStream then return file.as(FileStream)._file.address_is_null
                return false
        end
 
        fun io_read(buf: NativeString, len: Int): Int do
-               if file isa FStream then return file.as(FStream)._file.io_read(buf, len)
-               var str = file.as(IStream).read(len)
+               if file isa FileStream then return file.as(FileStream)._file.io_read(buf, len)
+               var str = file.as(Reader).read(len)
                str.to_cstring.copy_to(buf, str.length, 0, 0)
                return str.length
        end
 
        fun io_write(buf: NativeString, len: Int): Int do
-               if file isa FStream then return file.as(FStream)._file.io_write(buf, len)
-               file.as(OStream).write(buf.to_s_with_length(len))
+               if file isa FileStream then return file.as(FileStream)._file.io_write(buf, len)
+               file.as(Writer).write(buf.to_s_with_length(len))
                return len
        end
 
        fun io_close: Int do
-               if file isa FStream then return file.as(FStream)._file.io_close
+               if file isa FileStream then return file.as(FileStream)._file.io_close
                file.close
                return 0
        end
 
        fun fileno: Int do
-               if file isa FStream then return file.as(FStream)._file.fileno
+               if file isa FileStream then return file.as(FileStream)._file.fileno
                return 0
        end
 
        fun flush: Int do
-               if file isa FStream then return file.as(FStream)._file.flush
+               if file isa FileStream then return file.as(FileStream)._file.flush
                return 0
        end
 
        fun set_buffering_type(size, mode: Int): Int do
-               if file isa FStream then return file.as(FStream)._file.set_buffering_type(size, mode)
+               if file isa FileStream then return file.as(FileStream)._file.set_buffering_type(size, mode)
                return 0
        end
 end
index 517deab..65e7c67 100644 (file)
@@ -386,7 +386,7 @@ redef class ModelBuilder
                if not readme.file_exists then readme = dirpath2.join_path("README")
                if readme.file_exists then
                        var mdoc = new MDoc
-                       var s = new IFStream.open(readme)
+                       var s = new FileReader.open(readme)
                        while not s.eof do
                                mdoc.content.add(s.read_line)
                        end
@@ -430,7 +430,7 @@ redef class ModelBuilder
                self.toolcontext.info("load module {filename}", 2)
 
                # Load the file
-               var file = new IFStream.open(filename)
+               var file = new FileReader.open(filename)
                var lexer = new Lexer(new SourceFile(filename, file))
                var parser = new Parser(lexer)
                var tree = parser.parse
index d7154ca..83ed72f 100644 (file)
@@ -26,7 +26,7 @@ class SourceFile
        var string: String is noinit
 
        # The original stream used to initialize `string`
-       var stream: IStream
+       var stream: Reader
 
        init
        do
index 3522245..6193b9c 100644 (file)
@@ -77,7 +77,7 @@ do
                end
        end
        buf.append("\}\n")
-       var f = new OFStream.open(toolcontext.output_dir.join_path("class_hierarchy.dot"))
+       var f = new FileWriter.open(toolcontext.output_dir.join_path("class_hierarchy.dot"))
        f.write(buf.to_s)
        f.close
 end
@@ -99,7 +99,7 @@ do
                end
        end
        buf.append("\}\n")
-       var f = new OFStream.open(toolcontext.output_dir.join_path("classdef_hierarchy.dot"))
+       var f = new FileWriter.open(toolcontext.output_dir.join_path("classdef_hierarchy.dot"))
        f.write(buf.to_s)
        f.close
 end
index 43384d9..9e66e73 100644 (file)
@@ -186,7 +186,7 @@ do
                end
        end
        buf.append("</body></html>\n")
-       var f = new OFStream.open(toolcontext.output_dir.join_path("model.html"))
+       var f = new FileWriter.open(toolcontext.output_dir.join_path("model.html"))
        f.write(buf.to_s)
        f.close
 end
index 00ca5cf..f0f4ff9 100644 (file)
@@ -1757,6 +1757,9 @@ abstract class MProperty
        # The visibility of the property
        var visibility: MVisibility
 
+       # Is the property usable as an initializer?
+       var is_autoinit = false is writable
+
        init
        do
                intro_mclassdef.intro_mproperties.add(self)
index bdb8373..305cd23 100644 (file)
@@ -136,7 +136,7 @@ end
 # Interesting elements must be selected. See `mmodules`, ``
 # Display configuration can be set. See `cluster_group`, `project_group`
 class MProjectDot
-       super Streamable
+       super Writable
 
        # The model where to look for information
        var model: Model
@@ -161,7 +161,7 @@ class MProjectDot
        var project_group = true is writable
 
        # Recursively generate node and clusters for a mgroup
-       private fun dot_cluster(o: OStream, mgroup: MGroup)
+       private fun dot_cluster(o: Writer, mgroup: MGroup)
        do
                # Open the cluster, if required
                if mgroup.parent == null then
index 42dee1e..ba62b6e 100644 (file)
@@ -181,6 +181,7 @@ redef class ModelBuilder
                                        mparameters.add(mparameter)
                                end
                                initializers.add(npropdef.mpropdef.mproperty)
+                               npropdef.mpropdef.mproperty.is_autoinit = true
                        end
                        if npropdef isa AAttrPropdef then
                                if npropdef.mpropdef == null then return # Skip broken attribute
@@ -190,6 +191,7 @@ redef class ModelBuilder
                                        # For autoinit attributes, call the reader to force
                                        # the lazy initialization of the attribute.
                                        initializers.add(npropdef.mreadpropdef.mproperty)
+                                       npropdef.mreadpropdef.mproperty.is_autoinit = true
                                        continue
                                end
                                if npropdef.has_value then continue
@@ -202,9 +204,11 @@ redef class ModelBuilder
                                if msetter == null then
                                        # No setter, it is a old-style attribute, so just add it
                                        initializers.add(npropdef.mpropdef.mproperty)
+                                       npropdef.mpropdef.mproperty.is_autoinit = true
                                else
                                        # Add the setter to the list
                                        initializers.add(msetter.mproperty)
+                                       msetter.mproperty.is_autoinit = true
                                end
                        end
                end
@@ -218,39 +222,99 @@ redef class ModelBuilder
                        return
                end
 
-               # Search the longest-one and checks for conflict
-               var longest = spropdefs.first
-               if spropdefs.length > 1 then
-                       # Check for conflict in the order of initializers
-                       # Each initializer list must me a prefix of the longest list
-                       # part 1. find the longest list
-                       for spd in spropdefs do
-                               if spd.initializers.length > longest.initializers.length then longest = spd
+               # Look at the autoinit class-annotation
+               var autoinit = nclassdef.get_single_annotation("autoinit", self)
+               var noautoinit = nclassdef.get_single_annotation("noautoinit", self)
+               if autoinit != null then
+                       # Just throws the collected initializers
+                       mparameters.clear
+                       initializers.clear
+
+                       if noautoinit != null then
+                               error(autoinit, "Error: `autoinit` and `noautoinit` are incompatible.")
+                       end
+
+                       if autoinit.n_args.is_empty then
+                               error(autoinit, "Syntax error: `autoinit` expects method identifiers, use `noautoinit` to clear all autoinits.")
                        end
-                       # part 2. compare
-                       for spd in spropdefs do
-                               var i = 0
-                               for p in spd.initializers do
-                                       if p != longest.initializers[i] then
-                                               self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})")
-                                               return
+
+                       # Get and check each argument
+                       for narg in autoinit.n_args do
+                               var id = narg.as_id
+                               if id == null then
+                                       error(narg, "Syntax error: `autoinit` expects method identifiers.")
+                                       return
+                               end
+
+                               # Search the property.
+                               # To avoid bad surprises, try to get the setter first.
+                               var p = try_get_mproperty_by_name(narg, mclassdef, id + "=")
+                               if p == null then
+                                       p = try_get_mproperty_by_name(narg, mclassdef, id)
+                               end
+                               if p == null then
+                                       error(narg, "Error: unknown method `{id}`")
+                                       return
+                               end
+                               if not p.is_autoinit then
+                                       error(narg, "Error: `{p}` is not an autoinit method")
+                                       return
+                               end
+
+                               # Register the initializer and the parameters
+                               initializers.add(p)
+                               var pd = p.intro
+                               if pd isa MMethodDef then
+                                       # Get the signature resolved for the current receiver
+                                       var sig = pd.msignature.resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mclassdef.mmodule, false)
+                                       mparameters.add_all sig.mparameters
+                               else
+                                       # TODO attributes?
+                                       abort
+                               end
+                       end
+               else if noautoinit != null then
+                       if initializers.is_empty then
+                               warning(noautoinit, "useless-noautoinit", "Warning: the list of autoinit is already empty.")
+                       end
+                       # Just clear initializers
+                       mparameters.clear
+                       initializers.clear
+               else
+                       # Search the longest-one and checks for conflict
+                       var longest = spropdefs.first
+                       if spropdefs.length > 1 then
+                               # Check for conflict in the order of initializers
+                               # Each initializer list must me a prefix of the longest list
+                               # part 1. find the longest list
+                               for spd in spropdefs do
+                                       if spd.initializers.length > longest.initializers.length then longest = spd
+                               end
+                               # part 2. compare
+                               for spd in spropdefs do
+                                       var i = 0
+                                       for p in spd.initializers do
+                                               if p != longest.initializers[i] then
+                                                       self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})")
+                                                       return
+                                               end
+                                               i += 1
                                        end
-                                       i += 1
                                end
                        end
-               end
 
-               # Can we just inherit?
-               if spropdefs.length == 1 and mparameters.is_empty and defined_init == null then
-                       self.toolcontext.info("{mclassdef} inherits the basic constructor {longest}", 3)
-                       mclassdef.mclass.root_init = longest
-                       return
-               end
+                       # Can we just inherit?
+                       if spropdefs.length == 1 and mparameters.is_empty and defined_init == null then
+                               self.toolcontext.info("{mclassdef} inherits the basic constructor {longest}", 3)
+                               mclassdef.mclass.root_init = longest
+                               return
+                       end
 
-               # Combine the inherited list to what is collected
-               if longest.initializers.length > 0 then
-                       mparameters.prepend longest.new_msignature.mparameters
-                       initializers.prepend longest.initializers
+                       # Combine the inherited list to what is collected
+                       if longest.initializers.length > 0 then
+                               mparameters.prepend longest.new_msignature.mparameters
+                               initializers.prepend longest.initializers
+                       end
                end
 
                # If we already have a basic init definition, then setup its initializers
@@ -928,10 +992,11 @@ redef class AAttrPropdef
                has_value = n_expr != null or n_block != null
 
                var atnoinit = self.get_single_annotation("noinit", modelbuilder)
+               if atnoinit == null then atnoinit = self.get_single_annotation("noautoinit", modelbuilder)
                if atnoinit != null then
                        noinit = true
                        if has_value then
-                               modelbuilder.error(atnoinit, "Error: `noinit` attributes cannot have an initial value")
+                               modelbuilder.error(atnoinit, "Error: `noautoinit` attributes cannot have an initial value")
                                return
                        end
                end
index 0c8998b..5b64e3d 100644 (file)
@@ -124,7 +124,7 @@ if dir != null then
 
        var v = new HighlightVisitor
        toolcontext.info("write {dir}/style.css", 1)
-       var f = new OFStream.open("{dir}/style.css")
+       var f = new FileWriter.open("{dir}/style.css")
        f.write v.css_content
        f.close
 end
index 9412f5d..7ffc58c 100644 (file)
@@ -144,7 +144,7 @@ var files
 if opt_recursive.value then
        files = new Array[String]
        for d in tc.option_context.rest do
-               var pipe = new IProcess("find", d, "-name", "*.nit")
+               var pipe = new ProcessReader("find", d, "-name", "*.nit")
                while not pipe.eof do
                        var l = pipe.read_line
                        if l == "" then break # last line
index 9dd723e..d759992 100644 (file)
@@ -56,7 +56,7 @@ end
 
 # Return result from diff between `file1` and `file2`.
 private fun diff(file1, file2: String): String do
-       var p = new IProcess("diff", "-u", file1, file2)
+       var p = new ProcessReader("diff", "-u", file1, file2)
        var res = p.read_all
        p.wait
        p.close
index 4953156..98b1923 100644 (file)
@@ -36,16 +36,16 @@ import template
 class NitModule
        super Template
 
-       var header: nullable Streamable = null
+       var header: nullable Writable = null
 
        # The module's name
-       var name: Streamable
+       var name: Writable
 
        # Imports from this module
-       var imports = new Array[Streamable]
+       var imports = new Array[Writable]
 
        # Main content of this module
-       var content = new Array[Streamable]
+       var content = new Array[Writable]
 
        redef fun rendering
        do
index f4b04a6..c04bd28 100644 (file)
@@ -140,11 +140,17 @@ class AndroidToolchain
                        end
                end
 
-               ## Generate delegating makefile
+               ## Generate Application.mk
                dir = "{android_project_root}/jni/"
                """
+APP_ABI := armeabi armeabi-v7a x86 mips
+APP_PLATFORM := android-{{{app_target_api}}}
+""".write_to_file "{dir}/Application.mk"
+
+               ## Generate delegating makefile
+               """
 include $(call all-subdir-makefiles)
-               """.write_to_file("{dir}/Android.mk")
+""".write_to_file "{dir}/Android.mk"
 
                # Gather ldflags for Android
                var ldflags = new Array[String]
@@ -165,7 +171,7 @@ LOCAL_CFLAGS        := -D ANDROID -D WITH_LIBGC
 LOCAL_MODULE    := main
 LOCAL_SRC_FILES := \\
 {{{cfiles.join(" \\\n")}}}
-LOCAL_LDLIBS    := {{{ldflags.join(" ")}}} libgc.a
+LOCAL_LDLIBS    := {{{ldflags.join(" ")}}} $(TARGET_ARCH)/libgc.a
 LOCAL_STATIC_LIBRARIES := android_native_app_glue png
 
 include $(BUILD_SHARED_LIBRARY)
@@ -236,13 +242,20 @@ $(call import-module,android/native_app_glue)
                end
 
                # Ensure that android-setup-libgc.sh has been executed
-               if not "{share_dir}/libgc/lib".file_exists then
+               if not "{share_dir}/libgc/arm/lib".file_exists then
                        toolcontext.exec_and_check(["{share_dir}/libgc/android-setup-libgc.sh"], "Android project error")
                end
 
                # Copy GC files
-               toolcontext.exec_and_check(["cp", "{share_dir}/libgc/lib/libgc.a", "{android_project_root}/libgc.a"], "Android project error")
-               toolcontext.exec_and_check(["ln", "-s", "{share_dir}/libgc/include/gc/", "{android_project_root}/jni/nit_compile/gc"], "Android project error")
+               for arch in ["arm", "x86", "mips"] do
+                       dir = android_project_root/arch
+                       dir.mkdir
+                       toolcontext.exec_and_check(["cp", "{share_dir}/libgc/{arch}/lib/libgc.a",
+                               dir/"libgc.a"], "Android project error")
+               end
+
+               toolcontext.exec_and_check(["ln", "-s", "{share_dir}/libgc/arm/include/gc/",
+                       "{android_project_root}/jni/nit_compile/gc"], "Android project error")
 
                ### Link to assets (for mnit and others)
                # This will be accessed from `android_project_root`
@@ -285,7 +298,7 @@ $(call import-module,android/native_app_glue)
 """<?xml version="1.0" encoding="utf-8"?>
 <resources>
     <string name="app_name">{{{app_name}}}</string>
-</resources>""".write_to_file "{dir}/res/values/strings.xml"
+</resources>""".write_to_file "{android_project_root}/res/values/strings.xml"
                end
 
                # Android libs folder
index ad34b9a..484c0a6 100644 (file)
@@ -156,7 +156,7 @@ redef class AAnnotation
                                value = arg.as_id
                                if value == "git_revision" then
                                        # Get Git short revision
-                                       var proc = new IProcess("git", "rev-parse", "--short", "HEAD")
+                                       var proc = new ProcessReader("git", "rev-parse", "--short", "HEAD")
                                        proc.wait
                                        assert proc.status == 0
                                        var lines = proc.read_all
@@ -164,7 +164,7 @@ redef class AAnnotation
 
                                        # Is it dirty?
                                        # If not, the return of `git diff --shortstat` is an empty line
-                                       proc = new IProcess("git", "diff-index", "--quiet", "HEAD")
+                                       proc = new ProcessReader("git", "diff-index", "--quiet", "HEAD")
                                        proc.wait
                                        var dirty = proc.status != 0
                                        if dirty then revision += ".d"
index 1f96058..b4ba420 100644 (file)
@@ -77,7 +77,7 @@ private class FlowVisitor
 
        fun printflow
        do
-               var file = new OFStream.open("flow.dot")
+               var file = new FileWriter.open("flow.dot")
                file.write("digraph \{\n")
                for f in flows do
                        var s = ""
index f654f5b..89682cc 100644 (file)
@@ -115,7 +115,7 @@ else
                if no_file then
                        source = new SourceFile.from_string("", a)
                else
-                       var f = new IFStream.open(a)
+                       var f = new FileReader.open(a)
                        source = new SourceFile(a, f)
                        f.close
                end
index e975d85..d6de328 100644 (file)
@@ -144,7 +144,7 @@ class NitUnitExecutor
                var dir = file.dirname
                if dir != "" then dir.mkdir
                var f
-               f = new OFStream.open(file)
+               f = new FileWriter.open(file)
                f.write("# GENERATED FILE\n")
                f.write("# Docunits extracted from comments\n")
                f.write("import {mmodule.name}\n")
@@ -159,7 +159,7 @@ class NitUnitExecutor
                        f.write("end\n")
                end
                f.write("var a = args.first.to_i\n")
-               for j in [1..i[ do
+               for j in [1..i] do
                        f.write("if a == {j} then run_{j}\n")
                end
                f.close
@@ -193,7 +193,7 @@ class NitUnitExecutor
                        var res2 = sys.system("{file.to_program_name}.bin {i} >>'{file}.out1' 2>&1 </dev/null")
 
                        var msg
-                       f = new IFStream.open("{file}.out1")
+                       f = new FileReader.open("{file}.out1")
                        var n2
                        n2 = new HTMLTag("system-err")
                        tc.add n2
@@ -232,7 +232,7 @@ class NitUnitExecutor
                var dir = file.dirname
                if dir != "" then dir.mkdir
                var f
-               f = new OFStream.open(file)
+               f = new FileWriter.open(file)
                f.write("# GENERATED FILE\n")
                f.write("# Example extracted from a documentation\n")
                f.write("import {mmodule.name}\n")
@@ -256,7 +256,7 @@ class NitUnitExecutor
                end
 
                var msg
-               f = new IFStream.open("{file}.out1")
+               f = new FileReader.open("{file}.out1")
                var n2
                n2 = new HTMLTag("system-err")
                tc.add n2
index 19532c6..5f5b82d 100644 (file)
@@ -101,7 +101,7 @@ class NitUnitGenerator
        var nodot: Array[String] = ["+", "-", "*", "/", "%", "==", "!=", "<", "<=", "<=>", ">", ">=", ">"]
 
        # Generate subject init.
-       private fun gen_init(mclassdef: MClassDef): Streamable do
+       private fun gen_init(mclassdef: MClassDef): Writable do
                if mclassdef.mclass.arity == 0 then
                        return "\t\tvar subject: {mclassdef.name}"
                end
@@ -116,7 +116,7 @@ class NitUnitGenerator
        end
 
        # Generate call to `method` using `args`.
-       private fun gen_call(method: MMethodDef, args: Array[String]): Streamable do
+       private fun gen_call(method: MMethodDef, args: Array[String]): Writable do
                # Here we handle the magic of the Nit syntax, have fun :)
                var name = method.name
                if name == "[]" then return "subject[{args.join(", ")}]"
index 37f5c74..ad0b20a 100644 (file)
@@ -197,7 +197,7 @@ class TestSuite
                var include_dir = mmodule.location.file.filename.dirname
                var cmd = "{nitg} --no-color '{file}.nit' -I {include_dir} -o '{file}.bin' > '{file}.out' 2>&1 </dev/null"
                var res = sys.system(cmd)
-               var f = new IFStream.open("{file}.out")
+               var f = new FileReader.open("{file}.out")
                var msg = f.read_all
                f.close
                # set test case result
@@ -257,7 +257,7 @@ class TestCase
                var test_file = test_suite.test_file
                var res_name = "{test_file}_{method_name.escape_to_c}"
                var res = sys.system("{test_file}.bin {method_name} > '{res_name}.out1' 2>&1 </dev/null")
-               var f = new IFStream.open("{res_name}.out1")
+               var f = new FileReader.open("{res_name}.out1")
                var msg = f.read_all
                f.close
                # set test case result
index 021c2c7..a5b7ceb 100644 (file)
@@ -249,7 +249,7 @@ class ToolContext
                args.remove_at 0
 
                # Is the wanted program available?
-               var proc_which = new IProcess.from_a("which", [prog])
+               var proc_which = new ProcessReader.from_a("which", [prog])
                proc_which.wait
                var res = proc_which.status
                if res != 0 then
index 205297f..c985a04 100644 (file)
@@ -19,7 +19,7 @@ import uml_base
 
 redef class UMLModel
        # Generates a UML class diagram from a `Model`
-       fun generate_class_uml: Streamable do
+       fun generate_class_uml: Writable do
                var tpl = new Template
                tpl.add "digraph G \{\n"
                tpl.add """     fontname = "Bitstream Vera Sans"
@@ -43,7 +43,7 @@ end
 redef class Model
 
        # Generates a UML Class diagram from the entities of a `Model`
-       fun tpl_class(ctx: ToolContext, main: MModule): Streamable do
+       fun tpl_class(ctx: ToolContext, main: MModule): Writable do
                var t = new Template
                for i in mclasses do
                        if not ctx.private_gen and i.visibility != public_visibility then continue
@@ -56,13 +56,13 @@ redef class Model
 end
 
 redef class MEntity
-       # Generates a dot-compatible `Streamable` UML Class diagram from `self`
-       fun tpl_class(ctx: ToolContext, main: MModule): Streamable is abstract
+       # Generates a dot-compatible `Writable` UML Class diagram from `self`
+       fun tpl_class(ctx: ToolContext, main: MModule): Writable is abstract
 end
 
 redef class MClass
 
-       redef fun tpl_class(ctx, main): Streamable do
+       redef fun tpl_class(ctx, main): Writable do
                var t = new Template
                t.add "{name} [\n label = \"\{"
                if kind == abstract_kind then
@@ -174,7 +174,7 @@ redef class MVisibility
        #
        #    assert public_visibility.tpl_class == "+"
        #    assert private_visibility.tpl_class == "-"
-       fun tpl_class: Streamable do
+       fun tpl_class: Writable do
                if self == private_visibility then
                        return "-"
                else if self == protected_visibility then
index 8485c45..6e80325 100644 (file)
@@ -20,7 +20,7 @@ import uml_class
 
 redef class UMLModel
        # Generates a UML package diagram from a `Model`
-       fun generate_package_uml: Streamable do
+       fun generate_package_uml: Writable do
                var tpl = new Template
                tpl.add "digraph G \{\n"
                tpl.add """     fontname = "Bitstream Vera Sans"
@@ -42,7 +42,7 @@ end
 
 redef class Model
        # Returns a UML package diagram of `main`
-       fun tpl_module(ctx: ToolContext, main: MModule): Streamable do
+       fun tpl_module(ctx: ToolContext, main: MModule): Writable do
                return main.tpl_module(ctx, main)
        end
 end
@@ -63,7 +63,7 @@ end
 
 redef class MEntity
        # Builds a dot UML package diagram entity from `self`
-       fun tpl_module(ctx: ToolContext, main: MModule): Streamable is abstract
+       fun tpl_module(ctx: ToolContext, main: MModule): Writable is abstract
 end
 
 redef class MClassDef
index afce0f9..5930588 100644 (file)
@@ -16,9 +16,9 @@ import kernel
 
 class A
        var a: Object = get(5) is lazy
-       var b: Object is noinit
-       #alt1#var b2: Object = get(-4) is noinit
-       var c: Object is noinit
+       var b: Object is noautoinit
+       #alt1#var b2: Object = get(-4) is noautoinit
+       var c: Object is noautoinit
        var d: Object = get(2) is autoinit
        #alt2#var d2: Object = get(-2) is autoinit, lazy
        var e: Object = get(1)
diff --git a/tests/base_init_autoinit3.nit b/tests/base_init_autoinit3.nit
new file mode 100644 (file)
index 0000000..37c2cb2
--- /dev/null
@@ -0,0 +1,67 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+       var i: Int
+end
+
+class B
+       autoinit b, i #alt2# autoinit foo #alt4# autoinit fail
+       super A
+       var b: Bool #alt5# var b: Bool is noinit
+       fun foo do end
+end
+
+class C
+       super A
+       var f: Float
+end
+
+class D
+       autoinit i, b, f
+       super B
+       super C
+end
+
+class E
+       noautoinit #alt6#
+       #alt6,7# autoinit
+       super A
+       var a: A
+end
+
+class F
+       #alt8#noautoinit
+end
+
+var a = new A(1)
+a.i.output
+
+var b = new B(false, 2)
+b.i.output
+b.b.output
+
+var c = new C(3, 3.3)
+c.i.output
+c.f.output
+
+var d = new D(4, true, 4.4)
+d.i.output
+d.b.output
+d.f.output
+
+var e = new E
+#alt1# e.a.i.output
index 87de46e..f129d53 100644 (file)
@@ -15,8 +15,8 @@
 import kernel
 
 class A
-       var x: Object is noinit #alt1,3# var x: Object
-       var y: Object is noinit #alt2,3# var y: Object
+       var x: Object is noautoinit #alt1,3# var x: Object
+       var y: Object is noautoinit #alt2,3# var y: Object
        fun work
        do
                if isset _x then x.output
index 5ada70d..2add93c 100644 (file)
@@ -1,5 +1,5 @@
 import emscripten
-redef class IFStream
+redef class FileReader
        redef fun fill_buffer
        do
                print "NOT YET IMPLEMENTED"
index 9c9fbe0..25528d8 100644 (file)
@@ -1 +1 @@
-alt/base_init_autoinit2_alt1.nit:20,30--35: Error: `noinit` attributes cannot have an initial value
+alt/base_init_autoinit2_alt1.nit:20,30--39: Error: `noautoinit` attributes cannot have an initial value
diff --git a/tests/sav/base_init_autoinit3.res b/tests/sav/base_init_autoinit3.res
new file mode 100644 (file)
index 0000000..6851c6d
--- /dev/null
@@ -0,0 +1,8 @@
+1
+2
+false
+3
+3.300000
+4
+true
+4.400000
diff --git a/tests/sav/base_init_autoinit3_alt1.res b/tests/sav/base_init_autoinit3_alt1.res
new file mode 100644 (file)
index 0000000..92263fd
--- /dev/null
@@ -0,0 +1,9 @@
+Runtime error: Uninitialized attribute _a (alt/base_init_autoinit3_alt1.nit:43)
+1
+2
+false
+3
+3.300000
+4
+true
+4.400000
diff --git a/tests/sav/base_init_autoinit3_alt2.res b/tests/sav/base_init_autoinit3_alt2.res
new file mode 100644 (file)
index 0000000..cd95aed
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_autoinit3_alt2.nit:22,11--13: Error: `foo` is not an autoinit method
diff --git a/tests/sav/base_init_autoinit3_alt4.res b/tests/sav/base_init_autoinit3_alt4.res
new file mode 100644 (file)
index 0000000..269b2fd
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_autoinit3_alt4.nit:22,11--14: Error: unknown method `fail`
diff --git a/tests/sav/base_init_autoinit3_alt5.res b/tests/sav/base_init_autoinit3_alt5.res
new file mode 100644 (file)
index 0000000..67f272a
--- /dev/null
@@ -0,0 +1,2 @@
+alt/base_init_autoinit3_alt5.nit:22,11: Error: `b=` is not an autoinit method
+alt/base_init_autoinit3_alt5.nit:34,14: Error: `b=` is not an autoinit method
diff --git a/tests/sav/base_init_autoinit3_alt6.res b/tests/sav/base_init_autoinit3_alt6.res
new file mode 100644 (file)
index 0000000..e95f861
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_autoinit3_alt6.nit:40,2--41,9: Syntax error: `autoinit` expects method identifiers, use `noautoinit` to clear all autoinits.
diff --git a/tests/sav/base_init_autoinit3_alt7.res b/tests/sav/base_init_autoinit3_alt7.res
new file mode 100644 (file)
index 0000000..9fb22d1
--- /dev/null
@@ -0,0 +1,2 @@
+alt/base_init_autoinit3_alt7.nit:41,2--9: Error: `autoinit` and `noautoinit` are incompatible.
+alt/base_init_autoinit3_alt7.nit:41,2--9: Syntax error: `autoinit` expects method identifiers, use `noautoinit` to clear all autoinits.
diff --git a/tests/sav/base_init_autoinit3_alt8.res b/tests/sav/base_init_autoinit3_alt8.res
new file mode 100644 (file)
index 0000000..f88f100
--- /dev/null
@@ -0,0 +1,9 @@
+alt/base_init_autoinit3_alt8.nit:47,2--11: Warning: the list of autoinit is already empty.
+1
+2
+false
+3
+3.300000
+4
+true
+4.400000
index b79ac75..1f0479d 100644 (file)
@@ -1 +1 @@
-alt/base_init_noinit_alt5.nit:26,23--28: Error: `noinit` attributes cannot have an initial value
+alt/base_init_noinit_alt5.nit:26,23--28: Error: `noautoinit` attributes cannot have an initial value
diff --git a/tests/sav/niti/base_init_autoinit3_alt1.res b/tests/sav/niti/base_init_autoinit3_alt1.res
new file mode 100644 (file)
index 0000000..70e53f3
--- /dev/null
@@ -0,0 +1,9 @@
+Runtime error: Uninitialized attribute _a (alt/base_init_autoinit3_alt1.nit:67)
+1
+2
+false
+3
+3.300000
+4
+true
+4.400000
index 632da3c..0d8a256 100644 (file)
@@ -21,6 +21,6 @@ var src = "test_file_copy.nit"
 var dst = "{dir}/copy.nit"
 src.file_copy_to dst
 
-var file = new IFStream.open(dst)
+var file = new FileReader.open(dst)
 printn file.read_all
 file.close
index cd93882..61918c0 100644 (file)
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
@@ -43,7 +43,7 @@ printn(f.read_all)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
index d830b19..65a53af 100644 (file)
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
@@ -45,7 +45,7 @@ printn(f.read_all)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
@@ -75,7 +75,7 @@ printn(f.read_all)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
@@ -105,7 +105,7 @@ printn(f.read_all)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
@@ -136,7 +136,7 @@ printn(f.read_all)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
@@ -166,7 +166,7 @@ printn(f.read_all)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
index d5ff252..debcdd3 100644 (file)
@@ -774,22 +774,22 @@ Start ../src/test_parser.nit:17,1--147,1
                                 AListExprs ../src/test_parser.nit:116,44
                               TCpar ")" ../src/test_parser.nit:116,45
                       ABlockExpr ../src/test_parser.nit:118,4--121,5
-                        AVardeclExpr ../src/test_parser.nit:118,4--31
+                        AVardeclExpr ../src/test_parser.nit:118,4--33
                           TKwvar "var" ../src/test_parser.nit:118,4--6
                           TId "f" ../src/test_parser.nit:118,8
                           TAssign "=" ../src/test_parser.nit:118,10
-                          ANewExpr ../src/test_parser.nit:118,12--31
+                          ANewExpr ../src/test_parser.nit:118,12--33
                             TKwnew "new" ../src/test_parser.nit:118,12--14
-                            AType ../src/test_parser.nit:118,16--23
-                              TClassid "IFStream" ../src/test_parser.nit:118,16--23
-                            TId "open" ../src/test_parser.nit:118,25--28
-                            AParExprs ../src/test_parser.nit:118,29--31
-                              TOpar "(" ../src/test_parser.nit:118,29
-                              ACallExpr ../src/test_parser.nit:118,30
-                                AImplicitSelfExpr ../src/test_parser.nit:118,30
-                                TId "a" ../src/test_parser.nit:118,30
-                                AListExprs ../src/test_parser.nit:118,30
-                              TCpar ")" ../src/test_parser.nit:118,31
+                            AType ../src/test_parser.nit:118,16--25
+                              TClassid "FileReader" ../src/test_parser.nit:118,16--25
+                            TId "open" ../src/test_parser.nit:118,27--30
+                            AParExprs ../src/test_parser.nit:118,31--33
+                              TOpar "(" ../src/test_parser.nit:118,31
+                              ACallExpr ../src/test_parser.nit:118,32
+                                AImplicitSelfExpr ../src/test_parser.nit:118,32
+                                TId "a" ../src/test_parser.nit:118,32
+                                AListExprs ../src/test_parser.nit:118,32
+                              TCpar ")" ../src/test_parser.nit:118,33
                         ACallAssignExpr ../src/test_parser.nit:119,4--32
                           AImplicitSelfExpr ../src/test_parser.nit:119,4
                           TId "source" ../src/test_parser.nit:119,4--9
index 36dd49b..32c94e3 100644 (file)
@@ -641,13 +641,13 @@ Read token at ../src/test_parser.nit:118,4--6 text='var'
 Read token at ../src/test_parser.nit:118,8 text='f'
 Read token at ../src/test_parser.nit:118,10 text='='
 Read token at ../src/test_parser.nit:118,12--14 text='new'
-Read token at ../src/test_parser.nit:118,16--23 text='IFStream'
-Read token at ../src/test_parser.nit:118,24 text='.'
-Read token at ../src/test_parser.nit:118,25--28 text='open'
-Read token at ../src/test_parser.nit:118,29 text='('
-Read token at ../src/test_parser.nit:118,30 text='a'
-Read token at ../src/test_parser.nit:118,31 text=')'
-Read token at ../src/test_parser.nit:118,32--119,0 text='
+Read token at ../src/test_parser.nit:118,16--25 text='FileReader'
+Read token at ../src/test_parser.nit:118,26 text='.'
+Read token at ../src/test_parser.nit:118,27--30 text='open'
+Read token at ../src/test_parser.nit:118,31 text='('
+Read token at ../src/test_parser.nit:118,32 text='a'
+Read token at ../src/test_parser.nit:118,33 text=')'
+Read token at ../src/test_parser.nit:118,34--119,0 text='
 '
 Read token at ../src/test_parser.nit:119,4--9 text='source'
 Read token at ../src/test_parser.nit:119,11 text='='
index 8d11236..deb07b7 100644 (file)
@@ -124,7 +124,7 @@ var tests = new Array[Serializable].with_items(a, b, c, d, e, fi, ff)
 #alt1# tests = new Array[Serializable].with_items(a, b, c, d)
 
 for o in tests do
-       var stream = new StringOStream
+       var stream = new StringWriter
        var serializer = new JsonSerializer(stream)
        serializer.serialize(o)
 
index f64fed1..950e113 100644 (file)
@@ -15,9 +15,9 @@
 # limitations under the License.
 
 "out/test_directory_create.write/tmp_dir".mkdir
-var f =  new OFStream.open("out/test_directory_create.write/tmp_file")
+var f =  new FileWriter.open("out/test_directory_create.write/tmp_file")
 f.write("test")
 f.close
-f =  new OFStream.open("out/test_directory_create.write/tmp_dir/tmp_file_2")
+f =  new FileWriter.open("out/test_directory_create.write/tmp_dir/tmp_file_2")
 f.write("other test")
 f.close
index da3bf84..efb94b7 100644 (file)
@@ -22,14 +22,14 @@ print hw.status
 
 print ""
 
-var ip = new IProcess("echo", "B hello world!")
+var ip = new ProcessReader("echo", "B hello world!")
 ip.read_line.output
 ip.wait
 print ip.status
 
 print ""
 
-var op = new OProcess.from_a("cat", null)
+var op = new ProcessWriter.from_a("cat", null)
 op.write("C hello world!\n")
 op.close
 op.wait
@@ -37,7 +37,7 @@ print op.status
 
 print ""
 
-var iop = new IOProcess.from_a("cat", null)
+var iop = new ProcessDuplex.from_a("cat", null)
 iop.write("D hello world!\n")
 iop.read_line.output
 iop.close
@@ -52,7 +52,7 @@ print e1.status
 
 print ""
 
-var ioperr = new IOProcess.from_a("bad command", null)
+var ioperr = new ProcessDuplex.from_a("bad command", null)
 ioperr.write("D hello world!\n")
 ioperr.read_line.output
 ioperr.close
index 6de686a..0754f10 100644 (file)
@@ -16,9 +16,9 @@
 
 import file
 
-var fd_in = new IFStream.from_fd(0)
-var fd_out = new OFStream.from_fd(1)
-var fd_err = new OFStream.from_fd(2)
+var fd_in = new FileReader.from_fd(0)
+var fd_out = new FileWriter.from_fd(1)
+var fd_err = new FileWriter.from_fd(2)
 
 fd_out.write("Hello\n")
 
index 632da3c..0d8a256 100644 (file)
@@ -21,6 +21,6 @@ var src = "test_file_copy.nit"
 var dst = "{dir}/copy.nit"
 src.file_copy_to dst
 
-var file = new IFStream.open(dst)
+var file = new FileReader.open(dst)
 printn file.read_all
 file.close
index f71ed82..8e932d3 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var ifs = new IFStream.open("donotcreate.bing")
+var ifs = new FileReader.open("donotcreate.bing")
 
 var s = ifs.read_all
 
index 453a844..cffc2d2 100644 (file)
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 var s: String
 while not f.eof do
     s = f.read_line
index bc2943b..f4778b1 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new IFStream.open("test_file_read.nit")
+var f = new FileReader.open("test_file_read.nit")
 print f.read_all
 
 print "---"
 
-f = new IFStream.open("test_file_read.nit")
+f = new FileReader.open("test_file_read.nit")
 print f.read_lines.join("\n")
 
 print "---"
 
-f = new IFStream.open("test_file_read.nit")
+f = new FileReader.open("test_file_read.nit")
 print f.each_line.to_a.join("\n")
 
 print "---"
index 5a8f936..d6f02b1 100644 (file)
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-var f = new OFStream.open("out/test_file_write.write")
+var f = new FileWriter.open("out/test_file_write.write")
    f.write("Quatre vingt et un : {421}\n")
    f.write("Une autre ligne\nencore un")
    f.write(['e', '\n'].to_s)
index 59a449d..3a2c85a 100644 (file)
@@ -20,16 +20,16 @@ import filter_stream
 var filename_1 = "out/test_filterstream_tmp1.write"
 var filename_2 = "out/test_filterstream_tmp2.write"
 
-var output_file_1 = new OFStream.open(filename_1)
-var output_file_2 = new OFStream.open(filename_2)
+var output_file_1 = new FileWriter.open(filename_1)
+var output_file_2 = new FileWriter.open(filename_2)
 
 var stream_demux = new StreamDemux(output_file_1, output_file_2)
 
 stream_demux.write("Hello World !!\n")
 stream_demux.close
 
-var input_file_1 = new IFStream.open(filename_1)
-var input_file_2 = new IFStream.open(filename_2)
+var input_file_1 = new FileReader.open(filename_1)
+var input_file_2 = new FileReader.open(filename_2)
 
 var stream_cat = new StreamCat(input_file_1,input_file_2)
 
index cae1cd1..9400641 100644 (file)
@@ -14,7 +14,7 @@
 
 import for_abuse
 
-var escape_f: nullable IStream = null
+var escape_f: nullable Reader = null
 for f in file_open("test_for_abuse.nit") do
        escape_f = f
        print f.read_line
index 59aac77..1d3de0a 100644 (file)
@@ -95,7 +95,7 @@ var d = new D(false, 'b', 123.123, 2345, "new line ->\n<-", null, 1111, "\t\f\"\
 d.d = d
 
 for o in new Array[Serializable].with_items(a, b, c, d) do
-       var stream = new StringOStream
+       var stream = new StringWriter
        var serializer = new JsonSerializer(stream)
        serializer.serialize(o)
 
index 7981d06..3d5094c 100644 (file)
@@ -21,11 +21,11 @@ var p1
 var p2
 var p3
 
-p1 = new IProcess( "sleep", "0.2" )
-p2 = new IProcess( "sleep", "0.1" )
-p3 = new IProcess( "sleep", "0.4" )
+p1 = new ProcessReader( "sleep", "0.2" )
+p2 = new ProcessReader( "sleep", "0.1" )
+p3 = new ProcessReader( "sleep", "0.4" )
 
-var order = new Array[FStream]
+var order = new Array[FileStream]
 var streams = [p1.stream_in, p2.stream_in, p3.stream_in]
 
 while not streams.is_empty do
@@ -33,7 +33,7 @@ while not streams.is_empty do
        if s == null then continue # may have been interrupted
 
        order.add( s )
-       streams.remove( s.as(IFStream ) )
+       streams.remove( s.as(FileReader ) )
 end
 
 print order[0] == p2.stream_in