}
};
-// A named function parameter used in external functions
-class NamedFunctionParam
-{
- // bool has_name; // otherwise is _
- std::string name;
-
- std::unique_ptr<Type> param_type;
-
- // seemingly new since writing this node
- std::vector<Attribute> outer_attrs;
-
- NodeId node_id;
- location_t locus;
- bool variadic;
-
-public:
- /* Returns whether the named function parameter has a name (i.e. name is not
- * '_'). */
- bool has_name () const { return name != "_" && name != ""; }
-
- bool has_outer_attrs () const { return !outer_attrs.empty (); }
-
- // Returns whether the named function parameter is in an error state.
- bool is_error () const
- {
- // also if identifier is "" but that is probably more costly to compute
- return param_type == nullptr && !variadic;
- }
-
- bool is_variadic () const { return variadic; }
-
- std::string get_name () const { return name; }
-
- location_t get_locus () { return locus; }
-
- // Creates an error state named function parameter.
- static NamedFunctionParam create_error ()
- {
- return NamedFunctionParam ("", nullptr, {}, UNDEF_LOCATION);
- }
-
- NamedFunctionParam (std::string name, std::unique_ptr<Type> param_type,
- std::vector<Attribute> outer_attrs, location_t locus)
- : name (std::move (name)), param_type (std::move (param_type)),
- outer_attrs (std::move (outer_attrs)),
- node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus),
- variadic (false)
- {}
-
- NamedFunctionParam (std::string name, std::vector<Attribute> outer_attrs,
- location_t locus)
- : name (std::move (name)), param_type (nullptr),
- outer_attrs (std::move (outer_attrs)),
- node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus),
- variadic (true)
- {}
-
- NamedFunctionParam (std::vector<Attribute> outer_attrs, location_t locus)
- : name (""), param_type (nullptr), outer_attrs (std::move (outer_attrs)),
- node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus),
- variadic (true)
- {}
-
- // Copy constructor
- NamedFunctionParam (NamedFunctionParam const &other)
- : name (other.name), outer_attrs (other.outer_attrs),
- variadic (other.variadic)
- {
- node_id = other.node_id;
- // guard to prevent null dereference (only required if error state)
- if (other.param_type != nullptr)
- param_type = other.param_type->clone_type ();
- else
- param_type = nullptr;
- }
-
- ~NamedFunctionParam () = default;
-
- // Overloaded assignment operator to clone
- NamedFunctionParam &operator= (NamedFunctionParam const &other)
- {
- node_id = other.node_id;
- name = other.name;
- // has_name = other.has_name;
- outer_attrs = other.outer_attrs;
-
- // guard to prevent null dereference (only required if error state)
- if (other.param_type != nullptr)
- param_type = other.param_type->clone_type ();
- else
- param_type = nullptr;
-
- return *this;
- }
-
- // move constructors
- NamedFunctionParam (NamedFunctionParam &&other) = default;
- NamedFunctionParam &operator= (NamedFunctionParam &&other) = default;
-
- std::string as_string () const;
-
- // Based on idea that nane should never be empty.
- void mark_for_strip () { param_type = nullptr; };
- bool is_marked_for_strip () const { return is_error (); };
-
- // TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
-
- // TODO: is this better? Or is a "vis_block" better?
- Type &get_type ()
- {
- rust_assert (param_type != nullptr);
- return *param_type;
- }
-
- std::unique_ptr<Type> &get_type_ptr ()
- {
- rust_assert (param_type != nullptr);
- return param_type;
- }
-
- NodeId get_node_id () const { return node_id; }
-};
-
-// A function item used in an extern block
-class ExternalFunctionItem : public ExternalItem
-{
- // bool has_outer_attrs;
- std::vector<Attribute> outer_attrs;
-
- // bool has_visibility;
- Visibility visibility;
-
- Identifier item_name;
- location_t locus;
-
- // bool has_generics;
- // Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
-
- // bool has_return_type;
- // FunctionReturnType return_type;
- std::unique_ptr<Type> return_type; // inlined
-
- // bool has_where_clause;
- WhereClause where_clause;
-
- std::vector<NamedFunctionParam> function_params;
-
-public:
- // Returns whether item has generic parameters.
- bool has_generics () const { return !generic_params.empty (); }
-
- // Returns whether item has a return type (otherwise void).
- bool has_return_type () const { return return_type != nullptr; }
-
- // Returns whether item has a where clause.
- bool has_where_clause () const { return !where_clause.is_empty (); }
-
- // Returns whether item has outer attributes.
- bool has_outer_attrs () const { return !outer_attrs.empty (); }
-
- // Returns whether item has non-default visibility.
- bool has_visibility () const { return !visibility.is_error (); }
-
- // Returns whether item has variadic parameters.
- bool is_variadic () const
- {
- return function_params.size () != 0
- && function_params.back ().is_variadic ();
- }
-
- location_t get_locus () const { return locus; }
-
- Visibility &get_visibility () { return visibility; }
- const Visibility &get_visibility () const { return visibility; }
-
- ExternalFunctionItem (
- Identifier item_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
- std::unique_ptr<Type> return_type, WhereClause where_clause,
- std::vector<NamedFunctionParam> function_params, Visibility vis,
- std::vector<Attribute> outer_attrs, location_t locus)
- : ExternalItem (), outer_attrs (std::move (outer_attrs)),
- visibility (std::move (vis)), item_name (std::move (item_name)),
- locus (locus), generic_params (std::move (generic_params)),
- return_type (std::move (return_type)),
- where_clause (std::move (where_clause)),
- function_params (std::move (function_params))
- {
- // TODO: assert that if has variadic outer attrs, then has_variadics is
- // true?
- }
-
- // Copy constructor with clone
- ExternalFunctionItem (ExternalFunctionItem const &other)
- : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
- visibility (other.visibility), item_name (other.item_name),
- locus (other.locus), where_clause (other.where_clause),
- function_params (other.function_params)
- {
- node_id = other.node_id;
- // guard to prevent null pointer dereference
- if (other.return_type != nullptr)
- return_type = other.return_type->clone_type ();
-
- generic_params.reserve (other.generic_params.size ());
- for (const auto &e : other.generic_params)
- generic_params.push_back (e->clone_generic_param ());
- }
-
- // Overloaded assignment operator with clone
- ExternalFunctionItem &operator= (ExternalFunctionItem const &other)
- {
- outer_attrs = other.outer_attrs;
- visibility = other.visibility;
- item_name = other.item_name;
- locus = other.locus;
- where_clause = other.where_clause;
- function_params = other.function_params;
- node_id = other.node_id;
-
- // guard to prevent null pointer dereference
- if (other.return_type != nullptr)
- return_type = other.return_type->clone_type ();
- else
- return_type = nullptr;
-
- generic_params.reserve (other.generic_params.size ());
- for (const auto &e : other.generic_params)
- generic_params.push_back (e->clone_generic_param ());
-
- return *this;
- }
-
- // move constructors
- ExternalFunctionItem (ExternalFunctionItem &&other) = default;
- ExternalFunctionItem &operator= (ExternalFunctionItem &&other) = default;
-
- std::string as_string () const override;
-
- void accept_vis (ASTVisitor &vis) override;
-
- // Based on idea that nane should never be empty.
- void mark_for_strip () override { item_name = {""}; };
- bool is_marked_for_strip () const override { return item_name.empty (); };
-
- // TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
-
- std::vector<NamedFunctionParam> &get_function_params ()
- {
- return function_params;
- }
- const std::vector<NamedFunctionParam> &get_function_params () const
- {
- return function_params;
- }
-
- std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
- {
- return generic_params;
- }
- const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
- {
- return generic_params;
- }
-
- // TODO: is this better? Or is a "vis_block" better?
- WhereClause &get_where_clause () { return where_clause; }
-
- // TODO: is this better? Or is a "vis_block" better?
- Type &get_return_type ()
- {
- rust_assert (has_return_type ());
- return *return_type;
- }
-
- std::unique_ptr<Type> &get_return_type_ptr ()
- {
- rust_assert (has_return_type ());
- return return_type;
- }
-
- Identifier get_identifier () const { return item_name; };
-
-protected:
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- ExternalFunctionItem *clone_external_item_impl () const override
- {
- return new ExternalFunctionItem (*this);
- }
-};
-
// An extern block AST node
class ExternBlock : public VisItem
{
std::move (outer_attrs), locus));
}
-template <typename ManagedTokenSource>
-AST::NamedFunctionParam
-Parser<ManagedTokenSource>::parse_named_function_param ()
-{
- AST::AttrVec outer_attrs = parse_outer_attributes ();
- location_t locus = lexer.peek_token ()->get_locus ();
-
- if (lexer.peek_token ()->get_id () == ELLIPSIS) // Unnamed variadic
- {
- lexer.skip_token (); // Skip ellipsis
- return AST::NamedFunctionParam (std::move (outer_attrs), locus);
- }
-
- // parse identifier/_
- std::string name;
-
- const_TokenPtr t = lexer.peek_token ();
- location_t name_location = t->get_locus ();
- switch (t->get_id ())
- {
- case IDENTIFIER:
- name = t->get_str ();
- lexer.skip_token ();
- break;
- case UNDERSCORE:
- name = "_";
- lexer.skip_token ();
- break;
- default:
- // this is not a function param, but not necessarily an error
- return AST::NamedFunctionParam::create_error ();
- }
-
- if (!skip_token (COLON))
- {
- // skip after somewhere?
- return AST::NamedFunctionParam::create_error ();
- }
-
- if (lexer.peek_token ()->get_id () == ELLIPSIS) // Named variadic
- {
- lexer.skip_token (); // Skip ellipsis
- return AST::NamedFunctionParam (std::move (name), std::move (outer_attrs),
- locus);
- }
-
- // parse (required) type
- std::unique_ptr<AST::Type> param_type = parse_type ();
- if (param_type == nullptr)
- {
- Error error (
- lexer.peek_token ()->get_locus (),
- "could not parse param type in extern block function declaration");
- add_error (std::move (error));
-
- skip_after_semicolon ();
- return AST::NamedFunctionParam::create_error ();
- }
-
- return AST::NamedFunctionParam (std::move (name), std::move (param_type),
- std::move (outer_attrs), name_location);
-}
-
-template <typename ManagedTokenSource>
-template <typename EndTokenPred>
-std::vector<AST::NamedFunctionParam>
-Parser<ManagedTokenSource>::parse_named_function_params (
- EndTokenPred is_end_token)
-{
- std::vector<AST::NamedFunctionParam> params;
- if (is_end_token (lexer.peek_token ()->get_id ()))
- return params;
-
- auto initial_param = parse_named_function_param ();
- if (initial_param.is_error ())
- return params;
-
- params.push_back (std::move (initial_param));
- auto t = lexer.peek_token ();
- while (t->get_id () == COMMA)
- {
- lexer.skip_token ();
- if (is_end_token (lexer.peek_token ()->get_id ()))
- break;
-
- auto param = parse_named_function_param ();
- if (param.is_error ())
- {
- Error error (lexer.peek_token ()->get_locus (),
- "failed to parse param in c function params");
- add_error (error);
- return std::vector<AST::NamedFunctionParam> ();
- }
- params.push_back (std::move (param));
- t = lexer.peek_token ();
- }
- params.shrink_to_fit ();
- return params;
-}
-
// Parses a single extern block item (static or function declaration).
template <typename ManagedTokenSource>
std::unique_ptr<AST::ExternalItem>