return is_single_fragment_of_kind (SingleASTNode::Kind::Type);
}
+bool
+Fragment::is_pattern_fragment () const
+{
+ return is_single_fragment_of_kind (SingleASTNode::Kind::Pattern);
+}
+
std::unique_ptr<Expr>
Fragment::take_expression_fragment ()
{
return nodes[0].take_type ();
}
+std::unique_ptr<Pattern>
+Fragment::take_pattern_fragment ()
+{
+ assert_single_fragment (SingleASTNode::Kind::Pattern);
+ return nodes[0].take_pattern ();
+}
+
void
Fragment::accept_vis (ASTVisitor &vis)
{
{SingleASTNode::Kind::Expr, "expr"},
{SingleASTNode::Kind::Stmt, "stmt"},
{SingleASTNode::Kind::Extern, "extern"},
+ {SingleASTNode::Kind::Pattern, "pattern"},
};
auto actual = nodes[0].get_kind ();
bool is_expression_fragment () const;
bool is_type_fragment () const;
+ bool is_pattern_fragment () const;
std::unique_ptr<Expr> take_expression_fragment ();
std::unique_ptr<Type> take_type_fragment ();
+ std::unique_ptr<Pattern> take_pattern_fragment ();
void accept_vis (ASTVisitor &vis);
case Kind::Type:
type = other.type->clone_type ();
break;
+
+ case Kind::Pattern:
+ pattern = other.pattern->clone_pattern ();
+ break;
}
}
case Kind::Type:
type = other.type->clone_type ();
break;
+
+ case Kind::Pattern:
+ pattern = other.pattern->clone_pattern ();
+ break;
}
return *this;
}
case Kind::Type:
type->accept_vis (vis);
break;
+
+ case Kind::Pattern:
+ pattern->accept_vis (vis);
+ break;
}
}
return assoc_item == nullptr;
case Kind::Type:
return type == nullptr;
+ case Kind::Pattern:
+ return pattern == nullptr;
}
rust_unreachable ();
return "Associated Item: " + assoc_item->as_string ();
case Kind::Type:
return "Type: " + type->as_string ();
+ case Kind::Pattern:
+ return "Pattern: " + pattern->as_string ();
}
rust_unreachable ();
Extern,
Assoc,
Type,
+ Pattern,
};
private:
std::unique_ptr<ExternalItem> external_item;
std::unique_ptr<AssociatedItem> assoc_item;
std::unique_ptr<Type> type;
+ std::unique_ptr<Pattern> pattern;
public:
SingleASTNode (std::unique_ptr<Expr> expr)
: kind (Kind::Type), type (std::move (type))
{}
+ SingleASTNode (std::unique_ptr<Pattern> pattern)
+ : kind (Kind::Pattern), pattern (std::move (pattern))
+ {}
+
SingleASTNode (SingleASTNode const &other);
SingleASTNode operator= (SingleASTNode const &other);
return std::move (type);
}
+ std::unique_ptr<Pattern> take_pattern ()
+ {
+ rust_assert (!is_error ());
+ return std::move (pattern);
+ }
+
void accept_vis (ASTVisitor &vis) override;
bool is_error ();
return *pattern;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (pattern != nullptr);
+ return pattern;
+ }
+
Type &get_type ()
{
rust_assert (has_type_given ());
return *param_name;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (param_name != nullptr);
+ return param_name;
+ }
+
const Pattern &get_pattern () const
{
rust_assert (param_name != nullptr);
return *param_name;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (param_name != nullptr);
+ return param_name;
+ }
+
bool has_name () const { return param_name != nullptr; }
// TODO: is this better? Or is a "vis_block" better?
return *pattern_in_parens;
}
+ std::unique_ptr<Pattern> &get_pattern_in_parens_ptr ()
+ {
+ rust_assert (pattern_in_parens != nullptr);
+ return pattern_in_parens;
+ }
+
NodeId get_node_id () const override { return node_id; }
Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Grouped; }
return *variables_pattern;
}
+ std::unique_ptr<Pattern> &get_pattern_ptr ()
+ {
+ rust_assert (variables_pattern != nullptr);
+ return variables_pattern;
+ }
+
Type &get_type ()
{
rust_assert (has_type ());
#include "rust-expand-visitor.h"
#include "rust-ast-fragment.h"
+#include "rust-item.h"
#include "rust-proc-macro.h"
#include "rust-attributes.h"
#include "rust-ast.h"
{
switch (node.get_kind ())
{
- case AST::SingleASTNode::ITEM:
+ case AST::SingleASTNode::Kind::Item:
result.push_back (node.take_item ());
break;
default:
{
switch (node.get_kind ())
{
- case AST::SingleASTNode::ITEM:
+ case AST::SingleASTNode::Kind::Item:
result.push_back (node.take_item ());
break;
default:
{
switch (node.get_kind ())
{
- case AST::SingleASTNode::STMT:
+ case AST::SingleASTNode::Kind::Stmt:
result.push_back (node.take_stmt ());
break;
default:
final_fragment.take_type_fragment (), BUILTINS_LOCATION);
}
+void
+ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern)
+{
+ NodeId old_expect = pattern->get_node_id ();
+ std::swap (macro_invoc_expect_id, old_expect);
+
+ expander.push_context (MacroExpander::ContextType::PATTERN);
+ pattern->accept_vis (*this);
+ expander.pop_context ();
+
+ std::swap (macro_invoc_expect_id, old_expect);
+
+ auto final_fragment = expander.take_expanded_fragment ();
+ if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ())
+ pattern = final_fragment.take_pattern_fragment ();
+}
+
// FIXME: Can this be refactored into a `scoped` method? Which takes a
// ContextType as parameter and a lambda? And maybe just an std::vector<T>&?
void
{
for (auto ¶m : params)
{
+ maybe_expand_pattern (param.get_pattern_ptr ());
+
if (param.has_type_given ())
maybe_expand_type (param.get_type_ptr ());
}
auto &arm = match_case.get_arm ();
for (auto &pattern : arm.get_patterns ())
- visit (pattern);
+ maybe_expand_pattern (pattern);
if (arm.has_match_arm_guard ())
maybe_expand_expr (arm.get_guard_expr_ptr ());
}
}
+void
+ExpandVisitor::visit (AST::TupleExpr &expr)
+{
+ for (auto &sub : expr.get_tuple_elems ())
+ maybe_expand_expr (sub);
+}
+
void
ExpandVisitor::visit (AST::TypeParam ¶m)
{
void
ExpandVisitor::visit (AST::GroupedPattern &pattern)
{
- visit (pattern.get_pattern_in_parens ());
+ maybe_expand_pattern (pattern.get_pattern_in_parens_ptr ());
+}
+
+void
+ExpandVisitor::visit (AST::SlicePatternItemsNoRest &items)
+{
+ for (auto &sub : items.get_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::SlicePatternItemsHasRest &items)
+{
+ for (auto &sub : items.get_lower_patterns ())
+ maybe_expand_pattern (sub);
+ for (auto &sub : items.get_upper_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::AltPattern &pattern)
+{
+ for (auto &alt : pattern.get_alts ())
+ maybe_expand_pattern (alt);
+}
+
+void
+ExpandVisitor::visit (AST::TupleStructItemsNoRange &tuple_items)
+{
+ for (auto &sub : tuple_items.get_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::TupleStructItemsRange &tuple_items)
+{
+ for (auto &sub : tuple_items.get_lower_patterns ())
+ maybe_expand_pattern (sub);
+
+ for (auto &sub : tuple_items.get_upper_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items)
+{
+ for (auto &sub : tuple_items.get_patterns ())
+ maybe_expand_pattern (sub);
+}
+
+void
+ExpandVisitor::visit (AST::TuplePatternItemsRanged &tuple_items)
+{
+ for (auto &sub : tuple_items.get_lower_patterns ())
+ maybe_expand_pattern (sub);
+
+ for (auto &sub : tuple_items.get_upper_patterns ())
+ maybe_expand_pattern (sub);
}
void
ExpandVisitor::visit (AST::LetStmt &stmt)
{
- visit (stmt.get_pattern ());
+ maybe_expand_pattern (stmt.get_pattern_ptr ());
if (stmt.has_type ())
maybe_expand_type (stmt.get_type_ptr ());
void
ExpandVisitor::visit (AST::FunctionParam ¶m)
{
+ maybe_expand_pattern (param.get_pattern_ptr ());
maybe_expand_type (param.get_type_ptr ());
}
+void
+ExpandVisitor::visit (AST::VariadicParam ¶m)
+{
+ if (param.has_pattern ())
+ maybe_expand_pattern (param.get_pattern_ptr ());
+}
+
void
ExpandVisitor::visit (AST::SelfParam ¶m)
{
#define RUST_EXPAND_VISITOR_H
#include "rust-ast-visitor.h"
+#include "rust-item.h"
#include "rust-macro-expand.h"
#include "rust-proc-macro.h"
using AST::DefaultASTVisitor::visit;
- /*
- Maybe expand a macro invocation in lieu of an expression
- expr : Core guidelines R33, this function reseat the pointer.
- */
- void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr);
-
- /*
- Maybe expand a macro invocation in lieu of a type
- type : Core guidelines R33, this function reseat the pointer.
+ /**
+ * Maybe expand a macro invocation in lieu of an expression, type or pattern.
+ *
+ * @ptr Core guidelines R33, this function reseats the pointer.
*/
- void maybe_expand_type (std::unique_ptr<AST::Type> &type);
+ void maybe_expand_expr (std::unique_ptr<AST::Expr> &ptr);
+ void maybe_expand_type (std::unique_ptr<AST::Type> &ptr);
void maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type);
+ void maybe_expand_pattern (std::unique_ptr<AST::Pattern> &ptr);
/**
* Expand all macro invocations in lieu of types within a vector of struct
void visit (AST::IfLetExpr &expr) override;
void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::MatchExpr &expr) override;
+ void visit (AST::TupleExpr &expr) override;
void visit (AST::TypeParam ¶m) override;
void visit (AST::LifetimeWhereClauseItem &) override;
void visit (AST::TypeBoundWhereClauseItem &item) override;
void visit (AST::MetaListNameValueStr &) override;
void visit (AST::StructPatternFieldIdent &field) override;
void visit (AST::GroupedPattern &pattern) override;
+ void visit (AST::SlicePatternItemsNoRest &items) override;
+ void visit (AST::SlicePatternItemsHasRest &items) override;
+ void visit (AST::AltPattern &pattern) override;
+ void visit (AST::TupleStructItemsNoRange &tuple_items) override;
+ void visit (AST::TupleStructItemsRange &tuple_items) override;
+ void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
+ void visit (AST::TuplePatternItemsRanged &tuple_items) override;
void visit (AST::LetStmt &stmt) override;
void visit (AST::ExprStmt &stmt) override;
void visit (AST::BareFunctionType &type) override;
- void visit (AST::FunctionParam &type) override;
+ void visit (AST::FunctionParam ¶m) override;
+ void visit (AST::VariadicParam ¶m) override;
void visit (AST::SelfParam &type) override;
template <typename T>
return AST::Fragment ({std::move (type)}, lexer.get_token_slice (start, end));
}
+/**
+ * Transcribe one pattern from a macro invocation
+ *
+ * @param parser Parser to extract statements from
+ */
+static AST::Fragment
+transcribe_pattern (Parser<MacroInvocLexer> &parser)
+{
+ auto &lexer = parser.get_token_source ();
+ auto start = lexer.get_offs ();
+
+ auto pattern = parser.parse_pattern ();
+ for (auto err : parser.get_errors ())
+ err.emit ();
+
+ auto end = lexer.get_offs ();
+
+ return AST::Fragment ({std::move (pattern)},
+ lexer.get_token_slice (start, end));
+}
+
static AST::Fragment
transcribe_context (MacroExpander::ContextType ctx,
Parser<MacroInvocLexer> &parser, bool semicolon,
// -- Trait --> parser.parse_trait_item();
// -- Impl --> parser.parse_impl_item();
// -- Extern --> parser.parse_extern_item();
+ // -- Pattern --> parser.parse_pattern();
// -- None --> [has semicolon?]
// -- Yes --> parser.parse_stmt();
// -- No --> [switch invocation.delimiter()]
break;
case MacroExpander::ContextType::TYPE:
return transcribe_type (parser);
+ case MacroExpander::ContextType::PATTERN:
+ return transcribe_pattern (parser);
break;
case MacroExpander::ContextType::STMT:
return transcribe_many_stmts (parser, last_token_id, semicolon);
TRAIT,
IMPL,
TRAIT_IMPL,
+ PATTERN,
};
ExpansionCfg cfg;
--- /dev/null
+pub enum TypeCtor {
+ Slice,
+ Array,
+}
+pub struct ApplicationTy(TypeCtor);
+
+macro_rules! ty_app {
+ ($ctor:pat) => {
+ ApplicationTy($ctor)
+ };
+}
+
+pub fn foo(ty: ApplicationTy) {
+ match ty {
+ ty_app!(TypeCtor::Array) => {}
+ }
+}
--- /dev/null
+// { dg-additional-options "-frust-compile-until=lowering" }
+
+#[lang = "sized"]
+trait Sized {}
+
+enum Result<T, E> {
+ Ok(T),
+ Err(E),
+}
+
+use Result::{Err, Ok};
+
+struct Utf8Error;
+
+const CONT_MASK: u8 = 15;
+const TAG_CONT_U8: u8 = 15;
+
+#[inline(always)]
+pub fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
+ let mut index = 0;
+ let len = 64;
+
+ let usize_bytes = 8;
+ let ascii_block_size = 2 * usize_bytes;
+ let blocks_end = if len >= ascii_block_size {
+ len - ascii_block_size + 1
+ } else {
+ 0
+ };
+
+ while index < len {
+ let old_offset = index;
+ macro_rules! err {
+ ($error_len: expr) => {
+ return Err(Utf8Error)
+ };
+ }
+
+ macro_rules! next {
+ () => {{
+ index += 1;
+ // we needed data, but there was none: error!
+ if index >= len {
+ err!(None)
+ }
+ v[index]
+ }};
+ }
+
+ let first = v[index];
+ if first >= 128 {
+ let w = 15;
+ // 2-byte encoding is for codepoints \u{0080} to \u{07ff}
+ // first C2 80 last DF BF
+ // 3-byte encoding is for codepoints \u{0800} to \u{ffff}
+ // first E0 A0 80 last EF BF BF
+ // excluding surrogates codepoints \u{d800} to \u{dfff}
+ // ED A0 80 to ED BF BF
+ // 4-byte encoding is for codepoints \u{1000}0 to \u{10ff}ff
+ // first F0 90 80 80 last F4 8F BF BF
+ //
+ // Use the UTF-8 syntax from the RFC
+ //
+ // https://tools.ietf.org/html/rfc3629
+ // UTF8-1 = %x00-7F
+ // UTF8-2 = %xC2-DF UTF8-tail
+ // UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
+ // %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
+ // UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
+ // %xF4 %x80-8F 2( UTF8-tail )
+ match w {
+ 2 => {
+ if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(1))
+ }
+ }
+ 3 => {
+ match (first, next!()) {
+ (0xE0, 0xA0..=0xBF)
+ | (0xE1..=0xEC, 0x80..=0xBF)
+ | (0xED, 0x80..=0x9F)
+ | (0xEE..=0xEF, 0x80..=0xBF) => {}
+ _ => err!(Some(1)),
+ }
+ if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(2))
+ }
+ }
+ 4 => {
+ match (first, next!()) {
+ (0xF0, 0x90..=0xBF) | (0xF1..=0xF3, 0x80..=0xBF) | (0xF4, 0x80..=0x8F) => {}
+ _ => err!(Some(1)),
+ }
+ if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(2))
+ }
+ if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(3))
+ }
+ }
+ _ => err!(Some(1)),
+ }
+ index += 1;
+ } else {
+ index += 1;
+ }
+ }
+
+ Ok(())
+}
+
+fn main() {}