aboutsummaryrefslogtreecommitdiffstats
path: root/libs/json11/json11.hpp
blob: 0c47d0509326490105e098f3cd4204c4470f82f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/* json11
 *
 * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization.
 *
 * The core object provided by the library is json11::Json. A Json object represents any JSON
 * value: null, bool, number (int or double), string (std::string), array (std::vector), or
 * object (std::map).
 *
 * Json objects act like values: they can be assigned, copied, moved, compared for equality or
 * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and
 * Json::parse (static) to parse a std::string as a Json object.
 *
 * Internally, the various types of Json object are represented by the JsonValue class
 * hierarchy.
 *
 * A note on numbers - JSON specifies the syntax of number formatting but not its semantics,
 * so some JSON implementations distinguish between integers and floating-point numbers, while
 * some don't. In json11, we choose the latter. Because some JSON implementations (namely
 * Javascript itself) treat all numbers as the same type, distinguishing the two leads
 * to JSON that will be *silently* changed by a round-trip through those implementations.
 * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also
 * provides integer helpers.
 *
 * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the
 * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64
 * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch
 * will be exact for +/- 275 years.)
 */

/* Copyright (c) 2013 Dropbox, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#pragma once

#include <string>
#include <vector>
#include <map>
#include <memory>
#include <initializer_list>

#ifdef _MSC_VER
    #if _MSC_VER <= 1800 // VS 2013
        #ifndef noexcept
            #define noexcept throw()
        #endif

        #ifndef snprintf
            #define snprintf _snprintf_s
        #endif
    #endif
#endif

namespace json11 {

enum JsonParse {
    STANDARD, COMMENTS
};

class JsonValue;

class Json final {
public:
    // Types
    enum Type {
        NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT
    };

    // Array and object typedefs
    typedef std::vector<Json> array;
    typedef std::map<std::string, Json> object;

    // Constructors for the various types of JSON value.
    Json() noexcept;                // NUL
    Json(std::nullptr_t) noexcept;  // NUL
    Json(double value);             // NUMBER
    Json(int value);                // NUMBER
    Json(bool value);               // BOOL
    Json(const std::string &value); // STRING
    Json(std::string &&value);      // STRING
    Json(const char * value);       // STRING
    Json(const array &values);      // ARRAY
    Json(array &&values);           // ARRAY
    Json(const object &values);     // OBJECT
    Json(object &&values);          // OBJECT

    // Implicit constructor: anything with a to_json() function.
    template <class T, class = decltype(&T::to_json)>
    Json(const T & t) : Json(t.to_json()) {}

    // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
    template <class M, typename std::enable_if<
        std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value
        && std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value,
            int>::type = 0>
    Json(const M & m) : Json(object(m.begin(), m.end())) {}

    // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
    template <class V, typename std::enable_if<
        std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value,
            int>::type = 0>
    Json(const V & v) : Json(array(v.begin(), v.end())) {}

    // This prevents Json(some_pointer) from accidentally producing a bool. Use
    // Json(bool(some_pointer)) if that behavior is desired.
    Json(void *) = delete;

    // Accessors
    Type type() const;

    bool is_null()   const { return type() == NUL; }
    bool is_number() const { return type() == NUMBER; }
    bool is_bool()   const { return type() == BOOL; }
    bool is_string() const { return type() == STRING; }
    bool is_array()  const { return type() == ARRAY; }
    bool is_object() const { return type() == OBJECT; }

    // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
    // distinguish between integer and non-integer numbers - number_value() and int_value()
    // can both be applied to a NUMBER-typed object.
    double number_value() const;
    int int_value() const;

    // Return the enclosed value if this is a boolean, false otherwise.
    bool bool_value() const;
    // Return the enclosed string if this is a string, "" otherwise.
    const std::string &string_value() const;
    // Return the enclosed std::vector if this is an array, or an empty vector otherwise.
    const array &array_items() const;
    // Return the enclosed std::map if this is an object, or an empty map otherwise.
    const object &object_items() const;

    // Return a reference to arr[i] if this is an array, Json() otherwise.
    const Json & operator[](size_t i) const;
    // Return a reference to obj[key] if this is an object, Json() otherwise.
    const Json & operator[](const std::string &key) const;

    // Serialize.
    void dump(std::string &out) const;
    std::string dump() const {
        std::string out;
        dump(out);
        return out;
    }

    // Parse. If parse fails, return Json() and assign an error message to err.
    static Json parse(const std::string & in,
                      std::string & err,
                      JsonParse strategy = JsonParse::STANDARD);
    static Json parse(const char * in,
                      std::string & err,
                      JsonParse strategy = JsonParse::STANDARD) {
        if (in) {
            return parse(std::string(in), err, strategy);
        } else {
            err = "null input";
            return nullptr;
        }
    }
    // Parse multiple objects, concatenated or separated by whitespace
    static std::vector<Json> parse_multi(
        const std::string & in,
        std::string::size_type & parser_stop_pos,
        std::string & err,
        JsonParse strategy = JsonParse::STANDARD);

    static inline std::vector<Json> parse_multi(
        const std::string & in,
        std::string & err,
        JsonParse strategy = JsonParse::STANDARD) {
        std::string::size_type parser_stop_pos;
        return parse_multi(in, parser_stop_pos, err, strategy);
    }

    bool operator== (const Json &rhs) const;
    bool operator<  (const Json &rhs) const;
    bool operator!= (const Json &rhs) const { return !(*this == rhs); }
    bool operator<= (const Json &rhs) const { return !(rhs < *this); }
    bool operator>  (const Json &rhs) const { return  (rhs < *this); }
    bool operator>= (const Json &rhs) const { return !(*this < rhs); }

    /* has_shape(types, err)
     *
     * Return true if this is a JSON object and, for each item in types, has a field of
     * the given type. If not, return false and set err to a descriptive message.
     */
    typedef std::initializer_list<std::pair<std::string, Type>> shape;
    bool has_shape(const shape & types, std::string & err) const;

