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
# 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
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
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
import cocoa
-in "ObjC" `{
- #import <Cocoa/Cocoa.h>
-`}
-
fun dialog in "ObjC" `{
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"Hello world!"];
import cocoa::foundation
-in "ObjC" `{
- #import <Foundation/Foundation.h>
-`}
-
# Print `"Hello world!"` to the log
fun hello_world in "ObjC" `{
@autoreleasepool {
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.
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
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
# 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"]
# 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 <https://developer.github.com/v3/issues/events/>.
+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 <https://developer.github.com/v3/repos/statistics/>.
+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
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Events are emitted by Github Hooks.
+#
+# See <https://developer.github.com/v3/activity/events/types/>
+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
import glesv2
import egl
-import mnit_linux # for sdl
+import mnit_linux::sdl
import x11
if "NIT_TESTING".environ == "true" then exit(0)
import global_compiler
import compiler_ffi
-import android_platform
-import pnacl_platform
-import emscripten_platform
+import platform::android
+import platform::pnacl
+import platform::emscripten
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
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
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]
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};")
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
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
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}")
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)}:;")
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
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("\}")
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
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)
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
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
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
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"
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
# 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
# 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)
# 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)
+++ /dev/null
-../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.