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
])
25 var extern_classes_typing_phase_model
: Phase = new ExternClassesTypingPhaseModel(self, [extern_classes_typing_phase_ast
, modelize_class_phase
])
28 # Assigns the `ftype` to class definitions, work on the AST only
29 private class ExternClassesTypingPhaseAst
32 redef fun process_nclassdef
(nclassdef
)
34 if not nclassdef
isa AStdClassdef then return
36 var code_block
= nclassdef
.n_extern_code_block
37 if code_block
== null then return
39 if nclassdef
.n_kwredef
!= null then
40 # A redef cannot specifiy a different extern type
41 toolcontext
.error
(nclassdef
.location
, "Only the introduction of a class can specify an extern type.")
45 var ftype
= code_block
.language
.get_ftype
(code_block
, nclassdef
)
46 nclassdef
.ftype_cache
= ftype
47 nclassdef
.ftype_computed
= true
52 private var ftype_cache
: nullable ForeignType = null
53 private var ftype_computed
= false
55 # Associated extern type when defined on this classdef
56 fun ftype
: nullable ForeignType
62 private class ExternClassesTypingPhaseModel
65 redef fun process_nclassdef
(nclassdef
)
67 if not nclassdef
isa AStdClassdef then return
69 var mclassdef
= nclassdef
.mclassdef
70 var mclass
= nclassdef
.mclass
72 # We only need to do this once per class
73 if mclass
.intro
!= mclassdef
then return
75 if mclass
.kind
!= extern_kind
then return
77 mclass
.compute_ftype
(self)
82 private var ftype_cache
: nullable ForeignType = null
83 private var ftype_computed
= false
85 # Extern type associated to this class according to specialisation
86 fun ftype
: nullable ForeignType do return ftype_cache
88 redef fun ctype
do return ftype_cache
.ctype
90 # Type in C of the extern class
91 # If not defined in the intro of this class will look in super-classes
92 # FIXME this only supports type definition at intro, extend to superclasses by redef
93 private fun compute_ftype
(v
: ExternClassesTypingPhaseModel): nullable ForeignType
95 if ftype_computed
then return ftype_cache
96 if kind
!= extern_kind
then return null
99 if name
== "Pointer" then
100 ftype_cache
= new ForeignType
101 ftype_computed
= true
105 var intro_nclassdef
= v
.toolcontext
.modelbuilder
.mclassdef2nclassdef
[intro
]
106 var ftype
= intro_nclassdef
.ftype
107 if ftype
== null then
108 var ftype_b
: nullable ForeignType = null # FIXME hack to circumvent bug where ftype is typed null
110 # look in super classes
111 for s
in in_hierarchy
(intro
.mmodule
).direct_greaters
do
112 var super_ftype
= s
.compute_ftype
(v
)
113 if super_ftype
!= null then
114 if ftype_b
== null then
115 ftype_b
= super_ftype
119 if super_ftype
!= ftype_b
then
120 v
.toolcontext
.error
(null, "Extern type conflict in {self}")
131 ftype_computed
= true