From: Jean Privat Date: Tue, 20 Jan 2015 04:18:57 +0000 (+0700) Subject: Merge: Minor graphics related fixes and features X-Git-Tag: v0.7.1~20 X-Git-Url: http://nitlanguage.org?hp=84c0625971c611a8fef601acd0c03477092e249e Merge: Minor graphics related fixes and features Pull-Request: #1113 Reviewed-by: Lucas Bajolet Reviewed-by: Alexandre Terrasa --- diff --git a/contrib/nitiwiki/src/wiki_html.nit b/contrib/nitiwiki/src/wiki_html.nit index 7f213b7..89546ce 100644 --- a/contrib/nitiwiki/src/wiki_html.nit +++ b/contrib/nitiwiki/src/wiki_html.nit @@ -81,6 +81,7 @@ redef class WikiSection end var index = self.index if index isa WikiSectionIndex then + wiki.message("Render auto-index for section {out_path}", 1) index.is_dirty = true add_child index end @@ -322,6 +323,10 @@ class WikiSectionIndex # The section described by `self`. var section: WikiSection + redef fun title do return section.title + + redef fun url do return section.url + redef var is_dirty = false redef fun tpl_article do diff --git a/contrib/nitiwiki/tests/res/nitiwiki_render.res b/contrib/nitiwiki/tests/res/nitiwiki_render.res index adf25a7..25f17ab 100644 --- a/contrib/nitiwiki/tests/res/nitiwiki_render.res +++ b/contrib/nitiwiki/tests/res/nitiwiki_render.res @@ -1 +1,6 @@ Render section out +Render section out/sec1 +Render section out/sec2 +Render auto-index for section out/sec2 +Render section out/sec2/sub-sec21 +Render section out/sec2/sub-sec22 diff --git a/contrib/nitiwiki/tests/res/nitiwiki_status.res b/contrib/nitiwiki/tests/res/nitiwiki_status.res index 936a764..9eb2262 100644 --- a/contrib/nitiwiki/tests/res/nitiwiki_status.res +++ b/contrib/nitiwiki/tests/res/nitiwiki_status.res @@ -6,5 +6,12 @@ url: http://localhost/ There is modified files: + pages + /pages/index.md + + pages/sec1 + + /pages/sec1/index.md + + pages/sec2 + + pages/sec2/sub-sec21 + + /pages/sec2/sub-sec21/index.md + + pages/sec2/sub-sec22 + + /pages/sec2/sub-sec22/index.md Use nitiwiki --render to render modified files diff --git a/lib/cocoa/examples/cocoa_message_box.nit b/lib/cocoa/examples/cocoa_message_box.nit index 72e35d7..224c7ab 100644 --- a/lib/cocoa/examples/cocoa_message_box.nit +++ b/lib/cocoa/examples/cocoa_message_box.nit @@ -19,10 +19,6 @@ module cocoa_message_box import cocoa -in "ObjC" `{ - #import -`} - fun dialog in "ObjC" `{ NSAlert *alert = [[[NSAlert alloc] init] autorelease]; [alert setMessageText:@"Hello world!"]; diff --git a/lib/cocoa/examples/hello_cocoa.nit b/lib/cocoa/examples/hello_cocoa.nit index 3a2b168..960b001 100644 --- a/lib/cocoa/examples/hello_cocoa.nit +++ b/lib/cocoa/examples/hello_cocoa.nit @@ -19,10 +19,6 @@ module hello_cocoa import cocoa::foundation -in "ObjC" `{ - #import -`} - # Print `"Hello world!"` to the log fun hello_world in "ObjC" `{ @autoreleasepool { diff --git a/lib/github/api.nit b/lib/github/api.nit index 3e06f52..b979b5d 100644 --- a/lib/github/api.nit +++ b/lib/github/api.nit @@ -252,6 +252,25 @@ class GithubAPI return milestone.load_from_github end + # Get the Github issue event with `id`. + # + # Returns `null` if the event cannot be found. + # + # var api = new GithubAPI(get_github_oauth) + # var repo = api.load_repo("privat/nit") + # assert repo isa Repo + # var event = api.load_issue_event(repo, 199674194) + # assert event.actor.login == "privat" + # assert event.event == "labeled" + # assert event.labl.name == "need_review" + # assert event.issue.number == 945 + fun load_issue_event(repo: Repo, id: Int): nullable IssueEvent do + var event = new IssueEvent(self, repo, id) + event.load_from_github + if was_error then return null + return event + end + # Get the Github commit comment with `id`. # # Returns `null` if the comment cannot be found. @@ -475,6 +494,19 @@ class Repo return res end + # List of contributor related statistics. + fun contrib_stats: Array[ContributorStats] do + api.message(1, "Get contributor stats for {full_name}") + var res = new Array[ContributorStats] + var array = api.get("{key}/stats/contributors") + if array isa JsonArray then + for obj in array do + res.add new ContributorStats.from_json(api, obj.as(JsonObject)) + end + end + return res + end + # Repo default branch. fun default_branch: Branch do var name = json["default_branch"].to_s @@ -604,6 +636,17 @@ class Commit return new ISODate.from_string(author["date"].to_s) end + # List files staged in this commit. + fun files: Array[GithubFile] do + var res = new Array[GithubFile] + var files = json["files"] + if not files isa JsonArray then return res + for obj in files do + res.add(new GithubFile(obj.as(JsonObject))) + end + return res + end + # Commit message. fun message: String do return json["commit"].as(JsonObject)["message"].to_s end @@ -713,6 +756,22 @@ class Issue # Full description of the issue. fun body: String do return json["body"].to_s + # List of events on this issue. + fun events: Array[IssueEvent] do + var res = new Array[IssueEvent] + var page = 1 + var array = api.get("{key}/events?page={page}").as(JsonArray) + while not array.is_empty do + for obj in array do + if not obj isa JsonObject then continue + res.add new IssueEvent.from_json(api, repo, obj) + end + page += 1 + array = api.get("{key}/events?page={page}").as(JsonArray) + end + return res + end + # User that closed this issue (if any). fun closed_by: nullable User do var closer = json["closed_by"] @@ -1030,3 +1089,137 @@ class ReviewComment # Original commit id. fun original_commit_id: String do return json["original_commit_id"].to_s end + +# An event that occurs on a Github `Issue`. +# +# Should be accessed from `GithubAPI::load_issue_event`. +# +# See . +class IssueEvent + super RepoEntity + + redef var key is lazy do return "{repo.key}/issues/events/{id}" + + # Event id on Github. + var id: Int + + redef init from_json(api, repo, json) do + self.id = json["id"].as(Int) + super + end + + # Issue that contains `self`. + fun issue: Issue do + return new Issue.from_json(api, repo, json["issue"].as(JsonObject)) + end + + # User that initiated the event. + fun actor: User do + return new User.from_json(api, json["actor"].as(JsonObject)) + end + + # Creation time in ISODate format. + fun created_at: ISODate do + return new ISODate.from_string(json["created_at"].to_s) + end + + # Event descriptor. + fun event: String do return json["event"].to_s + + # Commit linked to this event (if any). + fun commit_id: nullable String do + var res = json["commit_id"] + if res == null then return null + return res.to_s + end + + # Label linked to this event (if any). + fun labl: nullable Label do + var res = json["label"] + if not res isa JsonObject then return null + return new Label.from_json(api, repo, res) + end + + # User linked to this event (if any). + fun assignee: nullable User do + var res = json["assignee"] + if not res isa JsonObject then return null + return new User.from_json(api, res) + end + + # Milestone linked to this event (if any). + fun milestone: nullable Milestone do + var res = json["milestone"] + if not res isa JsonObject then return null + return new Milestone.from_json(api, repo, res) + end + + # Rename linked to this event (if any). + fun rename: nullable RenameAction do + var res = json["rename"] + if res == null then return null + return new RenameAction(res.as(JsonObject)) + end +end + +# A rename action maintains the name before and after a renaming action. +class RenameAction + + # JSON content. + var json: JsonObject + + # Name before renaming. + fun from: String do return json["from"].to_s + + # Name after renaming. + fun to: String do return json["to"].to_s +end + +# Contributors list with additions, deletions, and commit counts. +# +# Should be accessed from `Repo::contrib_stats`. +# +# See . +class ContributorStats + super Comparable + + redef type OTHER: ContributorStats + + # Github API client. + var api: GithubAPI + + # Json content. + var json: JsonObject + + # Init `self` from a `json` object. + init from_json(api: GithubAPI, json: JsonObject) do + self.api = api + self.json = json + end + + # User these statistics are about. + fun author: User do + return new User.from_json(api, json["author"].as(JsonObject)) + end + + # Total number of commit. + fun total: Int do return json["total"].to_s.to_i + + # Are of weeks of activity with detailed statistics. + fun weeks: JsonArray do return json["weeks"].as(JsonArray) + + # ContributorStats can be compared on the total amount of commits. + redef fun <(o) do return total < o.total +end + +# A Github file representation. +# +# Mostly a wrapper around a json object. +class GithubFile + + # Json content. + var json: JsonObject + + # File name. + fun filename: String do return json["filename"].to_s +end diff --git a/lib/github/events.nit b/lib/github/events.nit new file mode 100644 index 0000000..b6e5af3 --- /dev/null +++ b/lib/github/events.nit @@ -0,0 +1,302 @@ +# 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. + +# Events are emitted by Github Hooks. +# +# See +module events + +import api + +# Github event stub. +class GithubEvent + + # Github API client. + var api: GithubAPI + + # Json representation of `self`. + var json: JsonObject is noinit + + init do + json = new JsonObject + end + + # Init `self` from a `json` object. + init from_json(api: GithubAPI, json: JsonObject) do + self.api = api + self.json = json + end + + # Action performed by the event. + fun action: String do return json["action"].to_s + + # Repo where this event occured. + fun repo: Repo do + return new Repo.from_json(api, json["repository"].as(JsonObject)) + end +end + +# Triggered when a commit comment is created. +class CommitCommentEvent + super GithubEvent + + # The `Comment` itself. + fun comment: CommitComment do + return new CommitComment.from_json(api, repo, json["comment"].as(JsonObject)) + end +end + +# Triggered when a repository, branch, or tag is created. +class CreateEvent + super GithubEvent + + # Oject type that was created. + # + # Can be one of `repository`, `branch`, or `tag`. + fun ref_type: String do return json["ref_type"].to_s + + # Git ref (or null if only a repository was created). + fun ref: String do return json["ref"].to_s + + # Name of the repo's default branch (usually master). + fun master_branch: String do return json["master_branch"].to_s + + # Repo's current description. + fun description: String do return json["description"].to_s +end + +# Triggered when a branch or a tag is deleted. +class DeleteEvent + super GithubEvent + + # Object type that was deleted. + # + # Can be one of `repository`, `branch`, or `tag`. + fun ref_type: String do return json["ref_type"].to_s + + # Git ref (or null if only a repository was deleted). + fun ref: String do return json["ref"].to_s +end + +# Triggered when a new snapshot is deployed. +# +# Deployement are mainly used with integration testing servers. +class DeploymentEvent + super GithubEvent + + # Commit SHA for which this deployment was created. + fun sha: String do return json["sha"].to_s + + # Name of repository for this deployment, formatted as :owner/:repo. + fun name: String do return json["name"].to_s + + # Optional extra information for this deployment. + fun payload: nullable String do + if not json.has_key("payload") then return null + return json["payload"].to_s + end + + # Optional environment to deploy to. + # Default: "production" + fun environment: nullable String do + if not json.has_key("environment") then return null + return json["environment"].to_s + end + + # Optional human-readable description added to the deployment. + fun description: nullable String do + if not json.has_key("description") then return null + return json["description"].to_s + end +end + +# Triggered when a deployement's status changes. +class DeploymentStatusEvent + super GithubEvent + + # New deployment state. + # + # Can be `pending`, `success`, `failure`, or `error`. + fun state: String do return json["state"].to_s + + # Optional link added to the status. + fun target_url: nullable String do + if not json.has_key("target_url") then return null + return json["target_url"].to_s + end + + # Deployment hash that this status is associated with. + fun deployment: String do return json["deployment"].to_s + + # Optional human-readable description added to the status. + fun description: nullable String do + if not json.has_key("description") then return null + return json["description"].to_s + end +end + +# Triggered when a user forks a repository. +class ForkEvent + super GithubEvent + + # Created repository. + fun forkee: Repo do return new Repo.from_json(api, json["forkee"].as(JsonObject)) +end + +# Triggered when an issue comment is created. +class IssueCommentEvent + super GithubEvent + + # `Issue` the comment belongs to. + fun issue: Issue do + return new Issue.from_json(api, repo, json["issue"].as(JsonObject)) + end + + # The `Comment` itself. + fun comment: IssueComment do + return new IssueComment.from_json(api, repo, json["comment"].as(JsonObject)) + end +end + +# Triggered when an event occurs on an issue. +# +# Triggered when an issue is assigned, unassigned, labeled, unlabeled, +# opened, closed or reopened. +class IssuesEvent + super GithubEvent + + # The `Issue` itself. + fun issue: Issue do return new Issue.from_json(api, repo, json["issue"].as(JsonObject)) + + # Optional `Label` that was added or removed from the issue. + fun lbl: nullable Label do + if not json.has_key("label") then return null + return new Label.from_json(api, repo, json["label"].as(JsonObject)) + end + + # Optional `User` that was assigned or unassigned from the issue. + fun assignee: nullable User do + if not json.has_key("assignee") then return null + return new User.from_json(api, json["assignee"].as(JsonObject)) + end +end + +# Triggered when a user is added as a collaborator to a repository. +class MemberEvent + super GithubEvent + + # `User` that was added. + fun member: User do return new User.from_json(api, json["member"].as(JsonObject)) +end + +# Triggered when an event occurs on a pull request. +# +# Triggered when a pull request is assigned, unassigned, +# labeled, unlabeled, opened, closed, reopened, or synchronized. +class PullRequestEvent + super GithubEvent + + # The pull request number. + fun number: Int do return json["number"].as(Int) + + # The `PullRequest` itself. + fun pull: PullRequest do + return new PullRequest.from_json(api, repo, json["pull_request"].as(JsonObject)) + end +end + +# Triggered when a comment is created on a pull request diff. +class PullRequestReviewCommentEvent + super GithubEvent + + # The `Comment` itself. + fun comment: ReviewComment do + return new ReviewComment.from_json(api, repo, json["comment"].as(JsonObject)) + end + + # `PullRequest` the `comment` belongs to. + fun pull: PullRequest do + return new PullRequest.from_json(api, repo, json["pull_request"].as(JsonObject)) + end +end + +# Triggered when a repository branch is pushed to. +class PushEvent + super GithubEvent + + # SHA of the HEAD commit on the repository. + fun head: String do return json["head"].to_s + + # Full Git ref that was pushed. + # + # Example: “refs/heads/master” + fun ref: String do return json["ref"].to_s + + # Number of commits in the push. + fun size: Int do return json["size"].as(Int) + + # Array of pushed commits. + fun commits: Array[Commit] do + var res = new Array[Commit] + var arr = json["commits"].as(JsonArray) + for obj in arr do + if not obj isa JsonObject then continue + res.add api.load_commit(repo, obj["sha"].to_s).as(not null) + end + return res + end +end + +# Triggered when the status of a Git commit changes. +class StatusEvent + super GithubEvent + + # The `Commit` itself. + fun commit: Commit do + return api.load_commit(repo, json["sha"].to_s).as(not null) + end + + # New state. + # + # Can be `pending`, `success`, `failure`, or `error`. + fun state: String do return json["state"].to_s + + # Optional human-readable description added to the status. + fun description: nullable String do + if not json.has_key("description") then return null + return json["description"].to_s + end + + # Optional link added to the status. + fun target_url: nullable String do + if not json.has_key("target_url") then return null + return json["target_url"].to_s + end + + # Array of branches containing the status' SHA. + # + # Each branch contains the given SHA, + # but the SHA may or may not be the head of the branch. + # + # The array includes a maximum of 10 branches. + fun branches: Array[Branch] do + var res = new Array[Branch] + var arr = json["branches"].as(JsonArray) + for obj in arr do + if not obj isa JsonObject then continue + res.add api.load_branch(repo, obj["name"].to_s).as(not null) + end + return res + end +end diff --git a/lib/glesv2/examples/opengles2_hello_triangle.nit b/lib/glesv2/examples/opengles2_hello_triangle.nit index cfab7ae..cbf851f 100644 --- a/lib/glesv2/examples/opengles2_hello_triangle.nit +++ b/lib/glesv2/examples/opengles2_hello_triangle.nit @@ -22,7 +22,7 @@ module opengles2_hello_triangle import glesv2 import egl -import mnit_linux # for sdl +import mnit_linux::sdl import x11 if "NIT_TESTING".environ == "true" then exit(0) diff --git a/src/compiler/compiler.nit b/src/compiler/compiler.nit index 902a656..ea60c0a 100644 --- a/src/compiler/compiler.nit +++ b/src/compiler/compiler.nit @@ -19,6 +19,6 @@ import separate_erasure_compiler import global_compiler import compiler_ffi -import android_platform -import pnacl_platform -import emscripten_platform +import platform::android +import platform::pnacl +import platform::emscripten diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index 68438c7..9c03910 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -560,7 +560,7 @@ class SeparateCompiler var r = pd.separate_runtime_function r.compile_to_c(self) var r2 = pd.virtual_runtime_function - r2.compile_to_c(self) + if r2 != r then r2.compile_to_c(self) end end self.mainmodule = old_module @@ -1180,8 +1180,10 @@ class SeparateCompilerVisitor var res0 = before_send(mmethod, arguments) + var runtime_function = mmethod.intro.virtual_runtime_function + var msignature = runtime_function.called_signature + var res: nullable RuntimeVariable - var msignature = mmethod.intro.msignature.resolve_for(mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.mmodule, true) var ret = msignature.return_mtype if ret == null then res = null @@ -1189,10 +1191,8 @@ class SeparateCompilerVisitor res = self.new_var(ret) end - var s = new FlatBuffer var ss = new FlatBuffer - s.append("val*") ss.append("{recv}") for i in [0..msignature.arity[ do var a = arguments[i+1] @@ -1200,16 +1200,12 @@ class SeparateCompilerVisitor if i == msignature.vararg_rank then t = arguments[i+1].mcasttype end - s.append(", {t.ctype}") a = self.autobox(a, t) ss.append(", {a}") end - - var r - if ret == null then r = "void" else r = ret.ctype self.require_declaration(const_color) - var call = "(({r} (*)({s}))({arguments.first}->class->vft[{const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/" + var call = "(({runtime_function.c_ret} (*){runtime_function.c_sig})({arguments.first}->class->vft[{const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/" if res != null then self.add("{res} = {call};") @@ -1778,108 +1774,112 @@ class SeparateCompilerVisitor end redef class MMethodDef - fun separate_runtime_function: AbstractRuntimeFunction + # The C function associated to a mmethoddef + fun separate_runtime_function: SeparateRuntimeFunction do var res = self.separate_runtime_function_cache if res == null then - res = new SeparateRuntimeFunction(self) + var recv = mclassdef.bound_mtype + var msignature = msignature.resolve_for(recv, recv, mclassdef.mmodule, true) + res = new SeparateRuntimeFunction(self, recv, msignature, c_name) self.separate_runtime_function_cache = res end return res end private var separate_runtime_function_cache: nullable SeparateRuntimeFunction - fun virtual_runtime_function: AbstractRuntimeFunction + # The C function associated to a mmethoddef, that can be stored into a VFT of a class + # The first parameter (the reciever) is always typed by val* in order to accept an object value + # The C-signature is always compatible with the intro + fun virtual_runtime_function: SeparateRuntimeFunction do var res = self.virtual_runtime_function_cache if res == null then - res = new VirtualRuntimeFunction(self) + # Because the function is virtual, the signature must match the one of the original class + var intromclassdef = mproperty.intro.mclassdef + var recv = intromclassdef.bound_mtype + + res = separate_runtime_function + if res.called_recv == recv then + self.virtual_runtime_function_cache = res + return res + end + + var msignature = mproperty.intro.msignature.resolve_for(recv, recv, intromclassdef.mmodule, true) + + if recv.ctype == res.called_recv.ctype and msignature.c_equiv(res.called_signature) then + self.virtual_runtime_function_cache = res + return res + end + + res = new SeparateRuntimeFunction(self, recv, msignature, "VIRTUAL_{c_name}") self.virtual_runtime_function_cache = res + res.is_thunk = true end return res end - private var virtual_runtime_function_cache: nullable VirtualRuntimeFunction + private var virtual_runtime_function_cache: nullable SeparateRuntimeFunction +end + +redef class MSignature + # Does the C-version of `self` the same than the C-version of `other`? + fun c_equiv(other: MSignature): Bool + do + if self == other then return true + if arity != other.arity then return false + for i in [0..arity[ do + if mparameters[i].mtype.ctype != other.mparameters[i].mtype.ctype then return false + end + if return_mtype != other.return_mtype then + if return_mtype == null or other.return_mtype == null then return false + if return_mtype.ctype != other.return_mtype.ctype then return false + end + return true + end end # The C function associated to a methoddef separately compiled class SeparateRuntimeFunction super AbstractRuntimeFunction - redef fun build_c_name: String do return "{mmethoddef.c_name}" + # The call-side static receiver + var called_recv: MType - redef fun to_s do return self.mmethoddef.to_s + # The call-side static signature + var called_signature: MSignature - redef fun compile_to_c(compiler) - do - var mmethoddef = self.mmethoddef + # The name on the compiled method + redef var build_c_name: String - var recv = self.mmethoddef.mclassdef.bound_mtype - var v = compiler.new_visitor - var selfvar = new RuntimeVariable("self", recv, recv) - var arguments = new Array[RuntimeVariable] - var frame = new StaticFrame(v, mmethoddef, recv, arguments) - v.frame = frame + # Statically call the original body instead + var is_thunk = false - var msignature = mmethoddef.msignature.resolve_for(mmethoddef.mclassdef.bound_mtype, mmethoddef.mclassdef.bound_mtype, mmethoddef.mclassdef.mmodule, true) + redef fun to_s do return self.mmethoddef.to_s - var sig = new FlatBuffer - var comment = new FlatBuffer - var ret = msignature.return_mtype + # The C return type (something or `void`) + var c_ret: String is lazy do + var ret = called_signature.return_mtype if ret != null then - sig.append("{ret.ctype} ") + return ret.ctype else - sig.append("void ") + return "void" end - sig.append(self.c_name) - sig.append("({selfvar.mtype.ctype} {selfvar}") - comment.append("({selfvar}: {selfvar.mtype}") - arguments.add(selfvar) - for i in [0..msignature.arity[ do - var mtype = msignature.mparameters[i].mtype - if i == msignature.vararg_rank then - mtype = v.get_class("Array").get_mtype([mtype]) + end + + # The C signature (only the parmeter part) + var c_sig: String is lazy do + var sig = new FlatBuffer + sig.append("({called_recv.ctype} self") + for i in [0..called_signature.arity[ do + var mtype = called_signature.mparameters[i].mtype + if i == called_signature.vararg_rank then + mtype = mmethoddef.mclassdef.mmodule.get_primitive_class("Array").get_mtype([mtype]) end - comment.append(", {mtype}") sig.append(", {mtype.ctype} p{i}") - var argvar = new RuntimeVariable("p{i}", mtype, mtype) - arguments.add(argvar) end sig.append(")") - comment.append(")") - if ret != null then - comment.append(": {ret}") - end - compiler.provide_declaration(self.c_name, "{sig};") - - v.add_decl("/* method {self} for {comment} */") - v.add_decl("{sig} \{") - if ret != null then - frame.returnvar = v.new_var(ret) - end - frame.returnlabel = v.get_name("RET_LABEL") - - if recv != arguments.first.mtype then - #print "{self} {recv} {arguments.first}" - end - mmethoddef.compile_inside_to_c(v, arguments) - - v.add("{frame.returnlabel.as(not null)}:;") - if ret != null then - v.add("return {frame.returnvar.as(not null)};") - end - v.add("\}") - if not self.c_name.has_substring("VIRTUAL", 0) then compiler.names[self.c_name] = "{mmethoddef.mclassdef.mmodule.name}::{mmethoddef.mclassdef.mclass.name}::{mmethoddef.mproperty.name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})" + return sig.to_s end -end - -# The C function associated to a methoddef on a primitive type, stored into a VFT of a class -# The first parameter (the reciever) is always typed by val* in order to accept an object value -class VirtualRuntimeFunction - super AbstractRuntimeFunction - - redef fun build_c_name: String do return "VIRTUAL_{mmethoddef.c_name}" - - redef fun to_s do return self.mmethoddef.to_s redef fun compile_to_c(compiler) do @@ -1887,25 +1887,20 @@ class VirtualRuntimeFunction var recv = self.mmethoddef.mclassdef.bound_mtype var v = compiler.new_visitor - var selfvar = new RuntimeVariable("self", v.object_type, recv) + var selfvar = new RuntimeVariable("self", called_recv, recv) var arguments = new Array[RuntimeVariable] var frame = new StaticFrame(v, mmethoddef, recv, arguments) v.frame = frame + var msignature = called_signature + var ret = called_signature.return_mtype + var sig = new FlatBuffer var comment = new FlatBuffer - - # Because the function is virtual, the signature must match the one of the original class - var intromclassdef = self.mmethoddef.mproperty.intro.mclassdef - var msignature = mmethoddef.mproperty.intro.msignature.resolve_for(intromclassdef.bound_mtype, intromclassdef.bound_mtype, intromclassdef.mmodule, true) - var ret = msignature.return_mtype - if ret != null then - sig.append("{ret.ctype} ") - else - sig.append("void ") - end + sig.append(c_ret) + sig.append(" ") sig.append(self.c_name) - sig.append("({selfvar.mtype.ctype} {selfvar}") + sig.append(c_sig) comment.append("({selfvar}: {selfvar.mtype}") arguments.add(selfvar) for i in [0..msignature.arity[ do @@ -1914,11 +1909,9 @@ class VirtualRuntimeFunction mtype = v.get_class("Array").get_mtype([mtype]) end comment.append(", {mtype}") - sig.append(", {mtype.ctype} p{i}") var argvar = new RuntimeVariable("p{i}", mtype, mtype) arguments.add(argvar) end - sig.append(")") comment.append(")") if ret != null then comment.append(": {ret}") @@ -1932,10 +1925,14 @@ class VirtualRuntimeFunction end frame.returnlabel = v.get_name("RET_LABEL") - var subret = v.call(mmethoddef, recv, arguments) - if ret != null then - assert subret != null - v.assign(frame.returnvar.as(not null), subret) + if is_thunk then + var subret = v.call(mmethoddef, recv, arguments) + if ret != null then + assert subret != null + v.assign(frame.returnvar.as(not null), subret) + end + else + mmethoddef.compile_inside_to_c(v, arguments) end v.add("{frame.returnlabel.as(not null)}:;") @@ -1943,11 +1940,8 @@ class VirtualRuntimeFunction v.add("return {frame.returnvar.as(not null)};") end v.add("\}") - if not self.c_name.has_substring("VIRTUAL", 0) then compiler.names[self.c_name] = "{mmethoddef.mclassdef.mmodule.name}::{mmethoddef.mclassdef.mclass.name}::{mmethoddef.mproperty.name} ({mmethoddef.location.file.filename}--{mmethoddef.location.line_start})" + compiler.names[self.c_name] = "{mmethoddef.full_name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})" end - - # TODO ? - redef fun call(v, arguments) do abort end redef class MEntity diff --git a/src/compiler/separate_erasure_compiler.nit b/src/compiler/separate_erasure_compiler.nit index 8a33265..2c90e65 100644 --- a/src/compiler/separate_erasure_compiler.nit +++ b/src/compiler/separate_erasure_compiler.nit @@ -235,13 +235,9 @@ class SeparateErasureCompiler v.add_decl("NULL, /* DEAD {mclass.intro_mmodule}:{mclass}:{mpropdef} */") continue end - if true or mpropdef.mclassdef.bound_mtype.ctype != "val*" then - v.require_declaration("VIRTUAL_{mpropdef.c_name}") - v.add_decl("(nitmethod_t)VIRTUAL_{mpropdef.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") - else - v.require_declaration("{mpropdef.c_name}") - v.add_decl("(nitmethod_t){mpropdef.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") - end + var rf = mpropdef.virtual_runtime_function + v.require_declaration(rf.c_name) + v.add_decl("(nitmethod_t){rf.c_name}, /* pointer to {mpropdef.full_name} */") end end v.add_decl("\}") diff --git a/src/doc/doc_down.nit b/src/doc/doc_down.nit index 1c77939..1cdc51a 100644 --- a/src/doc/doc_down.nit +++ b/src/doc/doc_down.nit @@ -143,6 +143,10 @@ private class NitdocDecorator end end +# Decorator for span elements. +# +# Because inline comments can appear as span elements, +# InlineDecorator do not decorate things like paragraphs or headers. private class InlineDecorator super NitdocDecorator @@ -150,6 +154,10 @@ private class InlineDecorator v.emit_in block end + redef fun add_headline(v, block) do + v.emit_in block + end + redef fun add_code(v, block) do # Try to parse code var ast = toolcontext.parse_something(block.block.text.to_s) diff --git a/src/ffi/header_dependency.nit b/src/ffi/header_dependency.nit index 10c1db3..84bbb29 100644 --- a/src/ffi/header_dependency.nit +++ b/src/ffi/header_dependency.nit @@ -33,36 +33,32 @@ redef class AModule end redef class MModule - private var header_dependencies_cache: nullable Array[MModule] = null - fun header_dependencies: Array[MModule] - do - var cache = header_dependencies_cache - assert cache != null - return cache - end + # Modules with public foreign code blocks (C header) + var header_dependencies: nullable HashSet[MModule] = null private fun compute_header_dependencies(v: HeaderDependancyPhase) do - if header_dependencies_cache != null then return + if header_dependencies != null then return - var header_dependencies = new Array[MModule] + var header_dependencies = new HashSet[MModule] # gather from importation for m in in_importation.direct_greaters do - m.compute_header_dependencies(v) + m.compute_header_dependencies v - # does the super module has inherited dependancies? + # does the super module has inherited dependencies? var hd = m.header_dependencies + assert hd != null if not hd.is_empty then - header_dependencies.add_all(hd) + header_dependencies.add_all hd end - # does the super module itself has extern dependancies? + # does the super module itself has extern dependencies? var amodule = v.toolcontext.modelbuilder.mmodule2node(m) if amodule != null and amodule.has_public_c_header then header_dependencies.add(m) end - header_dependencies_cache = header_dependencies + self.header_dependencies = header_dependencies end end diff --git a/src/ffi/objc.nit b/src/ffi/objc.nit index 5c7eeeb..f031289 100644 --- a/src/ffi/objc.nit +++ b/src/ffi/objc.nit @@ -32,6 +32,27 @@ end redef class MModule private var objc_file: nullable ObjCCompilationUnit = null + + private var has_public_objc_header = false + + # Imported modules with public Objective-C code blocks + var objc_imported_headers: HashSet[MModule] is lazy do + var dep = new HashSet[MModule] + + # gather from importation + for m in in_importation.direct_greaters do + # does the super module has inherited dependencies? + var import_dep = m.objc_imported_headers + if not import_dep.is_empty then + dep.add_all import_dep + end + + # does the super module itself has a public header? + if m.has_public_objc_header then dep.add(m) + end + + return dep + end end # The Objective-C langugage visitor @@ -47,6 +68,8 @@ class ObjCLanguage if block.is_objc_header then mmodule.objc_file.header_custom.add block.location.as_line_pragma mmodule.objc_file.header_custom.add block.code + + mmodule.has_public_objc_header = true else if block.is_objc_body then mmodule.objc_file.body_custom.add block.location.as_line_pragma mmodule.objc_file.body_custom.add block.code @@ -77,6 +100,12 @@ class ObjCLanguage var objc_file = mmodule.objc_file assert objc_file != null + # Import public Objective-C header of imported modules + var dep = mmodule.objc_imported_headers + for mod in dep do + objc_file.header_custom.add "#include \"{mod.c_name}._ffi_m.h\"\n" + end + # write .m and _m.h file mmodule.objc_file.header_c_types.add """ #include "{{{mmodule.c_name}}}._ffi.h" @@ -211,6 +240,13 @@ end private class FromObjCCallContext super ObjCCallContext + redef fun cast_to(mtype, name) + do + if mtype isa MClassType and mtype.mclass.ftype isa ForeignObjCType then + return "(__bridge void*)({name})" + else return name + end + redef fun cast_from(mtype, name) do if mtype isa MClassType and mtype.mclass.ftype isa ForeignObjCType then diff --git a/src/compiler/android_platform.nit b/src/platform/android.nit similarity index 99% rename from src/compiler/android_platform.nit rename to src/platform/android.nit index b7069e3..6ba5502 100644 --- a/src/compiler/android_platform.nit +++ b/src/platform/android.nit @@ -15,10 +15,10 @@ # limitations under the License. # Compile program for the Android platform -module android_platform +module android import platform -import abstract_compiler +import compiler::abstract_compiler import ffi intrude import ffi::extra_java_files import android_annotations diff --git a/src/compiler/android_annotations.nit b/src/platform/android_annotations.nit similarity index 100% rename from src/compiler/android_annotations.nit rename to src/platform/android_annotations.nit diff --git a/src/compiler/emscripten_platform.nit b/src/platform/emscripten.nit similarity index 97% rename from src/compiler/emscripten_platform.nit rename to src/platform/emscripten.nit index 6332098..dc2662f 100644 --- a/src/compiler/emscripten_platform.nit +++ b/src/platform/emscripten.nit @@ -15,10 +15,10 @@ # limitations under the License. # Compile to JavaScript using the Emscripten SDK -module emscripten_platform +module emscripten import platform -import abstract_compiler +import compiler::abstract_compiler redef class ToolContext redef fun platform_from_name(name) diff --git a/src/platform.nit b/src/platform/platform.nit similarity index 100% rename from src/platform.nit rename to src/platform/platform.nit diff --git a/src/compiler/pnacl_platform.nit b/src/platform/pnacl.nit similarity index 99% rename from src/compiler/pnacl_platform.nit rename to src/platform/pnacl.nit index 3f96318..9fceaad 100644 --- a/src/compiler/pnacl_platform.nit +++ b/src/platform/pnacl.nit @@ -15,10 +15,10 @@ # limitations under the License. # Compile program for the PNaCl platform -module pnacl_platform +module pnacl import platform -import abstract_compiler +import compiler::abstract_compiler redef class ToolContext redef fun platform_from_name(name) diff --git a/tests/sav/opengles2_hello_triangle.res b/tests/sav/opengles2_hello_triangle.res deleted file mode 100644 index c1dad34..0000000 --- a/tests/sav/opengles2_hello_triangle.res +++ /dev/null @@ -1,2 +0,0 @@ -../lib/mnit_linux/linux_app.nit:29,16--31: Redef Error: a virtual type cannot be refined. -../lib/mnit_linux/linux_app.nit:30,16--29: Redef Error: a virtual type cannot be refined.