Merge: Generalized class members
authorJean Privat <jean@pryen.org>
Thu, 26 Feb 2015 02:23:18 +0000 (09:23 +0700)
committerJean Privat <jean@pryen.org>
Thu, 26 Feb 2015 02:23:18 +0000 (09:23 +0700)
This PR change the way class members are parsed.

Before, the order was strict: class annotations, then extern code block, then super clauses, then properties.
After, annotations and super clauses can appear in any order within the properties

The need is to enable class annotations inside the class (cf #1158) I did not find another simple way to do this.

Now, one can write
~~~nit
class B
   super A
   serializable
   var i: Int
   autoinit x, i
end
~~~

Pull-Request: #1159
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>

156 files changed:
benchmarks/bench_engines.sh
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/nitrpg.user.js [new file with mode: 0644]
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/parser/parser_nodes.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 571d71f..61b6ba4 100755 (executable)
@@ -57,7 +57,8 @@ function run_compiler()
                bench_command "nitc-g" "nitc --global --no-cc ../src/nitls.nit" "./nitc.$title.bin" -v --global --no-cc ../src/nitls.nit
                bench_command "nitc-s" "nitc --separate ../src/nitc.nit" "./nitc.$title.bin" -v --no-cc --separate ../src/nitc.nit
                run_command "$@" ../src/nit.nit -o "nit.$title.bin"
-               bench_command "nit" "nit ../src/test_parser.nit ../src/nitls.nit" "./nit.$title.bin" -v ../src/test_parser.nit -- -n ../src/nitls.nit
+               bench_command "nit-queens" "nit queens.nit 8" "./nit.$title.bin" ../lib/ai/examples/queens.nit -q 8
+               bench_command "nit-nitcc" "nit nitcc.nit calc.sablecc" "./nit.$title.bin" ../contrib/nitcc/src/nitcc.nit ../contrib/nitcc/examples/calc.sablecc
                run_command "$@" ../src/nitdoc.nit -o "nitdoc.$title.bin"
                rm -r out 2> /dev/null
                mkdir out 2> /dev/null
@@ -72,6 +73,8 @@ function run_compiler()
                bench_command "queens" "bench_queens 13" "./queens.$title.bin" 13
                run_command "$@" "../lib/ai/examples/puzzle.nit" -o "puzzle.$title.bin"
                bench_command "puzzle" "puzzle 15-hard" "./puzzle.$title.bin" kleg.mondcafjhbi
+               run_command "$@" "markdown/engines/nitmd/nitmd.nit" -o "nitmd.$title.bin"
+               bench_command "nitmd" "markdown" "./nitmd.$title.bin" markdown/benches/out/mixed.md 80
        fi
 
        rm -r *.bin .nit_compile out
@@ -119,6 +122,11 @@ fi
 # get the bootstrapped nitc
 cp ../bin/nitc .
 
+if test -z "$fast"; then
+       make -C markdown/benches
+       make -C ../contrib/nitcc
+fi
+
 ## EFFECTIVE BENCHS ##
 
 function bench_steps()
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/nitrpg.user.js b/contrib/nitrpg/nitrpg.user.js
new file mode 100644 (file)
index 0000000..4440ea9
--- /dev/null
@@ -0,0 +1,33 @@
+// ==UserScript==
+// @name        Github.com - Add RPG tab
+// @namespace   nitlanguage/github/rpg
+// @description Adds a "Github RPG" Tab at the end of the tabs.
+// @include     https://github.com/privat/nit*
+// @version     1
+// @grant       none
+// ==/UserScript==
+
+/* This script is a userscript to use in browsers with the appropriate plug-in to add a "RPG" tab on the github site.
+*/
+
+/* TODO:
+ * Link to the player page (if logged and is a player)
+ * Link to other games (not just `privat/nit` but other)
+*/
+
+// The nav bar with tabs
+var nav = document.getElementsByClassName('repo-nav');
+
+// The new tab
+var html = '<li class="tooltipped tooltipped-w" aria-label="Github RPG">\
+    <a href="http://nitlanguage.org/rpg/games/privat/nit" aria-label="RPG" class="js-selected-navigation-item sunken-menu-item" data-selected-links="repo_settings /privat/nit/settings">\
+          <span class="octicon octicon-ruby"></span> <span class="full-word">Github RPG</span>\
+          <img alt="" class="mini-loader" height="16" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-32.gif" width="16">\
+</a></li>';
+
+// Create a new list to put the new tab
+var group = document.createElement('ul');
+group.setAttribute( 'class', 'sunken-menu-group' );
+group.innerHTML = html;
+
+nav[0].appendChild(group);
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 5d93adf..a643192 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 63913fe..270c185 100644 (file)
@@ -17,6 +17,7 @@
 module parser_nodes
 
 import location
+import ordered_tree
 
 # Root of the AST class-hierarchy
 abstract class ANode
@@ -33,6 +34,15 @@ abstract class ANode
                sys.stderr.write "{hot_location} {self.class_name}: {message}\n{hot_location.colored_line("0;32")}\n"
        end
 
+       # Write the subtree on stdout.
+       # See `ASTDump`
+       fun dump_tree
+       do
+               var d = new ASTDump
+               d.enter_visit(self)
+               d.write_to(sys.stdout)
+       end
+
        # Parent of the node in the AST
        var parent: nullable ANode = null
 
@@ -158,6 +168,33 @@ private class CollectAnnotationsByNameVisitor
        end
 end
 
+# A helper class to handle (print) Nit AST as an OrderedTree
+class ASTDump
+       super Visitor
+       super OrderedTree[ANode]
+
+       # Reference to the last parent in the Ordered Tree
+       # Is used to handle the initial node parent and workaround possible inconsistent `ANode::parent`
+       private var last_parent: nullable ANode = null
+
+       redef fun visit(n)
+       do
+               var p = last_parent
+               add(p, n)
+               last_parent = n
+               n.visit_all(self)
+               last_parent = p
+       end
+
+       redef fun display(n)
+       do
+               if n isa Token then
+                       return "{n.class_name} \"{n.text.escape_to_c}\" @{n.location}"
+               else
+                       return "{n.class_name} @{n.location}"
+               end
+       end
+end
 
 # A sequence of nodes
 # It is a specific class (instead of using a Array) to track the parent/child relation when nodes are added or removed
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 628689b..36503ed 100644 (file)
@@ -775,22 +775,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