private:
    std::shared_ptr<JsonValue> m_ptr;
};

// Internal class hierarchy - JsonValue objects are not exposed to users of this API.
class JsonValue {
protected:
    friend class Json;
    friend class JsonInt;
    friend class JsonDouble;
    virtual Json::Type type() const = 0;
    virtual bool equals(const JsonValue * other) const = 0;
    virtual bool less(const JsonValue * other) const = 0;
    virtual void dump(std::string &out) const = 0;
    virtual double number_value() const;
    virtual int int_value() const;
    virtual bool bool_value() const;
    virtual const std::string &string_value() const;
    virtual const Json::array &array_items() const;
    virtual const Json &operator[](size_t i) const;
    virtual const Json::object &object_items() const;
    virtual const Json &operator[](const std::string &key) const;
    virtual ~JsonValue() {}
};

} // namespace json11
span>), Get_Type (El), Val); end loop; end Elab_Disconnection_Specification; type Connect_Mode is ( -- Actual is a source for the formal. Connect_Source, -- Both. Connect_Both, -- Effective value of actual is the effective value of the formal. Connect_Effective, -- Actual is a value. Connect_Value ); type Connect_Data is record Actual_Node : Mnode; Actual_Type : Iir; -- Mode of the connection. Mode : Connect_Mode; -- If true, formal signal is a copy of the actual. By_Copy : Boolean; end record; -- Connect_effective: FORMAL is set from ACTUAL. -- Connect_Source: ACTUAL is set from FORMAL (source of ACTUAL). procedure Connect_Scalar (Formal_Node : Mnode; Formal_Type : Iir; Data : Connect_Data) is Act_Node, Form_Node : Mnode; begin if Data.By_Copy then New_Assign_Stmt (M2Lv (Formal_Node), M2E (Data.Actual_Node)); return; end if; case Data.Mode is when Connect_Both => Open_Temp; Act_Node := Stabilize (Data.Actual_Node, True); Form_Node := Stabilize (Formal_Node, True); when Connect_Source | Connect_Effective => Act_Node := Data.Actual_Node; Form_Node := Formal_Node; when Connect_Value => null; end case; if Data.Mode in Connect_Source .. Connect_Both then -- Formal is a source to actual. declare Constr : O_Assoc_List; begin Start_Association (Constr, Ghdl_Signal_Add_Source); New_Association (Constr, New_Convert_Ov (M2E (Act_Node), Ghdl_Signal_Ptr)); New_Association (Constr, New_Convert_Ov (M2E (Form_Node), Ghdl_Signal_Ptr)); New_Procedure_Call (Constr); end; end if; if Data.Mode in Connect_Both .. Connect_Effective then -- The effective value of formal is the effective value of actual. declare Constr : O_Assoc_List; begin Start_Association (Constr, Ghdl_Signal_Effective_Value); New_Association (Constr, New_Convert_Ov (M2E (Form_Node), Ghdl_Signal_Ptr)); New_Association (Constr, New_Convert_Ov (M2E (Act_Node), Ghdl_Signal_Ptr)); New_Procedure_Call (Constr); end; end if; if Data.Mode = Connect_Value then declare Type_Info : Type_Info_Acc; Subprg : O_Dnode; Constr : O_Assoc_List; Conv : O_Tnode; begin Type_Info := Get_Info (Formal_Type); case Type_Info.Type_Mode is when Type_Mode_B1 => Subprg := Ghdl_Signal_Associate_B1; Conv := Ghdl_Bool_Type; when Type_Mode_E8 => Subprg := Ghdl_Signal_Associate_E8; Conv := Ghdl_I32_Type; when Type_Mode_E32 => Subprg := Ghdl_Signal_Associate_E32; Conv := Ghdl_I32_Type; when Type_Mode_I32 => Subprg := Ghdl_Signal_Associate_I32; Conv := Ghdl_I32_Type; when Type_Mode_P64 => Subprg := Ghdl_Signal_Associate_I64; Conv := Ghdl_I64_Type; when Type_Mode_F64 => Subprg := Ghdl_Signal_Associate_F64; Conv := Ghdl_Real_Type; when others => Error_Kind ("connect_scalar", Formal_Type); end case; Start_Association (Constr, Subprg); New_Association (Constr, New_Convert_Ov (New_Value (M2Lv (Formal_Node)), Ghdl_Signal_Ptr)); New_Association (Constr, New_Convert_Ov (M2E (Data.Actual_Node), Conv)); New_Procedure_Call (Constr); end; end if; if Data.Mode = Connect_Both then Close_Temp; end if; end Connect_Scalar; function Connect_Prepare_Data_Composite (Targ : Mnode; Formal_Type : Iir; Data : Connect_Data) return Connect_Data is pragma Unreferenced (Targ, Formal_Type); Res : Connect_Data; Atype : Iir; begin Atype := Get_Base_Type (Data.Actual_Type); if Get_Kind (Atype) = Iir_Kind_Record_Type_Definition then Res := Data; Stabilize (Res.Actual_Node); return Res; else return Data; end if; end Connect_Prepare_Data_Composite; function Connect_Update_Data_Array (Data : Connect_Data; Formal_Type : Iir; Index : O_Dnode) return Connect_Data is pragma Unreferenced (Formal_Type); Res : Connect_Data; begin -- FIXME: should check matching elements! Res := (Actual_Node => Chap3.Index_Base (Chap3.Get_Array_Base (Data.Actual_Node), Data.Actual_Type, New_Obj_Value (Index)), Actual_Type => Get_Element_Subtype (Data.Actual_Type), Mode => Data.Mode, By_Copy => Data.By_Copy); return Res; end Connect_Update_Data_Array; function Connect_Update_Data_Record (Data : Connect_Data; Formal_Type : Iir; El : Iir_Element_Declaration) return Connect_Data is pragma Unreferenced (Formal_Type); Res : Connect_Data; begin Res := (Actual_Node => Chap6.Translate_Selected_Element (Data.Actual_Node, El), Actual_Type => Get_Type (El), Mode => Data.Mode, By_Copy => Data.By_Copy); return Res; end Connect_Update_Data_Record; procedure Connect_Finish_Data_Composite (Data : in out Connect_Data) is pragma Unreferenced (Data); begin null; end Connect_Finish_Data_Composite; procedure Connect is new Foreach_Non_Composite (Data_Type => Connect_Data, Composite_Data_Type => Connect_Data, Do_Non_Composite => Connect_Scalar, Prepare_Data_Array => Connect_Prepare_Data_Composite, Update_Data_Array => Connect_Update_Data_Array, Finish_Data_Array => Connect_Finish_Data_Composite, Prepare_Data_Record => Connect_Prepare_Data_Composite, Update_Data_Record => Connect_Update_Data_Record, Finish_Data_Record => Connect_Finish_Data_Composite); procedure Elab_Unconstrained_Port (Port : Iir; Actual : Iir) is Act_Node : Mnode; Bounds : Mnode; Tinfo : Type_Info_Acc; Bound_Var : O_Dnode; Actual_Type : Iir; begin Actual_Type := Get_Type (Actual); Open_Temp; if Is_Fully_Constrained_Type (Actual_Type) then Chap3.Create_Array_Subtype (Actual_Type, False); Tinfo := Get_Info (Actual_Type); Bounds := Chap3.Get_Array_Type_Bounds (Actual_Type); if Get_Alloc_Kind_For_Var (Tinfo.T.Array_Bounds) = Alloc_Stack then -- We need a copy. Bound_Var := Create_Temp (Tinfo.T.Bounds_Ptr_Type); New_Assign_Stmt (New_Obj (Bound_Var), Gen_Alloc (Alloc_System, New_Lit (New_Sizeof (Tinfo.T.Bounds_Type, Ghdl_Index_Type)), Tinfo.T.Bounds_Ptr_Type)); Gen_Memcpy (New_Obj_Value (Bound_Var), M2Addr (Bounds), New_Lit (New_Sizeof (Tinfo.T.Bounds_Type, Ghdl_Index_Type))); Bounds := Dp2M (Bound_Var, Tinfo, Mode_Value, Tinfo.T.Bounds_Type, Tinfo.T.Bounds_Ptr_Type); end if; else Bounds := Chap3.Get_Array_Bounds (Chap6.Translate_Name (Actual)); end if; Act_Node := Chap6.Translate_Name (Port); New_Assign_Stmt (-- FIXME: this works only because it is not stabilized, -- and therefore the bounds field is returned and not -- a pointer to the bounds. M2Lp (Chap3.Get_Array_Bounds (Act_Node)), M2Addr (Bounds)); Close_Temp; end Elab_Unconstrained_Port; -- Return TRUE if EXPR is a signal name. function Is_Signal (Expr : Iir) return Boolean is Obj : Iir; begin Obj := Sem_Names.Name_To_Object (Expr); if Obj /= Null_Iir then return Is_Signal_Object (Obj); else return False; end if; end Is_Signal; procedure Elab_Port_Map_Aspect_Assoc (Assoc : Iir; By_Copy : Boolean) is Formal : constant Iir := Get_Formal (Assoc); Actual : constant Iir := Get_Actual (Assoc); Formal_Type : constant Iir := Get_Type (Formal); Actual_Type : constant Iir := Get_Type (Actual); Inter : constant Iir := Get_Association_Interface (Assoc); Formal_Node : Mnode; Actual_Node : Mnode; Data : Connect_Data; Mode : Connect_Mode; begin if Get_Kind (Assoc) /= Iir_Kind_Association_Element_By_Expression then raise Internal_Error; end if; Open_Temp; if Get_In_Conversion (Assoc) = Null_Iir and then Get_Out_Conversion (Assoc) = Null_Iir then Formal_Node := Chap6.Translate_Name (Formal); if Get_Object_Kind (Formal_Node) /= Mode_Signal then raise Internal_Error; end if; if Is_Signal (Actual) then -- LRM93 4.3.1.2 -- For a signal of a scalar type, each source is either -- a driver or an OUT, INOUT, BUFFER or LINKAGE port of -- a component instance or of a block statement with -- which the signalis associated. -- LRM93 12.6.2 -- For a scalar signal S, the effective value of S is -- determined in the following manner: -- * If S is [...] a port of mode BUFFER or [...], -- then the effective value of S is the same as -- the driving value of S. -- * If S is a connected port of mode IN or INOUT, -- then the effective value of S is the same as -- the effective value of the actual part of the -- association element that associates an actual -- with S. -- * [...] case Get_Mode (Inter) is when Iir_In_Mode => Mode := Connect_Effective; when Iir_Inout_Mode => Mode := Connect_Both; when Iir_Out_Mode | Iir_Buffer_Mode | Iir_Linkage_Mode => Mode := Connect_Source; when Iir_Unknown_Mode => raise Internal_Error; end case; -- translate actual (abort if not a signal). Actual_Node := Chap6.Translate_Name (Actual); if Get_Object_Kind (Actual_Node) /= Mode_Signal then raise Internal_Error; end if; else declare Actual_Val : O_Enode; begin Actual_Val := Chap7.Translate_Expression (Actual, Formal_Type); Actual_Node := E2M (Actual_Val, Get_Info (Formal_Type), Mode_Value); Mode := Connect_Value; end; end if; if Get_Kind (Formal_Type) in Iir_Kinds_Array_Type_Definition then -- Check length matches. Stabilize (Formal_Node); Stabilize (Actual_Node); Chap3.Check_Array_Match (Formal_Type, Formal_Node, Actual_Type, Actual_Node, Assoc); end if; Data := (Actual_Node => Actual_Node, Actual_Type => Actual_Type, Mode => Mode, By_Copy => By_Copy); Connect (Formal_Node, Formal_Type, Data); else if Get_In_Conversion (Assoc) /= Null_Iir then Chap4.Elab_In_Conversion (Assoc, Actual_Node); Formal_Node := Chap6.Translate_Name (Formal); Data := (Actual_Node => Actual_Node, Actual_Type => Formal_Type, Mode => Connect_Effective, By_Copy => False); Connect (Formal_Node, Formal_Type, Data); end if; if Get_Out_Conversion (Assoc) /= Null_Iir then -- flow: FORMAL to ACTUAL Chap4.Elab_Out_Conversion (Assoc, Formal_Node); Actual_Node := Chap6.Translate_Name (Actual); Data := (Actual_Node => Actual_Node, Actual_Type => Actual_Type, Mode => Connect_Source, By_Copy => False); Connect (Formal_Node, Actual_Type, Data); end if; end if; Close_Temp; end Elab_Port_Map_Aspect_Assoc; -- Return TRUE if the collapse_signal_flag is set for each individual -- association. function Inherit_Collapse_Flag (Assoc : Iir) return Boolean is El : Iir; begin case Get_Kind (Assoc) is when Iir_Kind_Association_Element_By_Individual => El := Get_Individual_Association_Chain (Assoc); while El /= Null_Iir loop if Inherit_Collapse_Flag (El) = False then return False; end if; El := Get_Chain (El); end loop; return True; when Iir_Kind_Choice_By_Expression | Iir_Kind_Choice_By_Range | Iir_Kind_Choice_By_Name => El := Assoc; while El /= Null_Iir loop if not Inherit_Collapse_Flag (Get_Associated_Expr (Assoc)) then return False; end if; El := Get_Chain (El); end loop; return True; when Iir_Kind_Association_Element_By_Expression => return Get_Collapse_Signal_Flag (Assoc); when others => Error_Kind ("inherit_collapse_flag", Assoc); end case; end Inherit_Collapse_Flag; procedure Elab_Generic_Map_Aspect (Mapping : Iir) is Assoc : Iir; Formal : Iir; begin -- Elab generics, and associate. Assoc := Get_Generic_Map_Aspect_Chain (Mapping); while Assoc /= Null_Iir loop Open_Temp; Formal := Get_Formal (Assoc); if Get_Kind (Formal) in Iir_Kinds_Denoting_Name then Formal := Get_Named_Entity (Formal); end if; case Get_Kind (Assoc) is when Iir_Kind_Association_Element_By_Expression => declare Targ : Mnode; begin if Get_Whole_Association_Flag (Assoc) then Chap4.Elab_Object_Storage (Formal); Targ := Chap6.Translate_Name (Formal); Chap4.Elab_Object_Init (Targ, Formal, Get_Actual (Assoc)); else Targ := Chap6.Translate_Name (Formal); Chap7.Translate_Assign (Targ, Get_Actual (Assoc), Get_Type (Formal)); end if; end; when Iir_Kind_Association_Element_Open => Chap4.Elab_Object_Value (Formal, Get_Default_Value (Formal)); when Iir_Kind_Association_Element_By_Individual => -- Create the object. declare Formal_Type : constant Iir := Get_Type (Formal); Obj_Info : constant Object_Info_Acc := Get_Info (Formal); Obj_Type : constant Iir := Get_Actual_Type (Assoc); Formal_Node : Mnode; Type_Info : Type_Info_Acc; Bounds : Mnode; begin Chap3.Elab_Object_Subtype (Formal_Type); Type_Info := Get_Info (Formal_Type); Formal_Node := Get_Var (Obj_Info.Object_Var, Type_Info, Mode_Value); Stabilize (Formal_Node); if Obj_Type = Null_Iir then Chap4.Allocate_Complex_Object (Formal_Type, Alloc_System, Formal_Node); else Chap3.Create_Array_Subtype (Obj_Type, False); Bounds := Chap3.Get_Array_Type_Bounds (Obj_Type); Chap3.Translate_Object_Allocation (Formal_Node, Alloc_System, Formal_Type, Bounds); end if; end; when Iir_Kind_Association_Element_Package => pragma Assert (Get_Kind (Formal) = Iir_Kind_Interface_Package_Declaration); declare Uninst_Pkg : constant Iir := Get_Named_Entity (Get_Uninstantiated_Package_Name (Formal)); Uninst_Info : constant Ortho_Info_Acc := Get_Info (Uninst_Pkg); Formal_Info : constant Ortho_Info_Acc := Get_Info (Formal); Actual : constant Iir := Get_Named_Entity (Get_Actual (Assoc)); Actual_Info : constant Ortho_Info_Acc := Get_Info (Actual); begin New_Assign_Stmt (Get_Var (Formal_Info.Package_Instance_Spec_Var), New_Address (Get_Instance_Ref (Actual_Info.Package_Instance_Spec_Scope), Uninst_Info.Package_Spec_Ptr_Type)); New_Assign_Stmt (Get_Var (Formal_Info.Package_Instance_Body_Var), New_Address (Get_Instance_Ref (Actual_Info.Package_Instance_Body_Scope), Uninst_Info.Package_Body_Ptr_Type)); end; when others => Error_Kind ("elab_generic_map_aspect(1)", Assoc); end case; Close_Temp; Assoc := Get_Chain (Assoc); end loop; end Elab_Generic_Map_Aspect; procedure Elab_Port_Map_Aspect (Mapping : Iir; Block_Parent : Iir) is Assoc : Iir; Formal : Iir; Formal_Base : Iir; Fb_Type : Iir; Fbt_Info : Type_Info_Acc; Collapse_Individual : Boolean := False; begin -- Ports. Assoc := Get_Port_Map_Aspect_Chain (Mapping); while Assoc /= Null_Iir loop Formal := Get_Formal (Assoc); Formal_Base := Get_Association_Interface (Assoc); Fb_Type := Get_Type (Formal_Base); Open_Temp; -- Set bounds of unconstrained ports. Fbt_Info := Get_Info (Fb_Type); if Fbt_Info.Type_Mode = Type_Mode_Fat_Array then case Get_Kind (Assoc) is when Iir_Kind_Association_Element_By_Expression => if Get_Whole_Association_Flag (Assoc) then Elab_Unconstrained_Port (Formal, Get_Actual (Assoc)); end if; when Iir_Kind_Association_Element_Open => declare Actual_Type : Iir; Bounds : Mnode; Formal_Node : Mnode; begin Actual_Type := Get_Type (Get_Default_Value (Formal_Base)); Chap3.Create_Array_Subtype (Actual_Type, True); Bounds := Chap3.Get_Array_Type_Bounds (Actual_Type); Formal_Node := Chap6.Translate_Name (Formal); New_Assign_Stmt (M2Lp (Chap3.Get_Array_Bounds (Formal_Node)), M2Addr (Bounds)); end; when Iir_Kind_Association_Element_By_Individual => declare Actual_Type : Iir; Bounds : Mnode; Formal_Node : Mnode; begin Actual_Type := Get_Actual_Type (Assoc); Chap3.Create_Array_Subtype (Actual_Type, False); Bounds := Chap3.Get_Array_Type_Bounds (Actual_Type); Formal_Node := Chap6.Translate_Name (Formal); New_Assign_Stmt (M2Lp (Chap3.Get_Array_Bounds (Formal_Node)), M2Addr (Bounds)); end; when others => Error_Kind ("elab_map_aspect(2)", Assoc); end case; end if; Close_Temp; -- Allocate storage of ports. Open_Temp; case Get_Kind (Assoc) is when Iir_Kind_Association_Element_By_Individual | Iir_Kind_Association_Element_Open => Chap4.Elab_Signal_Declaration_Storage (Formal); when Iir_Kind_Association_Element_By_Expression => if Get_Whole_Association_Flag (Assoc) then Chap4.Elab_Signal_Declaration_Storage (Formal); end if; when others => Error_Kind ("elab_map_aspect(3)", Assoc); end case; Close_Temp; -- Create or copy signals. Open_Temp; case Get_Kind (Assoc) is when Iir_Kind_Association_Element_By_Expression => if Get_Whole_Association_Flag (Assoc) then if Get_Collapse_Signal_Flag (Assoc) then -- For collapsed association, copy signals. Elab_Port_Map_Aspect_Assoc (Assoc, True); else -- Create non-collapsed signals. Chap4.Elab_Signal_Declaration_Object (Formal, Block_Parent, False); -- And associate. Elab_Port_Map_Aspect_Assoc (Assoc, False); end if; else -- By sub-element. -- Either the whole signal is collapsed or it was already -- created. -- And associate. Elab_Port_Map_Aspect_Assoc (Assoc, Collapse_Individual); end if; when Iir_Kind_Association_Element_Open => -- Create non-collapsed signals. Chap4.Elab_Signal_Declaration_Object (Formal, Block_Parent, False); when Iir_Kind_Association_Element_By_Individual => -- Inherit the collapse flag. -- If it is set for all sub-associations, continue. -- Otherwise, create signals and do not collapse. -- FIXME: this may be slightly optimized. if not Inherit_Collapse_Flag (Assoc) then -- Create the formal. Chap4.Elab_Signal_Declaration_Object (Formal, Block_Parent, False); Collapse_Individual := False; else Collapse_Individual := True; end if; when others => Error_Kind ("elab_map_aspect(4)", Assoc); end case; Close_Temp; Assoc := Get_Chain (Assoc); end loop; end Elab_Port_Map_Aspect; procedure Elab_Map_Aspect (Mapping : Iir; Block_Parent : Iir) is begin -- The generic map must be done before the elaboration of -- the ports, since a port subtype may depend on a generic. Elab_Generic_Map_Aspect (Mapping); Elab_Port_Map_Aspect (Mapping, Block_Parent); end Elab_Map_Aspect; end Trans.Chap5;