void
TokenCollector::visit (FunctionParam ¶m)
{
- visit (param.get_pattern ());
- push (Rust::Token::make (COLON, UNDEF_LOCATION));
- visit (param.get_type ());
+ visit_items_as_lines (param.get_outer_attrs ());
+ if (!param.is_variadic ())
+ {
+ visit (param.get_pattern ());
+ push (Rust::Token::make (COLON, UNDEF_LOCATION));
+ visit (param.get_type ());
+ }
+ else
+ {
+ if (param.has_name ())
+ {
+ visit (param.get_pattern ());
+ push (Rust::Token::make (COLON, UNDEF_LOCATION));
+ }
+ push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION));
+ }
}
void
TokenCollector::visit (NamedFunctionParam ¶m)
{
auto name = param.get_name ();
- push (Rust::Token::make_identifier (param.get_locus (), std::move (name)));
- push (Rust::Token::make (COLON, UNDEF_LOCATION));
- visit (param.get_type ());
+ if (!param.is_variadic ())
+ {
+ push (
+ Rust::Token::make_identifier (param.get_locus (), std::move (name)));
+ push (Rust::Token::make (COLON, UNDEF_LOCATION));
+ visit (param.get_type ());
+ }
+ else
+ {
+ if (name != "")
+ {
+ push (Rust::Token::make_identifier (param.get_locus (),
+ std::move (name)));
+ push (Rust::Token::make (COLON, UNDEF_LOCATION));
+ }
+ push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION));
+ }
}
void
push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION));
visit_items_joined_by_separator (function.get_function_params ());
- if (function.is_variadic ())
- {
- push (Rust::Token::make (COMMA, UNDEF_LOCATION));
- // TODO: Add variadic outer attributes?
- // TODO: Add variadic name once implemented.
- push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION));
- }
push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION));
if (function.has_return_type ())
DefaultASTVisitor::visit (AST::FunctionParam ¶m)
{
visit_outer_attrs (param);
- visit (param.get_pattern ());
- visit (param.get_type ());
+ if (param.has_name ())
+ visit (param.get_pattern ());
+
+ if (!param.is_variadic ())
+ visit (param.get_type ());
}
void
DefaultASTVisitor::visit (AST::NamedFunctionParam ¶m)
{
visit_outer_attrs (param);
- visit (param.get_type ());
+ if (!param.is_variadic ())
+ visit (param.get_type ());
}
void
// function params
str += "\n Function params: ";
- if (function_params.empty () && !has_variadics)
+ if (function_params.empty ())
{
str += "none";
}
{
for (const auto ¶m : function_params)
str += "\n " + param.as_string ();
-
- if (has_variadics)
- {
- str += "\n variadic outer attrs: ";
- if (has_variadic_outer_attrs ())
- {
- for (const auto &attr : variadic_outer_attrs)
- str += "\n " + attr.as_string ();
- }
- else
- {
- str += "none";
- }
- str += "\n ... (variadic)";
- }
}
// add type on new line
{
std::string str = append_attributes (outer_attrs, OUTER);
- str += "\n" + name;
+ if (has_name ())
+ str += "\n" + name;
- str += "\n Type: " + param_type->as_string ();
+ if (is_variadic ())
+ str += "...";
+ else
+ str += "\n Type: " + param_type->as_string ();
return str;
}
return param_name;
}
+ bool has_name () const { return param_name != nullptr; }
+
// TODO: is this better? Or is a "vis_block" better?
std::unique_ptr<Type> &get_type ()
{
public:
/* Returns whether the named function parameter has a name (i.e. name is not
* '_'). */
- bool has_name () const { return name != "_"; }
+ bool has_name () const { return name != "_" && name != ""; }
bool has_outer_attrs () const { return !outer_attrs.empty (); }
return param_type == nullptr && !variadic;
}
+ bool is_variadic () const { return variadic; }
+
std::string get_name () const { return name; }
location_t get_locus () { return locus; }
WhereClause where_clause;
std::vector<NamedFunctionParam> function_params;
- bool has_variadics;
- std::vector<Attribute> variadic_outer_attrs;
public:
// Returns whether item has generic parameters.
bool has_visibility () const { return !visibility.is_error (); }
// Returns whether item has variadic parameters.
- bool is_variadic () const { return has_variadics; }
-
- // Returns whether item has outer attributes on its variadic parameters.
- bool has_variadic_outer_attrs () const
+ bool is_variadic () const
{
- return !variadic_outer_attrs.empty ();
+ return function_params.size () != 0
+ && function_params.back ().is_variadic ();
}
location_t get_locus () const { return locus; }
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, bool has_variadics,
- std::vector<Attribute> variadic_outer_attrs, Visibility vis,
+ 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)),
- has_variadics (has_variadics),
- variadic_outer_attrs (std::move (variadic_outer_attrs))
+ function_params (std::move (function_params))
{
// TODO: assert that if has variadic outer attrs, then has_variadics is
// true?
ExternalFunctionItem (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),
- has_variadics (other.has_variadics),
- variadic_outer_attrs (other.variadic_outer_attrs)
+ where_clause (other.where_clause), function_params (other.function_params)
{
node_id = other.node_id;
// guard to prevent null pointer dereference
locus = other.locus;
where_clause = other.where_clause;
function_params = other.function_params;
- has_variadics = other.has_variadics;
- variadic_outer_attrs = other.variadic_outer_attrs;
node_id = other.node_id;
// guard to prevent null pointer dereference
continue;
}
- auto &type = param.get_type ();
- type->accept_vis (*this);
+ if (!param.is_variadic ())
+ {
+ auto &type = param.get_type ();
+ param.get_type ()->accept_vis (*this);
- if (type->is_marked_for_strip ())
- rust_error_at (type->get_locus (),
- "cannot strip type in this position");
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus (),
+ "cannot strip type in this position");
+ }
// increment if nothing else happens
++it;
for (auto ¶m : item.get_generic_params ())
visit (param);
- // FIXME: Should this work? What is the difference between NamedFunctionParam
- // and FunctionParam?
- // expand_function_params (item.get_function_params ());
-
for (auto ¶m : item.get_function_params ())
- maybe_expand_type (param.get_type ());
+ if (!param.is_variadic ())
+ maybe_expand_type (param.get_type ());
if (item.has_return_type ())
maybe_expand_type (item.get_return_type ());
translated = new HIR::ExternalFunctionItem (
mapping, function.get_identifier (), std::move (generic_params),
std::unique_ptr<HIR::Type> (return_type), std::move (where_clause),
- std::move (function_params), function.is_variadic (), std::move (vis),
+ std::move (function_params), is_variadic, std::move (vis),
function.get_outer_attrs (), function.get_locus ());
}
function_params.push_back (std::move (p));
}
- AST::ExternalItem *external_item = new AST::ExternalFunctionItem (
- item_name, {} /* generic_params */, std::move (return_type),
- where_clause, std::move (function_params), false /* has_variadics */,
- {} /* variadic_outer_attrs */, vis, function.get_outer_attrs (),
- function.get_locus ());
+ AST::ExternalItem *external_item
+ = new AST::ExternalFunctionItem (item_name, {} /* generic_params */,
+ std::move (return_type), where_clause,
+ std::move (function_params), vis,
+ function.get_outer_attrs (),
+ function.get_locus ());
std::vector<std::unique_ptr<AST::ExternalItem>> external_items;
external_items.push_back (
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)
+ {
+ 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 ();
+ }
+
+ // 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;
+}
+
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::ExternalFunctionItem>
+Parser<ManagedTokenSource>::parse_external_function_item (
+ AST::Visibility vis, AST::AttrVec outer_attrs)
+{
+ location_t locus = lexer.peek_token ()->get_locus ();
+
+ // parse extern function declaration item
+ // skip function token
+ lexer.skip_token ();
+
+ // parse identifier
+ const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+ if (ident_tok == nullptr)
+ {
+ skip_after_semicolon ();
+ return nullptr;
+ }
+ Identifier ident{ident_tok};
+
+ // parse (optional) generic params
+ std::vector<std::unique_ptr<AST::GenericParam>> generic_params
+ = parse_generic_params_in_angles ();
+
+ if (!skip_token (LEFT_PAREN))
+ {
+ skip_after_semicolon ();
+ return nullptr;
+ }
+
+ // parse parameters
+ std::vector<AST::NamedFunctionParam> function_params
+ = parse_named_function_params (
+ [] (TokenId id) { return id == RIGHT_PAREN; });
+
+ if (!skip_token (RIGHT_PAREN))
+ {
+ skip_after_semicolon ();
+ return nullptr;
+ }
+
+ // parse (optional) return type
+ std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
+
+ // parse (optional) where clause
+ AST::WhereClause where_clause = parse_where_clause ();
+
+ if (!skip_token (SEMICOLON))
+ {
+ // skip somewhere?
+ return nullptr;
+ }
+
+ function_params.shrink_to_fit ();
+
+ return std::unique_ptr<AST::ExternalFunctionItem> (
+ new AST::ExternalFunctionItem (
+ std::move (ident), std::move (generic_params), std::move (return_type),
+ std::move (where_clause), std::move (function_params), std::move (vis),
+ std::move (outer_attrs), locus));
+}
+
// Parses a single extern block item (static or function declaration).
template <typename ManagedTokenSource>
std::unique_ptr<AST::ExternalItem>
has_mut, std::move (vis),
std::move (outer_attrs), locus));
}
- case FN_TOK: {
- // parse extern function declaration item
- // skip function token
- lexer.skip_token ();
-
- // parse identifier
- const_TokenPtr ident_tok = expect_token (IDENTIFIER);
- if (ident_tok == nullptr)
- {
- skip_after_semicolon ();
- return nullptr;
- }
- Identifier ident{ident_tok};
-
- // parse (optional) generic params
- std::vector<std::unique_ptr<AST::GenericParam>> generic_params
- = parse_generic_params_in_angles ();
-
- if (!skip_token (LEFT_PAREN))
- {
- skip_after_semicolon ();
- return nullptr;
- }
-
- // parse parameters
- std::vector<AST::NamedFunctionParam> function_params;
- bool is_variadic = false;
- AST::AttrVec variadic_attrs;
-
- const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () != RIGHT_PAREN)
- {
- AST::AttrVec maybe_variadic_attrs = parse_outer_attributes ();
- if (lexer.peek_token ()->get_id () == ELLIPSIS)
- {
- // variadic - use attrs for this
- lexer.skip_token ();
- is_variadic = true;
- variadic_attrs = std::move (maybe_variadic_attrs);
- t = lexer.peek_token ();
-
- if (t->get_id () != RIGHT_PAREN)
- {
- Error error (t->get_locus (),
- "expected right parentheses after variadic in "
- "named function "
- "parameters, found %qs",
- t->get_token_description ());
- add_error (std::move (error));
-
- skip_after_semicolon ();
- return nullptr;
- }
-
- break;
- }
-
- AST::NamedFunctionParam param
- = parse_named_function_param (std::move (maybe_variadic_attrs));
- if (param.is_error ())
- {
- Error error (t->get_locus (), "could not parse named function "
- "parameter in external function");
- add_error (std::move (error));
-
- skip_after_semicolon ();
- return nullptr;
- }
- function_params.push_back (std::move (param));
-
- if (lexer.peek_token ()->get_id () != COMMA)
- break;
-
- // skip comma
- lexer.skip_token ();
- t = lexer.peek_token ();
- }
-
- if (!skip_token (RIGHT_PAREN))
- {
- skip_after_semicolon ();
- return nullptr;
- }
-
- // parse (optional) return type
- std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
-
- // parse (optional) where clause
- AST::WhereClause where_clause = parse_where_clause ();
-
- if (!skip_token (SEMICOLON))
- {
- // skip somewhere?
- return nullptr;
- }
-
- function_params.shrink_to_fit ();
-
- return std::unique_ptr<AST::ExternalFunctionItem> (
- new AST::ExternalFunctionItem (
- std::move (ident), std::move (generic_params),
- std::move (return_type), std::move (where_clause),
- std::move (function_params), is_variadic,
- std::move (variadic_attrs), std::move (vis),
- std::move (outer_attrs), locus));
- }
+ case FN_TOK:
+ return parse_external_function_item (std::move (vis),
+ std::move (outer_attrs));
case TYPE:
return parse_external_type_item (std::move (vis),
std::move (outer_attrs));
}
}
-/* Parses an extern block function param (with "pattern" being _ or an
- * identifier). */
-template <typename ManagedTokenSource>
-AST::NamedFunctionParam
-Parser<ManagedTokenSource>::parse_named_function_param (
- AST::AttrVec outer_attrs)
-{
- // 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 ();
- }
-
- // 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);
-}
-
// Parses a statement (will further disambiguate any statement).
template <typename ManagedTokenSource>
std::unique_ptr<AST::Stmt>
AST::Lifetime lifetime_from_token (const_TokenPtr tok);
std::unique_ptr<AST::ExternalTypeItem>
parse_external_type_item (AST::Visibility vis, AST::AttrVec outer_attrs);
+ std::unique_ptr<AST::ExternalFunctionItem>
+ parse_external_function_item (AST::Visibility vis, AST::AttrVec outer_attrs);
+ AST::NamedFunctionParam parse_named_function_param ();
+ template <typename EndTokenPred>
+ std::vector<AST::NamedFunctionParam>
+ parse_named_function_params (EndTokenPred is_end_token);
+
std::unique_ptr<AST::TypeAlias> parse_type_alias (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::Struct> parse_struct (AST::Visibility vis,
AST::AttrVec outer_attrs);
std::unique_ptr<AST::ExternBlock>
parse_extern_block (AST::Visibility vis, AST::AttrVec outer_attrs);
- AST::NamedFunctionParam parse_named_function_param (AST::AttrVec outer_attrs
- = AST::AttrVec ());
AST::Method parse_method ();
// Expression-related (Pratt parsed)
// we make a new scope so the names of parameters are resolved and shadowed
// correctly
for (auto ¶m : function.get_function_params ())
- {
+ if (!param.is_variadic ())
ResolveType::go (param.get_type ().get ());
- }
// done
resolver->get_name_scope ().pop ();
generic->accept_vis (*this);
for (auto ¶m : item.get_function_params ())
- param.get_type ()->accept_vis (*this);
+ if (!param.is_variadic ())
+ param.get_type ()->accept_vis (*this);
if (item.has_return_type ())
item.get_return_type ()->accept_vis (*this);