1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Manages all extern classes and their associated foreign type.
22 redef class ToolContext
23 var extern_classes_typing_phase_ast
: Phase = new ExternClassesTypingPhaseAst(self, [ffi_language_assignation_phase
, modelize_class_phase
])
25 var extern_classes_typing_phase_model
: Phase = new ExternClassesTypingPhaseModel(self,
26 [extern_classes_typing_phase_ast
, modelize_class_phase
, modelize_property_phase
])
29 # Assigns the `ftype` to class definitions, work on the AST only
30 private class ExternClassesTypingPhaseAst
33 redef fun process_nclassdef
(nclassdef
)
35 if not nclassdef
isa AStdClassdef then return
37 var code_block
= nclassdef
.n_extern_code_block
38 if code_block
== null then return
40 if nclassdef
.n_kwredef
!= null then
41 # A redef cannot specifiy a different extern type
42 toolcontext
.error
(nclassdef
.location
, "Only the introduction of a class can specify an extern type.")
46 var ftype
= code_block
.language
.get_ftype
(code_block
, nclassdef
)
47 nclassdef
.mclassdef
.ftype_cache
= ftype
48 nclassdef
.mclassdef
.ftype_computed
= true
53 private var ftype_cache
: nullable ForeignType = null
54 private var ftype_computed
= false
56 # Associated extern type when defined on this classdef
57 fun ftype
: nullable ForeignType
63 private class ExternClassesTypingPhaseModel
66 redef fun process_nclassdef
(nclassdef
)
68 if not nclassdef
isa AStdClassdef then return
70 var mclassdef
= nclassdef
.mclassdef
71 if mclassdef
== null then return
72 var mclass
= mclassdef
.mclass
74 # We only need to do this once per class
75 if not mclassdef
.is_intro
then return
77 if mclass
.kind
!= extern_kind
then return
79 mclass
.compute_ftype
(self)
84 private var ftype_cache
: nullable ForeignType = null
85 private var ftype_computed
= false
87 # Extern type associated to this class according to specialisation
88 fun ftype
: nullable ForeignType do return ftype_cache
90 redef fun ctype
do return ftype_cache
.ctype
92 # Type in C of the extern class
93 # If not defined in the intro of this class will look in super-classes
94 # FIXME this only supports type definition at intro, extend to superclasses by redef
95 private fun compute_ftype
(v
: ExternClassesTypingPhaseModel): nullable ForeignType
97 if ftype_computed
then return ftype_cache
98 if kind
!= extern_kind
then return null
101 if name
== "Pointer" then
102 ftype_cache
= new ForeignType
103 ftype_computed
= true
107 var ftype
= intro
.ftype
108 if ftype
== null then
109 var ftype_b
: nullable ForeignType = null # FIXME hack to circumvent bug where ftype is typed null
111 # look in super classes
112 for s
in in_hierarchy
(intro
.mmodule
).direct_greaters
do
113 var super_ftype
= s
.compute_ftype
(v
)
114 if super_ftype
!= null then
115 if ftype_b
== null then
116 ftype_b
= super_ftype
120 if super_ftype
!= ftype_b
then
121 v
.toolcontext
.error
(null, "Extern type conflict in {self}")
132 ftype_computed
= true