From: Jean Privat Date: Wed, 14 Jan 2015 01:16:51 +0000 (-0500) Subject: Merge: Websockets X-Git-Tag: v0.7.1~30 X-Git-Url: http://nitlanguage.org?hp=fae2f024edb5497c02384c928143f0fa28cecc95 Merge: Websockets Fixed websockets with the new and improved sockets. While I'm at it, changed a bit the way it works, the old one was a bit (a lot ?) quick and dirty, so here's that. Pull-Request: #1096 Reviewed-by: Jean Privat Reviewed-by: Alexandre Terrasa --- diff --git a/lib/android/README.md b/lib/android/README.md new file mode 100644 index 0000000..1f4e659 --- /dev/null +++ b/lib/android/README.md @@ -0,0 +1,108 @@ +The `android` module provides support for the Android platform + +# Compilation for Android + +The compiler generates an APK file as the output when the `android` +module is imported by the compilation target. The path to the generated +file can be specified using the `-o` and `--dir` options. + +# Host system configuration + +To compile for Android, you must install the Android SDK and NDK. +The tools `android`, `ndk-build` and `ant` must be in your PATH. + +# Configure your Android application + +The `app.nit` framework and this project offers some services to +customized the generated Android application. + +## Module annotations + +* `app_version` specifies the version of the generated APK file. +It takes 3 arguments: the major, minor and revision version numbers. +The special function `git_revision` will use the prefix of the hash of the +latest git commit. The default version is 1.0. + + Example: `app_version(1, 0, git_revision)` + +* `app_name` takes a single argument, the visible name of the Android +application. By default, the compiler would use the name of the target +module. This name will be used as the name of the main activity and +as the launcher name. + + Example: `app_name "My App"` + +* `java_package` specifies the package used by the generated Java +classes and the APK file. Once the application is published, this +value should not be changed. By default, the compiler will use +the package `org.nitlanguage.{module_name}`. + +* Custom information can be added to the Android manifest file +using the annotations `android_manifest`, `android_manifest_application` +and `android_manifest_activity`. + + Example usage to specify an extra permission: + + ~~~ + android_manifest """""" + ~~~ + +* The API version target can be specified with `min_api_version`, +`max_api_version` and `target_api_version`. These take a single +integer as argument. They are applied in the Android manifest as +`minSdkVesion`, `targetSdkVersion` and `maxSdkVersion`. + + See http://developer.android.com/guide/topics/manifest/uses-sdk-element.html + +## Project entry points + +Importing `android::landscape` or `android::portrait` locks the generated +application in the specified orientation. This can be useful for games and +other multimedia applications. + +# Compilation modes + +There are two compilation modes for the Android platform, debug and release. +Theses modes are also applied to the generated Android projects. +The compilation mode is specified as an argument to `nitc`, only +`--release` can be specified as debug is the default behavior. + +## Debug mode + +Debug mode enables compiling to an APK file without handling signing keys +and their password. The APK file can be installed to a local device with +USB debugging enabled, but it cannot be published on the Play Store. + +By default, `nitc` will compile Android applications in debug mode. + +## Release mode + +Building in release mode will use your private key to sign the +APK file, it can then be published on the Play Store. + +1. Have a keystore with a valid key to sign your APK file. + + To create a new keystore, avoid using the default values of `jarsigner` +as they change between versions of the Java SDK. You should instead use a +command similar to the following, replacing `KEYSTORE_PATH` and `KEY_ALIAS` +with the desired values. + + ~~~ + keytool -genkey -keystore KEYSTORE_PATH -alias KEY_ALIAS -sigalg MD5withRSA -keyalg RSA -keysize 1024 -validity 10000 + ~~~ + +2. Set the environment variables used by `nitc`: `KEYSTORE`, `KEY_ALIAS` and +optionally `TSA_SERVER`. These settings can be set in a startup script such as +`~/.bashrc` or in a local Makefile. + + You can use the following commands by replacing the right hand values +to your own configuration. + + ~~~ + export KEYSTORE=keystore_path + export KEY_ALIAS=key_alias + export TSA_SERVER=timestamp_authority_server_url # Optional + ~~~ + +3. Call `nitc` with the `--release` options. You will be prompted for the +required passwords as needed by `jarsigner`. diff --git a/lib/android/android.nit b/lib/android/android.nit index 5523f30..584b89b 100644 --- a/lib/android/android.nit +++ b/lib/android/android.nit @@ -16,10 +16,6 @@ # Android services and implementation of app.nit # -# To use this module and compile for Android, you must install the -# Android SDK (with API level 10) and NDK (with the API level 9). -# The tools `android`, `ndk-build` and `ant` must be in your PATH. -# # This module provides basic logging facilities, advanced logging can be # achieved by importing `android::log`. module android diff --git a/lib/array_debug.nit b/lib/array_debug.nit index f112d7a..4d2edb4 100644 --- a/lib/array_debug.nit +++ b/lib/array_debug.nit @@ -21,6 +21,7 @@ redef class Sys # Keeps the average length of an Array when calling to_s var arr_len = new Counter[Int] + # Compute the average array length. fun avg_arr_len: Float do var total = 0 var sum = 0 @@ -31,6 +32,7 @@ redef class Sys return sum.to_f / total.to_f end + # Compute the average string length. fun avg_s_len: Float do var total = 0 var sum = 0 @@ -41,6 +43,7 @@ redef class Sys return sum.to_f / total.to_f end + # Display statistics in standard output. fun print_stats do if arr_len.sum == 0 then print "*** No Array stats ***" diff --git a/lib/bucketed_game.nit b/lib/bucketed_game.nit index 703ff5c..ae0d792 100644 --- a/lib/bucketed_game.nit +++ b/lib/bucketed_game.nit @@ -179,8 +179,6 @@ class Game # but cannot be used to add new Events. var last_turn: nullable ThinGameTurn[G] = null - init do end - # Execute and return a new GameTurn. # # This method calls `do_pre_turn` before executing the GameTurn diff --git a/lib/curl/curl.nit b/lib/curl/curl.nit index bca105c..c087642 100644 --- a/lib/curl/curl.nit +++ b/lib/curl/curl.nit @@ -85,8 +85,7 @@ class CurlHTTPRequest curl.prim_curl.easy_setopt(new CURLOption.user_agent, name) end - init (url: String, curl: nullable Curl) - do + init (url: String, curl: nullable Curl) is old_style_init do self.url = url self.curl = curl end @@ -211,8 +210,7 @@ class CurlMailRequest var body: nullable String = "" is writable private var supported_outgoing_protocol: Array[String] = ["smtp", "smtps"] - init (curl: nullable Curl) - do + init (curl: nullable Curl) is old_style_init do self.curl = curl end @@ -351,12 +349,6 @@ class CurlResponseFailed var error_code: Int var error_msg: String - - init (err_code: Int, err_msg: String) - do - self.error_code = err_code - self.error_msg = err_msg - end end # Success Abstract Response Success Class @@ -467,7 +459,7 @@ class HeaderMapIterator super MapIterator[String, String] private var iterator: Iterator[Couple[String, String]] - init(map: HeaderMap) do self.iterator = map.arr.iterator + init(map: HeaderMap) is old_style_init do self.iterator = map.arr.iterator redef fun is_ok do return self.iterator.is_ok redef fun next do self.iterator.next diff --git a/lib/filter_stream.nit b/lib/filter_stream.nit index 2797b67..8fb57fd 100644 --- a/lib/filter_stream.nit +++ b/lib/filter_stream.nit @@ -5,7 +5,7 @@ # # This file is free software, which comes along with NIT. This software is # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. You can modify it is you want, provided this header # is kept unaltered, and a notification of the changes is added. # You are allowed to redistribute it and sell it, alone or is a part of @@ -83,8 +83,8 @@ class StreamCat do _streams = streams.iterator end - init(streams: IStream ...) - do + + init(streams: IStream ...) is old_style_init do _streams = streams.iterator end end @@ -133,8 +133,7 @@ class StreamDemux _streams = streams end - init(streams: OStream ...) - do + init(streams: OStream ...) is old_style_init do _streams = streams end end diff --git a/lib/github/api.nit b/lib/github/api.nit index 138b079..9a9b4b1 100644 --- a/lib/github/api.nit +++ b/lib/github/api.nit @@ -203,6 +203,39 @@ class GithubAPI return commit end + # Get the Github issue #`number`. + # + # Returns `null` if the issue cannot be found. + # + # var api = new GithubAPI(get_github_oauth) + # var repo = api.load_repo("privat/nit") + # assert repo != null + # var issue = api.load_issue(repo, 1) + # assert issue.title == "Doc" + fun load_issue(repo: Repo, number: Int): nullable Issue do + var issue = new Issue(self, repo, number) + issue.load_from_github + if was_error then return null + return issue + end + + # Get the Github pull request #`number`. + # + # Returns `null` if the pull request cannot be found. + # + # var api = new GithubAPI(get_github_oauth) + # var repo = api.load_repo("privat/nit") + # assert repo != null + # var pull = api.load_pull(repo, 1) + # assert pull.title == "Doc" + # assert pull.user.login == "Morriar" + fun load_pull(repo: Repo, number: Int): nullable PullRequest do + var pull = new PullRequest(self, repo, number) + pull.load_from_github + if was_error then return null + return pull + end + # Get the Github label with `name`. # # Returns `null` if the label cannot be found. @@ -332,6 +365,31 @@ class Repo return res end + # List of issues associated with their ids. + fun issues: Map[Int, Issue] do + api.message(1, "Get issues for {full_name}") + var res = new HashMap[Int, Issue] + var issue = last_issue + if issue == null then return res + res[issue.number] = issue + while issue.number > 1 do + issue = api.load_issue(self, issue.number - 1) + assert issue isa Issue + res[issue.number] = issue + end + return res + end + + # Get the last published issue. + fun last_issue: nullable Issue do + var array = api.get("repos/{full_name}/issues") + if not array isa JsonArray then return null + if array.is_empty then return null + var obj = array.first + if not obj isa JsonObject then return null + return new Issue.from_json(api, self, obj) + end + # List of labels associated with their names. fun labels: Map[String, Label] do api.message(1, "Get labels for {full_name}") @@ -361,6 +419,28 @@ class Repo return res end + # List of pull-requests associated with their ids. + # + # Implementation notes: because PR numbers are not consecutive, + # PR are loaded from pages. + # See: https://developer.github.com/v3/pulls/#list-pull-requests + fun pulls: Map[Int, PullRequest] do + api.message(1, "Get pulls for {full_name}") + var res = new HashMap[Int, PullRequest] + var page = 1 + var array = api.get("{key}/pulls?page={page}").as(JsonArray) + while not array.is_empty do + for obj in array do + if not obj isa JsonObject then continue + var number = obj["number"].as(Int) + res[number] = new PullRequest.from_json(api, self, obj) + end + page += 1 + array = api.get("{key}/pulls?page={page}").as(JsonArray) + end + return res + end + # Repo default branch. fun default_branch: Branch do var name = json["default_branch"].to_s @@ -494,6 +574,194 @@ class Commit fun message: String do return json["commit"].as(JsonObject)["message"].to_s end +# A Github issue. +# +# Should be accessed from `GithubAPI::load_issue`. +# +# See . +class Issue + super RepoEntity + + redef var key is lazy do return "{repo.key}/issues/{number}" + + # Issue Github ID. + var number: Int + + redef init from_json(api, repo, json) do + self.number = json["number"].as(Int) + super + end + + # Issue title. + fun title: String do return json["title"].to_s + + # User that created this issue. + fun user: User do + return new User.from_json(api, json["user"].as(JsonObject)) + end + + # List of labels on this issue associated to their names. + fun labels: Map[String, Label] do + var res = new HashMap[String, Label] + for obj in json["labels"].as(JsonArray) do + if not obj isa JsonObject then continue + var name = obj["name"].to_s + res[name] = new Label.from_json(api, repo, obj) + end + return res + end + + # State of the issue on Github. + fun state: String do return json["state"].to_s + + # Is the issue locked? + fun locked: Bool do return json["locked"].as(Bool) + + # Assigned `User` (if any). + fun assignee: nullable User do + var assignee = json["assignee"] + if not assignee isa JsonObject then return null + return new User.from_json(api, assignee) + end + + # `Milestone` (if any). + fun milestone: nullable Milestone do + var milestone = json["milestone"] + if not milestone isa JsonObject then return null + return new Milestone.from_json(api, repo, milestone) + end + + # Number of comments on this issue. + fun comments_count: Int do return json["comments"].to_s.to_i + + # Creation time in ISODate format. + fun created_at: ISODate do + return new ISODate.from_string(json["created_at"].to_s) + end + + # Last update time in ISODate format (if any). + fun updated_at: nullable ISODate do + var res = json["updated_at"] + if res == null then return null + return new ISODate.from_string(res.to_s) + end + + # Close time in ISODate format (if any). + fun closed_at: nullable ISODate do + var res = json["closed_at"] + if res == null then return null + return new ISODate.from_string(res.to_s) + end + + # TODO link to pull request + + # Full description of the issue. + fun body: String do return json["body"].to_s + + # User that closed this issue (if any). + fun closed_by: nullable User do + var closer = json["closed_by"] + if not closer isa JsonObject then return null + return new User.from_json(api, closer) + end +end + +# A Github pull request. +# +# Should be accessed from `GithubAPI::load_pull`. +# +# PullRequest are basically Issues with more data. +# See . +class PullRequest + super Issue + + redef var key is lazy do return "{repo.key}/pulls/{number}" + + # Merge time in ISODate format (if any). + fun merged_at: nullable ISODate do + var res = json["merged_at"] + if res == null then return null + return new ISODate.from_string(res.to_s) + end + + # Merge commit SHA. + fun merge_commit_sha: String do return json["merge_commit_sha"].to_s + + # Count of comments made on the pull request diff. + fun review_comments: Int do return json["review_comments"].to_s.to_i + + # Pull request head (can be a commit SHA or a branch name). + fun head: PullRef do + var json = json["head"].as(JsonObject) + return new PullRef(api, json) + end + + # Pull request base (can be a commit SHA or a branch name). + fun base: PullRef do + var json = json["base"].as(JsonObject) + return new PullRef(api, json) + end + + # Is this pull request merged? + fun merged: Bool do return json["merged"].as(Bool) + + # Is this pull request mergeable? + fun mergeable: Bool do return json["mergeable"].as(Bool) + + # Mergeable state of this pull request. + # + # See . + fun mergeable_state: Int do return json["mergeable_state"].to_s.to_i + + # User that merged this pull request (if any). + fun merged_by: nullable User do + var merger = json["merged_by"] + if not merger isa JsonObject then return null + return new User.from_json(api, merger) + end + + # Count of commits in this pull request. + fun commits: Int do return json["commits"].to_s.to_i + + # Added line count. + fun additions: Int do return json["additions"].to_s.to_i + + # Deleted line count. + fun deletions: Int do return json["deletions"].to_s.to_i + + # Changed files count. + fun changed_files: Int do return json["changed_files"].to_s.to_i +end + +# A pull request reference (used for head and base). +class PullRef + + # Api instance that maintains self. + var api: GithubAPI + + # JSON representation. + var json: JsonObject + + # Label pointed by `self`. + fun labl: String do return json["label"].to_s + + # Reference pointed by `self`. + fun ref: String do return json["ref"].to_s + + # Commit SHA pointed by `self`. + fun sha: String do return json["sha"].to_s + + # User pointed by `self`. + fun user: User do + return new User.from_json(api, json["user"].as(JsonObject)) + end + + # Repo pointed by `self`. + fun repo: Repo do + return new Repo.from_json(api, json["repo"].as(JsonObject)) + end +end + # A Github label. # # Should be accessed from `GithubAPI::load_label`. diff --git a/lib/ini.nit b/lib/ini.nit index 60d2f12..71868b6 100644 --- a/lib/ini.nit +++ b/lib/ini.nit @@ -37,10 +37,7 @@ class ConfigTree # The ini file used to read/store data var ini_file: String - init(file: String) do - self.ini_file = file - if file.file_exists then load - end + init do if ini_file.file_exists then load # Get the config value for `key` # @@ -103,7 +100,6 @@ class ConfigTree # assert config.has_key("foo.bar") # assert not config.has_key("zoo") fun has_key(key: String): Bool do - var children = roots var parts = key.split(".").reversed var node = get_root(parts.pop) if node == null then return false @@ -223,7 +219,6 @@ class ConfigTree private var roots = new Array[ConfigNode] private fun set_node(key: String, value: nullable String) do - var children = roots var parts = key.split(".").reversed var k = parts.pop var root = get_root(k) @@ -250,7 +245,6 @@ class ConfigTree end private fun get_node(key: String): nullable ConfigNode do - var children = roots var parts = key.split(".").reversed var node = get_root(parts.pop) while not parts.is_empty do @@ -283,14 +277,11 @@ class ConfigTree end private class ConfigNode - var parent: nullable ConfigNode + + var parent: nullable ConfigNode = null var children = new HashMap[String, ConfigNode] var name: String is writable - var value: nullable String - - init(name: String) do - self.name = name - end + var value: nullable String = null fun key: String do if parent == null then diff --git a/lib/json/static.nit b/lib/json/static.nit index bb578fd..12dbc7c 100644 --- a/lib/json/static.nit +++ b/lib/json/static.nit @@ -34,12 +34,28 @@ interface Jsonable # SEE: `append_json` fun to_json: String is abstract + # Use `append_json` to implement `to_json`. + # + # Therefore, one that redefine `append_json` may use the following + # redefinition to link `to_json` and `append_json`: + # + # ~~~nitish + # redef fun to_json do return to_json_by_append + # ~~~ + # + # Note: This is not the default implementation of `to_json` in order to + # avoid cyclic references between `append_json` and `to_json` when none are + # implemented. + protected fun to_json_by_append: String do + var buffer = new RopeBuffer + append_json(buffer) + return buffer.write_to_string + end + # Append the JSON representation of `self` to the specified buffer. # # SEE: `to_json` - fun append_json(buffer: Buffer) do - buffer.append(to_json) - end + fun append_json(buffer: Buffer) do buffer.append(to_json) end redef class Text @@ -82,11 +98,7 @@ redef class Text # # assert "\t\"http://example.com\"\r\n\0\\".to_json == # "\"\\t\\\"http:\\/\\/example.com\\\"\\r\\n\\u0000\\\\\"" - redef fun to_json do - var buffer = new FlatBuffer - append_json(buffer) - return buffer.write_to_string - end + redef fun to_json do return to_json_by_append # Parse `self` as JSON. # @@ -211,11 +223,7 @@ interface JsonMapRead[K: String, V: nullable Jsonable] # obj = new JsonObject # obj["baz"] = null # assert obj.to_json == "\{\"baz\":null\}" - redef fun to_json do - var buffer = new FlatBuffer - append_json(buffer) - return buffer.write_to_string - end + redef fun to_json do return to_json_by_append private fun append_json_entry(iterator: MapIterator[String, nullable Jsonable], buffer: Buffer) do @@ -259,11 +267,7 @@ class JsonSequenceRead[E: nullable Jsonable] # assert arr.to_json =="[\"foo\"]" # arr.pop # assert arr.to_json =="[]" - redef fun to_json do - var buffer = new FlatBuffer - append_json(buffer) - return buffer.write_to_string - end + redef fun to_json do return to_json_by_append private fun append_json_entry(iterator: Iterator[nullable Jsonable], buffer: Buffer) do diff --git a/lib/more_collections.nit b/lib/more_collections.nit index 1bcc514..6396ec2 100644 --- a/lib/more_collections.nit +++ b/lib/more_collections.nit @@ -29,7 +29,7 @@ module more_collections # assert m.has_key("four") # assert m["four"] == ['i', 'i', 'i', 'i'] # assert m["zzz"] == new Array[Char] -class MultiHashMap[K: Object, V] +class MultiHashMap[K, V] super HashMap[K, Array[V]] # Add `v` to the array associated with `k`. @@ -59,7 +59,7 @@ end # assert hm2[1, "one"] == 1.0 # assert hm2[2, "not-two"] == null # ~~~~ -class HashMap2[K1: Object, K2: Object, V] +class HashMap2[K1, K2, V] private var level1 = new HashMap[K1, HashMap[K2, V]] # Return the value associated to the keys `k1` and `k2`. @@ -97,7 +97,7 @@ end # assert hm3[1, "one", 11] == 1.0 # assert hm3[2, "not-two", 22] == null # ~~~~ -class HashMap3[K1: Object, K2: Object, K3: Object, V] +class HashMap3[K1, K2, K3, V] private var level1 = new HashMap[K1, HashMap2[K2, K3, V]] # Return the value associated to the keys `k1`, `k2`, and `k3`. @@ -165,7 +165,7 @@ end # assert dma["b"] == [65, 66] # assert dma.default == [65] # ~~~~ -class DefaultMap[K: Object, V] +class DefaultMap[K, V] super HashMap[K, V] # The default value. diff --git a/lib/neo4j/graph/graph.nit b/lib/neo4j/graph/graph.nit new file mode 100644 index 0000000..39063f2 --- /dev/null +++ b/lib/neo4j/graph/graph.nit @@ -0,0 +1,278 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# This file is free software, which comes along with NIT. This software is +# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. You can modify it is you want, provided this header +# is kept unaltered, and a notification of the changes is added. +# You are allowed to redistribute it and sell it, alone or is a part of +# another product. + +# Provides an interface for services on a Neo4j graphs. +module neo4j::graph::graph + +import neo4j +import progression + +# A Neo4j graph with a local identification scheme for its nodes. +# +# An identification scheme can be defined by subclassing `NeoNodeCollection`. +# +# `GraphStore` can be subclassed to add ways to save or load a graph. The +# storing mechanisms may use `nodes.id_of` to identify the nodes in the graph +# while encoding the relationships. +class NeoGraph + # All the nodes in the graph. + var nodes: NeoNodeCollection + + # All the relationships in the graph. + var edges: SimpleCollection[NeoEdge] = new Array[NeoEdge] + + # Add a new node to the graph and return it. + # + # Set the local ID of the node before returning it. + # + # SEE: `NeoNodeCollection.add` + # SEE: `NeoNodeCollection.create_node` + # SEE: `NeoNodeCollection.register` + fun create_node: NeoNode do return nodes.create_node +end + +# All the nodes in a `NeoGraph`. +# +# An identification scheme can be defined throught the `register` and `add` +# methods. The `id_property` attribute defines where the local ID (that is the +# ID managed by the collection) is stored in each node. +abstract class NeoNodeCollection + super SimpleCollection[NeoNode] + + # The type of the local IDs. + type ID_TYPE: Jsonable + + # The property of the nodes that hold the local ID. + var id_property: String + + # Retrieve the node that has the specified local id. + # + # Note: The default implementation uses `get_or_null`. + fun [](id: ID_TYPE): NeoNode do + var n = get_or_null(id) + assert n isa NeoNode + return n + end + + # Retrieve the node that has the specified local id, or return `null`. + # + # Note: The default implementation uses `iterator`. + fun get_or_null(id: ID_TYPE): nullable NeoNode do + for n in self do + if id_of(n) == id then return n + end + return null + end + + # There is a node that has the specified local id? + # + # Note: The default implementation uses `get_or_null`. + fun has_id(id: ID_TYPE): Bool do return get_or_null(id) isa NeoNode + + # Return the local ID of the node. + fun id_of(node: NeoNode): ID_TYPE do return node[id_property].as(ID_TYPE) + + # Set the local ID of the specified node. + # + # Just update the property at `property_id`. Do not check anything. + protected fun id_of=(node: NeoNode, id: ID_TYPE) do + node[id_property] = id + end + + # Enlarge the collection to have at least the specified capacity. + # + # The capacity is specified in number of nodes. Used to minimize the + # number of times the collection need to be resized when adding nodes + # in batches. + # + # Do nothing by default. + fun enlarge(cap: Int) do end + + # Add the specified node to the graph and set its local ID. + # + # SEE: `add` + # SEE: `create_node` + fun register(node: NeoNode) is abstract + + # Add the specified node to the graph assuming that its local ID is already set. + # + # SEE: `create_node` + # SEE: `register` + redef fun add(node: NeoNode) is abstract + + # Add a new node to the graph and return it. + # + # Set the local ID of the node before returning it. + # + # SEE: `add` + # SEE: `register` + fun create_node: NeoNode do + var node = new NeoNode + register(node) + return node + end + + # Remove the node with the specified local ID. + fun remove_at(id: ID_TYPE) is abstract + + # Remove the specified node. + # + # The local ID is used instead of `==` to seek the node. + fun remove_node(node: NeoNode) do + remove_at(id_of(node)) + end + + redef fun clear do + for node in self do remove_node(node) + end + + redef fun remove(node: NeoNode) do + for n in self do + if node == n then + remove_node(n) + return + end + end + end + + redef fun remove_all(node: NeoNode) do + for n in self do + if node == n then remove_node(n) + end + end + + # Optimize the collection, possibly by rewritting it. + # + # The local ID of the elements may be changed by this method. + fun compact do end +end + +# A mean to save and load a Neo4j graph. +abstract class GraphStore + super Trackable + + # The graph to save or load. + var graph: NeoGraph + + # Can we save the graph without conflict? + fun isolated_save: Bool is abstract + + # Load the graph (or a part of it). + # + # Do not reset the graph. + fun load is abstract + + # Save the graph. + fun save do save_part(graph.nodes, graph.edges) + + # Save the specified part of the graph. + # + # Assume that for each relationship specified, both ends are already saved + # or are specified in the same call to this method. + fun save_part(nodes: Collection[NeoNode], + edges: Collection[NeoEdge]) is abstract +end + +# Save or load a graph using an actual Neo4j database. +class Neo4jGraphStore + super GraphStore + + # The maximum number of entities saved in one request. + # + # Also defines the granulity of the reported progression. + # + # TODO Also honor this limit in `load`. + var batch_max_size = 512 is writable + + # The Neo4j client to use. + var client: Neo4jClient + + # The label to use to retrieve the nodes. + var node_label: String + + private var done_part = 0 + private var total = 0 + + # Is the database already contains at least one node with the specified label? + fun has_node_label(name: String): Bool do + var query = new CypherQuery.from_string( + "match n where \{name\} in labels(n) return count(n)") + query.params["name"] = name + var data = client.cypher(query).as(JsonObject)["data"] + var result = data.as(JsonArray).first.as(JsonArray).first.as(Int) + return result > 0 + end + + redef fun isolated_save do return not has_node_label(node_label) + + redef fun load do + assert batch_max_size > 0 + fire_started + var db_nodes = client.nodes_with_label(node_label) + var nodes = graph.nodes + var edges = graph.edges + var i = 0 + + total = nodes.length * 2 + done_part = nodes.length + fire_progressed(done_part, total) + for node in db_nodes do + nodes.add(node) + edges.add_all(node.out_edges) + i += 1 + if i >= batch_max_size then + done_part += batch_max_size + fire_progressed(done_part, total) + end + end + fire_done + end + + redef fun save_part(nodes, edges) do + assert batch_max_size > 0 + fire_started + total = nodes.length + edges.length + done_part = 0 + + save_entities(nodes) + save_entities(edges) + fire_done + end + + # Save the specified entities. + private fun save_entities(neo_entities: Collection[NeoEntity]) do + var batch = new NeoBatch(client) + var batch_length = 0 + + for nentity in neo_entities do + batch.save_entity(nentity) + batch_length += 1 + if batch_length >= batch_max_size then + do_batch(batch) + done_part += batch_max_size + fire_progressed(done_part, total) + batch = new NeoBatch(client) + batch_length = 0 + end + end + do_batch(batch) + done_part += batch_length + end + + # Execute `batch` and check for errors. + # + # Abort if `batch.execute` returns errors. + private fun do_batch(batch: NeoBatch) do + var errors = batch.execute + assert errors.is_empty else + for e in errors do sys.stderr.write("{e}\n") + end + end +end diff --git a/lib/neo4j/graph/json_graph_store.nit b/lib/neo4j/graph/json_graph_store.nit new file mode 100644 index 0000000..9c97216 --- /dev/null +++ b/lib/neo4j/graph/json_graph_store.nit @@ -0,0 +1,321 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# This file is free software, which comes along with NIT. This software is +# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. You can modify it is you want, provided this header +# is kept unaltered, and a notification of the changes is added. +# You are allowed to redistribute it and sell it, alone or is a part of +# another product. + +# Provides JSON as a mean to store graphs. +module neo4j::graph::json_graph_store + +import graph + +# Save or load a graph using a JSON document. +# +# The graph (or the specified part of it) is stored as a JSON object with the +# following properties: +# +# * `"nodes"`: An array with all nodes. Each node is an object with the +# following properties: +# * `"labels"`: An array of all applied labels. +# * `"properties"`: An object mapping each defined property to its value. +# * `"edges"`: An array with all relationships. Each relationship is an object +# with the following properties: +# * `"type"`: The type (`String`) of the relationship. +# * `"properties"`: An object mapping each defined property to its value. +# * `"from"`: The local ID of the source node. +# * `"to"`: The local ID of the destination node. +# +# ~~~nit +# import neo4j::graph::sequential_id +# +# var graph = new NeoGraph(new SequentialNodeCollection("nid")) +# var a = new NeoNode +# a.labels.add "Foo" +# a["answer"] = 42 +# a["Ultimate question of"] = new JsonArray.from(["life", +# "the Universe", "and Everything."]) +# graph.nodes.register a +# var b = graph.create_node +# b.labels.add "Foo" +# b.labels.add "Bar" +# graph.edges.add new NeoEdge(a, "BAZ", b) +# +# var ostream = new StringOStream +# var store = new JsonGraphStore(graph) +# store.ostream = ostream +# store.save +# assert ostream.to_s == """{"nodes":[""" + """ +# {"labels":["Foo"],"properties":{"answer":42,""" + """ +# "Ultimate question of":["life","the Universe","and Everything."],""" + """ +# "nid":1}},""" + """ +# {"labels":["Foo","Bar"],"properties":{"nid":2}}],""" + """ +# "edges":[{"type":"BAZ","properties":{},"from":1,"to":2}]}""" +# +# graph.nodes.clear +# graph.edges.clear +# store.istream = new StringIStream(ostream.to_s) +# store.load +# assert 1 == graph.edges.length +# for edge in graph.edges do +# assert "BAZ" == edge.rel_type +# assert a.labels == edge.from.labels +# for k, v in a.properties do assert v == edge.from.properties[k] +# assert b.labels == edge.to.labels +# for k, v in b.properties do assert v == edge.to.properties[k] +# end +# assert 2 == graph.nodes.length +# ~~~ +class JsonGraphStore + super GraphStore + + # The stream to use for `load`. + var istream: nullable IStream = null is writable + + # The stream to use for `save` and `save_part`. + var ostream: nullable OStream = null is writable + + # Use the specified `IOStream`. + init from_io(graph: NeoGraph, iostream: IOStream) do + init(graph) + istream = iostream + ostream = iostream + end + + # Use the specified string to load the graph. + init from_string(graph: NeoGraph, string: String) do + init(graph) + istream = new StringIStream(string) + end + + redef fun isolated_save do return true + + redef fun load do + var istream = self.istream + assert istream isa IStream + fire_started + graph.load_json(istream.read_all) + fire_done + end + + redef fun save_part(nodes, edges) do + var ostream = self.ostream + assert ostream isa OStream + fire_started + ostream.write(graph.to_json) + fire_done + end +end + +redef class NeoGraph + super Jsonable + + # Retrieve the graph from the specified JSON document. + # + # For the expected format, see `JsonGraphStore`. + # + # ~~~nit + # import neo4j::graph::sequential_id + # + # var graph = new NeoGraph(new SequentialNodeCollection("node_id")) + # var a = new NeoNode + # a.labels.add "Foo" + # a["answer"] = 42 + # a["Ultimate question of"] = new JsonArray.from(["life", + # "the Universe", "and Everything."]) + # graph.nodes.register a + # var b = graph.create_node + # b.labels.add "Foo" + # b.labels.add "Bar" + # graph.edges.add new NeoEdge(a, "BAZ", b) + # + # graph = new NeoGraph.from_json( + # new SequentialNodeCollection("node_id"), graph.to_json) + # assert 1 == graph.edges.length + # for edge in graph.edges do + # assert "BAZ" == edge.rel_type + # assert a.labels == edge.from.labels + # for k, v in a.properties do assert v == edge.from.properties[k] + # assert b.labels == edge.to.labels + # for k, v in b.properties do assert v == edge.to.properties[k] + # end + # assert 2 == graph.nodes.length + # ~~~ + init from_json(nodes: NeoNodeCollection, t: Text) do + from_json_object(nodes, t.parse_json.as(JsonObject)) + end + + # Retrieve the graph from the specified JSON object. + # + # For the expected format, see `JsonGraphStore`. + init from_json_object(nodes: NeoNodeCollection, o: JsonObject) do + init(nodes) + load_json_object(o) + end + + # Retrieve a part of the graph from the specified JSON document. + # + # For the expected format, see `JsonGraphStore`. + fun load_json(t: Text) do + load_json_object(t.parse_json.as(JsonObject)) + end + + # Retrieve a part of the graph from the specified JSON object. + # + # For the expected format, see `JsonGraphStore`. + fun load_json_object(o: JsonObject) do + var json_nodes = o["nodes"].as(JsonArray) + var nodes = self.nodes + nodes.enlarge(nodes.length) + for json_node in json_nodes do + assert json_node isa JsonObject + var node = new NeoNode.from_json_object(json_node) + nodes.add node + end + + var json_edges = o["edges"].as(JsonArray) + var edges = self.edges + if edges isa AbstractArray[NeoEdge] then edges.enlarge(edges.length) + for json_edge in json_edges do + assert json_edge isa JsonObject + var from = nodes[nodes.id_from_jsonable(json_edge["from"])] + var to = nodes[nodes.id_from_jsonable(json_edge["to"])] + var rel_type = json_edge["type"].as(String) + var json_properties = json_edge["properties"].as(JsonObject) + var edge = new NeoEdge(from, rel_type, to) + edge.properties.recover_with(json_properties) + edges.add edge + end + end + + redef fun to_json do return to_json_by_append + + # Append the JSON representation of `self` to the specified buffer. + # + # For a description of the format, see `JsonGraphStore`. + # + # SEE: `to_json` + redef fun append_json(b) do + b.append "\{\"nodes\":[" + append_entities_json(nodes, b) + b.append "],\"edges\":[" + append_entities_json(edges, b) + b.append "]\}" + end + + # Encode `self` in JSON. + # + # For a description of the format, see `JsonGraphStore`. + # + # SEE: `append_json` + private fun append_entities_json(entities: Collection[NeoEntity], + b: Buffer) do + var i = entities.iterator + if i.is_ok then + i.item.append_json_for(self, b) + i.next + for entity in i do + b.add ',' + entity.append_json_for(self, b) + end + end + end +end + +redef class NeoNodeCollection + # Convert the specified JSON value into a local ID. + fun id_from_jsonable(id: nullable Jsonable): ID_TYPE do return id.as(ID_TYPE) +end + +redef class NeoEntity + + # Append the JSON representation of the entity to the specified buffer. + fun append_json_for(graph: NeoGraph, buffer: Buffer) is abstract +end + +# Make `NeoNode` `Jsonable`. +redef class NeoNode + super Jsonable + + # Retrieve the node from the specified JSON value. + # + # Note: Here, the `"id"` is optional and ignored. + # + # SEE: `JsonGraph` + # + # var node = new NeoNode.from_json(""" + # { + # "labels": ["foo", "Bar"], + # "properties": { + # "baz": 42 + # } + # } + # """) + # assert ["foo", "Bar"] == node.labels + # assert 42 == node["baz"] + init from_json(t: Text) do + from_json_object(t.parse_json.as(JsonObject)) + end + + # Retrieve the node from the specified JSON value. + # + # Note: Here, the `"id"` is optional and ignored. + # + # SEE: `JsonGraph` + init from_json_object(o: JsonObject) do + init + var labels = o["labels"].as(JsonArray) + for lab in labels do self.labels.add(lab.as(String)) + var json_properties = o["properties"].as(JsonObject) + properties.recover_with(json_properties) + end + + redef fun to_json do return to_json_by_append + + # Append the JSON representation of the node to the specified buffer. + # + # SEE: `JsonGraph` + redef fun append_json(b) do + b.append "\{\"labels\":[" + var i = labels.iterator + if i.is_ok then + i.item.append_json(b) + i.next + for lab in i do + b.add ',' + lab.append_json(b) + end + end + b.append "],\"properties\":" + properties.append_json(b) + b.add '}' + end + + redef fun to_s do return to_json + + # Append the JSON representation of the node to the specified buffer. + redef fun append_json_for(graph: NeoGraph, buffer: Buffer) do + append_json(buffer) + end +end + +redef class NeoEdge + + # Append the JSON representation of the relationship to the specified buffer. + # + # Use the IDs specfied by `graph.nodes`. + redef fun append_json_for(graph: NeoGraph, buffer: Buffer) do + buffer.append "\{\"type\":" + rel_type.append_json(buffer) + buffer.append ",\"properties\":" + properties.append_json(buffer) + buffer.append ",\"from\":" + graph.nodes.id_of(from).append_json(buffer) + buffer.append ",\"to\":" + graph.nodes.id_of(to).append_json(buffer) + buffer.append "}" + end +end diff --git a/lib/neo4j/graph/sequential_id.nit b/lib/neo4j/graph/sequential_id.nit new file mode 100644 index 0000000..fb6129f --- /dev/null +++ b/lib/neo4j/graph/sequential_id.nit @@ -0,0 +1,116 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# This file is free software, which comes along with NIT. This software is +# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. You can modify it is you want, provided this header +# is kept unaltered, and a notification of the changes is added. +# You are allowed to redistribute it and sell it, alone or is a part of +# another product. + +# Provides a sequential identification scheme for Neo4j nodes. +module neo4j::graph::sequential_id + +import graph +private import pipeline + + +# A Neo4j node collection using a sequential identification scheme. +# +# The local IDs are sequential numbers (integers) starting at `1`. +# +# Note: When loading nodes, the local IDs should forms a mostly contiguous +# range starting at `1`. Else, this collection will consume a lot of memory. +# Futhermore, the local IDs **must** be positive. +# +# ~~~nit +# var nodes = new SequentialNodeCollection("id") +# var a = nodes.create_node +# var b = new NeoNode +# var c = new NeoNode +# +# nodes.register b +# c["id"] = 4 +# nodes.add c +# assert a["id"] == 1 +# assert b["id"] == 2 +# assert c["id"] == 4 +# assert nodes.to_a == [a, b, c] +# assert nodes.length == 3 +# +# nodes.compact +# assert a["id"] == 1 +# assert b["id"] == 2 +# assert c["id"] == 3 +# assert nodes.to_a == [a, b, c] +# assert nodes.length == 3 +# ~~~ +class SequentialNodeCollection + super NeoNodeCollection + + redef type ID_TYPE: Int + + private var nodes = new Array[nullable NeoNode] + + redef var length = 0 + + redef fun iterator do return new NullSkipper[NeoNode](self.nodes.iterator) + + redef fun [](id) do return nodes[id].as(NeoNode) + + redef fun get_or_null(id) do + if id < 0 or id > nodes.length then return null + return nodes[id] + end + + redef fun has_id(id: Int): Bool do + return id >= 0 and id < nodes.length and nodes[id] isa NeoNode + end + + redef fun enlarge(cap) do nodes.enlarge(cap) + + redef fun register(node) do + nodes.add node + id_of(node) = nodes.length + length += 1 + end + + redef fun add(node) do + var id = node[id_property] + assert id isa Int else + sys.stderr.write "The local ID must be an `Int`.\n" + end + assert id >= 0 else + sys.stderr.write "The local ID must be greater or equal to 0. Got {id}.\n" + end + # Pad with nulls. + nodes.enlarge(id) + var delta = id - nodes.length + while delta > 0 do + nodes.add null + delta -= 1 + end + nodes[id] = node + length += 1 + end + + redef fun remove_at(id) do + nodes[id] = null + length -= 1 + end + + redef fun clear do + nodes.clear + length = 0 + end + + redef fun compact do + var i = iterator + + nodes = new Array[nullable NeoNode] + for n in i do + nodes.add n + id_of(n) = nodes.length + end + end +end diff --git a/lib/neo4j/json_store.nit b/lib/neo4j/json_store.nit deleted file mode 100644 index cf9f441..0000000 --- a/lib/neo4j/json_store.nit +++ /dev/null @@ -1,199 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# This file is free software, which comes along with NIT. This software is -# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. You can modify it is you want, provided this header -# is kept unaltered, and a notification of the changes is added. -# You are allowed to redistribute it and sell it, alone or is a part of -# another product. - -# Uses JSON as a storage medium for a Neo4j subgraph. -module neo4j::json_store - -import neo4j -private import template - -# A Neo4j graph that uses as a storage medium. -# -# The graph is stored as a JSON object with the following properties: -# -# * `"nodes"`: An array with all nodes. Each node is an object with the -# following properties: -# * `"id"`: The ID (`Int`) that uniquely identifies the node in the current -# graph. -# * `"labels"`: An array of all applied labels. -# * `"properties"`: An object mapping each defined property to its value. -# * `"links"`: An array with all relationships. Each relationship is an object -# with the following properties: -# * `"type"`: The type (`String`) of the relationship. -# * `"properties"`: An object mapping each defined property to its value. -# * `"from"`: The ID (`Int`) of the source node. -# * `"to"`: The ID (`Int`) of the destination node. -# -# TODO Refine the graph API instead when it will be available. -class JsonGraph - super Jsonable - - # All nodes in the graph. - var nodes: SimpleCollection[NeoNode] = new Array[NeoNode] - - # All relationships in the graph. - var links: SimpleCollection[NeoEdge] = new Array[NeoEdge] - - # Create an empty graph. - init do end - - # Retrieve the graph from the specified JSON value. - # - # var graph = new JsonGraph - # var a = new NeoNode - # a.labels.add "Foo" - # a["answer"] = 42 - # a["Ultimate question of"] = new JsonArray.from(["life", - # "the Universe", "and Everything."]) - # graph.nodes.add a - # var b = new NeoNode - # b.labels.add "Foo" - # b.labels.add "Bar" - # graph.nodes.add b - # graph.links.add new NeoEdge(a, "BAZ", b) - # # - # graph = new JsonGraph.from_json(graph.to_json) - # assert 1 == graph.links.length - # for link in graph.links do - # assert "BAZ" == link.rel_type - # assert a.labels == link.from.labels - # for k, v in a.properties do assert v == link.from.properties[k] - # assert b.labels == link.to.labels - # for k, v in b.properties do assert v == link.to.properties[k] - # end - # assert 2 == graph.nodes.length - init from_json(t: Text) do - from_json_object(t.parse_json.as(JsonObject)) - end - - # Retrieve the graph from the specified JSON object. - init from_json_object(o: JsonObject) do - var node_by_id = new HashMap[Int, NeoNode] - var nodes = o["nodes"].as(JsonArray) - for json_node in nodes do - assert json_node isa JsonObject - var node = new NeoNode.from_json_object(json_node) - node_by_id[json_node["id"].as(Int)] = node - self.nodes.add node - end - var links = o["links"].as(JsonArray) - for json_link in links do - assert json_link isa JsonObject - var from = node_by_id[json_link["from"].as(Int)] - var to = node_by_id[json_link["to"].as(Int)] - var rel_type = json_link["type"].as(String) - var json_properties = json_link["properties"].as(JsonObject) - var link = new NeoEdge(from, rel_type, to) - link.properties.recover_with(json_properties) - self.links.add link - end - end - - redef fun to_json do - var t = new Template - t.add "\{\"nodes\":[" - var i = 0 - for n in nodes do - if i > 0 then t.add "," - t.add n.to_json - i += 1 - end - t.add "],\"links\":[" - i = 0 - for link in links do - if i > 0 then t.add "," - t.add link.to_json - i += 1 - end - t.add "]\}" - return t.write_to_string - end -end - -# Make `NeoNode` `Jsonable`. -redef class NeoNode - super Jsonable - - # Retrieve the node from the specified JSON value. - # - # Note: Here, the `"id"` is optional and ignored. - # - # SEE: `JsonGraph` - # - # var node = new NeoNode.from_json(""" - # { - # "labels": ["foo", "Bar"], - # "properties": { - # "baz": 42 - # } - # } - # """) - # assert ["foo", "Bar"] == node.labels - # assert 42 == node["baz"] - init from_json(t: Text) do - from_json_object(t.parse_json.as(JsonObject)) - end - - # Retrieve the node from the specified JSON value. - # - # Note: Here, the `"id"` is optional and ignored. - # - # SEE: `JsonGraph` - init from_json_object(o: JsonObject) do - init - var labels = o["labels"].as(JsonArray) - for lab in labels do self.labels.add(lab.as(String)) - var json_properties = o["properties"].as(JsonObject) - properties.recover_with(json_properties) - end - - # Get the JSON representation of `self`. - # - # SEE: `JsonGraph` - redef fun to_json do - var t = new Template - t.add "\{\"id\":" - t.add object_id.to_json - t.add ",\"labels\":[" - var i = 0 - for lab in labels do - if i > 0 then t.add "," - t.add lab.to_json - i += 1 - end - t.add "],\"properties\":" - t.add properties.to_json - t.add "}" - return t.write_to_string - end - - redef fun to_s do return to_json -end - -# Make `NeoEdge` `Jsonable`. -redef class NeoEdge - super Jsonable - - redef fun to_json do - var t = new Template - t.add "\{\"type\":" - t.add rel_type.to_json - t.add ",\"properties\":" - t.add properties.to_json - t.add ",\"from\":" - t.add from.object_id.to_json - t.add ",\"to\":" - t.add to.object_id.to_json - t.add "}" - return t.write_to_string - end - - redef fun to_s do return to_json -end diff --git a/lib/nitcc_runtime.nit b/lib/nitcc_runtime.nit index 9c5ec01..31c0a45 100644 --- a/lib/nitcc_runtime.nit +++ b/lib/nitcc_runtime.nit @@ -374,10 +374,10 @@ end private class DephIterator super Iterator[Node] + var stack = new List[Iterator[nullable Node]] - init(i: Iterator[nullable Node]) - do + init(i: Iterator[nullable Node]) is old_style_init do stack.add i end diff --git a/lib/opts.nit b/lib/opts.nit index 8c8f9ea..fa5ce15 100644 --- a/lib/opts.nit +++ b/lib/opts.nit @@ -44,11 +44,13 @@ abstract class Option var default_value: VALUE is writable # Create a new option - init(help: String, default: VALUE, names: nullable Array[String]) - do + init(help: String, default: VALUE, names: nullable Array[String]) is old_style_init do init_opt(help, default, names) end + # Init option `helptext`, `default_value` and `names`. + # + # Also set current `value` to `default`. fun init_opt(help: String, default: VALUE, names: nullable Array[String]) do if names == null then @@ -80,6 +82,7 @@ abstract class Option return text.to_s end + # Pretty print the default value. fun pretty_default: String do var dv = default_value @@ -97,7 +100,9 @@ end # Not really an option. Just add a line of text when displaying the usage class OptionText super Option - init(text: String) do super(text, null, null) + + # Init a new OptionText with `text`. + init(text: String) is old_style_init do super(text, null, null) redef fun pretty(off) do return to_s @@ -109,7 +114,8 @@ class OptionBool super Option redef type VALUE: Bool - init(help: String, names: String...) do super(help, false, names) + # Init a new OptionBool with a `help` message and `names`. + init(help: String, names: String...) is old_style_init do super(help, false, names) redef fun read_param(it) do @@ -123,7 +129,8 @@ class OptionCount super Option redef type VALUE: Int - init(help: String, names: String...) do super(help, 0, names) + # Init a new OptionCount with a `help` message and `names`. + init(help: String, names: String...) is old_style_init do super(help, 0, names) redef fun read_param(it) do @@ -135,6 +142,8 @@ end # Option with one parameter (mandatory by default) abstract class OptionParameter super Option + + # Convert `str` to a value of type `VALUE`. protected fun convert(str: String): VALUE is abstract # Is the parameter mandatory? @@ -159,7 +168,8 @@ class OptionString super OptionParameter redef type VALUE: nullable String - init(help: String, names: String...) do super(help, null, names) + # Init a new OptionString with a `help` message and `names`. + init(help: String, names: String...) is old_style_init do super(help, null, names) redef fun convert(str) do return str end @@ -170,10 +180,14 @@ end class OptionEnum super OptionParameter redef type VALUE: Int + + # Values in the enumeration. var values: Array[String] - init(values: Array[String], help: String, default: Int, names: String...) - do + # Init a new OptionEnum from `values` with a `help` message and `names`. + # + # `default` is the index of the default value in `values`. + init(values: Array[String], help: String, default: Int, names: String...) is old_style_init do assert values.length > 0 self.values = values.to_a super("{help} <{values.join(", ")}>", default, names) @@ -190,6 +204,7 @@ class OptionEnum return id end + # Get the value name from `values`. fun value_name: String do return values[value] redef fun pretty_default @@ -203,7 +218,10 @@ class OptionInt super OptionParameter redef type VALUE: Int - init(help: String, default: Int, names: String...) do super(help, default, names) + # Init a new OptionInt with a `help` message, a `default` value and `names`. + init(help: String, default: Int, names: String...) is old_style_init do + super(help, default, names) + end redef fun convert(str) do return str.to_i end @@ -213,7 +231,10 @@ class OptionFloat super OptionParameter redef type VALUE: Float - init(help: String, default: Float, names: String...) do super(help, default, names) + # Init a new OptionFloat with a `help` message, a `default` value and `names`. + init(help: String, default: Float, names: String...) is old_style_init do + super(help, default, names) + end redef fun convert(str) do return str.to_f end @@ -224,8 +245,8 @@ class OptionArray super OptionParameter redef type VALUE: Array[String] - init(help: String, names: String...) - do + # Init a new OptionArray with a `help` message and `names`. + init(help: String, names: String...) is old_style_init do values = new Array[String] super(help, values, names) end @@ -352,6 +373,7 @@ class OptionContext end end + # Options parsing errors. fun get_errors: Array[String] do var errors = new Array[String] diff --git a/lib/pipeline.nit b/lib/pipeline.nit index be553ad..0ca08b2 100644 --- a/lib/pipeline.nit +++ b/lib/pipeline.nit @@ -159,6 +159,45 @@ redef interface Iterator[E] end end +# Wraps an iterator to skip nulls. +# +# ~~~nit +# var i: Iterator[Int] +# +# i = new NullSkipper[Int]([null, 1, null, 2, null: nullable Int].iterator) +# assert i.to_a == [1, 2] +# +# i = new NullSkipper[Int]([1, null, 2, 3: nullable Int].iterator) +# assert i.to_a == [1, 2, 3] +# ~~~ +class NullSkipper[E: Object] + super Iterator[E] + + # The inner iterator. + var inner: Iterator[nullable E] + + redef fun finish do inner.finish + + redef fun is_ok do + skip_nulls + return inner.is_ok + end + + redef fun item do + skip_nulls + return inner.item.as(E) + end + + redef fun next do + inner.next + skip_nulls + end + + private fun skip_nulls do + while inner.is_ok and inner.item == null do inner.next + end +end + # Interface that reify a function. # Concrete subclasses must implements the `apply` method. # diff --git a/lib/progression.nit b/lib/progression.nit new file mode 100644 index 0000000..b5d7f96 --- /dev/null +++ b/lib/progression.nit @@ -0,0 +1,68 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# This file is free software, which comes along with NIT. This software is +# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. You can modify it is you want, provided this header +# is kept unaltered, and a notification of the changes is added. +# You are allowed to redistribute it and sell it, alone or is a part of +# another product. + +# Event-based interface to track the progression of an operation. +module progression + +# An operation that is trackable using a `ProgressionListener`. +abstract class Trackable + + # Listen to the progression of the operation. + var progression_listeners: SimpleCollection[ProgressionListener] = + new Array[ProgressionListener] + + # Notice the registered `ProgessionListener` that the operation started. + protected fun fire_started do + for l in progression_listeners do + l.started + l.progressed(0) + end + end + + # Notice the registered `ProgessionListener` that the operation progressed. + # + # Parameter: + # + # * `done_part`: Indicates what is done. + # * `total`: Indicates what need to be done, `done_part` included. + protected fun fire_progressed(done_part: Int, total: Int) do + for l in progression_listeners do + l.progressed(done_part * l.progression_max / total) + end + end + + # Notice the registered `ProgessionListener` that the operation is done. + protected fun fire_done do + for l in progression_listeners do + l.progressed(l.progression_max) + l.done + end + end +end + +# Listens to the progression of a possibly long-running operation. +interface ProgressionListener + # The number that represents a completed operation. + fun progression_max: Int do return 100 + + # The operation started. + fun started do end + + # The operation progressed. + # + # Parameter: + # + # * `progression`: Indicator of the progession, between `0` and + # `progression_max`. + fun progressed(progression: Int) do end + + # The operation is done. + fun done do end +end diff --git a/lib/scene2d.nit b/lib/scene2d.nit index b01c3e5..aa567e8 100644 --- a/lib/scene2d.nit +++ b/lib/scene2d.nit @@ -48,9 +48,16 @@ class Sprite # height of the sprite var height: Int = 100 is writable + # X coordinate of left side. fun left: Int do return x - width/2 + + # X coordinate of right side. fun right: Int do return x + width/2 + + # Y coordinate of top. fun top: Int do return y - height/2 + + # Y coordinate of bottom. fun bottom: Int do return y + height/2 # x velocity (applied by `update') @@ -102,10 +109,6 @@ class LiveGroup[E: LiveObject] super LiveObject super List[E] - init - do - end - # Recursively update each live objects that `exists' redef fun update do diff --git a/lib/socket/socket.nit b/lib/socket/socket.nit index 69bd449..d9bc5a3 100644 --- a/lib/socket/socket.nit +++ b/lib/socket/socket.nit @@ -66,7 +66,11 @@ class TCPStream closed = true return end - socket.setsockopt(new NativeSocketOptLevels.socket, new NativeSocketOptNames.reuseaddr, 1) + if not socket.setsockopt(new NativeSocketOptLevels.socket, new NativeSocketOptNames.reuseaddr, 1) then + end_reached = true + closed = true + return + end var hostname = socket.gethostbyname(host) addrin = new NativeSocketAddrIn.with_hostent(hostname, port) @@ -175,8 +179,10 @@ class TCPStream # Send the data present in the socket buffer fun flush do - socket.setsockopt(new NativeSocketOptLevels.tcp, new NativeSocketOptNames.tcp_nodelay, 1) - socket.setsockopt(new NativeSocketOptLevels.tcp, new NativeSocketOptNames.tcp_nodelay, 0) + if not socket.setsockopt(new NativeSocketOptLevels.tcp, new NativeSocketOptNames.tcp_nodelay, 1) or + not socket.setsockopt(new NativeSocketOptLevels.tcp, new NativeSocketOptNames.tcp_nodelay, 0) then + closed = true + end end end @@ -194,7 +200,10 @@ class TCPServer socket = new NativeSocket.socket(new NativeSocketAddressFamilies.af_inet, new NativeSocketTypes.sock_stream, new NativeSocketProtocolFamilies.pf_null) assert not socket.address_is_null - socket.setsockopt(new NativeSocketOptLevels.socket, new NativeSocketOptNames.reuseaddr, 1) + if not socket.setsockopt(new NativeSocketOptLevels.socket, new NativeSocketOptNames.reuseaddr, 1) then + closed = true + return + end addrin = new NativeSocketAddrIn.with(port, new NativeSocketAddressFamilies.af_inet) address = addrin.address diff --git a/lib/socket/socket_c.nit b/lib/socket/socket_c.nit index 71867b9..44aff9e 100644 --- a/lib/socket/socket_c.nit +++ b/lib/socket/socket_c.nit @@ -37,6 +37,7 @@ in "C" `{ # Wrapper for the data structure PollFD used for polling on a socket class PollFD + super FinalizableOnce # The PollFD object private var poll_struct: NativeSocketPollFD @@ -76,27 +77,30 @@ class PollFD return response & mask; `} + redef fun finalize_once + do + poll_struct.free + end end # Data structure used by the poll function -private extern class NativeSocketPollFD `{ struct pollfd `} +private extern class NativeSocketPollFD `{ struct pollfd * `} - # File descriptor id - private fun fd: Int `{ return recv.fd; `} + # File descriptor + fun fd: Int `{ return recv->fd; `} # List of events to be watched - private fun events: Int `{ return recv.events; `} + fun events: Int `{ return recv->events; `} # List of events received by the last poll function - private fun revents: Int `{ return recv.revents; `} + fun revents: Int `{ return recv->revents; `} new (pid: Int, events: NativeSocketPollValues) `{ - struct pollfd poll; - poll.fd = pid; - poll.events = events; + struct pollfd *poll = malloc(sizeof(struct pollfd)); + poll->fd = pid; + poll->events = events; return poll; `} - end extern class NativeSocket `{ int* `} @@ -141,12 +145,14 @@ extern class NativeSocket `{ int* `} `} # Sets an option for the socket - fun setsockopt(level: NativeSocketOptLevels, option_name: NativeSocketOptNames, option_value: Int) `{ + # + # Returns `true` on success. + fun setsockopt(level: NativeSocketOptLevels, option_name: NativeSocketOptNames, option_value: Int): Bool `{ int err = setsockopt(*recv, level, option_name, &option_value, sizeof(int)); if(err != 0){ - perror("Error on setsockopts: "); - exit(1); + return 0; } + return 1; `} fun bind(addrIn: NativeSocketAddrIn): Int `{ return bind(*recv, (struct sockaddr*)addrIn, sizeof(*addrIn)); `} @@ -177,7 +183,7 @@ extern class NativeSocket `{ int* `} # The array's members are pollfd structures within which fd specifies an open file descriptor and events and revents are bitmasks constructed by # OR'ing a combination of the pollfd flags. private fun native_poll(filedesc: NativeSocketPollFD, timeout: Int): Int `{ - int poll_return = poll(&filedesc, 1, timeout); + int poll_return = poll(filedesc, 1, timeout); return poll_return; `} @@ -368,9 +374,6 @@ extern class NativeSocketAddressFamilies `{ int `} # Novell Internet Protocol new af_ipx `{ return AF_IPX; `} - # Integrated Services Digital Network - new af_isdn `{ return AF_ISDN; `} - # IPv6 new af_inet6 `{ return AF_INET6; `} @@ -387,7 +390,6 @@ extern class NativeSocketProtocolFamilies `{ int `} new pf_decnet `{ return PF_DECnet; `} new pf_route `{ return PF_ROUTE; `} new pf_ipx `{ return PF_IPX; `} - new pf_isdn `{ return PF_ISDN; `} new pf_key `{ return PF_KEY; `} new pf_inet6 `{ return PF_INET6; `} new pf_max `{ return PF_MAX; `} diff --git a/lib/standard/collection/abstract_collection.nit b/lib/standard/collection/abstract_collection.nit index d5621a9..bb17064 100644 --- a/lib/standard/collection/abstract_collection.nit +++ b/lib/standard/collection/abstract_collection.nit @@ -377,7 +377,7 @@ interface Set[E: Object] end # MapRead are abstract associative collections: `key` -> `item`. -interface MapRead[K: Object, V] +interface MapRead[K, V] # Get the item at `key` # # var x = new HashMap[String, Int] @@ -492,7 +492,7 @@ end # assert map.values.has(1) == true # assert map.values.has(3) == false # -interface Map[K: Object, V] +interface Map[K, V] super MapRead[K, V] # Set the `value` at `key`. @@ -552,7 +552,7 @@ interface Map[K: Object, V] end # Iterators for Map. -interface MapIterator[K: Object, V] +interface MapIterator[K, V] # The current item. # Require `is_ok`. fun item: V is abstract @@ -583,7 +583,7 @@ interface MapIterator[K: Object, V] end # Iterator on a 'keys' point of view of a map -class MapKeysIterator[K: Object, V] +class MapKeysIterator[K, V] super Iterator[K] # The original iterator var original_iterator: MapIterator[K, V] @@ -594,7 +594,7 @@ class MapKeysIterator[K: Object, V] end # Iterator on a 'values' point of view of a map -class MapValuesIterator[K: Object, V] +class MapValuesIterator[K, V] super Iterator[V] # The original iterator var original_iterator: MapIterator[K, V] @@ -941,7 +941,7 @@ end # Associative arrays that internally uses couples to represent each (key, value) pairs. # This is an helper class that some specific implementation of Map may implements. -interface CoupleMap[K: Object, V] +interface CoupleMap[K, V] super Map[K, V] # Return the couple of the corresponding key @@ -968,7 +968,7 @@ end # Iterator on CoupleMap # # Actually it is a wrapper around an iterator of the internal array of the map. -private class CoupleMapIterator[K: Object, V] +private class CoupleMapIterator[K, V] super MapIterator[K, V] redef fun item do return _iter.item.second diff --git a/lib/standard/collection/array.nit b/lib/standard/collection/array.nit index 68f84e7..44ea5d3 100644 --- a/lib/standard/collection/array.nit +++ b/lib/standard/collection/array.nit @@ -536,7 +536,7 @@ end # Associative arrays implemented with an array of (key, value) pairs. -class ArrayMap[K: Object, E] +class ArrayMap[K, E] super CoupleMap[K, E] # O(n) @@ -618,7 +618,7 @@ class ArrayMap[K: Object, E] end end -private class ArrayMapKeys[K: Object, E] +private class ArrayMapKeys[K, E] super RemovableCollection[K] # The original map var map: ArrayMap[K, E] @@ -638,7 +638,7 @@ private class ArrayMapKeys[K: Object, E] redef fun remove_all(key) do self.remove(key) end -private class ArrayMapValues[K: Object, E] +private class ArrayMapValues[K, E] super RemovableCollection[E] # The original map var map: ArrayMap[K, E] diff --git a/lib/standard/collection/hash_collection.nit b/lib/standard/collection/hash_collection.nit index d389c5a..f3857293 100644 --- a/lib/standard/collection/hash_collection.nit +++ b/lib/standard/collection/hash_collection.nit @@ -10,13 +10,18 @@ # You are allowed to redistribute it and sell it, alone or is a part of # another product. -# Introduce Hashmap and Hashset. +# Introduce `HashMap` and `HashSet`. module hash_collection import array +redef class Map[K, V] + # Get a `HashMap[K, V]` as default implementation + new do return new HashMap[K, V] +end + # A HashCollection is an array of HashNode[K] indexed by the K hash value -private abstract class HashCollection[K: Object] +private abstract class HashCollection[K] type N: HashNode[K] var array: nullable NativeArray[nullable N] = null # Used to store items @@ -35,12 +40,14 @@ private abstract class HashCollection[K: Object] # Return the index of the key k fun index_at(k: K): Int do + if k == null then return 0 + var i = k.hash % _capacity if i < 0 then i = - i return i end - # Return the node assosiated with the key + # Return the node associated with the key fun node_at(k: K): nullable N do # cache: `is` is used instead of `==` because it is a faster filter (even if not exact) @@ -52,7 +59,7 @@ private abstract class HashCollection[K: Object] return res end - # Return the node assosiated with the key (but with the index already known) + # Return the node associated with the key (but with the index already known) fun node_at_idx(i: Int, k: K): nullable N do var c = _array[i] @@ -190,7 +197,7 @@ private abstract class HashCollection[K: Object] end end -private abstract class HashNode[K: Object] +private abstract class HashNode[K] var key: K type N: HashNode[K] var next_item: nullable N = null @@ -199,9 +206,20 @@ private abstract class HashNode[K: Object] var next_in_bucklet: nullable N = null end -# A map implemented with a hash table. -# Keys of such a map cannot be null and require a working `hash` method -class HashMap[K: Object, V] +# A `Map` implemented with a hash table. +# +# ~~~ +# var map = new HashMap[nullable String, Int] +# map[null] = 0 +# map["one"] = 1 +# map["two"] = 2 +# +# assert map[null] == 0 +# assert map["one"] == 1 +# assert map.keys.has("two") +# assert map.values.length == 3 +# ~~~ +class HashMap[K, V] super Map[K, V] super HashCollection[K] @@ -249,7 +267,7 @@ class HashMap[K: Object, V] end # View of the keys of a HashMap -private class HashMapKeys[K: Object, V] +private class HashMapKeys[K, V] super RemovableCollection[K] # The original map var map: HashMap[K, V] @@ -270,7 +288,7 @@ private class HashMapKeys[K: Object, V] end # View of the values of a Map -private class HashMapValues[K: Object, V] +private class HashMapValues[K, V] super RemovableCollection[V] # The original map var map: HashMap[K, V] @@ -340,14 +358,14 @@ private class HashMapValues[K: Object, V] end end -private class HashMapNode[K: Object, V] +private class HashMapNode[K, V] super HashNode[K] redef type N: HashMapNode[K, V] var value: V end # A `MapIterator` over a `HashMap`. -class HashMapIterator[K: Object, V] +class HashMapIterator[K, V] super MapIterator[K, V] redef fun is_ok do return _node != null diff --git a/lib/standard/gc.nit b/lib/standard/gc.nit index acee1f6..23fa47f 100644 --- a/lib/standard/gc.nit +++ b/lib/standard/gc.nit @@ -36,3 +36,29 @@ class Finalizable # to use attributes of this instances. fun finalize do end end + +# An object to be finalized only once +# +# This is an utility sub-class to `Finalizable` which ensures that `finalized_once` +# is called only once per instance. User classes implementing `FinalizableOnce` +# shoud specialize `finalize_once` and _not_ `finalize`. When manipulating the user +# class, only `finalize` should be called as it protects `finalize_once`. +class FinalizableOnce + super Finalizable + + # Has `self` been finalized? (either by the GC or an explicit call to `finalize`) + var finalized = false + + redef fun finalize + do + if finalized then return + + finalize_once + finalized = true + end + + # Real finalization method of `FinalizableOnce`, will be called only once + # + # See: `Finalizable::finalize` for restrictions on finalizer methods. + protected fun finalize_once do end +end diff --git a/lib/standard/stream.nit b/lib/standard/stream.nit index 46ad73c..ddc01fe 100644 --- a/lib/standard/stream.nit +++ b/lib/standard/stream.nit @@ -493,5 +493,12 @@ class StringIStream source = "" end + redef fun read_all do + var c = cursor + cursor = source.length + if c == 0 then return source + return source.substring_from(c) + end + redef fun eof do return cursor >= source.length end diff --git a/lib/standard/string.nit b/lib/standard/string.nit index b5cfa71..2c46179 100644 --- a/lib/standard/string.nit +++ b/lib/standard/string.nit @@ -2178,7 +2178,7 @@ redef class Map[K,V] var i = iterator var k = i.key var e = i.item - s.append("{k}{couple_sep}{e or else ""}") + s.append("{k or else ""}{couple_sep}{e or else ""}") # Concat other items i.next @@ -2186,7 +2186,7 @@ redef class Map[K,V] s.append(sep) k = i.key e = i.item - s.append("{k}{couple_sep}{e or else ""}") + s.append("{k or else ""}{couple_sep}{e or else ""}") i.next end return s.to_s diff --git a/lib/symbol.nit b/lib/symbol.nit index 1e9fb67..b865017 100644 --- a/lib/symbol.nit +++ b/lib/symbol.nit @@ -32,8 +32,5 @@ end # A symbol is a unique immutable string class Symbol private var string: String - redef fun to_s do return _string.to_s - - # Only used by String::to_symbol - private init(s: String) do _string = s + redef fun to_s do return string.to_s end diff --git a/share/man/nitc.md b/share/man/nitc.md index 9c1d562..f98d50d 100644 --- a/share/man/nitc.md +++ b/share/man/nitc.md @@ -329,6 +329,18 @@ Usually you do not need them since they make the generated code slower. `--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. diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 2312544..dfe463c 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -120,20 +120,16 @@ redef class ModelBuilder # Simple indirection to `Toolchain::write_and_make` protected fun write_and_make(compiler: AbstractCompiler) do - var platform = compiler.mainmodule.target_platform - var toolchain - if platform == null then - toolchain = new MakefileToolchain(toolcontext) - else - toolchain = platform.toolchain(toolcontext) - end + var platform = compiler.target_platform + var toolchain = platform.toolchain(toolcontext) compile_dir = toolchain.compile_dir toolchain.write_and_make compiler end end redef class Platform - fun toolchain(toolcontext: ToolContext): Toolchain is abstract + # The specific tool-chain associated to the platform + fun toolchain(toolcontext: ToolContext): Toolchain do return new MakefileToolchain(toolcontext) end class Toolchain @@ -189,10 +185,10 @@ class MakefileToolchain fun write_files(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String]) do - var platform = compiler.mainmodule.target_platform - if self.toolcontext.opt_stacktrace.value == "nitstack" and (platform == null or platform.supports_libunwind) then compiler.build_c_to_nit_bindings + var platform = compiler.target_platform + if self.toolcontext.opt_stacktrace.value == "nitstack" and platform.supports_libunwind then compiler.build_c_to_nit_bindings var cc_opt_with_libgc = "-DWITH_LIBGC" - if platform != null and not platform.supports_libgc then cc_opt_with_libgc = "" + if not platform.supports_libgc then cc_opt_with_libgc = "" # Add gc_choser.h to aditionnal bodies var gc_chooser = new ExternCFile("gc_chooser.c", cc_opt_with_libgc) @@ -311,7 +307,7 @@ class MakefileToolchain fun write_makefile(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String]) do var mainmodule = compiler.mainmodule - var platform = compiler.mainmodule.target_platform + var platform = compiler.target_platform var outname = outfile(mainmodule) @@ -336,7 +332,7 @@ class MakefileToolchain makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g -O2 -Wno-unused-value -Wno-switch -Wno-attributes\nCINCL =\nLDFLAGS ?= \nLDLIBS ?= -lm {linker_options.join(" ")}\n\n") var ost = toolcontext.opt_stacktrace.value - if (ost == "libunwind" or ost == "nitstack") and (platform == null or platform.supports_libunwind) then makefile.write("NEED_LIBUNWIND := YesPlease\n") + if (ost == "libunwind" or ost == "nitstack") and platform.supports_libunwind then makefile.write("NEED_LIBUNWIND := YesPlease\n") # Dynamic adaptations # While `platform` enable complex toolchains, they are statically applied @@ -371,6 +367,18 @@ class MakefileToolchain dep_rules.add(o) end + # Generate linker script, if any + 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) + for l in compiler.linker_script do + f.write l + f.write "\n" + end + f.close + end + var java_files = new Array[ExternFile] var pkgconfigs = new Array[String] @@ -476,9 +484,13 @@ abstract class AbstractCompiler # Is hardening asked? (see --hardening) fun hardening: Bool do return self.modelbuilder.toolcontext.opt_hardening.value + # The targeted specific platform + var target_platform: Platform is noinit + init do self.realmainmodule = mainmodule + target_platform = mainmodule.target_platform or else new Platform end # Do the full code generation of the program `mainmodule` @@ -511,6 +523,10 @@ abstract class AbstractCompiler # Where global declaration are stored (the main .h) var header: CodeWriter is writable, noinit + # Additionnal linker script for `ld`. + # Mainly used to do specific link-time symbol resolution + var linker_script = new Array[String] + # Provide a declaration that can be requested (before or latter) by a visitor fun provide_declaration(key: String, s: String) do @@ -681,11 +697,11 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ); var v = self.new_visitor v.add_decl("#include ") var ost = modelbuilder.toolcontext.opt_stacktrace.value - var platform = mainmodule.target_platform + var platform = target_platform - if platform != null and not platform.supports_libunwind then ost = "none" + if not platform.supports_libunwind then ost = "none" - var no_main = (platform != null and platform.no_main) or modelbuilder.toolcontext.opt_no_main.value + var no_main = platform.no_main or modelbuilder.toolcontext.opt_no_main.value if ost == "nitstack" or ost == "libunwind" then v.add_decl("#define UNW_LOCAL_ONLY") diff --git a/src/compiler/android_platform.nit b/src/compiler/android_platform.nit index 5d6d312..b7069e3 100644 --- a/src/compiler/android_platform.nit +++ b/src/compiler/android_platform.nit @@ -36,6 +36,8 @@ class AndroidPlatform redef fun supports_libunwind do return false + redef fun supports_linker_script do return false + redef fun toolchain(toolcontext) do return new AndroidToolchain(toolcontext) end @@ -174,7 +176,8 @@ $(call import-module,android/native_app_glue) + android:debuggable="{{{not release}}}" + {{{icon_declaration}}}> @@ -290,12 +293,40 @@ $(call import-module,android/native_app_glue) # Move the apk to the target var outname = outfile(compiler.mainmodule) - var src_apk_suffix if release then - src_apk_suffix = "release-unsigned" - else src_apk_suffix = "debug" + var apk_path = "{android_project_root}/bin/{compiler.mainmodule.name}-release-unsigned.apk" + + # Sign APK + var keystore_path= "KEYSTORE".environ + var key_alias= "KEY_ALIAS".environ + var tsa_server= "TSA_SERVER".environ + + if key_alias.is_empty then + toolcontext.fatal_error(null, + "Fatal Error: the environment variable `KEY_ALIAS` must be set to use the `--release` option on Android projects.") + end + + args = ["jarsigner", "-sigalg", "MD5withRSA", "-digestalg", "SHA1", apk_path, key_alias] + + ## Use a custom keystore + if not keystore_path.is_empty then args.add_all(["-keystore", keystore_path]) - toolcontext.exec_and_check(["mv", "{android_project_root}/bin/{compiler.mainmodule.name}-{src_apk_suffix}.apk", outname], "Android project error") + ## Use a TSA server + if not tsa_server.is_empty then args.add_all(["-tsa", tsa_server]) + + toolcontext.exec_and_check(args, "Android project error") + + # Clean output file + if outname.to_path.exists then outname.to_path.delete + + # Align APK + args = ["zipalign", "4", apk_path, outname] + toolcontext.exec_and_check(args, "Android project error") + else + # Move to the expected output path + args = ["mv", "{android_project_root}/bin/{compiler.mainmodule.name}-debug.apk", outname] + toolcontext.exec_and_check(args, "Android project error") + end end end diff --git a/src/compiler/compiler_ffi.nit b/src/compiler/compiler_ffi.nit index ca22005..8466af1 100644 --- a/src/compiler/compiler_ffi.nit +++ b/src/compiler/compiler_ffi.nit @@ -43,7 +43,7 @@ redef class MModule ensure_compile_nitni_base(v) - nitni_ccu.header_c_types.add("#include \"{name}._ffi.h\"\n") + nitni_ccu.header_c_types.add("#include \"{c_name}._ffi.h\"\n") nitni_ccu.header_c_types.add """ extern void nitni_global_ref_incr(void*); extern void nitni_global_ref_decr(void*); @@ -255,11 +255,11 @@ end redef class CCompilationUnit fun write_as_nitni(mmodule: MModule, compdir: String) do - var base_name = "{mmodule.name}._nitni" + var base_name = "{mmodule.c_name}._nitni" var h_file = "{base_name}.h" write_header_to_file( mmodule, "{compdir}/{h_file}", new Array[String], - "{mmodule.cname.to_s.to_upper}_NITG_NITNI_H") + "{mmodule.c_name.to_s.to_upper}_NITG_NITNI_H") var c_file = "{base_name}.c" write_body_to_file( mmodule, "{compdir}/{c_file}", ["\"{h_file}\""] ) diff --git a/src/compiler/emscripten_platform.nit b/src/compiler/emscripten_platform.nit index 0a262fc..6332098 100644 --- a/src/compiler/emscripten_platform.nit +++ b/src/compiler/emscripten_platform.nit @@ -33,6 +33,7 @@ class EmscriptenPlatform redef fun supports_libunwind do return false redef fun supports_libgc do return false + redef fun supports_linker_script do return false redef fun toolchain(toolcontext) do return new EnscriptenToolchain(toolcontext) end diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index 1f1cf67..68438c7 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -29,6 +29,9 @@ redef class ToolContext 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") + # --inline-coloring-numbers var opt_inline_coloring_numbers = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers") # --inline-some-methods @@ -50,7 +53,7 @@ redef class ToolContext 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) + self.option_context.add_option(self.opt_no_shortcut_equate, opt_colors_are_symbols) 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) @@ -252,27 +255,21 @@ class SeparateCompiler fun compile_color_const(v: SeparateCompilerVisitor, m: Object, color: Int) do if color_consts_done.has(m) then return - if m isa MProperty then - if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then - self.provide_declaration(m.const_color, "#define {m.const_color} {color}") - else - self.provide_declaration(m.const_color, "extern const int {m.const_color};") - v.add("const int {m.const_color} = {color};") - end - else if m isa MPropDef then + if m isa MEntity then if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then self.provide_declaration(m.const_color, "#define {m.const_color} {color}") - else + else if not modelbuilder.toolcontext.opt_colors_are_symbols.value or not v.compiler.target_platform.supports_linker_script then self.provide_declaration(m.const_color, "extern const int {m.const_color};") v.add("const int {m.const_color} = {color};") - end - else if m isa MType then - if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then - self.provide_declaration(m.const_color, "#define {m.const_color} {color}") else - self.provide_declaration(m.const_color, "extern const int {m.const_color};") - v.add("const int {m.const_color} = {color};") + # The color 'C' is the ``address'' of a false static variable 'XC' + self.provide_declaration(m.const_color, "#define {m.const_color} ((long)&X{m.const_color})\nextern const void X{m.const_color};") + if color == -1 then color = 0 # Symbols cannot be negative, so just use 0 for dead things + # Teach the linker that the address of 'XC' is `color`. + linker_script.add("X{m.const_color} = {color};") end + else + abort end color_consts_done.add(m) end @@ -1953,20 +1950,18 @@ class VirtualRuntimeFunction redef fun call(v, arguments) do abort end -redef class MType - fun const_color: String do return "COLOR_{c_name}" +redef class MEntity + var const_color: String is lazy do return "COLOR_{c_name}" end interface PropertyLayoutElement end redef class MProperty super PropertyLayoutElement - fun const_color: String do return "COLOR_{c_name}" end redef class MPropDef super PropertyLayoutElement - fun const_color: String do return "COLOR_{c_name}" end redef class AMethPropdef diff --git a/src/ffi/cpp.nit b/src/ffi/cpp.nit index 8ca389a..a6a8ca3 100644 --- a/src/ffi/cpp.nit +++ b/src/ffi/cpp.nit @@ -124,7 +124,7 @@ class CPPLanguage # write .cpp and .hpp file cpp_file.header_custom.add("extern \"C\" \{\n") - cpp_file.header_custom.add("#include \"{mmodule.name}._ffi.h\"\n") + cpp_file.header_custom.add("#include \"{mmodule.c_name}._ffi.h\"\n") cpp_file.header_custom.add("\}\n") var file = cpp_file.write_to_files(mmodule, compdir) @@ -158,10 +158,10 @@ class CPPCompilationUnit fun write_to_files(mmodule: MModule, compdir: String): ExternCppFile do - var base_name = "{mmodule.name}._ffi" + var base_name = "{mmodule.c_name}._ffi" var h_file = "{base_name}.hpp" - var guard = "{mmodule.cname.to_s.to_upper}_NIT_HPP" + var guard = "{mmodule.c_name.to_s.to_upper}_NIT_HPP" write_header_to_file(mmodule, "{compdir}/{h_file}", new Array[String], guard) diff --git a/src/ffi/ffi.nit b/src/ffi/ffi.nit index 019d201..b854750 100644 --- a/src/ffi/ffi.nit +++ b/src/ffi/ffi.nit @@ -57,7 +57,7 @@ redef class MModule # include dependancies FFI for mod in header_dependencies do - if mod.uses_ffi then ffi_ccu.header_custom.add("#include \"{mod.name}._ffi.h\"\n") + if mod.uses_ffi then ffi_ccu.header_custom.add("#include \"{mod.c_name}._ffi.h\"\n") end ffi_ccu.write_as_impl(self, compdir) @@ -95,7 +95,7 @@ redef class AModule language.compile_module_block(block, ffi_ccu, mmodule) end - ffi_ccu.header_c_base.add( "#include \"{mmodule.name}._nitni.h\"\n" ) + ffi_ccu.header_c_base.add( "#include \"{mmodule.c_name}._nitni.h\"\n" ) ffi_ccu.body_decl.add("#ifdef ANDROID\n") ffi_ccu.body_decl.add(" #include \n") diff --git a/src/ffi/ffi_base.nit b/src/ffi/ffi_base.nit index e470276..babab08 100644 --- a/src/ffi/ffi_base.nit +++ b/src/ffi/ffi_base.nit @@ -152,10 +152,10 @@ end redef class CCompilationUnit fun write_as_impl(mmodule: MModule, compdir: String) do - var base_name = "{mmodule.name}._ffi" + var base_name = "{mmodule.c_name}._ffi" var h_file = "{base_name}.h" - var guard = "{mmodule.cname.to_s.to_upper}_NIT_H" + var guard = "{mmodule.c_name.to_upper}_NIT_H" write_header_to_file(mmodule, "{compdir}/{h_file}", new Array[String], guard) var c_file = "{base_name}.c" diff --git a/src/ffi/objc.nit b/src/ffi/objc.nit index 9ab6f7f..5c7eeeb 100644 --- a/src/ffi/objc.nit +++ b/src/ffi/objc.nit @@ -79,7 +79,7 @@ class ObjCLanguage # write .m and _m.h file mmodule.objc_file.header_c_types.add """ - #include "{{{mmodule.cname}}}._ffi.h" + #include "{{{mmodule.c_name}}}._ffi.h" """ var file = objc_file.write_to_files(mmodule, compdir) @@ -114,10 +114,10 @@ private class ObjCCompilationUnit # Write this compilation unit to Objective-C source files fun write_to_files(mmodule: MModule, compdir: String): ExternObjCFile do - var base_name = "{mmodule.cname}._ffi" + var base_name = "{mmodule.c_name}._ffi" var h_file = "{base_name}_m.h" - var guard = "{mmodule.cname.to_s.to_upper}_NIT_OBJC_H" + var guard = "{mmodule.c_name.to_upper}_NIT_OBJC_H" write_header_to_file(mmodule, compdir/h_file, new Array[String], guard) var c_file = "{base_name}.m" diff --git a/src/nitni/nitni_base.nit b/src/nitni/nitni_base.nit index 4f31aaf..6685029 100644 --- a/src/nitni/nitni_base.nit +++ b/src/nitni/nitni_base.nit @@ -22,7 +22,6 @@ module nitni_base import parser import modelbuilder # builder only for externcalls -private import compiler::abstract_compiler redef class MMethod # Short name of this method in C (without the class name) @@ -52,12 +51,6 @@ redef class MMethod end end -redef class MModule - # Mangled name of this module in C - fun cname: String do return c_name # FIXME this is a hack to keep the internal FFI - # API independent of the compilers while still using the `MModule::c_name` service. -end - redef class MMethodDef # Name of the function to callback this method from C, # also used in other functions names used for this method. diff --git a/src/nitpretty.nit b/src/nitpretty.nit index af3fae0..9dd723e 100644 --- a/src/nitpretty.nit +++ b/src/nitpretty.nit @@ -32,6 +32,20 @@ redef class ToolContext var opt_meld = new OptionBool("Show diff between source and output using meld", "--meld") + # Break too long string literals. + var opt_break_str = new OptionBool("Break too long string literals", "--break-strings") + + # Force `do` on the same line as the method signature. + var opt_inline_do = new OptionBool("Force do keyword on the same line as the method signature", + "--inline-do") + + # Force formatting on empty lines. + # + # By default empty lines are kept as they were typed in the file. + # When enabling this option, `nitpretty` will decide where to break lines + # and will put empty lines to separate properties and code blocks. + var opt_skip_empty = new OptionBool("Force formatting of empty lines", "--skip-empty") + # Check formatting instead of pretty printing. # # This option create a tempory pretty printed file then check if @@ -52,9 +66,11 @@ end # process options var toolcontext = new ToolContext -toolcontext.option_context. - add_option(toolcontext.opt_dir, toolcontext.opt_output, toolcontext.opt_diff, - toolcontext.opt_meld, toolcontext.opt_check) +var opts = toolcontext.option_context +opts.add_option(toolcontext.opt_dir, toolcontext.opt_output) +opts.add_option(toolcontext.opt_diff, toolcontext.opt_meld, toolcontext.opt_check) +opts.add_option(toolcontext.opt_break_str, toolcontext.opt_inline_do) +opts.add_option(toolcontext.opt_skip_empty) toolcontext.tooldescription = "Usage: nitpretty [OPTION]... \n" + "Pretty print Nit code from Nit source files." @@ -81,6 +97,16 @@ var dir = toolcontext.opt_dir.value or else ".nitpretty" if not dir.file_exists then dir.mkdir var v = new PrettyPrinterVisitor +if toolcontext.opt_break_str.value then + v.break_strings = true +end +if toolcontext.opt_inline_do.value then + v.inline_do = true +end +if toolcontext.opt_skip_empty.value then + v.skip_empty = true +end + for mmodule in mmodules do var nmodule = mbuilder.mmodule2node(mmodule) if nmodule == null then diff --git a/src/platform.nit b/src/platform.nit index 8f2edbb..5b7f7a5 100644 --- a/src/platform.nit +++ b/src/platform.nit @@ -103,7 +103,7 @@ end # Sub-classes of `Platform` represent the target platform of a compilation # # Services will be added to this class in other modules. -abstract class Platform +class Platform # Does the platform provide and support the library `unwind`? fun supports_libunwind: Bool do return true @@ -112,4 +112,7 @@ abstract class Platform # Does this platform declare its own main function? If so, we won't generate one in Nit. fun no_main: Bool do return false + + # Does the platform accepts linker scripts? + fun supports_linker_script: Bool do return true end diff --git a/src/pretty.nit b/src/pretty.nit index 3b9f7ef..2d08571 100644 --- a/src/pretty.nit +++ b/src/pretty.nit @@ -79,7 +79,7 @@ class PrettyPrinterVisitor current_token = nmodule.location.file.first_token visit nmodule catch_up nmodule.location.file.last_token - tpl.add "\n" + if skip_empty then tpl.add "\n" return tpl.as(not null) end @@ -172,7 +172,7 @@ class PrettyPrinterVisitor else abort end - assert current_token.location <= token.location + if current_token.location > token.location then return while current_token != token do visit current_token end @@ -183,7 +183,7 @@ class PrettyPrinterVisitor visit current_token end - while current_token isa TEol do skip + while current_token isa TEol do visit(current_token) end # The template under construction. @@ -223,6 +223,14 @@ class PrettyPrinterVisitor if current_length == 0 and last_line_is_blank then return previous_length = current_length current_length = 0 + if skip_empty then wait_addn += 1 + end + + # Perform `addn` even if not `skip_empty`. + fun forcen do + if current_length == 0 and last_line_is_blank then return + previous_length = current_length + current_length = 0 wait_addn += 1 end @@ -243,6 +251,15 @@ class PrettyPrinterVisitor consume "." end end + + # Do we break string literals that are too long? + var break_strings = false is public writable + + # Do we force `do` to be on the same line as the method signature? + var inline_do = false is public writable + + # Do we force the deletion of empty lines? + var skip_empty = false is public writable end # Base framework redefs @@ -255,9 +272,10 @@ redef class ANodes[E] if e != first then if not e_can_inline then v.add "," - v.addn - v.addt + v.forcen + v.indent += 1 v.addt + v.indent -= 1 else v.add ", " end @@ -308,6 +326,17 @@ redef class Token redef fun was_inline do return true end +redef class TEol + redef fun accept_pretty_printer(v) do + if v.skip_empty then + super + else + v.add text + v.current_token = next_token + end + end +end + redef class Prod redef fun accept_pretty_printer(v) do v.visit first_token @@ -344,7 +373,7 @@ redef class Prod end redef fun was_inline do - return first_token.location.line_start == last_token.location.line_end + return start_token.location.line_start == last_token.location.line_end end end @@ -355,13 +384,13 @@ redef class TComment if is_adoc then v.addt super - v.addn + v.forcen return end if is_licence then super - v.addn + v.forcen if is_last_in_group then v.addn return end @@ -370,7 +399,7 @@ redef class TComment v.addn v.addt super - v.addn + v.forcen v.addn return end @@ -379,13 +408,14 @@ redef class TComment if next_token isa TComment and is_first_in_group then v.addn v.addt super - v.addn + v.forcen var prev_token = self.prev_token if prev_token isa TComment and prev_token.is_inline and is_last_in_group then v.addn return end super + if not v.skip_empty then v.forcen end # Is `self` part of an `ADoc`? @@ -434,7 +464,6 @@ redef class AAnnotations redef fun accept_pretty_printer(v) do v.adds v.consume "is" - if v.can_inline(self) then v.adds for n_item in n_items do @@ -443,21 +472,27 @@ redef class AAnnotations v.add ", " end end - v.finish_line - else if n_items.length > 1 then - v.addn + if not was_inline then + v.finish_line + if v.current_token isa TKwend then v.skip + end + else + v.forcen v.indent += 1 - for n_item in n_items do v.addt v.visit n_item v.finish_line - v.addn + if n_item != n_items.last then + if was_inline then + v.forcen + else + v.addn + end + end end - v.indent -= 1 end - if not was_inline and v.current_token isa TKwend then v.skip end redef fun is_inlinable do @@ -469,6 +504,10 @@ end redef class AAnnotation redef fun accept_pretty_printer(v) do + if n_visibility != null and not n_visibility isa APublicVisibility then + v.visit n_visibility + v.adds + end v.visit n_atid if not n_args.is_empty then if n_opar == null then @@ -494,7 +533,7 @@ redef class AModule v.visit n_moduledecl if not n_imports.is_empty then - v.addn + if v.skip_empty then v.addn for n_import in n_imports do v.catch_up n_import @@ -516,7 +555,7 @@ redef class AModule end if not n_classdefs.is_empty then - v.addn + if v.skip_empty then v.addn for n_classdef in n_classdefs do v.catch_up n_classdef @@ -561,7 +600,7 @@ redef class AModuledecl end v.finish_line - v.addn + if v.skip_empty then v.addn end end @@ -582,7 +621,7 @@ redef class ANoImport v.adds v.visit n_kwend v.finish_line - v.addn + if v.skip_empty then v.addn end end @@ -597,7 +636,7 @@ redef class AStdImport v.adds v.visit n_name v.finish_line - v.addn + if v.skip_empty then v.addn end end @@ -609,9 +648,9 @@ redef class AClassdef v.catch_up n_propdef if n_propdef.n_doc != null or not v.can_inline(n_propdef) then - if n_propdef != n_propdefs.first then v.addn + if v.skip_empty and n_propdef != n_propdefs.first then v.addn v.visit n_propdef - if n_propdef != n_propdefs.last then v.addn + if v.skip_empty and n_propdef != n_propdefs.last then v.addn else v.visit n_propdef end @@ -660,7 +699,7 @@ redef class AStdClassdef end else v.finish_line - v.addn + if v.skip_empty then v.addn v.indent += 1 for n_superclass in n_superclasses do @@ -672,7 +711,7 @@ redef class AStdClassdef end if not n_superclasses.is_empty and not n_propdefs.is_empty then - v.addn + if v.skip_empty then v.addn end super @@ -682,7 +721,7 @@ redef class AStdClassdef v.visit n_kwend v.finish_line - v.addn + if v.skip_empty then v.addn assert v.indent == 0 end @@ -772,6 +811,90 @@ redef class APropdef end end + # Factorize annotations visit for all APropdef. + # + # Return true if annotations were inlined. + fun visit_annotations(v: PrettyPrinterVisitor, n_annotations: nullable AAnnotations): Bool do + var res = v.can_inline(n_annotations) + if n_annotations != null then v.visit n_annotations + return res + end + + # Factorize block visit for APropdefs. + # + # Were annotations printed inline? If so, we need to print the block differently. + fun visit_block(v: PrettyPrinterVisitor, n_block: nullable AExpr, annot_inline: Bool) do + # var can_inline = v.can_inline(n_block) + if n_block == null then return + if n_annotations != null and not annot_inline then + v.forcen + v.addt + end + if v.inline_do then + while not v.current_token isa TKwdo do v.skip + end + var token = v.current_token + var do_inline = true + loop + if token isa TEol then + v.skip + if not v.can_inline(n_block) then + v.forcen + v.addt + do_inline = false + end + end + token = v.current_token + if token isa TKwdo then break + end + if annot_inline and do_inline then v.adds + v.consume "do" + + if v.can_inline(n_block) and do_inline then + v.adds + + if n_block isa ABlockExpr then + if n_block.n_expr.is_empty then + v.visit n_block.n_kwend + else + v.visit n_block.n_expr.first + v.current_token = n_block.n_kwend + v.skip + end + else + v.visit n_block + if v.current_token isa TKwend then v.skip + end + else + v.finish_line + if was_inline then + v.forcen + else + v.addn + end + v.indent += 1 + + if n_block isa ABlockExpr then + n_block.force_block = true + v.visit n_block + v.catch_up n_block.n_kwend + else + v.addt + v.visit n_block + v.forcen + end + + v.indent -= 1 + v.addt + if n_block isa ABlockExpr then + v.visit n_block.n_kwend + else + v.add "end" + end + end + v.finish_line + end + redef fun start_token do if n_doc == null then return super return n_doc.last_token.next_token @@ -798,7 +921,8 @@ redef class AAttrPropdef v.visit n_expr end - if n_annotations != null then v.visit n_annotations + var annot_inline = visit_annotations(v, n_annotations) + visit_block(v, n_block, annot_inline) v.finish_line v.addn end @@ -822,6 +946,7 @@ redef class ATypePropdef v.consume ":" v.adds v.visit n_type + visit_annotations(v, n_annotations) v.finish_line v.addn end @@ -834,7 +959,6 @@ redef class AMethPropdef # TODO: Handle extern annotations var before = v.indent - var can_inline = v.can_inline(self) super if n_kwinit != null then v.visit n_kwinit if n_kwmeth != null then v.visit n_kwmeth @@ -847,72 +971,15 @@ redef class AMethPropdef v.visit n_signature - if n_annotations != null then - v.visit n_annotations - else - v.adds - end + var annot_inline = visit_annotations(v, n_annotations) if n_extern_calls != null or n_extern_code_block != null then - if n_annotations != null then v.adds + v.adds if n_extern_calls != null then v.visit n_extern_calls if n_extern_code_block != null then v.visit n_extern_code_block end - var n_block = self.n_block - - if n_block != null then - while not v.current_token isa TKwdo do v.skip - if n_annotations != null then - if v.can_inline(n_annotations) then - v.adds - else - v.addt - end - end - v.consume "do" - - if can_inline then - v.adds - - if n_block isa ABlockExpr then - if n_block.n_expr.is_empty then - v.visit n_block.n_kwend - else - v.visit n_block.n_expr.first - v.current_token = n_block.n_kwend - v.skip - end - else - v.visit n_block - if v.current_token isa TKwend then v.skip - end - else - v.finish_line - v.addn - v.indent += 1 - - if n_block isa ABlockExpr then - n_block.force_block = true - v.visit n_block - v.catch_up n_block.n_kwend - else - v.addt - v.visit n_block - v.addn - end - - v.indent -= 1 - v.addt - if n_block isa ABlockExpr then - v.visit n_block.n_kwend - else - v.add "end" - end - end - end - - v.finish_line + visit_block(v, n_block, annot_inline) v.addn assert v.indent == before end @@ -934,7 +1001,7 @@ end redef class AMainMethPropdef redef fun accept_pretty_printer(v) do v.visit n_block - v.addn + if v.skip_empty then v.addn end end @@ -980,8 +1047,9 @@ redef class AExternCalls v.visit_list n_extern_calls else v.addn + v.indent += 1 v.addt - v.addt + v.indent -= 1 v.visit_list n_extern_calls end @@ -1087,7 +1155,7 @@ redef class TExternCodeSegment for line in lines do v.add line.r_trim - v.addn + v.forcen end v.addt @@ -1177,11 +1245,18 @@ redef class AIfExpr else if n_then == null then v.add "end" end - v.skip_to last_token.last_real_token_in_line else v.finish_line - v.addn + if was_inline then + v.forcen + else if not v.skip_empty and n_then != null and + n_then.was_inline and + n_then.location.line_end == location.line_start then + v.forcen # Xymus fucking syntax + else + v.addn + end v.indent += 1 if n_then != null then @@ -1191,7 +1266,11 @@ redef class AIfExpr else v.addt v.visit n_then - v.addn + if n_then.was_inline then + v.forcen + else + v.addn + end end end @@ -1210,7 +1289,11 @@ redef class AIfExpr v.visit n_else else v.finish_line - v.addn + if was_inline then + v.forcen + else + v.addn + end v.indent += 1 if n_else isa ABlockExpr then @@ -1219,7 +1302,11 @@ redef class AIfExpr else v.addt v.visit n_else - v.addn + if n_else.was_inline then + v.forcen + else + v.addn + end end if last_token isa TKwend then @@ -1479,7 +1566,6 @@ redef class ACallExpr if not n_expr isa AImplicitSelfExpr and not can_inline then v.addn v.addt - v.addt end v.visit n_id @@ -1640,8 +1726,9 @@ redef class ANewExpr if not can_inline then v.addn + v.indent += 1 v.addt - v.addt + v.indent -= 1 end v.visit n_id @@ -1749,16 +1836,15 @@ redef class AAssertExpr v.visit n_else else v.addn + v.indent += 1 if n_else isa ABlockExpr then - v.indent += 1 n_else.force_block = true v.visit n_else v.indent -= 1 v.addt v.visit n_else.n_kwend else - v.indent += 1 v.addt v.visit n_else v.addn @@ -1897,8 +1983,9 @@ private class ABinOpHelper v.visit bin_expr2 else v.addn + v.indent += 1 v.addt - v.addt + v.indent -= 1 v.visit bin_expr2 end end @@ -2073,9 +2160,13 @@ end redef class AStringFormExpr redef fun accept_pretty_printer(v) do - var can_inline = v.can_inline(self) - - if can_inline then + if not v.break_strings then + # n_string.force_inline = true + v.visit n_string + return + end + if v.can_inline(self) then + n_string.force_inline = true v.visit n_string else var text = n_string.text @@ -2086,7 +2177,11 @@ redef class AStringFormExpr if v.current_length >= v.max_size and i <= text.length - 3 then v.add "\" +" - v.addn + if was_inline then + v.forcen + else + v.addn + end v.indent += 1 v.addt v.indent -= 1 @@ -2103,7 +2198,12 @@ end redef class ASuperstringExpr redef fun accept_pretty_printer(v) do - for n_expr in n_exprs do v.visit n_expr + for n_expr in n_exprs do + if not v.break_strings then + n_expr.force_inline = true + end + v.visit n_expr + end end redef fun must_be_inline do diff --git a/src/semantize/typing.nit b/src/semantize/typing.nit index ae697d4..8fb3852 100644 --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@ -975,7 +975,7 @@ redef class AForExpr is_col = true end - if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type, objcla.mclass_type.as_nullable])) then + if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then # Map Iterator var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla) var variables = self.variables diff --git a/src/toolcontext.nit b/src/toolcontext.nit index 3e99de2..021c2c7 100644 --- a/src/toolcontext.nit +++ b/src/toolcontext.nit @@ -242,28 +242,30 @@ class ToolContext # # Stops execution and prints errors if the program isn't available or didn't end correctly fun exec_and_check(args: Array[String], error: String) - do - var prog = args.first - args.remove_at 0 - - # Is the wanted program available? - var proc_which = new IProcess.from_a("which", [prog]) - proc_which.wait - var res = proc_which.status - if res != 0 then - print "{error}: executable \"{prog}\" not found" - exit 1 - end - - # Execute the wanted program - var proc = new Process.from_a(prog, args) - proc.wait - res = proc.status - if res != 0 then - print "{error}: execution of \"{prog} {args.join(" ")}\" failed" - exit 1 - end - end + do + info("+ {args.join(" ")}", 2) + + var prog = args.first + args.remove_at 0 + + # Is the wanted program available? + var proc_which = new IProcess.from_a("which", [prog]) + proc_which.wait + var res = proc_which.status + if res != 0 then + print "{error}: executable \"{prog}\" not found" + exit 1 + end + + # Execute the wanted program + var proc = new Process.from_a(prog, args) + proc.wait + res = proc.status + if res != 0 then + print "{error}: execution of \"{prog} {args.join(" ")}\" failed" + exit 1 + end + end # Global OptionContext var option_context = new OptionContext diff --git a/tests/nitpretty.args b/tests/nitpretty.args index 61b0157..77c26ea 100644 --- a/tests/nitpretty.args +++ b/tests/nitpretty.args @@ -1,3 +1,34 @@ +--skip-empty test_pretty/test_mod1.nit +--skip-empty test_pretty/test_mod2.nit +--skip-empty test_pretty/test_mod3.nit +--skip-empty test_pretty/test_class1.nit +--skip-empty test_pretty/test_class2.nit +--skip-empty test_pretty/test_class3.nit +--skip-empty test_pretty/test_prop1.nit +--skip-empty test_pretty/test_prop2.nit +--skip-empty test_pretty/test_prop3.nit +--skip-empty test_pretty/test_loop1.nit +--skip-empty test_pretty/test_loop2.nit +--skip-empty test_pretty/test_loop3.nit +--skip-empty test_pretty/test_call1.nit +--skip-empty test_pretty/test_call2.nit +--skip-empty test_pretty/test_if1.nit +--skip-empty test_pretty/test_if2.nit +--skip-empty test_pretty/test_if3.nit +--skip-empty test_pretty/test_op1.nit +--skip-empty test_pretty/test_op2.nit +--skip-empty test_pretty/test_op3.nit +--skip-empty test_pretty/test_extern1.nit +--skip-empty test_pretty/test_attr1.nit +--skip-empty test_pretty/test_attr2.nit +--skip-empty test_pretty/test_comments1.nit +--skip-empty test_pretty/test_indent1.nit +--skip-empty test_pretty/test_prims1.nit +--skip-empty test_pretty/test_annot1.nit +--skip-empty --break-strings test_pretty/test_prop1.nit +--skip-empty --break-strings test_pretty/test_indent1.nit +--skip-empty --inline-do test_pretty/test_prop1.nit +--skip-empty --inline-do test_pretty/test_indent1.nit test_pretty/test_mod1.nit test_pretty/test_mod2.nit test_pretty/test_mod3.nit @@ -25,3 +56,7 @@ test_pretty/test_comments1.nit test_pretty/test_indent1.nit test_pretty/test_prims1.nit test_pretty/test_annot1.nit +--break-strings test_pretty/test_prop1.nit +--break-strings test_pretty/test_indent1.nit +--inline-do test_pretty/test_prop1.nit +--inline-do test_pretty/test_indent1.nit diff --git a/tests/sav/fixme/nitpretty_args22.res b/tests/sav/fixme/nitpretty_args22.res deleted file mode 100644 index 4ad3dc3..0000000 --- a/tests/sav/fixme/nitpretty_args22.res +++ /dev/null @@ -1 +0,0 @@ -UNDEFINED diff --git a/tests/sav/fixme/nitpretty_args48.res b/tests/sav/fixme/nitpretty_args48.res new file mode 100644 index 0000000..c3a432c --- /dev/null +++ b/tests/sav/fixme/nitpretty_args48.res @@ -0,0 +1,61 @@ +# 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. + +var a = 1 +var b = 2 + +# 0 +if a == b then # 1 + # 2 +else # 3 + # 4 +end # 5 + +if a == b then print a # printing a + +if a == b then + print a # printing a +end + +if a == b then print a + # end + +if a == b then a = b + +if a == b then end + +if a == b then end + +if a != b then a = b + + +if a > b then + a = b +else + a = b +end + +if a < b then + a = b +else if a == b then + a = b +end + +if a < b then + a = b +else if a == b then + a = b +else + a = b +end diff --git a/tests/sav/fixme/nitpretty_args58.res b/tests/sav/fixme/nitpretty_args58.res new file mode 100644 index 0000000..2e6ac9a --- /dev/null +++ b/tests/sav/fixme/nitpretty_args58.res @@ -0,0 +1,51 @@ +# 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. + +module test_annot1 is platform("android") + +class A + fun goo is intern + + # test + fun foo is a, b + fun bar is a, b do print "1" + fun baz is + a + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + do print "2" +end + +class B + fun foo is a, b + + + fun bar is a, b + do print "1" + + fun baz is a, b + do + bar + print "2" + end + + fun gaz is + a + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + do + bar + print "2" + end + +end diff --git a/tests/sav/nitpretty_args21.res b/tests/sav/nitpretty_args21.res index 9b58418..7a8fe04 100644 --- a/tests/sav/nitpretty_args21.res +++ b/tests/sav/nitpretty_args21.res @@ -78,8 +78,8 @@ extern class TimeT `{time_t`} # Difference in secondes from start (self if the end time) fun difftime(start: TimeT): Float `{ return difftime(recv, start); `} - private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]): nullable Int is extern import - Array[Int].length, Array[Int].[], Int.as(nullable Int) `{`} + private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]): nullable Int is + extern import Array[Int].length, Array[Int].[], Int.as(nullable Int) `{`} end fun address_is_null: Bool is extern "address_is_null" diff --git a/tests/sav/nitpretty_args25.res b/tests/sav/nitpretty_args25.res index 6638706..e8ba342 100644 --- a/tests/sav/nitpretty_args25.res +++ b/tests/sav/nitpretty_args25.res @@ -15,7 +15,8 @@ class Foo fun bar: Bool do return true - fun foo(other: Foo): Foo do + fun foo(other: Foo): Foo + do if other.bar then return other else @@ -34,7 +35,8 @@ class Foo return nb end - fun gaz: Int do + fun gaz: Int + do if bar then # 3 return 1 else @@ -67,7 +69,9 @@ class Test[E] end end - fun save_those_nodes(nodes: Collection[Object]) do for node in nodes do count(node) + fun save_those_nodes(nodes: Collection[Object]) do + for node in nodes do count(node) + end end fun foo do @@ -78,28 +82,12 @@ fun foo do end end -print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidun" + - "t sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit a" + - "met lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus" + - " eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pell" + - "entesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae" + - " consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae" + - " lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas" + - " turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed phar" + - "etra lacus." +print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." var lorem = "lorem" var ipsum = "ipsum" # for fun -print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, con" + - "sectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius a" + - "t non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisi" + - "s neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}" + - ". Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} pla" + - "cerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus pl" + - "acerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum " + - "augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pell" + - "entesque vitae arcu justo. Aliquam sed pharetra lacus." # ending +print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." # ending var title = "title" var links = new Array[String] # why not? diff --git a/tests/sav/nitpretty_args27.res b/tests/sav/nitpretty_args27.res index 0406b29..422cc2a 100644 --- a/tests/sav/nitpretty_args27.res +++ b/tests/sav/nitpretty_args27.res @@ -15,15 +15,17 @@ module test_annot1 is platform("android") class A + fun goo is intern + + # test fun foo is a, b + fun bar is a, b do print "1" fun baz is a bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - do - print "2" - end + do print "2" end class B diff --git a/tests/sav/nitpretty_args28.res b/tests/sav/nitpretty_args28.res new file mode 100644 index 0000000..1944090 --- /dev/null +++ b/tests/sav/nitpretty_args28.res @@ -0,0 +1,51 @@ +# 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. + +# comment 1 +class A + type FOO: Discrete + private var foo: FOO # comment + + # comment 2 + var bar: Int = 10 +end + +class B + super A + + redef type FOO: Int + + # comment 3 + redef fun foo do return bar # comment + + redef fun bar + do + return 10 # comment 4 + end + + fun baz do return # comment 5 + protected fun baz2 do end + + fun other: String do + return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaa" + end + + fun foo1(arr: Array[String], len: Int, ind: Int): String + do + return "Hello World!" + end +end + +# end diff --git a/tests/sav/nitpretty_args29.res b/tests/sav/nitpretty_args29.res new file mode 100644 index 0000000..4d75c17 --- /dev/null +++ b/tests/sav/nitpretty_args29.res @@ -0,0 +1,127 @@ +# 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. + +class Foo + fun bar: Bool do return true + + fun foo(other: Foo): Foo + do + if other.bar then + return other + else + return self + end + end + + fun baz: Int do + var nb = 0 + + while nb < 10 do + print nb + nb += 1 + end # 1 + + return nb + end + + fun gaz: Int + do + if bar then # 3 + return 1 + else + return -1 # 4 + end + end +end + +class Test[E] + var heap: ArrayHeap[E] + init to(comparator: Comparator[E]) do heap = new ArrayHeap[E](comparator) + + init from(comparator: Comparator[E], items: Collection[E]) do + heap = new ArrayHeap[E].from(comparator, items.to_a) + end + + fun count(k: E): Int do + if heap.has(k) then + return 1 + else + return 0 + end + end + + fun node_at_idx(i: Int, k: E) do + while heap != null do + if heap.is_empty or i == k then # FIXME prefilter because the compiler is not smart enought yet + break + end + end + end + + fun save_those_nodes(nodes: Collection[Object]) do + for node in nodes do count(node) + end +end + +fun foo do + if last_slash > 0 then + return substring(last_slash + 1, length) + else + return null + end +end + +print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidun" + + "t sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit a" + + "met lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus" + + " eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pell" + + "entesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae" + + " consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae" + + " lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas" + + " turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed phar" + + "etra lacus." + +var lorem = "lorem" +var ipsum = "ipsum" # for fun + +print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, con" + + "sectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius a" + + "t non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisi" + + "s neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}" + + ". Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} pla" + + "cerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus pl" + + "acerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum " + + "augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pell" + + "entesque vitae arcu justo. Aliquam sed pharetra lacus." # ending + +var title = "title" +var links = new Array[String] # why not? + +var body = """ + + + + + + {{{title}}} + + +
+

