A suggestion of @Morriar is to use a class-level annotation `autoinit` to list initializers.
It should ne rarely used, in case of conflict for instance, or to restrict the number of initializers (but this could be fragile).
A step towards #785
~~~nit
class A
var a: Int
var b: String
end
class B
autoinit c, b, a
super A
var c: Bool
end
var a = new A(10, "foo")
var b = new B(true, "foo", 10)
~~~
Some issues remains, I my require your input on these
* why I am required to put `autoinit` before the `super` clause?
because the grammar is ugly.
Maybe I should find a way to enable the `autoinit` clause everywhere in the body of the class?
This is a grammar issue that can be solved independently I think.
* what are the validity of initializers?
The first commit is used to discriminate properties that are initializers and those that are not.
I am not sure if restricting what can be used an initializer makes sense. In fact I really do not know what is the best expressive-but-safe policy here. See the last point for a related issue
* what about clearing the full list of initializers (so no parameters in the new)?
The annotation `noautoinit` will do the trick.
* what about setters?
when one writes `class A var x: Int`, in fact the initializer is not the getter `x` but the setter `x=`. It is obvious once one understand that `var a = new A(10)` is just `var a = alloc A; a.x = 10; a.init`.
However, I chose to implicitly try to search the setter first when given `x` as an element of the `autoinit` clause, so that one can write `autoinit x` instead of the less POLA `autoinit x=` (that also works by the way).
Unfortunately this kind of heuristic makes the specification more complex, but also prevents one to use a method `x` as an initializer if a method `x=` exists.
Pull-Request: #1158
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
}
bench_compilation_time
+function bench_linkboost()
+{
+ name="$FUNCNAME"
+ skip_test "$name" && return
+ prepare_res "$name-nitc-st.dat" "nitc-st" "nitc with --separate --trampoline-call"
+ run_compiler "nitc-st" ./nitc --separate --trampoline-call
+ prepare_res "$name-nitc-s.dat" "nitc-s" "nitc with --separate"
+ run_compiler "nitc-s" ./nitc --separate
+ prepare_res "$name-nitc-sc.dat" "nitc-sc" "nitc with --separate --colors-are-symbols"
+ run_compiler "nitc-sc" ./nitc --separate --colors-are-symbols
+ prepare_res "$name-nitc-sct.dat" "nitc-sct" "nitc with --separate --colors-are-symbols --trampoline-call"
+ run_compiler "nitc-sct" ./nitc --separate --colors-are-symbols --trampoline-call
+ prepare_res "$name-nitc-sl.dat" "nitc-sl" "nitc with --separate --link-boost"
+ run_compiler "nitc-scts" ./nitc --separate --link-boost
+ prepare_res "$name-nitc-sg.dat" "nitc-sg" "nitc with --separate --semi-global"
+ run_compiler "nitc-sg" ./nitc --separate --semi-global
+ plot "$name.gnu"
+}
+bench_linkboost
+
if test -n "$html"; then
echo >>"$html" "</body></html>"
fi
middle = (dept + 1) / 2
end
- var file: nullable OFStream = null
+ var file: nullable FileWriter = null
fun write(str: String)
do
file.write(str)
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
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"
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"
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} \{"
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>"
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"
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"
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"
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
return response
end
- var stream = new StringOStream
+ var stream = new StringWriter
var serializer = new JsonSerializer(stream)
serializer.serialize events
var serialized = stream.to_s
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
# 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
# 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
# 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
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
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
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)
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
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
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)
# 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")
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")
var text
if fi != "-" then
- var f = new IFStream.open(fi)
+ var f = new FileReader.open(fi)
text = f.read_all
f.close
else
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
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
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}}}
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
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
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
# 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
# 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]
# 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
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
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)
# 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\">"
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)
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)
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
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
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
--- /dev/null
+# 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
# 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
#
# 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
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
# 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
#
# 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
# 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
super GameReactor
redef fun react_event(game, e) do
- super # log events
e.react_stats_event(game)
end
end
# Panels templates for `nitpg`.
module panels
-import templates_base
+import templates_events
# A panel can be displayed in a html page.
#
redef fun render_title do
add "<span class=\"glyphicon glyphicon-home\"></span> "
- add "<a href=\"{game.url}\">{game.name}</a>"
+ add "{game.link}"
end
redef fun render_body do
add "<a href=\"{player.url}\">"
add " <img class=\"img-circle\" style=\"width: 30px\""
add " src=\"{player.user.avatar_url}\" alt=\"{player.name}\">"
- add "</a> "
- add "<a href=\"{player.url}\">{player.name}</a>"
+ add "</a> {player.link}"
end
redef fun render_body do
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
end
(new PlayerCoinComparator).sort(players)
for player in players do
- add "<a href=\"{player.url}\">"
- add player.name
- add "</a> ({player.nitcoins})<br>"
+ add "{player.nitcoins} - {player.link}<br>"
end
end
end
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
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>
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> "
+ 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
# 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
--- /dev/null
+# 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
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.
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
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
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)
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
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">
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)
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")
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" )
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" )
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
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
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
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
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
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)
# 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
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)
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)
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 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
# 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)
# 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
# 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)
# A CSV document representation.
class CsvDocument
- super Streamable
+ super Writable
# The format to use.
#
# * `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
# * `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
# 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([""])
class CsvWriter
# The output stream.
- var ostream: OStream
+ var ostream: Writer
# The format to use.
#
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
# 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
super Iterator[Array[String]]
# The input stream.
- var istream: IStream
+ var istream: Reader
# The format to use.
#
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
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
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)
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} " +
# 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
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
end
class StreamCat
- super FilterIStream
- private var streams: Iterator[IStream]
+ super FilterReader
+ private var streams: Iterator[Reader]
redef fun eof: Bool
do
end
end
- redef fun stream: nullable IStream
+ redef fun stream: nullable Reader
do
var res = super
if res == null and _streams.is_ok then
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
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
# 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
# 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
# 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
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
# 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
# An HTML element.
class HTMLTag
- super Streamable
+ super Writable
# HTML element type.
#
# 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
# 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
# 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.
#
super PushBackReader
# The parent stream.
- var parent: IStream
+ var parent: Reader
# The stack of the pushed-back bytes.
#
super TestSuite
private fun sample: PushBackDecorator do
- return new PushBackDecorator(new StringIStream("""
+ return new PushBackDecorator(new StringReader("""
abcd
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
end
fun test_eof_empty do
- var subject = new PushBackDecorator(new StringIStream(""))
+ var subject = new PushBackDecorator(new StringReader(""))
assert subject.eof
end
# 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?
#
# 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?
#
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
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
super Serializer
# Target writing stream
- var stream: OStream
+ var stream: Writer
redef fun serialize(object)
do
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
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
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
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
# 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
exit 0
end
-var ifs = new IFStream.open(file)
+var ifs = new FileReader.open(file)
var md = ifs.read_all
ifs.close
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
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
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
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]]]`
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.
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)
# 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
#
# 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
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
# 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
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
# 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
# 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")
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
end
text = args.shift
else
- var f = new IFStream.open(filepath)
+ var f = new FileReader.open(filepath)
text = f.read_all
f.close
end
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
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
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
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
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
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
# 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)
# 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)
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]
# 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)
#
# 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]
# 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
# 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
# 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.
#
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
# 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
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
# 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
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
# 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
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
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
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
#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
# 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
#
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.
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
# Standard input stream.
class Stdin
- super IFStream
+ super FileReader
init do
_file = new NativeFile.native_stdin
# Standard output stream.
class Stdout
- super OFStream
+ super FileWriter
init do
_file = new NativeFile.native_stdout
path = "/dev/stdout"
# Standard error stream.
class Stderr
- super OFStream
+ super FileWriter
init do
_file = new NativeFile.native_stderr
path = "/dev/stderr"
###############################################################################
-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
# 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
# print content
# ~~~
#
- # See `IStream::read_all` for details.
+ # See `Reader::read_all` for details.
fun read_all: String
do
var s = open_ro
# end
# ~~~
#
- # See `IStream::read_lines` for details.
+ # See `Reader::read_lines` for details.
fun read_lines: Array[String]
do
var s = open_ro
#
# 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
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"
# 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
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
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
#
# ~~~
# 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"
#
# ~~~
# 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"
#
# ~~~
# var txt = "Hello\n\nWorld\n"
- # var i = new StringIStream(txt)
+ # var i = new StringReader(txt)
# assert i.read_lines == ["Hello", "", "World"]
# ~~~
#
#
# ~~~
# var txt = "Hello\n\nWorld\n"
- # var i = new StringIStream(txt)
+ # var i = new StringReader(txt)
# assert i.each_line.to_a == ["Hello", "", "World"]
# ~~~
#
# 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"
#
# ~~~
# 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
#
# ~~~
# 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"
# 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)
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
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
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)
#
# 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
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
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
# 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
end
end
-redef class OFStream
+redef class FileWriter
redef fun write(s)
do
assert is_writable
end
end
-redef class OFStream
+redef class FileWriter
redef fun write(s)
do
assert is_writable
# 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")
# 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
# 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
# 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
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
end
private class TemplateStringIterator
- super MapIterator[String, nullable Streamable]
+ super MapIterator[String, nullable Writable]
var subject: TemplateString
var key_it: Iterator[String] is noinit
#
# # 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.
#
# class LnkTmpl
# super Template
-# var text: Streamable
+# var text: Writable
# var title: nullable String
# var href: String
# redef fun rendering do
# 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.
#
# 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
# 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
# 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`.
# 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
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
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
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"
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)
(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.
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
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
: Do not compile dead methods (semi-global).
Need `--rta`.
+## LINK-BOOST OPTIMIZATIONS
+
+In `--separate` and in `--erasure` modes, some optimization can be gained by hijacking the linker process.
+
+Warning: these optimisations are not portable since they use extra features of the GNU linker `ld`.
+However, there is very few reasons to not use them if GNU `ld` is available.
+
+`--link-boost`
+: Enable all link-boost optimizations.
+
+`--colors-are-symbols`
+: Store colors as symbols instead of static data.
+
+ By default, the various identifiers used to implement OO-mechanisms are stored as genuine constant static variables.
+
+ This option uses linker symbols to encode these identifiers.
+ This makes the compiled program faster since less indirections are required to get the values.
+ It also produces executables that are a little bit smaller since static memory does not have to store the colors.
+
+`--substitute-monomorph`
+: Replace monomorphic trampolines with direct call.
+
+ Late-binding is implemented with *trampolines*, that are small functions that just select and jump the to right implementations.
+ If, at link-time, is it known that the target will always by the same implementation then all calls to the trampoline are replaced by
+ direct calls to this single implementation.
+
+ Note that using trampolines as indirection slows down the executable.
+ However, it is expected that the gain of monomorphic direct-calls overcompensates the additional indirections in polymorphic trampoline-calls.
+
+ Note: automatically enable option `--trampoline-call`.
## DANGEROUS OPTIMIZATIONS
`--colo-dead-methods`
: Force colorization of dead methods.
-`--colors-are-symbols`
-: Store colors as symbols instead of static data.
-
- By default, the various identifiers used to implement OO-mechanisms are stored as genuine constant static variables.
-
- This option uses linker symbols to encode these identifiers.
- This makes the compiled program faster since less indirections are required to get the values.
- It also produces executables that are a little bit smaller since static memory does not have to store the colors.
-
- Warning: the usage of linker symbols is not portable on all toolchains (eg. Mac OS X).
- Also, this option does nothing on some platforms (like android).
-
`--no-gcc-directive`
: Disable advanced gcc directives for optimization.
+`--trampoline-call`
+: Use an indirection when calling.
+
+ Just add the trampolines of `--substitute-monomorph` without doing any aditionnal optimizations.
## INTERNAL OPTIONS
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 )
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 )
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"
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
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
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
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
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"
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")
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
var opt_no_union_attribute = new OptionBool("Put primitive attibutes in a box instead of an union", "--no-union-attribute")
# --no-shortcut-equate
var opt_no_shortcut_equate = new OptionBool("Always call == in a polymorphic way", "--no-shortcut-equal")
+
# --colors-are-symbols
- var opt_colors_are_symbols = new OptionBool("Store colors as symbols (faster)", "--colors-are-symbols")
+ var opt_colors_are_symbols = new OptionBool("Store colors as symbols (link-boost)", "--colors-are-symbols")
+ # --trampoline-call
+ var opt_trampoline_call = new OptionBool("Use an indirection when calling", "--trampoline-call")
+ # --substitute-monomorph
+ var opt_substitute_monomorph = new OptionBool("Replace monomorph trampoline with direct call (link-boost)", "--substitute-monomorph")
+ # --link-boost
+ var opt_link_boost = new OptionBool("Enable all link-boost optimizations", "--link-boost")
# --inline-coloring-numbers
var opt_inline_coloring_numbers = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers")
self.option_context.add_option(self.opt_separate)
self.option_context.add_option(self.opt_no_inline_intern)
self.option_context.add_option(self.opt_no_union_attribute)
- self.option_context.add_option(self.opt_no_shortcut_equate, opt_colors_are_symbols)
+ self.option_context.add_option(self.opt_no_shortcut_equate)
+ self.option_context.add_option(opt_colors_are_symbols, opt_trampoline_call, opt_substitute_monomorph, opt_link_boost)
self.option_context.add_option(self.opt_inline_coloring_numbers, opt_inline_some_methods, opt_direct_call_monomorph, opt_skip_dead_methods, opt_semi_global)
self.option_context.add_option(self.opt_colo_dead_methods)
self.option_context.add_option(self.opt_tables_metrics)
tc.opt_direct_call_monomorph.value = true
tc.opt_skip_dead_methods.value = true
end
+ if tc.opt_link_boost.value then
+ tc.opt_colors_are_symbols.value = true
+ tc.opt_substitute_monomorph.value = true
+ end
+ if tc.opt_substitute_monomorph.value then
+ tc.opt_trampoline_call.value = true
+ end
end
var separate_compiler_phase = new SeparateCompilerPhase(self, null)
r.compile_to_c(self)
var r2 = pd.virtual_runtime_function
if r2 != r then r2.compile_to_c(self)
+
+ # Generate trampolines
+ if modelbuilder.toolcontext.opt_trampoline_call.value then
+ r2.compile_trampolines(self)
+
+ # Replace monomorphic call to a trampoline by a direct call to the virtual implementation
+ if modelbuilder.toolcontext.opt_substitute_monomorph.value then do
+ var m = pd.mproperty
+ if rta == null then
+ # Without RTA, monomorphic means alone (uniq name)
+ if m.mpropdefs.length != 1 then break label
+ else
+ # With RTA, monomorphic means only live methoddef
+ if not rta.live_methoddefs.has(pd) then break label
+ for md in m.mpropdefs do
+ if md != pd and rta.live_methoddefs.has(md) then break label
+ end
+ end
+ # Here the trick, GNU ld can substitute symbols with specific values.
+ var n2 = "CALL_" + m.const_color
+ linker_script.add("{n2} = {r2.c_name};")
+ end label
+ end
end
end
self.mainmodule = old_module
return res
end
- return table_send(mmethod, arguments, mmethod.const_color)
+ return table_send(mmethod, arguments, mmethod)
end
# Handle common special cases before doing the effective method invocation
return res
end
- private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
+ private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], mentity: MEntity): nullable RuntimeVariable
do
compiler.modelbuilder.nb_invok_by_tables += 1
if compiler.modelbuilder.toolcontext.opt_invocation_metrics.value then add("count_invoke_by_tables++;")
ss.append(", {a}")
end
- self.require_declaration(const_color)
- var call = "(({runtime_function.c_ret} (*){runtime_function.c_sig})({arguments.first}->class->vft[{const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/"
+ var const_color = mentity.const_color
+ var call
+ if not compiler.modelbuilder.toolcontext.opt_trampoline_call.value then
+ self.require_declaration(const_color)
+ call = "(({runtime_function.c_funptrtype})({arguments.first}->class->vft[{const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/"
+ else
+ var callsym = "CALL_" + const_color
+ self.require_declaration(callsym)
+ call = "{callsym}({ss}) /* {mmethod} on {arguments.first.inspect}*/"
+ end
if res != null then
self.add("{res} = {call};")
self.compiler.mainmodule = main
return res
end
- return table_send(m.mproperty, arguments, m.const_color)
+ return table_send(m.mproperty, arguments, m)
end
redef fun vararg_instance(mpropdef, recv, varargs, elttype)
return sig.to_s
end
+ # The C type for the function pointer.
+ var c_funptrtype: String is lazy do return "{c_ret}(*){c_sig}"
+
+ # The arguments, as generated by `compile_to_c`
+ private var arguments: Array[RuntimeVariable] is noinit
+
redef fun compile_to_c(compiler)
do
var mmethoddef = self.mmethoddef
comment.append(": {ret}")
end
compiler.provide_declaration(self.c_name, "{sig};")
+ self.arguments = arguments.to_a
v.add_decl("/* method {self} for {comment} */")
v.add_decl("{sig} \{")
v.add("\}")
compiler.names[self.c_name] = "{mmethoddef.full_name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})"
end
+
+ # Compile the trampolines used to implement late-binding.
+ #
+ # See `opt_trampoline_call`.
+ fun compile_trampolines(compiler: SeparateCompiler)
+ do
+ var recv = self.mmethoddef.mclassdef.bound_mtype
+ var selfvar = arguments.first
+ var ret = called_signature.return_mtype
+
+ if mmethoddef.is_intro and recv.ctype == "val*" then
+ var m = mmethoddef.mproperty
+ var n2 = "CALL_" + m.const_color
+ compiler.provide_declaration(n2, "{c_ret} {n2}{c_sig};")
+ var v2 = compiler.new_visitor
+ v2.add "{c_ret} {n2}{c_sig} \{"
+ v2.require_declaration(m.const_color)
+ var call = "(({c_funptrtype})({selfvar}->class->vft[{m.const_color}]))({arguments.join(", ")});"
+ if ret != null then
+ v2.add "return {call}"
+ else
+ v2.add call
+ end
+
+ v2.add "\}"
+
+ end
+ if mmethoddef.has_supercall and recv.ctype == "val*" then
+ var m = mmethoddef
+ var n2 = "CALL_" + m.const_color
+ compiler.provide_declaration(n2, "{c_ret} {n2}{c_sig};")
+ var v2 = compiler.new_visitor
+ v2.add "{c_ret} {n2}{c_sig} \{"
+ v2.require_declaration(m.const_color)
+ var call = "(({c_funptrtype})({selfvar}->class->vft[{m.const_color}]))({arguments.join(", ")});"
+ if ret != null then
+ v2.add "return {call}"
+ else
+ v2.add call
+ end
+
+ v2.add "\}"
+ end
+ end
end
redef class MEntity
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>"
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\">"
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
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]
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.
#
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
end
# Add a raw content to the menu
- fun add_raw(content: Streamable) do
+ fun add_raw(content: Writable) do
elts.add content
end
# 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
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
super TplSummaryElt
# Text to display
- var text: Streamable
+ var text: Writable
# Children of this entry
# Will be displayed as a tree
# 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
# 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
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
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'>"
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
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
# 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(" ")}'>"
# 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
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
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"))
# 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
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
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
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
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
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
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}")
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
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"
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"
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
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
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
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
# Wrapper for `NativeFile`
class PrimitiveNativeFile
- var file: IOS
+ var file: Stream
init native_stdin do
file = sys.stdin
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
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
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
var string: String is noinit
# The original stream used to initialize `string`
- var stream: IStream
+ var stream: Reader
init
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
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
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
# 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
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
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
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
# 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
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
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
# 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"
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 = ""
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
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")
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
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")
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
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
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(", ")}]"
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
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
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
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"
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
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
#
# 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
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"
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
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
import emscripten
-redef class IFStream
+redef class FileReader
redef fun fill_buffer
do
print "NOT YET IMPLEMENTED"
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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
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
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='='
#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)
# 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
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
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
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
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")
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
# 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
# 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
# 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 "---"
# 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)
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)
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
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)
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
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