mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
gccrs: format-args: Fix Rust interface and add input parsing.
gcc/rust/ChangeLog: * ast/rust-ast.cc: Make FormatArgs inherit from AST::Expr * ast/rust-builtin-ast-nodes.h: Improve FormatArg* nodes and helpers. * ast/rust-fmt.cc (Pieces::collect): Fix interface to match FFI function. * ast/rust-fmt.h (collect_pieces): Likewise. (struct Pieces): Add append_newline parameter. * expand/rust-macro-builtins.cc: Add proper parsing of format_args input. * hir/rust-ast-lower-base.cc: Include diagnostics header. libgrust/ChangeLog: * libformat_parser/src/lib.rs: Switch interface to use more parser parameters. * libformat_parser/src/bin.rs: Use new interface.
This commit is contained in:
parent
d9fa4153c8
commit
68cb878c1d
@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
#include "rust-ast.h"
|
||||
#include "optional.h"
|
||||
#include "rust-builtin-ast-nodes.h"
|
||||
#include "rust-system.h"
|
||||
#include "rust-ast-full.h"
|
||||
#include "rust-diagnostics.h"
|
||||
@ -5054,6 +5055,56 @@ FormatArgs::accept_vis (ASTVisitor &vis)
|
||||
vis.visit (*this);
|
||||
}
|
||||
|
||||
std::string
|
||||
FormatArgs::as_string () const
|
||||
{
|
||||
// FIXME(Arthur): Improve
|
||||
return "FormatArgs";
|
||||
}
|
||||
|
||||
location_t
|
||||
FormatArgs::get_locus () const
|
||||
{
|
||||
rust_unreachable ();
|
||||
}
|
||||
|
||||
bool
|
||||
FormatArgs::is_expr_without_block () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
FormatArgs::mark_for_strip ()
|
||||
{
|
||||
marked_for_strip = true;
|
||||
}
|
||||
|
||||
bool
|
||||
FormatArgs::is_marked_for_strip () const
|
||||
{
|
||||
return marked_for_strip;
|
||||
}
|
||||
|
||||
std::vector<Attribute> &
|
||||
FormatArgs::get_outer_attrs ()
|
||||
{
|
||||
rust_unreachable ();
|
||||
}
|
||||
|
||||
void FormatArgs::set_outer_attrs (std::vector<Attribute>)
|
||||
{
|
||||
rust_unreachable ();
|
||||
}
|
||||
|
||||
Expr *
|
||||
FormatArgs::clone_expr_impl () const
|
||||
{
|
||||
std::cerr << "[ARTHUR] cloning FormatArgs! " << std::endl;
|
||||
|
||||
return new FormatArgs (*this);
|
||||
}
|
||||
|
||||
} // namespace AST
|
||||
|
||||
std::ostream &
|
||||
|
@ -59,17 +59,10 @@ namespace AST {
|
||||
// └─┘ └─┘
|
||||
// positions (could be names, numbers, empty, or `*`)
|
||||
|
||||
// FIXME: Merge with the class below this one?
|
||||
class FormatArgumentKind
|
||||
{
|
||||
public:
|
||||
Identifier &get_ident ()
|
||||
{
|
||||
rust_assert (kind == Kind::Captured || kind == Kind::Named);
|
||||
|
||||
return ident.value ();
|
||||
}
|
||||
|
||||
private:
|
||||
enum class Kind
|
||||
{
|
||||
Normal,
|
||||
@ -77,17 +70,97 @@ private:
|
||||
Captured,
|
||||
} kind;
|
||||
|
||||
Identifier &get_ident ()
|
||||
{
|
||||
rust_assert (kind == Kind::Captured || kind == Kind::Named);
|
||||
|
||||
return ident.value ();
|
||||
}
|
||||
|
||||
FormatArgumentKind (Kind kind, tl::optional<Identifier> ident)
|
||||
: kind (kind), ident (ident)
|
||||
{}
|
||||
|
||||
FormatArgumentKind (const FormatArgumentKind &other)
|
||||
{
|
||||
kind = other.kind;
|
||||
ident = other.ident;
|
||||
}
|
||||
|
||||
FormatArgumentKind operator= (const FormatArgumentKind &other)
|
||||
{
|
||||
kind = other.kind;
|
||||
ident = other.ident;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
tl::optional<Identifier> ident;
|
||||
};
|
||||
|
||||
class FormatArgument
|
||||
{
|
||||
public:
|
||||
static FormatArgument normal (std::unique_ptr<Expr> expr)
|
||||
{
|
||||
return FormatArgument (FormatArgumentKind::Kind::Normal, tl::nullopt,
|
||||
std::move (expr));
|
||||
}
|
||||
|
||||
static FormatArgument named (Identifier ident, std::unique_ptr<Expr> expr)
|
||||
{
|
||||
return FormatArgument (FormatArgumentKind::Kind::Named, ident,
|
||||
std::move (expr));
|
||||
}
|
||||
|
||||
static FormatArgument captured (Identifier ident, std::unique_ptr<Expr> expr)
|
||||
{
|
||||
return FormatArgument (FormatArgumentKind::Kind::Captured, ident,
|
||||
std::move (expr));
|
||||
}
|
||||
|
||||
FormatArgument (const FormatArgument &other)
|
||||
: kind (other.kind), expr (other.expr->clone_expr ())
|
||||
{}
|
||||
|
||||
FormatArgument operator= (const FormatArgument &other)
|
||||
{
|
||||
kind = other.kind;
|
||||
expr = other.expr->clone_expr ();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
FormatArgument (FormatArgumentKind::Kind kind, tl::optional<Identifier> ident,
|
||||
std::unique_ptr<Expr> expr)
|
||||
: kind (FormatArgumentKind (kind, ident)), expr (std::move (expr))
|
||||
{}
|
||||
|
||||
FormatArgumentKind kind;
|
||||
std::unique_ptr<Expr> expr;
|
||||
};
|
||||
|
||||
class FormatArguments
|
||||
{
|
||||
public:
|
||||
FormatArguments () {}
|
||||
FormatArguments (FormatArguments &&) = default;
|
||||
FormatArguments (const FormatArguments &other)
|
||||
{
|
||||
args = std::vector<FormatArgument> ();
|
||||
args.reserve (other.args.size ());
|
||||
|
||||
for (const auto &arg : other.args)
|
||||
args.emplace_back (arg);
|
||||
};
|
||||
|
||||
FormatArguments &operator= (const FormatArguments &other) = default;
|
||||
|
||||
void push (FormatArgument &&elt) { args.emplace_back (std::move (elt)); }
|
||||
|
||||
private:
|
||||
std::vector<FormatArgument> args;
|
||||
};
|
||||
|
||||
@ -100,7 +173,7 @@ class FormatArguments
|
||||
// format_args!("result: {}", some_result))` -> `format_args!("heyo result: {}",
|
||||
// some_result)`
|
||||
// FIXME: Move to rust-macro.h
|
||||
class FormatArgs : public Visitable
|
||||
class FormatArgs : public Expr
|
||||
{
|
||||
public:
|
||||
enum class Newline
|
||||
@ -109,18 +182,56 @@ public:
|
||||
No
|
||||
};
|
||||
|
||||
FormatArgs (location_t loc, Fmt::PieceSlice template_str,
|
||||
FormatArguments arguments)
|
||||
FormatArgs (location_t loc, Fmt::Pieces &&template_str,
|
||||
FormatArguments &&arguments)
|
||||
: loc (loc), template_str (std::move (template_str)),
|
||||
arguments (std::move (arguments))
|
||||
{}
|
||||
|
||||
void accept_vis (AST::ASTVisitor &vis);
|
||||
FormatArgs (FormatArgs &&other)
|
||||
: loc (std::move (other.loc)),
|
||||
template_str (std::move (other.template_str)),
|
||||
arguments (std::move (other.arguments))
|
||||
{
|
||||
std::cerr << "[ARTHUR] moving FormatArgs" << std::endl;
|
||||
}
|
||||
|
||||
// FIXME: This might be invalid - we are reusing the same memory allocated
|
||||
// on the Rust side for `other`. This is probably valid as long as we only
|
||||
// ever read that memory and never write to it.
|
||||
FormatArgs (const FormatArgs &other)
|
||||
: loc (other.loc), template_str (other.template_str),
|
||||
arguments (other.arguments)
|
||||
{
|
||||
std::cerr << "[ARTHUR] copying FormatArgs" << std::endl;
|
||||
}
|
||||
|
||||
// FormatArgs &operator= (const FormatArgs &other) = default;
|
||||
// : template_str (other.template_str), arguments (other.arguments)
|
||||
// {}
|
||||
|
||||
void accept_vis (AST::ASTVisitor &vis) override;
|
||||
|
||||
private:
|
||||
location_t loc;
|
||||
Fmt::PieceSlice template_str;
|
||||
// FIXME: This probably needs to be a separate type - it is one in rustc's
|
||||
// expansion of format_args!(). There is extra handling associated with it.
|
||||
// we can maybe do that in rust-fmt.cc? in collect_pieces()? like do the
|
||||
// transformation into something we can handle better
|
||||
Fmt::Pieces template_str;
|
||||
FormatArguments arguments;
|
||||
|
||||
bool marked_for_strip = false;
|
||||
|
||||
protected:
|
||||
virtual std::string as_string () const override;
|
||||
virtual location_t get_locus () const override;
|
||||
virtual bool is_expr_without_block () const override;
|
||||
virtual void mark_for_strip () override;
|
||||
virtual bool is_marked_for_strip () const override;
|
||||
virtual std::vector<Attribute> &get_outer_attrs () override;
|
||||
virtual void set_outer_attrs (std::vector<Attribute>) override;
|
||||
virtual Expr *clone_expr_impl () const override;
|
||||
};
|
||||
|
||||
} // namespace AST
|
||||
|
@ -23,9 +23,9 @@ namespace Rust {
|
||||
namespace Fmt {
|
||||
|
||||
Pieces
|
||||
Pieces::collect (std::string &&to_parse)
|
||||
Pieces::collect (std::string &&to_parse, bool append_newline)
|
||||
{
|
||||
auto piece_slice = collect_pieces (to_parse.c_str ());
|
||||
auto piece_slice = collect_pieces (to_parse.c_str (), append_newline);
|
||||
|
||||
rust_debug ("[ARTHUR] %p, %lu", (const void *) piece_slice.base_ptr,
|
||||
piece_slice.len);
|
||||
@ -37,7 +37,39 @@ Pieces::collect (std::string &&to_parse)
|
||||
return Pieces (piece_slice, std::move (to_parse));
|
||||
}
|
||||
|
||||
Pieces::~Pieces () { destroy_pieces (slice); }
|
||||
Pieces::~Pieces ()
|
||||
{
|
||||
std::cerr << "Arthur: destoying pieces. this: " << (void *) this
|
||||
<< " slice: " << slice.base_ptr << std::endl;
|
||||
destroy_pieces (slice);
|
||||
}
|
||||
|
||||
Pieces::Pieces (const Pieces &other) : to_parse (other.to_parse)
|
||||
{
|
||||
slice = clone_pieces (other.slice.base_ptr, other.slice.len, other.slice.cap);
|
||||
std::cerr << "Arthur: copying pieces: other.to_parse: "
|
||||
<< (void *) other.to_parse.c_str ()
|
||||
<< " ours to_parse: " << (void *) to_parse.c_str () << std::endl;
|
||||
// auto pieces = std::vector (slice.base_ptr, slice.base_ptr + slice.len);
|
||||
}
|
||||
|
||||
Pieces &
|
||||
Pieces::operator= (const Pieces &other)
|
||||
{
|
||||
slice = clone_pieces (other.slice.base_ptr, other.slice.len, other.slice.cap);
|
||||
to_parse = other.to_parse;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Pieces::Pieces (Pieces &&other)
|
||||
: slice (
|
||||
clone_pieces (other.slice.base_ptr, other.slice.len, other.slice.cap)),
|
||||
to_parse (std::move (other.to_parse))
|
||||
{
|
||||
std::cerr << "Arthur: moving pieces. to_parse: " << (void *) to_parse.c_str ()
|
||||
<< " base_ptr/slice: " << (void *) slice.base_ptr << std::endl;
|
||||
}
|
||||
|
||||
} // namespace Fmt
|
||||
} // namespace Rust
|
||||
|
@ -222,7 +222,7 @@ struct Piece
|
||||
|
||||
struct NextArgument_Body
|
||||
{
|
||||
const Argument *_0;
|
||||
Argument _0;
|
||||
};
|
||||
|
||||
Tag tag;
|
||||
@ -243,7 +243,10 @@ struct PieceSlice
|
||||
extern "C" {
|
||||
|
||||
PieceSlice
|
||||
collect_pieces (const char *input);
|
||||
collect_pieces (const char *input, bool append_newline);
|
||||
|
||||
PieceSlice
|
||||
clone_pieces (const Piece *base_ptr, size_t len, size_t cap);
|
||||
|
||||
void destroy_pieces (PieceSlice);
|
||||
|
||||
@ -251,9 +254,21 @@ void destroy_pieces (PieceSlice);
|
||||
|
||||
struct Pieces
|
||||
{
|
||||
static Pieces collect (std::string &&to_parse);
|
||||
static Pieces collect (std::string &&to_parse, bool append_newline);
|
||||
~Pieces ();
|
||||
|
||||
Pieces (const Pieces &other);
|
||||
Pieces &operator= (const Pieces &other);
|
||||
|
||||
Pieces (Pieces &&other);
|
||||
|
||||
// {
|
||||
// slice = clone_pieces (&other.slice);
|
||||
// to_parse = other.to_parse;
|
||||
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
private:
|
||||
Pieces (PieceSlice slice, std::string &&to_parse)
|
||||
: slice (slice), to_parse (std::move (to_parse))
|
||||
|
@ -16,6 +16,7 @@
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "expected.h"
|
||||
#include "libproc_macro_internal/tokenstream.h"
|
||||
#include "rust-ast-full-decls.h"
|
||||
#include "rust-builtin-ast-nodes.h"
|
||||
@ -35,6 +36,7 @@
|
||||
#include "rust-session-manager.h"
|
||||
#include "rust-attribute-values.h"
|
||||
#include "rust-fmt.h"
|
||||
#include "rust-token.h"
|
||||
|
||||
namespace Rust {
|
||||
|
||||
@ -956,33 +958,115 @@ MacroBuiltin::stringify_handler (location_t invoc_locus,
|
||||
return AST::Fragment ({node}, std::move (token));
|
||||
}
|
||||
|
||||
struct FormatArgsInput
|
||||
{
|
||||
std::unique_ptr<AST::Expr> format_str;
|
||||
AST::FormatArguments args;
|
||||
// bool is_literal?
|
||||
};
|
||||
|
||||
struct FormatArgsParseError
|
||||
{
|
||||
enum class Kind
|
||||
{
|
||||
MissingArguments
|
||||
} kind;
|
||||
};
|
||||
|
||||
static tl::expected<FormatArgsInput, FormatArgsParseError>
|
||||
format_args_parse_arguments (AST::MacroInvocData &invoc)
|
||||
{
|
||||
MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
|
||||
Parser<MacroInvocLexer> parser (lex);
|
||||
|
||||
// TODO: check if EOF - return that format_args!() requires at least one
|
||||
// argument
|
||||
|
||||
auto args = AST::FormatArguments ();
|
||||
auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
|
||||
std::unique_ptr<AST::Expr> format_str = nullptr;
|
||||
|
||||
// TODO: Handle the case where we're not parsing a string literal (macro
|
||||
// invocation for e.g.)
|
||||
if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
|
||||
format_str = parser.parse_literal_expr ();
|
||||
|
||||
// TODO: Allow implicit captures ONLY if the the first arg is a string literal
|
||||
// and not a macro invocation
|
||||
|
||||
// TODO: How to consume all of the arguments until the delimiter?
|
||||
|
||||
// TODO: What we then want to do is as follows:
|
||||
// for each token, check if it is an identifier
|
||||
// yes? is the next token an equal sign (=)
|
||||
// yes?
|
||||
// -> if that identifier is already present in our map, error
|
||||
// out
|
||||
// -> parse an expression, return a FormatArgument::Named
|
||||
// no?
|
||||
// -> if there have been named arguments before, error out
|
||||
// (positional after named error)
|
||||
// -> parse an expression, return a FormatArgument::Normal
|
||||
while (parser.peek_current_token ()->get_id () != last_token_id)
|
||||
{
|
||||
parser.skip_token (COMMA);
|
||||
|
||||
if (parser.peek_current_token ()->get_id () == IDENTIFIER
|
||||
&& parser.peek (1)->get_id () == EQUAL)
|
||||
{
|
||||
// FIXME: This is ugly - just add a parser.parse_identifier()?
|
||||
auto ident_tok = parser.peek_current_token ();
|
||||
auto ident = Identifier (ident_tok);
|
||||
|
||||
parser.skip_token (IDENTIFIER);
|
||||
parser.skip_token (EQUAL);
|
||||
|
||||
auto expr = parser.parse_expr ();
|
||||
|
||||
// TODO: Handle graciously
|
||||
if (!expr)
|
||||
rust_unreachable ();
|
||||
|
||||
args.push (AST::FormatArgument::named (ident, std::move (expr)));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto expr = parser.parse_expr ();
|
||||
|
||||
// TODO: Handle graciously
|
||||
if (!expr)
|
||||
rust_unreachable ();
|
||||
|
||||
args.push (AST::FormatArgument::normal (std::move (expr)));
|
||||
}
|
||||
// we need to skip commas, don't we?
|
||||
}
|
||||
|
||||
return FormatArgsInput{std::move (format_str), std::move (args)};
|
||||
}
|
||||
|
||||
tl::optional<AST::Fragment>
|
||||
MacroBuiltin::format_args_handler (location_t invoc_locus,
|
||||
AST::MacroInvocData &invoc,
|
||||
AST::FormatArgs::Newline nl)
|
||||
{
|
||||
// Remove the delimiters from the macro invocation:
|
||||
// the invoc data for `format_args!(fmt, arg1, arg2)` is `(fmt, arg1, arg2)`,
|
||||
// so we pop the front and back to remove the parentheses (or curly brackets,
|
||||
// or brackets)
|
||||
auto tokens = invoc.get_delim_tok_tree ().to_token_stream ();
|
||||
tokens.erase (tokens.begin ());
|
||||
tokens.pop_back ();
|
||||
auto input = format_args_parse_arguments (invoc);
|
||||
|
||||
auto append_newline = nl == AST::FormatArgs::Newline::Yes ? true : false;
|
||||
auto fmt_arg
|
||||
= parse_single_string_literal (append_newline ? BuiltinMacro::FormatArgsNl
|
||||
: BuiltinMacro::FormatArgs,
|
||||
invoc.get_delim_tok_tree (), invoc_locus,
|
||||
invoc.get_expander ());
|
||||
// auto fmt_arg
|
||||
// // FIXME: this eneds to be split up into a smaller function
|
||||
// = parse_single_string_literal (append_newline ?
|
||||
// BuiltinMacro::FormatArgsNl
|
||||
// : BuiltinMacro::FormatArgs,
|
||||
// invoc.get_delim_tok_tree (), invoc_locus,
|
||||
// invoc.get_expander ());
|
||||
|
||||
if (!fmt_arg->is_literal ())
|
||||
{
|
||||
rust_sorry_at (
|
||||
invoc_locus,
|
||||
"cannot yet use eager macro invocations as format strings");
|
||||
return AST::Fragment::create_empty ();
|
||||
}
|
||||
// if (!fmt_arg->is_literal ())
|
||||
// {
|
||||
// rust_sorry_at (
|
||||
// invoc_locus,
|
||||
// "cannot yet use eager macro invocations as format strings");
|
||||
// return AST::Fragment::create_empty ();
|
||||
// }
|
||||
|
||||
// FIXME: We need to handle this
|
||||
// // if it is not a literal, it's an eager macro invocation - return it
|
||||
@ -993,38 +1077,54 @@ MacroBuiltin::format_args_handler (location_t invoc_locus,
|
||||
// token_tree.to_token_stream ());
|
||||
// }
|
||||
|
||||
auto fmt_str = static_cast<AST::LiteralExpr &> (*fmt_arg.get ());
|
||||
// auto fmt_str = static_cast<AST::LiteralExpr &> (*fmt_arg.get ());
|
||||
|
||||
// Switch on the format string to know if the string is raw or cooked
|
||||
switch (fmt_str.get_lit_type ())
|
||||
{
|
||||
// case AST::Literal::RAW_STRING:
|
||||
case AST::Literal::STRING:
|
||||
break;
|
||||
case AST::Literal::CHAR:
|
||||
case AST::Literal::BYTE:
|
||||
case AST::Literal::BYTE_STRING:
|
||||
case AST::Literal::INT:
|
||||
case AST::Literal::FLOAT:
|
||||
case AST::Literal::BOOL:
|
||||
case AST::Literal::ERROR:
|
||||
rust_unreachable ();
|
||||
}
|
||||
// switch (fmt_str.get_lit_type ())
|
||||
// {
|
||||
// // case AST::Literal::RAW_STRING:
|
||||
// case AST::Literal::STRING:
|
||||
// break;
|
||||
// case AST::Literal::CHAR:
|
||||
// case AST::Literal::BYTE:
|
||||
// case AST::Literal::BYTE_STRING:
|
||||
// case AST::Literal::INT:
|
||||
// case AST::Literal::FLOAT:
|
||||
// case AST::Literal::BOOL:
|
||||
// case AST::Literal::ERROR:
|
||||
// rust_unreachable ();
|
||||
// }
|
||||
|
||||
// Remove the delimiters from the macro invocation:
|
||||
// the invoc data for `format_args!(fmt, arg1, arg2)` is `(fmt, arg1, arg2)`,
|
||||
// so we pop the front and back to remove the parentheses (or curly brackets,
|
||||
// or brackets)
|
||||
auto tokens = invoc.get_delim_tok_tree ().to_token_stream ();
|
||||
tokens.erase (tokens.begin ());
|
||||
tokens.pop_back ();
|
||||
|
||||
std::stringstream stream;
|
||||
for (const auto &tok : tokens)
|
||||
stream << tok->as_string () << ' ';
|
||||
|
||||
rust_debug ("[ARTHUR]: `%s`", stream.str ().c_str ());
|
||||
|
||||
auto pieces = Fmt::Pieces::collect (stream.str ());
|
||||
auto append_newline = nl == AST::FormatArgs::Newline::Yes ? true : false;
|
||||
auto pieces = Fmt::Pieces::collect (stream.str (), append_newline);
|
||||
|
||||
// TODO:
|
||||
// do the transformation into an AST::FormatArgs node
|
||||
// return that
|
||||
// expand it during lowering
|
||||
|
||||
return AST::Fragment::create_empty ();
|
||||
// TODO: we now need to take care of creating `unfinished_literal`? this is
|
||||
// for creating the `template`
|
||||
|
||||
auto fmt_args_node = new AST::FormatArgs (invoc_locus, std::move (pieces),
|
||||
std::move (input->args));
|
||||
auto node = std::unique_ptr<AST::Expr> (fmt_args_node);
|
||||
auto single_node = AST::SingleASTNode (std::move (node));
|
||||
|
||||
return AST::Fragment ({std::move (single_node)},
|
||||
invoc.get_delim_tok_tree ().to_token_stream ());
|
||||
}
|
||||
|
||||
tl::optional<AST::Fragment>
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "rust-ast-lower-extern.h"
|
||||
#include "rust-ast.h"
|
||||
#include "rust-attribute-values.h"
|
||||
#include "rust-diagnostics.h"
|
||||
#include "rust-item.h"
|
||||
#include "rust-system.h"
|
||||
|
||||
|
@ -2,6 +2,9 @@ use libformat_parser::rust;
|
||||
|
||||
fn main() {
|
||||
dbg!(rust::collect_pieces(
|
||||
std::env::args().nth(1).unwrap().as_str()
|
||||
std::env::args().nth(1).unwrap().as_str(),
|
||||
None,
|
||||
None,
|
||||
false
|
||||
));
|
||||
}
|
||||
|
@ -77,20 +77,15 @@ mod ffi {
|
||||
|
||||
/// A piece is a portion of the format string which represents the next part
|
||||
/// to emit. These are emitted as a stream by the `Parser` class.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub enum Piece<'a> {
|
||||
/// A literal string which should directly be emitted
|
||||
String(&'a str),
|
||||
/// This describes that formatting should process the next argument (as
|
||||
/// specified inside) for emission.
|
||||
NextArgument(*const Argument<'a>),
|
||||
}
|
||||
|
||||
impl<'a> Drop for Piece<'a> {
|
||||
fn drop(&mut self) {
|
||||
println!("dropping Piece: {:?}", self)
|
||||
}
|
||||
// do we need a pointer here? we're doing big cloning anyway
|
||||
NextArgument(Argument<'a>),
|
||||
}
|
||||
|
||||
/// Representation of an argument specification.
|
||||
@ -216,7 +211,7 @@ mod ffi {
|
||||
let ptr = Box::leak(x);
|
||||
let dst = Into::<Argument>::into(*ptr);
|
||||
|
||||
Piece::NextArgument(&dst as *const Argument)
|
||||
Piece::NextArgument(dst)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -321,8 +316,13 @@ mod ffi {
|
||||
pub mod rust {
|
||||
use generic_format_parser::{ParseMode, Parser, Piece};
|
||||
|
||||
pub fn collect_pieces(input: &str) -> Vec<Piece<'_>> {
|
||||
let parser = Parser::new(input, None, None, true, ParseMode::Format);
|
||||
pub fn collect_pieces(
|
||||
input: &str,
|
||||
style: Option<usize>,
|
||||
snippet: Option<String>,
|
||||
append_newline: bool,
|
||||
) -> Vec<Piece<'_>> {
|
||||
let parser = Parser::new(input, style, snippet, append_newline, ParseMode::Format);
|
||||
|
||||
parser.into_iter().collect()
|
||||
}
|
||||
@ -337,13 +337,15 @@ pub struct PieceSlice {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn collect_pieces(input: *const libc::c_char) -> PieceSlice {
|
||||
pub extern "C" fn collect_pieces(input: *const libc::c_char, append_newline: bool) -> PieceSlice {
|
||||
dbg!(input);
|
||||
|
||||
// FIXME: Add comment
|
||||
let str = unsafe { CStr::from_ptr(input) };
|
||||
dbg!(str);
|
||||
|
||||
// FIXME: No unwrap
|
||||
let pieces: Vec<ffi::Piece<'_>> = rust::collect_pieces(str.to_str().unwrap())
|
||||
let pieces: Vec<ffi::Piece<'_>> =
|
||||
rust::collect_pieces(str.to_str().unwrap(), None, None, append_newline)
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect();
|
||||
@ -358,6 +360,29 @@ pub extern "C" fn collect_pieces(input: *const libc::c_char) -> PieceSlice {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn destroy_pieces(PieceSlice { base_ptr, len, cap }: PieceSlice) {
|
||||
let _ = unsafe { Vec::from_raw_parts(base_ptr, len, cap) };
|
||||
pub unsafe extern "C" fn destroy_pieces(PieceSlice { base_ptr, len, cap }: PieceSlice) {
|
||||
eprintln!("[ARTHUR] destroying pieces: {base_ptr:?} {len} {cap}");
|
||||
drop(Vec::from_raw_parts(base_ptr, len, cap));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn clone_pieces(
|
||||
base_ptr: *mut ffi::Piece<'static>,
|
||||
len: usize,
|
||||
cap: usize,
|
||||
) -> PieceSlice {
|
||||
eprintln!("[ARTHUR] cloning pieces: {base_ptr:?} {len} {cap}");
|
||||
|
||||
let v = unsafe { Vec::from_raw_parts(base_ptr, len, cap) };
|
||||
|
||||
let cloned_v = v.clone();
|
||||
|
||||
// FIXME: Add documentation
|
||||
v.leak();
|
||||
|
||||
PieceSlice {
|
||||
len: cloned_v.len(),
|
||||
cap: cloned_v.capacity(),
|
||||
base_ptr: dbg!(cloned_v.leak().as_mut_ptr()),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user