summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/macro.hpp7
-rw-r--r--src/ast/path.hpp4
-rw-r--r--src/expand/mod.cpp2
-rw-r--r--src/include/span.hpp2
-rw-r--r--src/parse/common.hpp2
-rw-r--r--src/parse/pattern.cpp3
-rw-r--r--src/parse/root.cpp10
-rw-r--r--src/parse/types.cpp3
-rw-r--r--src/types.hpp5
9 files changed, 27 insertions, 11 deletions
diff --git a/src/ast/macro.hpp b/src/ast/macro.hpp
index 4696c732..4804f52b 100644
--- a/src/ast/macro.hpp
+++ b/src/ast/macro.hpp
@@ -3,6 +3,7 @@
#define _AST_MACRO_HPP_
#include "../parse/tokentree.hpp"
+#include <span.hpp>
#include "attrs.hpp"
namespace AST {
@@ -10,6 +11,8 @@ namespace AST {
class MacroInvocation:
public Serialisable
{
+ Span m_span;
+
::AST::MetaItems m_attrs;
::std::string m_macro_name;
::std::string m_ident;
@@ -19,7 +22,8 @@ public:
{
}
- MacroInvocation(MetaItems attrs, ::std::string macro, ::std::string ident, TokenTree input):
+ MacroInvocation(Span span, MetaItems attrs, ::std::string macro, ::std::string ident, TokenTree input):
+ m_span( mv$(span) ),
m_attrs( mv$(attrs) ),
m_macro_name( mv$(macro) ),
m_ident( mv$(ident) ),
@@ -39,6 +43,7 @@ public:
m_input = TokenTree();
}
+ const Span& span() const { return m_span; }
const ::std::string& name() const { return m_macro_name; }
const ::std::string& input_ident() const { return m_ident; }
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index 1260ece3..4fc08bb1 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -130,6 +130,7 @@ public:
private:
/// The crate defining the root of this path (used for path resolution)
::std::string m_crate;
+ Span m_span;
public:
Class m_class;
@@ -197,6 +198,9 @@ public:
}
+ const Span& span() const {
+ return m_span;
+ }
Class::Tag class_tag() const {
return m_class.tag();
}
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp
index 3f35d4dc..c6d5eec2 100644
--- a/src/expand/mod.cpp
+++ b/src/expand/mod.cpp
@@ -80,7 +80,7 @@ AST::Expr Expand_Macro(bool is_early, LList<const AST::Module*> modstack, ::AST:
if( ! is_early ) {
// TODO: Error - Unknown macro name
// TODO: Get a span via MacroInvocation and emit a good error
- throw ::std::runtime_error( FMT("Unknown macro '" << mi.name() << "'") );
+ ERROR(mi.span(), E0000, "Unknown macro '" << mi.name() << "'");
}
// Leave valid and return an empty expression
diff --git a/src/include/span.hpp b/src/include/span.hpp
index 7603b080..49169e5b 100644
--- a/src/include/span.hpp
+++ b/src/include/span.hpp
@@ -59,7 +59,7 @@ struct Spanned
T m_item;
};
-#define ERROR(span, code, msg) do { (Span()/*span*/).error(code, [&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Error fell through" #code); } while(0)
+#define ERROR(span, code, msg) do { (span).error(code, [&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Error fell through" #code); } while(0)
#define BUG(span, msg) do { (span).bug([&](::std::ostream& os) { os << msg; }); throw ::std::runtime_error("Bug fell through"); } while(0)
#define TODO(span, msg) do { (span).bug([&](::std::ostream& os) { os << "TODO: " << msg; }); throw ::std::runtime_error("Bug (todo) fell through"); } while(0)
diff --git a/src/parse/common.hpp b/src/parse/common.hpp
index 4b6ceb54..ed052a33 100644
--- a/src/parse/common.hpp
+++ b/src/parse/common.hpp
@@ -39,7 +39,7 @@ extern ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
extern AST::MetaItem Parse_MetaItem(TokenStream& lex);
-extern ::AST::MacroInvocation Parse_MacroInvocation(::AST::MetaItems meta_items, ::std::string name, TokenStream& lex);
+extern ::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan ps, ::AST::MetaItems meta_items, ::std::string name, TokenStream& lex);
extern TypeRef Parse_Type(TokenStream& lex);
extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable);
diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp
index e8ccd962..dcbc8c5d 100644
--- a/src/parse/pattern.cpp
+++ b/src/parse/pattern.cpp
@@ -37,13 +37,14 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable);
AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)
{
TRACE_FUNCTION;
+ auto ps = lex.start_span();
Token tok;
tok = lex.getToken();
if( tok.type() == TOK_MACRO )
{
- return AST::Pattern( AST::Pattern::TagMacro(), box$(Parse_MacroInvocation(AST::MetaItems(), tok.str(), lex)));
+ return AST::Pattern( AST::Pattern::TagMacro(), box$(Parse_MacroInvocation(ps, AST::MetaItems(), tok.str(), lex)));
}
bool expect_bind = false;
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index faa2b9bb..0860a008 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -917,9 +917,10 @@ void Parse_Impl(TokenStream& lex, AST::Module& mod, AST::MetaItems attrs, bool i
// A sequence of method implementations
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
{
+ auto ps = lex.start_span();
if( tok.type() == TOK_MACRO )
{
- impl.add_macro_invocation( Parse_MacroInvocation( AST::MetaItems(), mv$(tok.str()), lex ) );
+ impl.add_macro_invocation( Parse_MacroInvocation( ps, AST::MetaItems(), mv$(tok.str()), lex ) );
// - Silently consume ';' after the macro
if( GET_TOK(tok, lex) != TOK_SEMICOLON )
lex.putback(tok);
@@ -1206,7 +1207,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)>
}
-::AST::MacroInvocation Parse_MacroInvocation(::AST::MetaItems meta_items, ::std::string name, TokenStream& lex)
+::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan span_start, ::AST::MetaItems meta_items, ::std::string name, TokenStream& lex)
{
Token tok;
::std::string ident;
@@ -1217,7 +1218,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)>
lex.putback(tok);
}
TokenTree tt = Parse_TT(lex, true);
- return ::AST::MacroInvocation( mv$(meta_items), mv$(name), mv$(ident), mv$(tt));
+ return ::AST::MacroInvocation( lex.end_span(span_start), mv$(meta_items), mv$(name), mv$(ident), mv$(tt));
}
void Parse_ExternCrate(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items)
@@ -1598,10 +1599,11 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod, LList<AST::Module*>
DEBUG("meta_items = " << meta_items);
// root-level macros
+ auto ps = lex.start_span();
if( GET_TOK(tok, lex) == TOK_MACRO )
{
::std::string name = mv$(tok.str());
- mod.add_macro_invocation( Parse_MacroInvocation( mv$(meta_items), mv$(name), lex ) );
+ mod.add_macro_invocation( Parse_MacroInvocation( ps, mv$(meta_items), mv$(name), lex ) );
// - Silently consume ';' after the macro
// TODO: Check the tt next token before parsing to tell if this is needed
if( GET_TOK(tok, lex) != TOK_SEMICOLON )
diff --git a/src/parse/types.cpp b/src/parse/types.cpp
index e6aadbbe..16e95f6d 100644
--- a/src/parse/types.cpp
+++ b/src/parse/types.cpp
@@ -28,13 +28,14 @@ TypeRef Parse_Type(TokenStream& lex)
TypeRef Parse_Type_Int(TokenStream& lex)
{
//TRACE_FUNCTION;
+ auto ps = lex.start_span();
Token tok;
switch( GET_TOK(tok, lex) )
{
case TOK_MACRO:
- return TypeRef(TypeRef::TagMacro(), Parse_MacroInvocation(AST::MetaItems(), mv$(tok.str()), lex));
+ return TypeRef(TypeRef::TagMacro(), Parse_MacroInvocation(ps, AST::MetaItems(), mv$(tok.str()), lex));
// '!' - Only ever used as part of function prototypes, but is kinda a type... not allowed here though
case TOK_EXCLAM:
throw ParseError::Generic(lex, "! is not a real type");
diff --git a/src/types.hpp b/src/types.hpp
index 24c0d9ea..5b19d036 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -103,6 +103,7 @@ TAGGED_UNION(TypeData, None,
class TypeRef:
public Serialisable
{
+ Span m_span;
public:
TypeData m_data;
@@ -215,7 +216,9 @@ public:
m_data(TypeData::make_TraitObject({ mv$(hrls), ::std::move(traits) }))
{}
-
+
+ const Span& span() const { return m_span; }
+
/// Dereference the type (return the result of *type_instance)
bool deref(bool is_implicit);
/// Merge with another type (combines known aspects, conflitcs cause an exception)