• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_PLUGINS_ETS_TYPEAPI_CREATE_H
17 #define PANDA_PLUGINS_ETS_TYPEAPI_CREATE_H
18 
19 #include "assembly-function.h"
20 #include "assembly-program.h"
21 #include "ets_typeapi_create_panda_constants.h"
22 
23 namespace ark {
24 template <typename T>
25 class VMHandle;
26 }  // namespace ark
27 
28 namespace ark::coretypes {
29 class Array;
30 }  // namespace ark::coretypes
31 
32 namespace ark::ets {
33 class EtsCoroutine;
34 class EtsArray;
35 }  // namespace ark::ets
36 
37 namespace ark::ets {
38 class TypeCreatorCtx {
39 public:
Program()40     pandasm::Program &Program()
41     {
42         return prog_;
43     }
44 
45     template <typename T, typename... A>
Alloc(A &&...a)46     T *Alloc(A &&...a)
47     {
48         auto p = std::make_shared<T>(std::forward<A>(a)...);
49         auto ret = p.get();
50         datas_.push_back(std::move(p));
51         return ret;
52     }
53 
54     /**
55      * Adds field with permanent data used in TypeAPI$CtxData$_
56      * also adds intializer into TypeAPI$CtxData$_.cctor that loads that id
57      * from
58      * @param id index of filed in init array
59      * @param type type of that field
60      * @returns field id that can be passed into pandasm instructions to access it
61      */
62     std::string AddInitField(uint32_t id, const pandasm::Type &type);
63 
64     /**
65      * Adds TypeAPI$CtxData$_ to program if it was used
66      * also emplaces necessary cctors
67      */
68     void FlushTypeAPICtxDataRecordsToProgram();
69 
70     /**
71      * Saves objects into current context to provide them to TypeAPI$CtxData$_.cctor
72      * @param objects must live until end of call to `InitializeCtxDataRecord` and may be changed inside this function
73      */
74     void SaveObjects(EtsCoroutine *coro, VMHandle<EtsArray> &objects);
75 
76     EtsArray *GetObjects(EtsCoroutine *coro);
77 
78     /// Initializes TypeAPI$CtxData$_
79     void InitializeCtxDataRecord(EtsCoroutine *coro);
80 
81     /**
82      * Creates TypeAPI$CtxData record if it wasn't created before
83      * @returns TypeAPI$CtxData record
84      */
85     pandasm::Record &GetTypeAPICtxDataRecord();
86 
87     pandasm::Record &AddRefTypeAsExternal(const std::string &name);
88 
89     /**
90      * Lazily declares primitive reference wrapper
91      * @returns pair of constructor and unwrapper
92      */
93     const std::pair<std::string, std::string> &DeclarePrimitive(const std::string &primTypeName);
94 
AddError(std::string_view err)95     void AddError(std::string_view err)
96     {
97         error_ += err;
98     }
99 
GetError()100     std::optional<std::string_view> GetError() const
101     {
102         if (error_.empty()) {
103             return std::nullopt;
104         }
105         return error_;
106     }
107 
108 private:
109     pandasm::Program prog_;
110     pandasm::Record ctxDataRecord_ {"", panda_file::SourceLang::ETS};
111     std::string ctxDataRecordName_ {};
112     pandasm::Function ctxDataRecordCctor_ {"", panda_file::SourceLang::ETS};
113     std::map<std::string, std::pair<std::string, std::string>> primitiveTypesCtorDtor_;
114     std::vector<std::shared_ptr<void>> datas_;
115     std::string error_;
116 
117     coretypes::Array *initArrObject_ {};
118 };
119 
120 enum class TypeCreatorKind {
121     CLASS,
122     INTERFACE,
123     LAMBDA_TYPE,
124 };
125 
126 class TypeCreator {
127 public:
128     virtual TypeCreatorKind GetKind() const = 0;
129     virtual pandasm::Type GetType() const = 0;
130 
TypeCreator(TypeCreatorCtx * ctx)131     explicit TypeCreator(TypeCreatorCtx *ctx) : ctx_(ctx) {}
132 
GetCtx()133     TypeCreatorCtx *GetCtx() const
134     {
135         return ctx_;
136     }
137 
138 private:
139     TypeCreatorCtx *ctx_;
140 };
141 
142 class ClassCreator final : public TypeCreator {
143 public:
ClassCreator(pandasm::Record * rec,TypeCreatorCtx * ctx)144     explicit ClassCreator(pandasm::Record *rec, TypeCreatorCtx *ctx) : TypeCreator(ctx), rec_(rec) {}
145 
GetKind()146     TypeCreatorKind GetKind() const override
147     {
148         return TypeCreatorKind::CLASS;
149     }
150 
GetType()151     pandasm::Type GetType() const override
152     {
153         return pandasm::Type {rec_->name, 0, true};
154     }
155 
GetRec()156     pandasm::Record *GetRec() const
157     {
158         return rec_;
159     }
160 
161 private:
162     pandasm::Record *rec_;
163 };
164 
165 class InterfaceCreator final : public TypeCreator {
166 public:
InterfaceCreator(pandasm::Record * rec,TypeCreatorCtx * ctx)167     explicit InterfaceCreator(pandasm::Record *rec, TypeCreatorCtx *ctx) : TypeCreator(ctx), rec_(rec) {}
168 
GetKind()169     TypeCreatorKind GetKind() const override
170     {
171         return TypeCreatorKind::INTERFACE;
172     }
173 
GetType()174     pandasm::Type GetType() const override
175     {
176         return pandasm::Type {rec_->name, 0, true};
177     }
178 
GetRec()179     pandasm::Record *GetRec() const
180     {
181         return rec_;
182     }
183 
184 private:
185     pandasm::Record *rec_;
186 };
187 
188 class LambdaTypeCreator final : public TypeCreator {
189 public:
LambdaTypeCreator(TypeCreatorCtx * ctx)190     explicit LambdaTypeCreator(TypeCreatorCtx *ctx) : TypeCreator(ctx)
191     {
192         for (const auto &attr : typeapi_create_consts::ATTR_INTERFACE) {
193             rec_.metadata->SetAttribute(attr);
194         }
195         rec_.metadata->SetAttributeValue(typeapi_create_consts::ATTR_ACCESS,
196                                          typeapi_create_consts::ATTR_ACCESS_VAL_PUBLIC);
197     }
198 
GetKind()199     TypeCreatorKind GetKind() const override
200     {
201         return TypeCreatorKind::LAMBDA_TYPE;
202     }
203 
GetType()204     pandasm::Type GetType() const override
205     {
206         ASSERT(finished_);
207         return pandasm::Type {name_, 0};
208     }
209 
GetFunctionName()210     const std::string &GetFunctionName() const
211     {
212         ASSERT(finished_);
213         return fnName_;
214     }
215 
216     void AddParameter(pandasm::Type param);
217 
218     void AddResult(const pandasm::Type &type);
219 
220     void Create();
221 
222 private:
223     std::string name_ = "std.core.Function";
224     std::string fnName_ = "invoke0";
225     pandasm::Record rec_ {name_, SourceLanguage::ETS};
226     pandasm::Function fn_ {fnName_, SourceLanguage::ETS};
227     bool finished_ = false;
228 };
229 
230 class PandasmMethodCreator {
231 public:
PandasmMethodCreator(std::string name,TypeCreatorCtx * ctx)232     PandasmMethodCreator(std::string name, TypeCreatorCtx *ctx)
233         : ctx_(ctx), name_(name), fn_(std::move(name), SourceLanguage::ETS)
234     {
235     }
236 
237     void AddParameter(pandasm::Type param);
238 
239     void AddResult(pandasm::Type type);
240 
241     void Create();
242 
GetFunctionName()243     const std::string &GetFunctionName() const
244     {
245         ASSERT(finished_);
246         return name_;
247     }
248 
GetFn()249     pandasm::Function &GetFn()
250     {
251         ASSERT(!finished_);
252         return fn_;
253     }
254 
Ctx()255     TypeCreatorCtx *Ctx() const
256     {
257         return ctx_;
258     }
259 
260 private:
261     TypeCreatorCtx *ctx_;
262     std::string name_;
263     pandasm::Function fn_;
264     bool finished_ = false;
265 };
266 
267 }  // namespace ark::ets
268 
269 #endif  // PANDA_PLUGINS_ETS_TYPEAPI_CREATE_H
270