1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 # Injects model for the classes annotated with "is actor" so
15 # that the later generated code can be properly used for compilation
16 module actors_injection_phase
19 intrude import modelize_property
22 redef class ModelBuilder
23 redef fun build_a_mclass
(nmodule
, nclassdef
)
27 # Catch the wanted annotation
28 var at
= nclassdef
.get_single_annotation
("actor", self)
29 if at
== null then return
31 # Get context information
32 var mod
= nmodule
.mmodule
33 if mod
== null then return
34 var mclass
= nclassdef
.mclass
35 if mclass
== null then return
36 if mclass
.intro_mmodule
!= mod
then
37 error
(at
, "`actor` can only be used at introductions.")
43 var injected_name
= "Proxy"
45 # Create the actor class
46 var actor_class
= new MClass(mod
, injected_name
+ mclass
.name
, l
, null, concrete_kind
, public_visibility
)
47 var actor_class_definition
= new MClassDef(mod
, actor_class
.mclass_type
, l
)
48 actor_class_definition
.set_supertypes
([mod
.object_type
])
49 var proxy_classes
= mclass
.model
.get_mclasses_by_name
("Proxy")
50 assert proxy_classes
!= null
51 var proxy_class
= proxy_classes
.first
52 actor_class_definition
.supertypes
.add
(proxy_class
.mclass_type
)
55 mclass
.actor
= actor_class
58 redef fun build_properties
(nclassdef
)
60 if nclassdef
.build_properties_is_done
then return
63 # Get context information
64 var mclass
= nclassdef
.mclass
65 if mclass
== null then return
66 var mclass_def
= nclassdef
.mclassdef
67 if mclass_def
== null then return
69 var actor_mclass
= mclass
.actor
70 if actor_mclass
== null then return
71 var actor_mclass_def
= actor_mclass
.mclassdefs
.first
73 # Adds an `async` attribute in the worker class which is the actor class
74 if mclass_def
.is_intro
then
75 var async
= new MMethod(mclass_def
, "async", mclass
.location
, public_visibility
)
76 var async_def
= new MMethodDef(mclass_def
, async
, mclass
.location
)
77 async_def
.msignature
= new MSignature(new Array[MParameter], actor_mclass
.mclass_type
)
78 async_def
.is_abstract
= true
81 # For each introduced property
82 for method
in mclass_def
.mpropdefs
do
83 if not method
isa MMethodDef then continue
84 if not method
.is_intro
then continue
85 if method
.name
== "async" then continue
87 # Create a proxied method
88 var actor_method
= new MMethod(actor_mclass_def
, method
.name
, actor_mclass
.location
, method
.mproperty
.visibility
)
89 var actor_method_def
= new MMethodDef(actor_mclass_def
, actor_method
, actor_mclass
.location
)
91 # Get the signature of the method ( replacing the return value with a Future if there is one)
92 var signature
= method
.msignature
93 if signature
!= null then
94 var parameters
= signature
.mparameters
95 var s_return_type
= signature
.return_mtype
96 if s_return_type
!= null then
97 var future_mclasses
= mclass_def
.model
.get_mclasses_by_name
("Future")
98 assert future_mclasses
!= null
99 var future_mclass
= future_mclasses
.first
100 var return_type
= future_mclass
.get_mtype
([s_return_type
])
101 actor_method_def
.msignature
= new MSignature(parameters
, return_type
)
103 actor_method_def
.msignature
= new MSignature(parameters
, null)
106 actor_method_def
.is_abstract
= true
112 # Adding the actor class to a class annotated with "is actor"
113 var actor
: nullable MClass = null