summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp6
-rw-r--r--src/ast/ast.hpp41
-rw-r--r--src/ast/expr.cpp18
-rw-r--r--src/ast/expr.hpp14
-rw-r--r--src/ast/path.cpp2
-rw-r--r--src/ast/path.hpp5
-rw-r--r--src/convert/ast_iterate.cpp7
-rw-r--r--src/convert/ast_iterate.hpp3
-rw-r--r--src/convert/typecheck_expr.cpp43
-rw-r--r--src/dump_as_rust.cpp21
-rw-r--r--src/include/serialise.hpp2
-rw-r--r--src/include/serialiser_texttree.hpp2
-rw-r--r--src/parse/common.hpp2
-rw-r--r--src/parse/expr.cpp36
-rw-r--r--src/parse/root.cpp125
-rw-r--r--src/serialise.cpp13
-rw-r--r--src/types.hpp9
17 files changed, 286 insertions, 63 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 870d4eff..3eb646e5 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -531,6 +531,12 @@ SERIALISE_TYPE(Trait::, "AST_Trait", {
s.item(m_functions);
})
+SERIALISE_TYPE_A(EnumVariant::, "AST_EnumVariant", {
+ s.item(m_name);
+ s.item(m_sub_types);
+ s.item(m_value);
+})
+
SERIALISE_TYPE(Enum::, "AST_Enum", {
s << m_params;
s << m_variants;
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 8928aa97..b38e9953 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -282,6 +282,7 @@ public:
CLASS_REFMETHOD,
CLASS_MUTMETHOD,
CLASS_VALMETHOD,
+ CLASS_MUTVALMETHOD,
};
typedef ::std::vector< ::std::pair<AST::Pattern,TypeRef> > Arglist;
@@ -296,15 +297,15 @@ public:
Function():
m_fcn_class(CLASS_UNBOUND)
{}
- Function(TypeParams params, Class fcn_class, TypeRef ret_type, Arglist args, Expr code):
+ Function(TypeParams params, Class fcn_class, TypeRef ret_type, Arglist args):
m_fcn_class(fcn_class),
m_params(params),
- m_code( ::std::move(code) ),
m_rettype( move(ret_type) ),
m_args( move(args) )
{
}
+ void set_code(Expr code) { m_code = ::std::move(code); }
void set_self_lifetime(::std::string s) { m_lifetime = s; }
const Class fcn_class() const { return m_fcn_class; }
@@ -353,23 +354,51 @@ public:
SERIALISABLE_PROTOTYPES();
};
+struct EnumVariant:
+ public Serialisable
+{
+ ::std::string m_name;
+ ::std::vector<TypeRef> m_sub_types;
+ int64_t m_value;
+
+ EnumVariant():
+ m_value(0)
+ {
+ }
+
+ EnumVariant(::std::string name, int64_t value):
+ m_name( ::std::move(name) ),
+ m_value( value )
+ {
+ }
+
+ EnumVariant(::std::string name, ::std::vector<TypeRef> sub_types):
+ m_name( ::std::move(name) ),
+ m_sub_types( ::std::move(sub_types) ),
+ m_value(0)
+ {
+ }
+
+ SERIALISABLE_PROTOTYPES();
+};
+
class Enum:
public Serialisable
{
TypeParams m_params;
- ::std::vector<StructItem> m_variants;
+ ::std::vector<EnumVariant> m_variants;
public:
Enum() {}
- Enum( TypeParams params, ::std::vector<StructItem> variants ):
+ Enum( TypeParams params, ::std::vector<EnumVariant> variants ):
m_params( move(params) ),
m_variants( move(variants) )
{}
const TypeParams& params() const { return m_params; }
- const ::std::vector<StructItem>& variants() const { return m_variants; }
+ const ::std::vector<EnumVariant>& variants() const { return m_variants; }
TypeParams& params() { return m_params; }
- ::std::vector<StructItem>& variants() { return m_variants; }
+ ::std::vector<EnumVariant>& variants() { return m_variants; }
SERIALISABLE_PROTOTYPES();
};
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
index 1f5eb377..59fe2162 100644
--- a/src/ast/expr.cpp
+++ b/src/ast/expr.cpp
@@ -1,6 +1,7 @@
/*
*/
#include "expr.hpp"
+#include "ast.hpp"
namespace AST {
@@ -55,6 +56,7 @@ SERIALISE_TYPE(Expr::, "Expr", {
else _(ExprNode_Flow)
else _(ExprNode_Const)
else _(ExprNode_Import)
+ else _(ExprNode_Extern)
else _(ExprNode_LetBinding)
else _(ExprNode_Assign)
else _(ExprNode_CallPath)
@@ -154,12 +156,25 @@ NODE(ExprNode_Const, {
os << "const " << m_name << ": " << m_type << " = " << *m_value;
})
+
+ExprNode_Extern::ExprNode_Extern()
+{}
+ExprNode_Extern::ExprNode_Extern(ExprNode_Extern::imports_t imports):
+ m_imports( ::std::move(imports) )
+{}
+
NODE(ExprNode_Import, {
s.item(m_imports);
},{
os << "/* todo: use /*";
})
+NODE(ExprNode_Extern, {
+ s.item(m_imports);
+},{
+ os << "/* todo: export /*";
+})
+
NODE(ExprNode_LetBinding, {
s.item(m_pat);
s.item(m_type);
@@ -442,6 +457,7 @@ NODE(ExprNode_BinOp, {
case MODULO: os << "%"; break;
case ADD: os << "+"; break;
case SUB: os << "-"; break;
+ case RANGE: os << ".."; break;
}
os << " " << *m_right << ")";
})
@@ -482,6 +498,7 @@ NODE(ExprNode_UniOp, {
case INVERT: os << "(!"; break;
case BOX: os << "(box "; break;
case REF: os << "(&"; break;
+ case REFMUT: os << "(&mut "; break;
}
os << *m_value << ")";
})
@@ -510,6 +527,7 @@ NV(ExprNode_Const,
visit(node.m_value);
})
NV(ExprNode_Import, {})
+NV(ExprNode_Extern, {})
NV(ExprNode_LetBinding,
{
// TODO: Handle recurse into Let pattern
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp
index 21f67c2f..e84e3df6 100644
--- a/src/ast/expr.hpp
+++ b/src/ast/expr.hpp
@@ -128,6 +128,18 @@ struct ExprNode_Import:
NODE_METHODS();
};
+struct ExprNode_Extern:
+ public ExprNode
+{
+ typedef ::std::vector< ::std::pair< ::std::string, AST::Function> > imports_t;
+ imports_t m_imports;
+
+ ExprNode_Extern();
+ ExprNode_Extern(imports_t imports);
+ // - Non-local because AST::Function
+
+ NODE_METHODS();
+};
struct ExprNode_LetBinding:
public ExprNode
{
@@ -583,6 +595,7 @@ public:
NT(ExprNode_Flow);
NT(ExprNode_Const);
NT(ExprNode_Import);
+ NT(ExprNode_Extern);
NT(ExprNode_LetBinding);
NT(ExprNode_Assign);
NT(ExprNode_CallPath);
@@ -626,6 +639,7 @@ public:
NT(ExprNode_Flow);
NT(ExprNode_Const);
NT(ExprNode_Import);
+ NT(ExprNode_Extern);
NT(ExprNode_LetBinding);
NT(ExprNode_Assign);
NT(ExprNode_CallPath);
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index 103ca1b2..4f83ae34 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -267,7 +267,7 @@ void Path::bind_enum_var(const Enum& ent, const ::std::string& name, const ::std
unsigned int idx = 0;
for( idx = 0; idx < ent.variants().size(); idx ++ )
{
- if( ent.variants()[idx].name == name ) {
+ if( ent.variants()[idx].m_name == name ) {
break;
}
}
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index 4ff128c6..51dd70f5 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -105,6 +105,11 @@ public:
m_class(LOCAL),
m_nodes({PathNode(name, {})})
{}
+ struct TagSuper {};
+ Path(TagSuper):
+ m_class(RELATIVE),
+ m_nodes({PathNode("super", {})})
+ {}
Path(::std::initializer_list<PathNode> l):
m_class(ABSOLUTE),
diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp
index 68c84a31..e53e1ba8 100644
--- a/src/convert/ast_iterate.cpp
+++ b/src/convert/ast_iterate.cpp
@@ -156,7 +156,7 @@ void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint)
}
void CASTIterator::handle_pattern_enum(
::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args,
- const AST::TypeParams& enum_params, const AST::StructItem& var,
+ const AST::TypeParams& enum_params, const AST::EnumVariant& var,
::std::vector<AST::Pattern>& sub_patterns
)
{
@@ -278,7 +278,10 @@ void CASTIterator::handle_enum(AST::Path path, AST::Enum& enm)
start_scope();
handle_params( enm.params() );
for( auto& f : enm.variants() )
- handle_type( f.data );
+ {
+ for( auto& t : f.m_sub_types )
+ handle_type(t);
+ }
end_scope();
}
void CASTIterator::handle_trait(AST::Path path, AST::Trait& trait)
diff --git a/src/convert/ast_iterate.hpp b/src/convert/ast_iterate.hpp
index 979831a5..78f6b271 100644
--- a/src/convert/ast_iterate.hpp
+++ b/src/convert/ast_iterate.hpp
@@ -11,6 +11,7 @@ class ExprNode;
class Pattern;
class TypeParams;
class Impl;
+class EnumVariant;
template<typename T> struct Item;
};
@@ -39,7 +40,7 @@ public:
virtual void handle_pattern(AST::Pattern& pat, const TypeRef& type_hint);
virtual void handle_pattern_enum(
::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args,
- const AST::TypeParams& enum_params, const AST::Item<TypeRef>& var,
+ const AST::TypeParams& enum_params, const AST::EnumVariant& var,
::std::vector<AST::Pattern>& sub_patterns
);
diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp
index 6d88b1dd..a6a69186 100644
--- a/src/convert/typecheck_expr.cpp
+++ b/src/convert/typecheck_expr.cpp
@@ -40,7 +40,7 @@ public:
virtual void handle_pattern_enum(
::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args,
- const AST::TypeParams& enum_params, const AST::StructItem& var,
+ const AST::TypeParams& enum_params, const AST::EnumVariant& var,
::std::vector<AST::Pattern>& sub_patterns
) override;
@@ -57,7 +57,7 @@ private:
void check_enum_variant(
::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes,
- const AST::TypeParams& params, const AST::StructItem& var
+ const AST::TypeParams& params, const AST::EnumVariant& var
);
void iterate_traits(::std::function<bool(const TypeRef& trait)> fcn);
};
@@ -128,15 +128,14 @@ void CTypeChecker::handle_params(AST::TypeParams& params)
}
void CTypeChecker::handle_pattern_enum(
::std::vector<TypeRef>& pat_args, const ::std::vector<TypeRef>& hint_args,
- const AST::TypeParams& enum_params, const AST::StructItem& var,
+ const AST::TypeParams& enum_params, const AST::EnumVariant& var,
::std::vector<AST::Pattern>& sub_patterns
)
{
check_enum_variant(pat_args, hint_args, enum_params, var);
// Ensure that sub_patterns is the same length as the variant
- assert(var.data.is_tuple());
- const auto& var_types = var.data.sub_types();
+ const auto& var_types = var.m_sub_types;
if( sub_patterns.size() != var_types.size() )
throw ::std::runtime_error(FMT("Enum pattern size mismatch"));
for( unsigned int i = 0; i < sub_patterns.size(); i ++ )
@@ -217,6 +216,9 @@ void CTypeChecker::handle_function(AST::Path path, AST::Function& fcn)
local_variable(false, "self", TypeRef(TypeRef::TagReference(), true, get_local_type("Self")));
break;
case AST::Function::CLASS_VALMETHOD:
+ local_variable(false, "self", TypeRef(get_local_type("Self")));
+ break;
+ case AST::Function::CLASS_MUTVALMETHOD:
local_variable(true, "self", TypeRef(get_local_type("Self")));
break;
}
@@ -251,7 +253,7 @@ void CTypeChecker::iterate_traits(::std::function<bool(const TypeRef& trait)> fc
}
}
-void CTypeChecker::check_enum_variant(::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes, const AST::TypeParams& params, const AST::StructItem& var)
+void CTypeChecker::check_enum_variant(::std::vector<TypeRef>& path_args, const ::std::vector<TypeRef>& argtypes, const AST::TypeParams& params, const AST::EnumVariant& var)
{
// We know the enum, but it might have type params, need to handle that case
if( params.n_params() > 0 )
@@ -263,18 +265,21 @@ void CTypeChecker::check_enum_variant(::std::vector<TypeRef>& path_args, const :
// 2. Create a pattern from the argument types and the format of the variant
DEBUG("argtypes = [" << argtypes << "]");
::std::vector<TypeRef> item_args(params.n_params());
- DEBUG("variant type = " << var.data << "");
- var.data.match_args(
- TypeRef(TypeRef::TagTuple(), argtypes),
- [&](const char *name, const TypeRef& t) {
- DEBUG("Binding " << name << " to type " << t);
- int idx = params.find_name(name);
- if( idx == -1 ) {
- throw ::std::runtime_error(FMT("Can't find generic " << name));
+ DEBUG("variant type = " << var.m_sub_types << "");
+ for( unsigned int i = 0; i < var.m_sub_types.size(); i ++ )
+ {
+ var.m_sub_types[i].match_args(
+ TypeRef(TypeRef::TagTuple(), argtypes),
+ [&](const char *name, const TypeRef& t) {
+ DEBUG("Binding " << name << " to type " << t);
+ int idx = params.find_name(name);
+ if( idx == -1 ) {
+ throw ::std::runtime_error(FMT("Can't find generic " << name));
+ }
+ item_args.at(idx).merge_with( t );
}
- item_args.at(idx).merge_with( t );
- }
- );
+ );
+ }
DEBUG("item_args = [" << item_args << "]");
// 3. Merge the two sets of arguments
for( unsigned int i = 0; i < path_args.size(); i ++ )
@@ -303,8 +308,8 @@ void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node)
auto idx = p.bound_idx();
// Enum variant:
// - Check that this variant takes no arguments
- if( !enm.variants()[idx].data.is_unit() )
- throw ::std::runtime_error( FMT("Used a non-unit variant as a raw value - " << enm.variants()[idx].data));
+ if( enm.variants()[idx].m_sub_types.size() > 0 )
+ throw ::std::runtime_error( FMT("Used a non-unit variant as a raw value - " << enm.variants()[idx].m_sub_types));
// - Set output type to the enum (wildcard params, not default)
AST::Path tp = p;
tp.nodes().pop_back();
diff --git a/src/dump_as_rust.cpp b/src/dump_as_rust.cpp
index d8d5ad13..f76f5942 100644
--- a/src/dump_as_rust.cpp
+++ b/src/dump_as_rust.cpp
@@ -80,6 +80,11 @@ public:
for( const auto& item : n.m_imports )
m_os << "use " << item.second << " as " << item.first << ";\n" << indent();
}
+ virtual void visit(AST::ExprNode_Extern& n) override {
+ m_expr_root = false;
+ for( const auto& item : n.m_imports )
+ m_os << "extern \"\" fn " << item.first /*<< item.second*/ << ";\n" << indent();
+ }
virtual void visit(AST::ExprNode_LetBinding& n) override {
m_expr_root = false;
m_os << "let ";
@@ -423,6 +428,7 @@ public:
case AST::ExprNode_BinOp::MODULO: m_os << "%"; break;
case AST::ExprNode_BinOp::ADD: m_os << "+"; break;
case AST::ExprNode_BinOp::SUB: m_os << "-"; break;
+ case AST::ExprNode_BinOp::RANGE: m_os << ".."; break;
}
m_os << " ";
if( IS(*n.m_right, AST::ExprNode_BinOp) )
@@ -438,7 +444,7 @@ public:
case AST::ExprNode_UniOp::INVERT: m_os << "!"; break;
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::REFMUT: m_os << "&mut "; break;
}
if( IS(*n.m_value, AST::ExprNode_BinOp) )
@@ -718,9 +724,16 @@ void RustPrinter::handle_enum(const AST::Enum& s)
inc_indent();
for( const auto& i : s.variants() )
{
- m_os << indent() << i.name;
- if( i.data.sub_types().size() )
- m_os << i.data.print_pretty();
+ m_os << indent() << i.m_name;
+ if( i.m_sub_types.size() )
+ {
+ for( const auto& t : i.m_sub_types )
+ m_os << t.print_pretty() << ", ";
+ }
+ else
+ {
+ m_os << " = " << i.m_value;
+ }
m_os << ",\n";
}
dec_indent();
diff --git a/src/include/serialise.hpp b/src/include/serialise.hpp
index e70ec113..07812899 100644
--- a/src/include/serialise.hpp
+++ b/src/include/serialise.hpp
@@ -44,6 +44,7 @@ public:
virtual Serialiser& operator<<(bool val) = 0;
virtual Serialiser& operator<<(uint64_t val) = 0;
+ virtual Serialiser& operator<<(int64_t val) = 0;
virtual Serialiser& operator<<(double val) = 0;
virtual Serialiser& operator<<(const char* s) = 0;
Serialiser& operator<<(const ::std::string& s) {
@@ -106,6 +107,7 @@ protected:
public:
virtual void item(bool& b) = 0;
virtual void item(uint64_t& v) = 0;
+ virtual void item(int64_t& val) = 0;
virtual void item(double& v) = 0;
virtual void item(::std::string& s) = 0;
diff --git a/src/include/serialiser_texttree.hpp b/src/include/serialiser_texttree.hpp
index 890be31a..bdad7d7a 100644
--- a/src/include/serialiser_texttree.hpp
+++ b/src/include/serialiser_texttree.hpp
@@ -19,6 +19,7 @@ public:
virtual Serialiser& operator<<(bool val) override;
virtual Serialiser& operator<<(uint64_t val) override;
+ virtual Serialiser& operator<<(int64_t val) override;
virtual Serialiser& operator<<(double val) override;
virtual Serialiser& operator<<(const char* s) override;
@@ -54,6 +55,7 @@ protected:
public:
virtual void item(bool& b) override;
virtual void item(uint64_t& v) override;
+ virtual void item(int64_t& v) override;
virtual void item(double& v) override;
virtual void item(::std::string& s) override;
diff --git a/src/parse/common.hpp b/src/parse/common.hpp
index 4af48174..da7d767d 100644
--- a/src/parse/common.hpp
+++ b/src/parse/common.hpp
@@ -1,6 +1,7 @@
#ifndef PARSE_COMMON_HPP_INCLUDED
#define PARSE_COMMON_HPP_INCLUDED
#include <iostream>
+#include "../ast/ast.hpp"
#define GET_TOK(tok, lex) ((tok = lex.getToken()).type())
#define LOOK_AHEAD(lex) (lex.lookahead(0))
@@ -28,6 +29,7 @@ extern AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMo
extern ::std::vector<TypeRef> Parse_Path_GenericList(TokenStream& lex);
extern TypeRef Parse_Type(TokenStream& lex);
extern void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)> fcn);
+extern AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self, bool can_be_prototype);
extern AST::Expr Parse_Expr(TokenStream& lex, bool const_only);
extern AST::Expr Parse_ExprBlock(TokenStream& lex);
diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp
index a8a16c7d..eadd8e56 100644
--- a/src/parse/expr.cpp
+++ b/src/parse/expr.cpp
@@ -255,6 +255,42 @@ ExprNodeP Parse_Stmt(TokenStream& lex, bool& opt_semicolon)
});
return NEWNODE( AST::ExprNode_Import, ::std::move(imports) );
}
+ // 'extern' blocks
+ case TOK_RWORD_EXTERN: {
+ opt_semicolon = true;
+ // - default ABI is "C"
+ ::std::string abi = "C";
+ if( GET_TOK(tok, lex) == TOK_STRING ) {
+ abi = tok.str();
+ }
+ else
+ lex.putback(tok);
+
+ ::std::vector< ::std::pair< ::std::string, AST::Function> > imports;
+ bool is_block = false;
+ if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
+ is_block = true;
+ else
+ lex.putback(tok);
+
+ do {
+ ::std::string name;
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_RWORD_FN:
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = tok.str();
+ imports.push_back( ::std::make_pair( ::std::move(name), Parse_FunctionDef(lex, abi, AST::MetaItems(), false, true) ) );
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+ break;
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+ } while( is_block && LOOK_AHEAD(lex) != TOK_BRACE_CLOSE );
+ if( is_block )
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
+ return NEWNODE( AST::ExprNode_Extern, ::std::move(imports) );
+ }
case TOK_RWORD_CONST: {
opt_semicolon = false;
GET_CHECK_TOK(tok, lex, TOK_IDENT);
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 0e22b117..f84b11f6 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -167,7 +167,7 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::string abi);
TypeRef Parse_Type(TokenStream& lex)
{
- TRACE_FUNCTION;
+ //TRACE_FUNCTION;
Token tok;
@@ -417,7 +417,7 @@ void Parse_WhereClause(TokenStream& lex, AST::TypeParams& params)
return ::std::make_pair( ::std::move(pat), ::std::move(type) );
}
-/// Parse a function definition (after the 'fn')
+/// Parse a function definition (after the 'fn <name>')
AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self, bool can_be_prototype)
{
TRACE_FUNCTION;
@@ -483,6 +483,17 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt
lex.putback(tok); // un-eat the '&'
}
}
+ else if( tok.type() == TOK_RWORD_MUT )
+ {
+ if( LOOK_AHEAD(lex) == TOK_RWORD_SELF )
+ {
+ GET_TOK(tok, lex);
+ if( allow_self == false )
+ throw ParseError::Generic(lex, "Self binding not expected");
+ fcn_class = AST::Function::CLASS_MUTVALMETHOD;
+ GET_TOK(tok, lex);
+ }
+ }
else if( tok.type() == TOK_RWORD_SELF )
{
// By-value method
@@ -541,23 +552,19 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt
else {
lex.putback(tok);
}
-
- AST::Expr code;
- if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
- {
- lex.putback(tok);
- code = Parse_ExprBlock(lex);
- }
- else
- {
- CHECK_TOK(tok, TOK_SEMICOLON);
- if( !can_be_prototype )
- {
- throw ParseError::Generic("Expected code for function");
- }
- }
- return AST::Function(params, fcn_class, ret_type, args, code);
+ return AST::Function(params, fcn_class, ret_type, args);
+}
+
+AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self)
+{
+ TRACE_FUNCTION;
+ Token tok;
+ auto ret = Parse_FunctionDef(lex, abi, ::std::move(attrs), allow_self, false);
+ GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
+ lex.putback(tok);
+ ret.set_code( Parse_ExprBlock(lex) );
+ return ret;
}
AST::TypeAlias Parse_TypeAlias(TokenStream& lex, const AST::MetaItems meta_items)
@@ -709,7 +716,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
GET_TOK(tok, lex);
}
-
+ ::std::string abi = "rust";
switch(tok.type())
{
case TOK_RWORD_STATIC: {
@@ -739,15 +746,41 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
CHECK_TOK(tok, TOK_SEMICOLON);
trait.add_type( ::std::move(name), ::std::move(default_type) );
break; }
+
// Functions (possibly unsafe)
case TOK_RWORD_UNSAFE:
item_attrs.push_back( AST::MetaItem("#UNSAFE") );
- GET_CHECK_TOK(tok, lex, TOK_RWORD_FN);
+ if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN )
+ case TOK_RWORD_EXTERN:
+ {
+ abi = "C";
+ if( GET_TOK(tok, lex) == TOK_STRING )
+ abi = tok.str();
+ else
+ lex.putback(tok);
+
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_RWORD_FN);
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
// Self allowed, prototype-form allowed (optional names and no code)
- trait.add_function( ::std::move(name), Parse_FunctionDef(lex, "rust", item_attrs, true, true) );
+ auto fcn = Parse_FunctionDef(lex, abi, item_attrs, true, true);
+ if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
+ {
+ lex.putback(tok);
+ fcn.set_code( Parse_ExprBlock(lex) );
+ }
+ else if( tok.type() == TOK_SEMICOLON )
+ {
+ // Accept it
+ }
+ else
+ {
+ throw ParseError::Unexpected(lex, tok);
+ }
+ trait.add_function( ::std::move(name), ::std::move(fcn) );
break; }
default:
throw ParseError::Unexpected(lex, tok);
@@ -780,27 +813,46 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems meta_items)
// Body
CHECK_TOK(tok, TOK_BRACE_OPEN);
- ::std::vector<AST::StructItem> variants;
+ ::std::vector<AST::EnumVariant> variants;
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
{
+ AST::MetaItems item_attrs;
+ while( tok.type() == TOK_ATTR_OPEN )
+ {
+ item_attrs.push_back( Parse_MetaItem(lex) );
+ GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE);
+ GET_TOK(tok, lex);
+ }
+
CHECK_TOK(tok, TOK_IDENT);
::std::string name = tok.str();
if( GET_TOK(tok, lex) == TOK_PAREN_OPEN )
{
::std::vector<TypeRef> types;
// Get type list
- // TODO: Handle 'Variant()'?
do
{
types.push_back( Parse_Type(lex) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_PAREN_CLOSE);
GET_TOK(tok, lex);
- variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagTuple(), ::std::move(types)), true) );
+ variants.push_back( AST::EnumVariant(::std::move(name), ::std::move(types)) );
+ }
+ else if( tok.type() == TOK_EQUAL )
+ {
+ bool is_neg = false;
+ if( GET_TOK(tok, lex) == TOK_DASH )
+ is_neg = true;
+ else
+ lex.putback(tok);
+ GET_CHECK_TOK(tok, lex, TOK_INTEGER);
+ int64_t val = (is_neg ? -tok.intval() : tok.intval());
+ variants.push_back( AST::EnumVariant(::std::move(name), val) );
+ GET_TOK(tok, lex);
}
else
{
- variants.push_back( AST::StructItem(::std::move(name), TypeRef(TypeRef::TagUnit()), true) );
+ variants.push_back( AST::EnumVariant(::std::move(name), ::std::vector<TypeRef>()) );
}
if( tok.type() != TOK_COMMA )
@@ -928,6 +980,7 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe=false)
GET_TOK(tok, lex);
}
+ ::std::string abi = "rust";
switch(tok.type())
{
case TOK_RWORD_TYPE: {
@@ -937,11 +990,22 @@ AST::Impl Parse_Impl(TokenStream& lex, bool is_unsafe=false)
impl.add_type(is_public, name, Parse_Type(lex));
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break; }
+ case TOK_RWORD_EXTERN:
+ {
+ abi = "C";
+ if( GET_TOK(tok, lex) == TOK_STRING )
+ abi = tok.str();
+ else
+ lex.putback(tok);
+
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_RWORD_FN);
case TOK_RWORD_FN: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
// - Self allowed, can't be prototype-form
- impl.add_function(is_public, name, Parse_FunctionDef(lex, "rust", item_attrs, true, false));
+ impl.add_function(is_public, ::std::move(name), Parse_FunctionDefWithCode(lex, abi, ::std::move(item_attrs), true));
break; }
default:
@@ -979,6 +1043,7 @@ void Parse_ExternBlock(TokenStream& lex, AST::Module& mod, ::std::string abi)
// parse function as prototype
// - no self
mod.add_function(is_public, tok.str(), Parse_FunctionDef(lex, abi, ::std::move(meta_items), false, true));
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break;
default:
throw ParseError::Unexpected(lex, tok);
@@ -1004,7 +1069,7 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::Path, ::std::string)>
path = AST::Path( ); // relative path
break;
case TOK_RWORD_SUPER:
- throw ParseError::Todo(lex, "Parse_Use - super");
+ path = AST::Path( AST::Path::TagSuper() );
break;
case TOK_IDENT:
path.append( AST::PathNode(tok.str(), {}) );
@@ -1302,7 +1367,7 @@ void Parse_MacroRules(TokenStream& lex, AST::Module& mod, AST::MetaItems& meta_i
void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod, LList<AST::Module*>& modstack, const ::std::string& path)
{
- TRACE_FUNCTION;
+ //TRACE_FUNCTION;
const bool nested_module = (path == "-"); // 'mod name { code }', as opposed to 'mod name;'
Token tok;
@@ -1473,7 +1538,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod,
case TOK_RWORD_FN:
GET_CHECK_TOK(tok, lex, TOK_IDENT);
// - self not allowed, not prototype
- mod.add_function(is_public, tok.str(), Parse_FunctionDef(lex, "rust", ::std::move(meta_items), false, false));
+ mod.add_function(is_public, tok.str(), Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false));
break;
case TOK_RWORD_TRAIT: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
@@ -1492,7 +1557,7 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Crate& crate, AST::Module& mod,
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
// - self not allowed, not prototype
- mod.add_function(is_public, name, Parse_FunctionDef(lex, "rust", ::std::move(meta_items), false, false));
+ mod.add_function(is_public, name, Parse_FunctionDefWithCode(lex, "rust", ::std::move(meta_items), false));
break; }
case TOK_RWORD_TYPE: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
diff --git a/src/serialise.cpp b/src/serialise.cpp
index 55555c7c..72a6dc50 100644
--- a/src/serialise.cpp
+++ b/src/serialise.cpp
@@ -80,6 +80,12 @@ Serialiser& Serialiser_TextTree::operator<<(uint64_t val)
m_os << val << "\n";
return *this;
}
+Serialiser& Serialiser_TextTree::operator<<(int64_t val)
+{
+ print_indent();
+ m_os << val << "\n";
+ return *this;
+}
Serialiser& Serialiser_TextTree::operator<<(double val)
{
print_indent();
@@ -195,6 +201,13 @@ void Deserialiser_TextTree::item(uint64_t& v)
if( !m_is.good() )
throw ::std::runtime_error("TODO: Less shit exception, item(uint64_t)");
}
+void Deserialiser_TextTree::item(int64_t& v)
+{
+ eat_ws();
+ m_is >> v;
+ if( !m_is.good() )
+ throw ::std::runtime_error("TODO: Less shit exception, item(int64_t)");
+}
void Deserialiser_TextTree::item(double& v)
{
eat_ws();
diff --git a/src/types.hpp b/src/types.hpp
index adc28f6f..9505f2cd 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -201,4 +201,13 @@ public:
SERIALISABLE_PROTOTYPES();
};
+class Type_Function:
+ public Serialisable
+{
+ bool is_unsafe;
+ ::std::string m_abi;
+ TypeRef m_rettype;
+ ::std::vector<TypeRef> m_arg_types;
+};
+
#endif // TYPES_HPP_INCLUDED