{{{title}}}

+
    +
  • {{{links.join("
  • \n\t\t\t
  • ")}}}
  • +
+
+ +""" diff --git a/tests/sav/nitpretty_args30.res b/tests/sav/nitpretty_args30.res new file mode 100644 index 0000000..57f7966 --- /dev/null +++ b/tests/sav/nitpretty_args30.res @@ -0,0 +1,48 @@ +# 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. + +# comment 1 +class A + type FOO: Discrete + private var foo: FOO # comment + + # comment 2 + var bar: Int = 10 +end + +class B + super A + + redef type FOO: Int + + # comment 3 + redef fun foo do return bar # comment + + redef fun bar do + return 10 # comment 4 + end + + fun baz do return # comment 5 + protected fun baz2 do end + + fun other: String do + return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + end + + fun foo1(arr: Array[String], len: Int, ind: Int): String do + return "Hello World!" + end +end + +# end diff --git a/tests/sav/nitpretty_args31.res b/tests/sav/nitpretty_args31.res new file mode 100644 index 0000000..99d53dd --- /dev/null +++ b/tests/sav/nitpretty_args31.res @@ -0,0 +1,109 @@ +# 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. + +class Foo + fun bar: Bool do return true + + fun foo(other: Foo): Foo do + if other.bar then + return other + else + return self + end + end + + fun baz: Int do + var nb = 0 + + while nb < 10 do + print nb + nb += 1 + end # 1 + + return nb + end + + fun gaz: Int do + if bar then # 3 + return 1 + else + return -1 # 4 + end + end +end + +class Test[E] + var heap: ArrayHeap[E] + init to(comparator: Comparator[E]) do heap = new ArrayHeap[E](comparator) + + init from(comparator: Comparator[E], items: Collection[E]) do + heap = new ArrayHeap[E].from(comparator, items.to_a) + end + + fun count(k: E): Int do + if heap.has(k) then + return 1 + else + return 0 + end + end + + fun node_at_idx(i: Int, k: E) do + while heap != null do + if heap.is_empty or i == k then # FIXME prefilter because the compiler is not smart enought yet + break + end + end + end + + fun save_those_nodes(nodes: Collection[Object]) do + for node in nodes do count(node) + end +end + +fun foo do + if last_slash > 0 then + return substring(last_slash + 1, length) + else + return null + end +end + +print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." + +var lorem = "lorem" +var ipsum = "ipsum" # for fun + +print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." # ending + +var title = "title" +var links = new Array[String] # why not? + +var body = """ + + + + + + {{{title}}} + + +
+

{{{title}}}

+
    +
  • {{{links.join("
  • \n\t\t\t
  • ")}}}
  • +
+
+ +""" diff --git a/tests/sav/nitpretty_args32.res b/tests/sav/nitpretty_args32.res new file mode 100644 index 0000000..f55be8f --- /dev/null +++ b/tests/sav/nitpretty_args32.res @@ -0,0 +1,18 @@ +# 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. + + + +# An empty module + diff --git a/tests/sav/nitpretty_args33.res b/tests/sav/nitpretty_args33.res new file mode 100644 index 0000000..76149a7 --- /dev/null +++ b/tests/sav/nitpretty_args33.res @@ -0,0 +1,24 @@ +# 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. + +# Testing only imports + +# Module comment +module test_mod2 # second comment + +import standard::kernel +#import standard::string + +import template # no need for string +# import standard \ No newline at end of file diff --git a/tests/sav/nitpretty_args34.res b/tests/sav/nitpretty_args34.res new file mode 100644 index 0000000..6ee57a1 --- /dev/null +++ b/tests/sav/nitpretty_args34.res @@ -0,0 +1,25 @@ +# 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. + +# A simple module +module test_mod3 + +# before +print "Hello World" # comment +# after + +# end + + + diff --git a/tests/sav/nitpretty_args35.res b/tests/sav/nitpretty_args35.res new file mode 100644 index 0000000..ed30bc2 --- /dev/null +++ b/tests/sav/nitpretty_args35.res @@ -0,0 +1,24 @@ +# 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. + +# comment 1 +interface A end + +abstract class B # comment 2 +end + +class C end # comment 3 + +enum D end # comment 4 + diff --git a/tests/sav/nitpretty_args36.res b/tests/sav/nitpretty_args36.res new file mode 100644 index 0000000..2a61cf1 --- /dev/null +++ b/tests/sav/nitpretty_args36.res @@ -0,0 +1,25 @@ +# 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. + +module test_class2 + + +# comment +class A end + +class B[T] # comment +end + +private class C[U, V: B[A]] end # comment + diff --git a/tests/sav/nitpretty_args37.res b/tests/sav/nitpretty_args37.res new file mode 100644 index 0000000..feedd55 --- /dev/null +++ b/tests/sav/nitpretty_args37.res @@ -0,0 +1,39 @@ +# 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. + +# comment +class A end + +class B[T] # comment + # comment + super A # comment + + + super C[A, B[A]] + # comment +end + +class C[U, V: B[A]] end # comment + +class D super A end # comment + +class E + + + + super A # comment +end + +# end + diff --git a/tests/sav/nitpretty_args38.res b/tests/sav/nitpretty_args38.res new file mode 100644 index 0000000..31e90fc --- /dev/null +++ b/tests/sav/nitpretty_args38.res @@ -0,0 +1,46 @@ +# 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. + +# comment 1 +class A + type FOO: Discrete + private var foo: FOO # comment + # comment 2 + var bar: Int = 10 +end + +class B + super A + + redef type FOO: Int + # comment 3 + redef fun foo do return bar # comment + redef fun bar + do + return 10 # comment 4 + end + fun baz do return # comment 5 + protected fun baz2 do end + fun other: String do + return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + end + + fun foo1(arr: Array[String], len: Int, ind: Int): String + do + return "Hello World!" + end +end + +# end + diff --git a/tests/sav/nitpretty_args39.res b/tests/sav/nitpretty_args39.res new file mode 100644 index 0000000..e48e1da --- /dev/null +++ b/tests/sav/nitpretty_args39.res @@ -0,0 +1,32 @@ +# 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. + +class A + fun foo(a, b: Int): Bool do return true # 1 + + fun foo2(a, b: Int): Bool do return true # 2 + + fun foo3(a, b: Int): Bool do return true + + fun foo4(a, b: Int): Bool do + var res = true # 3 + return res # 4 + end + + fun foo5 do end # 5 + # fun foo6 do end +end + +# end + diff --git a/tests/sav/nitpretty_args40.res b/tests/sav/nitpretty_args40.res new file mode 100644 index 0000000..59e2e25 --- /dev/null +++ b/tests/sav/nitpretty_args40.res @@ -0,0 +1,35 @@ +# 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. + +class A + fun foo(aaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: Int): Bool do return true # comment + + fun foo2(a, b: Int): Bool do return true # comment + + fun foo3(a, b: Int): Bool do # comment + return true # comment + end # comment + + fun foo4(a, b: Int): Bool do # comment + var res = true # comment + return res # comment + end # comment + + fun foo5 do end # comment + + fun foo6(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: Int) do print 1 + +end # comment \ No newline at end of file diff --git a/tests/sav/nitpretty_args41.res b/tests/sav/nitpretty_args41.res new file mode 100644 index 0000000..1be308b --- /dev/null +++ b/tests/sav/nitpretty_args41.res @@ -0,0 +1,34 @@ +# 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. + +var a = 1 +var b = 2 + +while a != b do # comment 1 + # comment 2 + var tmp = a + a = b + b = tmp + # comment 3 +end + +# comment 4 +while a != b do a = b # comment 5 + +while a != b do + # comment 6 +end # comment 7 + +# end + diff --git a/tests/sav/nitpretty_args42.res b/tests/sav/nitpretty_args42.res new file mode 100644 index 0000000..6b49ffa --- /dev/null +++ b/tests/sav/nitpretty_args42.res @@ -0,0 +1,47 @@ +# 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. + +var a = 0 +var b = 2 + +do # comment 1 + # comment 2 + var tmp = a + a = b + b = tmp + # comment 3 +end + +# comment 4 +do a = b # comment 5 + +do + # comment 6 +end + +if a > b then loop print a # test + +if a > b then loop print a + + +if a > b then loop print a + + +if a > b then + loop + # comment 7 + print a + end +end + diff --git a/tests/sav/nitpretty_args43.res b/tests/sav/nitpretty_args43.res new file mode 100644 index 0000000..0135aa1 --- /dev/null +++ b/tests/sav/nitpretty_args43.res @@ -0,0 +1,27 @@ +# 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. + +var a = 0 + +for i in [1, 2, 3] do # comment 1 + # comment 2 + a += i +end + +# comment 4 +for i in [1..3] do a += i # comment 5 + +for i in [1..3[ do + # comment 6 +end diff --git a/tests/sav/nitpretty_args44.res b/tests/sav/nitpretty_args44.res new file mode 100644 index 0000000..2cd014e --- /dev/null +++ b/tests/sav/nitpretty_args44.res @@ -0,0 +1,36 @@ +# 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. + +class A + fun foo do end + fun bar(a: Int): Int do return 1 + fun baz(a, b: Int) do end + fun gaz(a: Int, b: Float...) do end +end + +fun top1 do end +fun top2(a: Int) do end + +# comment 1 +var a = new A # comment 2 +a.foo # comment 3 +a.bar 1 # comment 4 +a.baz(1, 2) # comment 5 +top1 # comment 6 +top2 10 # comment 7 + +print 10 # comment 8 + +var b = a.bar(1) + diff --git a/tests/sav/nitpretty_args45.res b/tests/sav/nitpretty_args45.res new file mode 100644 index 0000000..789abdd --- /dev/null +++ b/tests/sav/nitpretty_args45.res @@ -0,0 +1,39 @@ +# 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. + +class A + var attr: Int + fun foo1=(i: Int) do end + fun foo2=(i, j: Int) do end + fun [](a: Int): Int is abstract + fun []=(a, b: Int) do end +end + +class B + fun [](a, b: Int): Int is abstract + fun []=(a, b, c: Int) do end +end + +# comment 1 +var a = new A(10) # comment 2 + +a.foo1 = 10 # comment 3 +a.foo2(1) = 10 # comment 4 +print a[1] # comment 5 +a[1] = 2 # comment 6 +a[2] += 3 # comment 7 + +var b = new B +print b[1, 2] +b[1, 2] = 10 diff --git a/tests/sav/nitpretty_args46.res b/tests/sav/nitpretty_args46.res new file mode 100644 index 0000000..60bf5ef --- /dev/null +++ b/tests/sav/nitpretty_args46.res @@ -0,0 +1,50 @@ +# 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. + +var a = 1 +var b = 2 + +if a == b then a = b + +if a != b then + a = b + a = b +end + +if a > b then + b = a + a = b +else + a = b + a = b +end + +if a < b then + a = b + a = b +else if a == b then + b = a + a = b +end + +if a < b then + a = b + a = b +else if a == b then + b = b + a = b +else + a = b + a = b +end diff --git a/tests/sav/nitpretty_args47.res b/tests/sav/nitpretty_args47.res new file mode 100644 index 0000000..12d8db5 --- /dev/null +++ b/tests/sav/nitpretty_args47.res @@ -0,0 +1,81 @@ +# 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. + +# comment +var a = 1 # comment +# comment +var b = 2 # comment + +# comment +if a == b then a = b # comment + +# comment +if a != b then # comment + # comment + a = b # comment + # comment + a = b # comment + # comment +end # comment + +# comment +if a > b then # comment + # comment + b = a # comment + # comment + a = b # comment + # comment +else # comment + # comment + a = b # comment + # comment + a = b # comment + # comment +end # comment + +# comment +if a < b then # comment + # comment + a = b # comment + # comment + a = b # comment + # comment +else if a == b then # comment + # comment + b = a # comment + # comment + a = b # comment + # comment +end # comment + +# comment +if a < b then # comment + # comment + a = b # comment + # comment + a = b # comment + # comment +else if a == b then # comment + # comment + b = b # comment + # comment + a = b # comment + # comment +else # comment + # comment + a = b # comment + # comment + a = b # comment + # comment +end # comment \ No newline at end of file diff --git a/tests/sav/nitpretty_args48.res b/tests/sav/nitpretty_args48.res new file mode 100644 index 0000000..bfde8c2 --- /dev/null +++ b/tests/sav/nitpretty_args48.res @@ -0,0 +1,59 @@ +# 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. + +var a = 1 +var b = 2 + +# 0 +if a == b then # 1 + # 2 +else # 3 + # 4 +end # 5 + +if a == b then print a # printing a + +if a == b then + print a # printing a +end + +if a == b then print a # end + +if a == b then a = b + +if a == b then end + +if a == b then end + +if a != b then a = b + +if a > b then + a = b +else + a = b +end + +if a < b then + a = b +else if a == b then + a = b +end + +if a < b then + a = b +else if a == b then + a = b +else + a = b +end diff --git a/tests/sav/nitpretty_args49.res b/tests/sav/nitpretty_args49.res new file mode 100644 index 0000000..4fec81e --- /dev/null +++ b/tests/sav/nitpretty_args49.res @@ -0,0 +1,21 @@ +# 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. + +var a: nullable Int = 1 +var b: nullable Int = a.as(Int) +var c: nullable Int = a.as(not null) + +assert c isa Int +assert test1: c isa Int +assert test2: c isa Int else abort diff --git a/tests/sav/nitpretty_args50.res b/tests/sav/nitpretty_args50.res new file mode 100644 index 0000000..c428dcb --- /dev/null +++ b/tests/sav/nitpretty_args50.res @@ -0,0 +1,31 @@ +# 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. + +var a = 1 +var b = 2 + +assert a == 2 +assert not a < 2 # comment 1 +assert a > 2 and b >= 2 +assert b != 2 or a <= 2 +assert b != null # comment 2 + +# comment 3 +print a + b +print a - b # comment 4 +print a * b +print a / b +print a % b + +print -a # comment 5 \ No newline at end of file diff --git a/tests/sav/nitpretty_args51.res b/tests/sav/nitpretty_args51.res new file mode 100644 index 0000000..90425ff --- /dev/null +++ b/tests/sav/nitpretty_args51.res @@ -0,0 +1,27 @@ +# 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. + +var a = 1 +var b = 2 + +assert not a < 2 and (a == b or a > b) # comment 1 +assert not a < 2 and (a == b or ((a > b) or a <= b)) +assert (a > 2 and b >= 2) +assert (b >= 2) + +# comment 3 +var c = a + (b - a) +var d = (a - b) + c # comment 4 +var e = (-a) # comment 5 +var f = -(a - c) diff --git a/tests/sav/fixme/nitpretty_args21.res b/tests/sav/nitpretty_args52.res similarity index 93% rename from tests/sav/fixme/nitpretty_args21.res rename to tests/sav/nitpretty_args52.res index f4a3324..415c33f 100644 --- a/tests/sav/fixme/nitpretty_args21.res +++ b/tests/sav/nitpretty_args52.res @@ -34,9 +34,8 @@ fun errno: Int is extern `{ return errno; `} -fun errnoooooooooooooooooooooooooooooooooooooooooooooooooooooooooo: Int is extern `{ - return errno; -`} +fun errnoooooooooooooooooooooooooooooooooooooooooooooooooooooooooo: Int is + extern `{ return errno; `} private class A var my_attr = 1234 @@ -69,6 +68,7 @@ end extern class TimeT `{time_t`} new `{ return time(NULL); `} new from_i(i: Int) `{ return i; `} + fun update `{ time(&recv); `} fun ctime: String import NativeString.to_s_with_copy `{ @@ -78,10 +78,11 @@ extern class TimeT `{time_t`} # Difference in secondes from start (self if the end time) fun difftime(start: TimeT): Float `{ return difftime(recv, start); `} - private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]): nullable Int is import - Array[Int].length, Array[Int].[], Int.as(nullable Int) `{`} + private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]): nullable Int is + extern import Array[Int].length, Array[Int].[], Int.as(nullable Int) `{`} end fun address_is_null: Bool is extern "address_is_null" fun free `{ free(recv); `} + diff --git a/tests/sav/nitpretty_args53.res b/tests/sav/nitpretty_args53.res new file mode 100644 index 0000000..8152504 --- /dev/null +++ b/tests/sav/nitpretty_args53.res @@ -0,0 +1,35 @@ +# 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. + +class A + var a: Int # comment + private var b: nullable Int # happy + protected var c = 10 # ending + var d: Int = 10 + + + + + + # Test test... + var e: Int is writable + var f: Int is protected writable + # Adoc + var k: Int = 10 is protected writable + + + + # more comments +end # end + diff --git a/tests/sav/nitpretty_args54.res b/tests/sav/nitpretty_args54.res new file mode 100644 index 0000000..08a4d49 --- /dev/null +++ b/tests/sav/nitpretty_args54.res @@ -0,0 +1,24 @@ +# 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. + +class Foo + var a: Int + private var b: nullable Int + protected var c = 10 + var d: Int = 10 +end + +var foo = new Foo(1, 2) +print foo._a +foo._a = 10 diff --git a/tests/sav/nitpretty_args55.res b/tests/sav/nitpretty_args55.res new file mode 100644 index 0000000..2096847 --- /dev/null +++ b/tests/sav/nitpretty_args55.res @@ -0,0 +1,98 @@ +# 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. + + +# toplevel comment + + + + + + +# block +# block +# block + + + + + +# Adoc1 +class A # ending comments + + super Object + # super Int + + + super String + # super Truc + + + + # inclass comments + # comm + # ented + # blocks + + + + # Adoc2 + fun foo do + + # comment + + + + var truc + + # comment + # comment + + + + # comment + + + var chose + + # comment + end + + # comm + # ented + # blocks + + + fun bar do end + + + fun baz do end + # comment before end + +end # ending comments + +# comm +# ented +# blocks + +abstract class B # comment +end + +abstract class C end + +abstract class B # comment 2 + +end + +abstract class C end diff --git a/tests/sav/nitpretty_args56.res b/tests/sav/nitpretty_args56.res new file mode 100644 index 0000000..adabdcf --- /dev/null +++ b/tests/sav/nitpretty_args56.res @@ -0,0 +1,111 @@ +# 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. + +class Foo + fun bar: Bool do return true + + fun foo(other: Foo): Foo + do + if other.bar then + return other + else + return self + end + end + + fun baz: Int do + var nb = 0 + while nb < 10 do + print nb + nb += 1 + end # 1 + return nb + end + + fun gaz: Int + do + if bar then # 3 + return 1 + else + return -1 # 4 + end + end +end + +class Test[E] + var heap: ArrayHeap[E] + + init to(comparator: Comparator[E]) do heap = new ArrayHeap[E](comparator) + + init from(comparator: Comparator[E], items: Collection[E]) do + heap = new ArrayHeap[E].from(comparator, items.to_a) + end + + fun count(k: E): Int do + if heap.has(k) then + return 1 + else + return 0 + end + end + + fun node_at_idx(i: Int, k: E) do + while heap != null do + if heap.is_empty or i == k then # FIXME prefilter because the compiler is not smart enought yet + break + end + end + end + + fun save_those_nodes(nodes: Collection[Object]) do + for node in nodes do count(node) + end +end + +fun foo do + if last_slash > 0 then + return substring(last_slash + 1, length) + else + return null + end +end + +print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." + +var lorem = "lorem" +var ipsum = "ipsum" # for fun + +print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." # ending + +var title = "title" +var links = new Array[String] # why not? + +var body = """ + + + + + + {{{title}}} + + +
+

{{{title}}}

+
    +
  • {{{links.join("
  • \n\t\t\t
  • ")}}}
  • +
+
+ +""" + diff --git a/tests/sav/nitpretty_args57.res b/tests/sav/nitpretty_args57.res new file mode 100644 index 0000000..e385838 --- /dev/null +++ b/tests/sav/nitpretty_args57.res @@ -0,0 +1,48 @@ +# 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. + +# prims + +var a = true +var b = false + +var c = 10 +var d = -10 +var e = 1.12 + +var f = -1.12 +var n = 'a' +var o = null +var p = 0x12345678 + +# strings + +var g = "test" +var h1 = "Hello {g}" +var h2 = "Hello \"{g}\" Hello" +var h3 = "Hello {g}" +var m = """ +bla + bla + +bla""" + +# arrays + +var j = [1, 2, 3] +var k = [1..2[ +var l = [1..2] + + + diff --git a/tests/sav/nitpretty_args58.res b/tests/sav/nitpretty_args58.res new file mode 100644 index 0000000..edc3f3f --- /dev/null +++ b/tests/sav/nitpretty_args58.res @@ -0,0 +1,48 @@ +# 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. + +module test_annot1 is platform("android") + +class A + fun goo is intern + + # test + fun foo is a, b + fun bar is a, b do print "1" + fun baz is + a + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb do print "2" +end + +class B + fun foo is a, b + + + fun bar is a, b do print "1" + + fun baz is a, b + do + bar + print "2" + end + + fun gaz is + a + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + do + bar + print "2" + end + +end diff --git a/tests/sav/nitpretty_args59.res b/tests/sav/nitpretty_args59.res new file mode 100644 index 0000000..dadc656 --- /dev/null +++ b/tests/sav/nitpretty_args59.res @@ -0,0 +1,47 @@ +# 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. + +# comment 1 +class A + type FOO: Discrete + private var foo: FOO # comment + # comment 2 + var bar: Int = 10 +end + +class B + super A + + redef type FOO: Int + # comment 3 + redef fun foo do return bar # comment + redef fun bar + do + return 10 # comment 4 + end + fun baz do return # comment 5 + protected fun baz2 do end + fun other: String do + return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaa" + end + + fun foo1(arr: Array[String], len: Int, ind: Int): String + do + return "Hello World!" + end +end + +# end + diff --git a/tests/sav/nitpretty_args60.res b/tests/sav/nitpretty_args60.res new file mode 100644 index 0000000..0fd4ac4 --- /dev/null +++ b/tests/sav/nitpretty_args60.res @@ -0,0 +1,127 @@ +# 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. + +class Foo + fun bar: Bool do return true + + fun foo(other: Foo): Foo + do + if other.bar then + return other + else + return self + end + end + + fun baz: Int do + var nb = 0 + while nb < 10 do + print nb + nb += 1 + end # 1 + return nb + end + + fun gaz: Int + do + if bar then # 3 + return 1 + else + return -1 # 4 + end + end +end + +class Test[E] + var heap: ArrayHeap[E] + + init to(comparator: Comparator[E]) do heap = new ArrayHeap[E](comparator) + + init from(comparator: Comparator[E], items: Collection[E]) do + heap = new ArrayHeap[E].from(comparator, items.to_a) + end + + fun count(k: E): Int do + if heap.has(k) then + return 1 + else + return 0 + end + end + + fun node_at_idx(i: Int, k: E) do + while heap != null do + if heap.is_empty or i == k then # FIXME prefilter because the compiler is not smart enought yet + break + end + end + end + + fun save_those_nodes(nodes: Collection[Object]) do + for node in nodes do count(node) + end +end + +fun foo do + if last_slash > 0 then + return substring(last_slash + 1, length) + else + return null + end +end + +print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidun" + + "t sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit a" + + "met lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus" + + " eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pell" + + "entesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae" + + " consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae" + + " lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas" + + " turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed phar" + + "etra lacus." + +var lorem = "lorem" +var ipsum = "ipsum" # for fun + +print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, con" + + "sectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius a" + + "t non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisi" + + "s neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}" + + ". Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} pla" + + "cerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus pl" + + "acerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum " + + "augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pell" + + "entesque vitae arcu justo. Aliquam sed pharetra lacus." # ending + +var title = "title" +var links = new Array[String] # why not? + +var body = """ + + + + + + {{{title}}} + + +
+

{{{title}}}

+
    +
  • {{{links.join("
  • \n\t\t\t
  • ")}}}
  • +
+
+ +""" + diff --git a/tests/sav/nitpretty_args61.res b/tests/sav/nitpretty_args61.res new file mode 100644 index 0000000..6b5b168 --- /dev/null +++ b/tests/sav/nitpretty_args61.res @@ -0,0 +1,44 @@ +# 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. + +# comment 1 +class A + type FOO: Discrete + private var foo: FOO # comment + # comment 2 + var bar: Int = 10 +end + +class B + super A + + redef type FOO: Int + # comment 3 + redef fun foo do return bar # comment + redef fun bar do + return 10 # comment 4 + end + fun baz do return # comment 5 + protected fun baz2 do end + fun other: String do + return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + end + + fun foo1(arr: Array[String], len: Int, ind: Int): String do + return "Hello World!" + end +end + +# end + diff --git a/tests/sav/nitpretty_args62.res b/tests/sav/nitpretty_args62.res new file mode 100644 index 0000000..329aa03 --- /dev/null +++ b/tests/sav/nitpretty_args62.res @@ -0,0 +1,109 @@ +# 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. + +class Foo + fun bar: Bool do return true + + fun foo(other: Foo): Foo do + if other.bar then + return other + else + return self + end + end + + fun baz: Int do + var nb = 0 + while nb < 10 do + print nb + nb += 1 + end # 1 + return nb + end + + fun gaz: Int do + if bar then # 3 + return 1 + else + return -1 # 4 + end + end +end + +class Test[E] + var heap: ArrayHeap[E] + + init to(comparator: Comparator[E]) do heap = new ArrayHeap[E](comparator) + + init from(comparator: Comparator[E], items: Collection[E]) do + heap = new ArrayHeap[E].from(comparator, items.to_a) + end + + fun count(k: E): Int do + if heap.has(k) then + return 1 + else + return 0 + end + end + + fun node_at_idx(i: Int, k: E) do + while heap != null do + if heap.is_empty or i == k then # FIXME prefilter because the compiler is not smart enought yet + break + end + end + end + + fun save_those_nodes(nodes: Collection[Object]) do + for node in nodes do count(node) + end +end + +fun foo do + if last_slash > 0 then + return substring(last_slash + 1, length) + else + return null + end +end + +print "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis lorem. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus ipsum placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." + +var lorem = "lorem" +var ipsum = "ipsum" # for fun + +print "We also need to handle super strings: {lorem} {ipsum} dolor sit amet, consectetur adipiscing elit. Aliquam tincidunt sapien et velit fringilla varius at non eros. Nunc ut ultricies metus, sit amet lacinia felis. Donec in facilisis neque, non laoreet nibh. Etiam nec purus eu orci congue iaculis eu quis {lorem}. Ut et blandit erat. Cras fermentum pellentesque ante, ut dapibus {ipsum} placerat sit amet. Vivamus pharetra, sem vitae consequat venenatis, diam risus placerat est, sed hendrerit purus justo vitae lectus. In id quam mattis, rutrum augue eu, vehicula ipsum. Nulla nec egestas turpis, nec ullamcorper odio. Pellentesque vitae arcu justo. Aliquam sed pharetra lacus." # ending + +var title = "title" +var links = new Array[String] # why not? + +var body = """ + + + + + + {{{title}}} + + +
+

{{{title}}}

+
    +
  • {{{links.join("
  • \n\t\t\t
  • ")}}}
  • +
+
+ +""" + diff --git a/tests/sav/nitpretty_args7.res b/tests/sav/nitpretty_args7.res index e404557..ea248bc 100644 --- a/tests/sav/nitpretty_args7.res +++ b/tests/sav/nitpretty_args7.res @@ -29,7 +29,8 @@ class B # comment 3 redef fun foo do return bar # comment - redef fun bar do + redef fun bar + do return 10 # comment 4 end @@ -37,8 +38,12 @@ class B protected fun baz2 do end fun other: String do - return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaa" + return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + end + + fun foo1(arr: Array[String], len: Int, ind: Int): String + do + return "Hello World!" end end diff --git a/tests/sav/nitpretty_args9.res b/tests/sav/nitpretty_args9.res index bd21dbb..46c03e1 100644 --- a/tests/sav/nitpretty_args9.res +++ b/tests/sav/nitpretty_args9.res @@ -31,7 +31,5 @@ class A fun foo5 do end # comment fun foo6(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: Int) do - print 1 - end + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: Int) do print 1 end # comment diff --git a/tests/test_pretty/test_annot1.nit b/tests/test_pretty/test_annot1.nit index 381cc4f..695020f 100644 --- a/tests/test_pretty/test_annot1.nit +++ b/tests/test_pretty/test_annot1.nit @@ -15,6 +15,9 @@ module test_annot1 is platform("android") class A + fun goo is intern + + # test fun foo is a, b fun bar is a, b do print "1" fun baz is a, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb do print "2" diff --git a/tests/test_pretty/test_prop1.nit b/tests/test_pretty/test_prop1.nit index 0b46c27..3b692a5 100644 --- a/tests/test_pretty/test_prop1.nit +++ b/tests/test_pretty/test_prop1.nit @@ -35,6 +35,11 @@ class B end # comment 5 protected fun baz2 do end fun other: String do return "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + fun foo1(arr: Array[String], len: Int, ind: Int): String + do + return "Hello World!" + end end # end