1/**
2 * Copyright (c) 2021-2022 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#include "annotation.h"
17
18namespace panda::pandasm {
19
20std::unique_ptr<ScalarValue> InitScalarValue(const ScalarValue &sc_val)
21{
22    std::unique_ptr<ScalarValue> copy_val;
23    switch (sc_val.GetType()) {
24        case Value::Type::U1: {
25            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::U1>(sc_val.GetValue<uint8_t>()));
26            break;
27        }
28        case Value::Type::U8: {
29            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::U8>(sc_val.GetValue<uint8_t>()));
30            break;
31        }
32        case Value::Type::U16: {
33            copy_val =
34                std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::U16>(sc_val.GetValue<uint16_t>()));
35            break;
36        }
37        case Value::Type::U32: {
38            copy_val =
39                std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::U32>(sc_val.GetValue<uint32_t>()));
40            break;
41        }
42        case Value::Type::U64: {
43            copy_val =
44                std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::U64>(sc_val.GetValue<uint64_t>()));
45            break;
46        }
47        case Value::Type::I8: {
48            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::I8>(sc_val.GetValue<int8_t>()));
49            break;
50        }
51        case Value::Type::I16: {
52            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::I16>(sc_val.GetValue<int16_t>()));
53            break;
54        }
55        case Value::Type::I32: {
56            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::I32>(sc_val.GetValue<int32_t>()));
57            break;
58        }
59        case Value::Type::I64: {
60            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::I64>(sc_val.GetValue<int64_t>()));
61            break;
62        }
63        case Value::Type::F32: {
64            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::F32>(sc_val.GetValue<float>()));
65            break;
66        }
67        case Value::Type::F64: {
68            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::F64>(sc_val.GetValue<double>()));
69            break;
70        }
71        case Value::Type::STRING: {
72            copy_val =
73                std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::STRING>(sc_val.GetValue<std::string>()));
74            break;
75        }
76        case Value::Type::STRING_NULLPTR: {
77            copy_val = std::make_unique<ScalarValue>(
78                ScalarValue::Create<Value::Type::STRING_NULLPTR>(sc_val.GetValue<int32_t>()));
79            break;
80        }
81        case Value::Type::RECORD: {
82            copy_val = std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::RECORD>(sc_val.GetValue<Type>()));
83            break;
84        }
85        case Value::Type::METHOD: {
86            copy_val =
87                std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::METHOD>(sc_val.GetValue<std::string>()));
88            break;
89        }
90        case Value::Type::ENUM: {
91            copy_val =
92                std::make_unique<ScalarValue>(ScalarValue::Create<Value::Type::ENUM>(sc_val.GetValue<std::string>()));
93            break;
94        }
95        case Value::Type::ANNOTATION: {
96            copy_val = std::make_unique<ScalarValue>(
97                ScalarValue::Create<Value::Type::ANNOTATION>(sc_val.GetValue<AnnotationData>()));
98            break;
99        }
100        case Value::Type::LITERALARRAY: {
101            copy_val = std::make_unique<ScalarValue>(
102                ScalarValue::Create<Value::Type::LITERALARRAY>(sc_val.GetValue<std::string>()));
103            break;
104        }
105        default: {
106            UNREACHABLE();
107            copy_val = nullptr;
108            break;
109        }
110    }
111    return copy_val;
112}
113
114std::unique_ptr<Value> making_value(const AnnotationElement &ann_elem)
115{
116    std::unique_ptr<Value> copy_val;
117    switch (ann_elem.GetValue()->GetType()) {
118        case Value::Type::U1:
119        case Value::Type::U8:
120        case Value::Type::U16:
121        case Value::Type::U32:
122        case Value::Type::U64:
123        case Value::Type::I8:
124        case Value::Type::I16:
125        case Value::Type::I32:
126        case Value::Type::I64:
127        case Value::Type::F32:
128        case Value::Type::F64:
129        case Value::Type::STRING:
130        case Value::Type::STRING_NULLPTR:
131        case Value::Type::RECORD:
132        case Value::Type::METHOD:
133        case Value::Type::ENUM:
134        case Value::Type::ANNOTATION:
135        case Value::Type::LITERALARRAY: {
136            copy_val = InitScalarValue(*static_cast<ScalarValue *>(ann_elem.GetValue()));
137            break;
138        }
139        case Value::Type::ARRAY: {
140            Value::Type c_type;
141            auto *elem_arr = static_cast<ArrayValue *>(ann_elem.GetValue());
142            if (elem_arr->GetValues().size() == 0) {
143                c_type = Value::Type::VOID;
144            } else {
145                c_type = elem_arr->GetValues().front().GetType();
146            }
147            std::vector<ScalarValue> sc_vals;
148            for (const auto &sc_val : elem_arr->GetValues()) {
149                sc_vals.push_back(*InitScalarValue(sc_val));
150            }
151            copy_val = std::make_unique<ArrayValue>(c_type, std::move(sc_vals));
152            break;
153        }
154        default: {
155            UNREACHABLE();
156            copy_val = nullptr;
157            break;
158        }
159    }
160    return copy_val;
161}
162
163AnnotationElement::AnnotationElement(const AnnotationElement &ann_elem)
164{
165    this->value_ = making_value(ann_elem);
166    this->name_ = ann_elem.GetName();
167}
168
169AnnotationElement &AnnotationElement::operator=(const AnnotationElement &ann_elem)
170{
171    if (this == &ann_elem) {
172        return *this;
173    }
174
175    this->value_ = making_value(ann_elem);
176    this->name_ = ann_elem.GetName();
177    return *this;
178}
179
180ScalarValue *Value::GetAsScalar()
181{
182    ASSERT(!IsArray());
183    return static_cast<ScalarValue *>(this);
184}
185
186const ScalarValue *Value::GetAsScalar() const
187{
188    ASSERT(!IsArray());
189    return static_cast<const ScalarValue *>(this);
190}
191
192ArrayValue *Value::GetAsArray()
193{
194    ASSERT(IsArray());
195    return static_cast<ArrayValue *>(this);
196}
197
198const ArrayValue *Value::GetAsArray() const
199{
200    ASSERT(IsArray());
201    return static_cast<const ArrayValue *>(this);
202}
203
204/* static */
205std::string AnnotationElement::TypeToString(Value::Type type)
206{
207    switch (type) {
208        case Value::Type::U1:
209            return "u1";
210        case Value::Type::I8:
211            return "i8";
212        case Value::Type::U8:
213            return "u8";
214        case Value::Type::I16:
215            return "i16";
216        case Value::Type::U16:
217            return "u16";
218        case Value::Type::I32:
219            return "i32";
220        case Value::Type::U32:
221            return "u32";
222        case Value::Type::I64:
223            return "i64";
224        case Value::Type::U64:
225            return "u64";
226        case Value::Type::F32:
227            return "f32";
228        case Value::Type::F64:
229            return "f64";
230        case Value::Type::STRING:
231            return "string";
232        case Value::Type::RECORD:
233            return "class";
234        case Value::Type::METHOD:
235            return "method";
236        case Value::Type::ENUM:
237            return "enum";
238        case Value::Type::ANNOTATION:
239            return "annotation";
240        case Value::Type::ARRAY:
241            return "array";
242        case Value::Type::VOID:
243            return "void";
244        default: {
245            UNREACHABLE();
246            return "unknown";
247        }
248    }
249}
250
251void AnnotationData::SetOrAddElementByIndex(size_t ele_idx, AnnotationElement &&element)
252{
253    auto len = elements_.size();
254    ASSERT(ele_idx <= len);
255    if (ele_idx == len) {
256        AddElement(std::move(element));
257        return;
258    }
259    elements_[ele_idx] = std::forward<AnnotationElement>(element);
260}
261
262void AnnotationData::DeleteAnnotationElementByName(const std::string_view &annotation_elem_name)
263{
264    auto annotation_elem_iter = std::find_if(elements_.begin(), elements_.end(),
265        [&](pandasm::AnnotationElement &annotation_element) -> bool {
266        return annotation_element.GetName() == annotation_elem_name;
267    });
268    if (annotation_elem_iter != elements_.end()) {
269        (void)elements_.erase(annotation_elem_iter);
270    }
271}
272}  // namespace panda::pandasm
273