summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/expr.cpp6
-rw-r--r--src/ast/expr.hpp12
-rw-r--r--src/dump_as_rust.cpp11
-rw-r--r--src/parse/expr.cpp14
-rw-r--r--src/parse/root.cpp34
5 files changed, 64 insertions, 13 deletions
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
index 49ebdbe2..a2f9cbd1 100644
--- a/src/ast/expr.cpp
+++ b/src/ast/expr.cpp
@@ -380,6 +380,7 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) {
_(CMPGT);
_(CMPGTE);
_(RANGE);
+ _(RANGE_INC);
_(BOOLAND);
_(BOOLOR);
_(BITAND);
@@ -408,6 +409,7 @@ void operator%(::Deserialiser& s, ExprNode_BinOp::Type& t) {
_(CMPGT);
_(CMPGTE);
_(RANGE);
+ _(RANGE_INC);
_(BOOLAND);
_(BOOLOR);
_(BITAND);
@@ -451,6 +453,7 @@ NODE(ExprNode_BinOp, {
case ADD: os << "+"; break;
case SUB: os << "-"; break;
case RANGE: os << ".."; break;
+ case RANGE_INC: os << "..."; break;
case PLACE_IN: os << "<-"; break;
}
os << " " << *m_right << ")";
@@ -465,6 +468,7 @@ void operator%(::Serialiser& s, const ExprNode_UniOp::Type t) {
_(BOX)
_(REF)
_(REFMUT)
+ _(QMARK)
#undef _
}
}
@@ -478,6 +482,7 @@ void operator%(::Deserialiser& s, enum ExprNode_UniOp::Type& t) {
_(BOX)
_(REF)
_(REFMUT)
+ _(QMARK)
#undef _
else
throw ::std::runtime_error( FMT("No uniop type for '" << n << "'") );
@@ -493,6 +498,7 @@ NODE(ExprNode_UniOp, {
case BOX: os << "(box "; break;
case REF: os << "(&"; break;
case REFMUT: os << "(&mut "; break;
+ case QMARK: os << "(" << *m_value << "?)"; return;
}
os << *m_value << ")";
})
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp
index 19b7cddc..19c348cb 100644
--- a/src/ast/expr.hpp
+++ b/src/ast/expr.hpp
@@ -513,6 +513,7 @@ struct ExprNode_BinOp:
CMPGTE,
RANGE,
+ RANGE_INC,
BOOLAND,
BOOLOR,
@@ -551,11 +552,12 @@ struct ExprNode_UniOp:
public ExprNode
{
enum Type {
- REF,
- REFMUT,
- BOX,
- INVERT,
- NEGATE,
+ REF, // '& <expr>'
+ REFMUT, // '&mut <expr>'
+ BOX, // 'box <expr>'
+ INVERT, // '!<expr>'
+ NEGATE, // '-<expr>'
+ QMARK, // '<expr>?'
};
enum Type m_type;
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp
index f72b2df5..357795c5 100644
--- a/src/dump_as_rust.cpp
+++ b/src/dump_as_rust.cpp
@@ -487,6 +487,7 @@ public:
case AST::ExprNode_BinOp::ADD: m_os << "+"; break;
case AST::ExprNode_BinOp::SUB: m_os << "-"; break;
case AST::ExprNode_BinOp::RANGE: m_os << ".."; break;
+ case AST::ExprNode_BinOp::RANGE_INC: m_os << "..."; break;
case AST::ExprNode_BinOp::PLACE_IN: m_os << "<-"; break;
}
m_os << " ";
@@ -504,11 +505,19 @@ public:
case AST::ExprNode_UniOp::BOX: m_os << "box "; break;
case AST::ExprNode_UniOp::REF: m_os << "&"; break;
case AST::ExprNode_UniOp::REFMUT: m_os << "&mut "; break;
+ case AST::ExprNode_UniOp::QMARK: break;
}
if( IS(*n.m_value, AST::ExprNode_BinOp) )
- m_os << " ";
+ m_os << "(";
AST::NodeVisitor::visit(n.m_value);
+ if( IS(*n.m_value, AST::ExprNode_BinOp) )
+ m_os << ")";
+ switch(n.m_type)
+ {
+ case AST::ExprNode_UniOp::QMARK: m_os << "?"; break;
+ default: break;
+ }
}
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index 58c82a0b..407afbf3 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -578,12 +578,12 @@ bool Parse_IsTokValue(eTokenType tok_type)
}
}
-ExprNodeP Parse_Expr1_5(TokenStream& lex);
+ExprNodeP Parse_Expr1_1(TokenStream& lex);
// Very evil handling for '..'
ExprNodeP Parse_Expr1(TokenStream& lex)
{
Token tok;
- ExprNodeP (*next)(TokenStream&) = Parse_Expr1_5;
+ ExprNodeP (*next)(TokenStream&) = Parse_Expr1_1;
ExprNodeP left, right;
if( GET_TOK(tok, lex) != TOK_DOUBLE_DOT )
@@ -610,6 +610,12 @@ ExprNodeP Parse_Expr1(TokenStream& lex)
return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE, ::std::move(left), ::std::move(right) );
}
+// TODO: Is this left associative?
+LEFTASSOC(Parse_Expr1_1, Parse_Expr1_5,
+ case TOK_TRIPLE_DOT:
+ rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, mv$(rv), next(lex) );
+ break;
+)
// 1: Bool OR
LEFTASSOC(Parse_Expr1_5, Parse_Expr2,
case TOK_DOUBLE_PIPE:
@@ -765,6 +771,10 @@ ExprNodeP Parse_ExprFC(TokenStream& lex)
Token tok;
switch(GET_TOK(tok, lex))
{
+ case TOK_QMARK:
+ val = NEWNODE( AST::ExprNode_UniOp, AST::ExprNode_UniOp::QMARK, mv$(val) );
+ break;
+
case TOK_PAREN_OPEN:
// Expression method call
lex.putback(tok);
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 4aba4874..0ce6935b 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -972,7 +972,8 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break; }
case TOK_RWORD_CONST:
- if( GET_TOK(tok, lex) != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE )
+ GET_TOK(tok, lex);
+ if( tok.type() != TOK_RWORD_FN && tok.type() != TOK_RWORD_UNSAFE )
{
CHECK_TOK(tok, TOK_IDENT);
auto name = mv$(tok.str());
@@ -989,11 +990,14 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
}
else if( tok.type() == TOK_RWORD_UNSAFE )
{
- if( GET_TOK(tok, lex) != TOK_RWORD_FN )
- ERROR(lex.end_span(lex.start_span()), E0000, "");
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ // TODO: Use a better marker
item_attrs.push_back( AST::MetaItem("#UNSAFE") );
}
+ // TODO: Mark `const fn` as const (properly)
+ item_attrs.push_back( AST::MetaItem("#CONST") );
if( 0 )
+ // FALL
case TOK_RWORD_EXTERN:
{
abi = "C";
@@ -1005,6 +1009,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
GET_TOK(tok, lex);
}
CHECK_TOK(tok, TOK_RWORD_FN);
+ // FALL
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
@@ -1012,6 +1017,21 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
auto fcn = Parse_FunctionDefWithCode(lex, abi, item_attrs, true);
impl.add_function(is_public, ::std::move(name), mv$(fcn));
break; }
+
+ case TOK_IDENT:
+ if( tok.str() == "default" ) {
+ // TODO: Mark `default` functions as default (i.e. specialisable)
+ GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ ::std::string name = tok.str();
+ // - Self allowed, can't be prototype-form
+ auto fcn = Parse_FunctionDefWithCode(lex, abi, item_attrs, true);
+ impl.add_function(is_public, ::std::move(name), mv$(fcn));
+ }
+ else {
+ throw ParseError::Unexpected(lex, tok);
+ }
+ break;
default:
throw ParseError::Unexpected(lex, tok);
@@ -1340,13 +1360,16 @@ void Parse_Mod_Item(TokenStream& lex, bool file_controls_dir, const ::std::strin
GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
// TODO: Mark as const and unsafe
+ meta_items.push_back( AST::MetaItem("#UNSAFE") );
+ meta_items.push_back( AST::MetaItem("#CONST") );
auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false);
mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items));
break; }
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- // - self not allowed, not prototype
// TODO: Mark as const
+ meta_items.push_back( AST::MetaItem("#CONST") );
+ // - self not allowed, not prototype
auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false);
mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items));
break; }
@@ -1403,8 +1426,9 @@ void Parse_Mod_Item(TokenStream& lex, bool file_controls_dir, const ::std::strin
// `unsafe fn`
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
- // - self not allowed, not prototype
// TODO: Mark as unsafe
+ meta_items.push_back( AST::MetaItem("#UNSAFE") );
+ // - self not allowed, not prototype
auto i = Parse_FunctionDefWithCode(lex, "rust", meta_items, false);
//i.set_unsafe();
mod.add_function(is_public, tok.str(), mv$(i), mv$(meta_items));