summaryrefslogtreecommitdiff
path: root/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast')
-rw-r--r--src/ast/ast.cpp11
-rw-r--r--src/ast/attrs.hpp4
-rw-r--r--src/ast/expr.cpp162
-rw-r--r--src/ast/expr.hpp10
-rw-r--r--src/ast/macro.hpp7
-rw-r--r--src/ast/path.cpp7
-rw-r--r--src/ast/path.hpp1
-rw-r--r--src/ast/pattern.cpp73
-rw-r--r--src/ast/pattern.hpp7
-rw-r--r--src/ast/types.cpp6
-rw-r--r--src/ast/types.hpp2
11 files changed, 256 insertions, 34 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index 2521a878..802bde37 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -22,6 +22,9 @@ namespace {
}
}
+MetaItems::~MetaItems()
+{
+}
MetaItems MetaItems::clone() const
{
return MetaItems( m_span, clone_mivec(m_items) );
@@ -45,7 +48,9 @@ SERIALISE_TYPE_A(MetaItems::, "AST_MetaItems", {
s.item(m_items);
})
-
+MetaItem::~MetaItem()
+{
+}
MetaItem MetaItem::clone() const
{
TU_MATCH(MetaItemData, (m_data), (e),
@@ -183,6 +188,10 @@ SERIALISE_TYPE_A(UseStmt::, "AST_UseStmt", {
})
+MacroInvocation MacroInvocation::clone() const
+{
+ return MacroInvocation(m_span, m_attrs.clone(), m_macro_name, m_ident, m_input.clone());
+}
SERIALISE_TYPE_A(MacroInvocation::, "AST_MacroInvocation", {
s.item(m_attrs);
s.item(m_macro_name);
diff --git a/src/ast/attrs.hpp b/src/ast/attrs.hpp
index a2b82c40..fbe63be4 100644
--- a/src/ast/attrs.hpp
+++ b/src/ast/attrs.hpp
@@ -14,6 +14,7 @@ public:
Span m_span;
::std::vector<MetaItem> m_items;
+ virtual ~MetaItems();
MetaItems() {}
MetaItems(MetaItems&&) = default;
MetaItems& operator=(MetaItems&&) = default;
@@ -57,7 +58,10 @@ class MetaItem:
::std::string m_name;
MetaItemData m_data;
public:
+ virtual ~MetaItem();
MetaItem() {}
+ MetaItem(MetaItem&& ) = default;
+ MetaItem& operator=(MetaItem&& ) = default;
MetaItem(::std::string name):
m_name(name),
m_data( MetaItemData::make_None({}) )
diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp
index 675c26b8..42010868 100644
--- a/src/ast/expr.cpp
+++ b/src/ast/expr.cpp
@@ -89,11 +89,20 @@ SERIALISE_TYPE(Expr::, "Expr", {
ExprNode::~ExprNode() {
}
-#define NODE(class, serialise, _print)\
- void class::visit(NodeVisitor& nv) { nv.visit(*this); } \
- /*void class::visit(NodeVisitor& nv) const { nv.visit(*this); }*/ \
- void class::print(::std::ostream& os) const _print \
- SERIALISE_TYPE_S(class, serialise) \
+#define NODE(class, serialise, _print, _clone)\
+ void class::visit(NodeVisitor& nv) { nv.visit(*this); } \
+ void class::print(::std::ostream& os) const _print \
+ ::std::unique_ptr<ExprNode> class::clone() const _clone \
+ SERIALISE_TYPE_S(class, serialise)
+#define OPT_CLONE(node) (node.get() ? node->clone() : ::AST::ExprNodeP())
+
+namespace {
+ static inline ExprNodeP mk_exprnodep(const Position& pos, AST::ExprNode* en) {
+ en->set_pos(pos);
+ return ExprNodeP(en);
+ }
+ #define NEWNODE(type, ...) mk_exprnodep(get_pos(), new type(__VA_ARGS__))
+}
NODE(ExprNode_Block, {
s.item(m_nodes);
@@ -102,6 +111,13 @@ NODE(ExprNode_Block, {
for(const auto& n : m_nodes)
os << *n << ";";
os << "}";
+},{
+ ::std::vector<ExprNodeP> nodes;
+ for(const auto& n : m_nodes)
+ nodes.push_back( n->clone() );
+ if( m_local_mod )
+ TODO(get_pos(), "Handle cloning ExprNode_Block with a module");
+ return NEWNODE(ExprNode_Block, mv$(nodes), nullptr);
})
NODE(ExprNode_Macro, {
@@ -115,6 +131,8 @@ NODE(ExprNode_Macro, {
os << " " << m_ident << " ";
}
os << "(" << ")";
+},{
+ return NEWNODE(ExprNode_Macro, m_name, m_ident, m_tokens.clone());
})
void operator%(::Serialiser& s, const ExprNode_Flow::Type t) {
@@ -151,6 +169,8 @@ NODE(ExprNode_Flow, {
case CONTINUE: os << "continue"; break;
}
os << " " << *m_value;
+},{
+ return NEWNODE(ExprNode_Flow, m_type, m_target, m_value->clone());
})
@@ -160,6 +180,8 @@ NODE(ExprNode_LetBinding, {
s.item(m_value);
},{
os << "let " << m_pat << ": " << m_type << " = " << *m_value;
+},{
+ return NEWNODE(ExprNode_LetBinding, m_pat.clone(), TypeRef(m_type), OPT_CLONE(m_value));
})
NODE(ExprNode_Assign, {
@@ -167,6 +189,8 @@ NODE(ExprNode_Assign, {
s.item(m_value);
},{
os << *m_slot << " = " << *m_value;
+},{
+ return NEWNODE(ExprNode_Assign, m_op, m_slot->clone(), m_value->clone());
})
NODE(ExprNode_CallPath, {
@@ -178,6 +202,12 @@ NODE(ExprNode_CallPath, {
os << *a << ",";
}
os << ")";
+},{
+ ::std::vector<ExprNodeP> args;
+ for(const auto& a : m_args) {
+ args.push_back( a->clone() );
+ }
+ return NEWNODE(ExprNode_CallPath, AST::Path(m_path), mv$(args));
})
NODE(ExprNode_CallMethod, {
@@ -190,6 +220,12 @@ NODE(ExprNode_CallMethod, {
os << *a << ",";
}
os << ")";
+},{
+ ::std::vector<ExprNodeP> args;
+ for(const auto& a : m_args) {
+ args.push_back( a->clone() );
+ }
+ return NEWNODE(ExprNode_CallMethod, m_val->clone(), m_method, mv$(args));
})
NODE(ExprNode_CallObject, {
@@ -201,6 +237,12 @@ NODE(ExprNode_CallObject, {
os << *a << ",";
}
os << ")";
+},{
+ ::std::vector<ExprNodeP> args;
+ for(const auto& a : m_args) {
+ args.push_back( a->clone() );
+ }
+ return NEWNODE(ExprNode_CallObject, m_val->clone(), mv$(args));
})
void operator%(::Serialiser& s, const ExprNode_Loop::Type t) {
@@ -235,6 +277,8 @@ NODE(ExprNode_Loop, {
s.item(m_code);
},{
os << "LOOP [" << m_label << "] " << m_pattern << " in/= " << *m_cond << " " << *m_code;
+},{
+ return NEWNODE(ExprNode_Loop, m_label, m_type, m_pattern.clone(), OPT_CLONE(m_cond), m_code->clone());
})
SERIALISE_TYPE_A(ExprNode_Match_Arm::, "ExprNode_Match_Arm", {
@@ -256,6 +300,17 @@ NODE(ExprNode_Match, {
os << " => " << *arm.m_code << ",";
}
os << "}";
+},{
+ ::std::vector< ExprNode_Match_Arm> arms;
+ for(const auto& arm : m_arms) {
+ ::std::vector< AST::Pattern> patterns;
+ for( const auto& pat : arm.m_patterns ) {
+ patterns.push_back( pat.clone() );
+ }
+ arms.push_back( ExprNode_Match_Arm( mv$(patterns), OPT_CLONE(arm.m_cond), arm.m_code->clone() ) );
+ arms.back().m_attrs = arm.m_attrs.clone();
+ }
+ return NEWNODE(ExprNode_Match, m_val->clone(), mv$(arms));
})
NODE(ExprNode_If, {
@@ -264,6 +319,8 @@ NODE(ExprNode_If, {
s.item(m_false);
},{
os << "if " << *m_cond << " { " << *m_true << " } else { " << *m_false << " }";
+},{
+ return NEWNODE(ExprNode_If, m_cond->clone(), m_true->clone(), OPT_CLONE(m_false));
})
NODE(ExprNode_IfLet, {
s.item(m_pattern);
@@ -272,6 +329,8 @@ NODE(ExprNode_IfLet, {
s.item(m_false);
},{
os << "if let " << m_pattern << " = (" << *m_value << ") { " << *m_true << " } else { " << *m_false << " }";
+},{
+ return NEWNODE(ExprNode_IfLet, m_pattern.clone(), m_value->clone(), m_true->clone(), OPT_CLONE(m_false));
})
NODE(ExprNode_Integer, {
@@ -279,22 +338,30 @@ NODE(ExprNode_Integer, {
s.item(m_value);
},{
os << m_value;
+},{
+ return NEWNODE(ExprNode_Integer, m_value, m_datatype);
})
NODE(ExprNode_Float, {
s % m_datatype;
s.item(m_value);
},{
os << m_value;
+},{
+ return NEWNODE(ExprNode_Float, m_value, m_datatype);
})
NODE(ExprNode_Bool, {
s.item(m_value);
},{
os << m_value;
+},{
+ return NEWNODE(ExprNode_Bool, m_value);
})
NODE(ExprNode_String, {
s.item(m_value);
},{
os << "\"" << m_value << "\"";
+},{
+ return NEWNODE(ExprNode_String, m_value);
})
NODE(ExprNode_Closure, {
@@ -303,6 +370,12 @@ NODE(ExprNode_Closure, {
s.item(m_code);
},{
os << "/* todo: closure */";
+},{
+ ExprNode_Closure::args_t args;
+ for(const auto& a : m_args) {
+ args.push_back( ::std::make_pair(a.first.clone(), TypeRef(a.second)) );
+ }
+ return NEWNODE(ExprNode_Closure, mv$(args), TypeRef(m_return), m_code->clone());
});
NODE(ExprNode_StructLiteral, {
@@ -311,6 +384,14 @@ NODE(ExprNode_StructLiteral, {
s.item(m_values);
},{
os << "/* todo: sl */";
+},{
+ ExprNode_StructLiteral::t_values vals;
+
+ for(const auto& v : m_values) {
+ vals.push_back( ::std::make_pair(v.first, v.second->clone()) );
+ }
+
+ return NEWNODE(ExprNode_StructLiteral, AST::Path(m_path), OPT_CLONE(m_base_value), mv$(vals) );
})
NODE(ExprNode_Array, {
@@ -324,6 +405,18 @@ NODE(ExprNode_Array, {
for(const auto& a : m_values)
os << *a << ",";
os << "]";
+},{
+ if( m_size.get() )
+ {
+ return NEWNODE(ExprNode_Array, m_values[0]->clone(), m_size->clone());
+ }
+ else
+ {
+ ::std::vector<ExprNodeP> nodes;
+ for(const auto& n : m_values)
+ nodes.push_back( n->clone() );
+ return NEWNODE(ExprNode_Array, mv$(nodes));
+ }
})
NODE(ExprNode_Tuple, {
@@ -334,12 +427,19 @@ NODE(ExprNode_Tuple, {
os << *a << ",";
}
os << ")";
+},{
+ ::std::vector<ExprNodeP> nodes;
+ for(const auto& n : m_values)
+ nodes.push_back( n->clone() );
+ return NEWNODE(ExprNode_Tuple, mv$(nodes));
})
NODE(ExprNode_NamedValue, {
s.item(m_path);
},{
os << m_path;
+},{
+ return NEWNODE(ExprNode_NamedValue, AST::Path(m_path));
})
NODE(ExprNode_Field, {
@@ -347,6 +447,8 @@ NODE(ExprNode_Field, {
s.item(m_name);
},{
os << "(" << *m_obj << ")." << m_name;
+},{
+ return NEWNODE(ExprNode_Field, m_obj->clone(), m_name);
})
NODE(ExprNode_Index, {
@@ -354,12 +456,16 @@ NODE(ExprNode_Index, {
s.item(m_idx);
},{
os << "(" << *m_obj << ")[" << *m_idx << "]";
+},{
+ return NEWNODE(ExprNode_Index, m_obj->clone(), m_idx->clone());
})
NODE(ExprNode_Deref, {
s.item(m_value);
},{
os << "*(" << *m_value << ")";
+},{
+ return NEWNODE(ExprNode_Deref, m_value->clone());
});
NODE(ExprNode_Cast, {
@@ -367,9 +473,11 @@ NODE(ExprNode_Cast, {
s.item(m_type);
},{
os << "(" << *m_value << " as " << m_type << ")";
+},{
+ return NEWNODE(ExprNode_Cast, m_value->clone(), TypeRef(m_type));
})
-void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) {
+void operator%(::Serialiser& s, const ExprNode_BinOp::Type& t) {
switch(t)
{
#define _(v) case ExprNode_BinOp::v: s << #v; return
@@ -388,11 +496,11 @@ void operator%(::Serialiser& s, const ExprNode_BinOp::Type t) {
_(BITXOR);
_(SHL);
_(SHR);
- _(MULTIPLY);
- _(DIVIDE);
- _(MODULO);
- _(ADD);
- _(SUB);
+ _(MULTIPLY);
+ _(DIVIDE);
+ _(MODULO);
+ _(ADD);
+ _(SUB);
_(PLACE_IN);
#undef _
}
@@ -417,11 +525,11 @@ void operator%(::Deserialiser& s, ExprNode_BinOp::Type& t) {
_(BITXOR);
_(SHL);
_(SHR);
- _(MULTIPLY);
- _(DIVIDE);
- _(MODULO);
- _(ADD);
- _(SUB);
+ _(MULTIPLY);
+ _(DIVIDE);
+ _(MODULO);
+ _(ADD);
+ _(SUB);
#undef _
else
throw ::std::runtime_error("");
@@ -447,16 +555,18 @@ NODE(ExprNode_BinOp, {
case BITXOR: os << "^"; break;
case SHR: os << ">>"; break;
case SHL: os << "<<"; break;
- case MULTIPLY: os << "*"; break;
- case DIVIDE: os << "/"; break;
- case MODULO: os << "%"; break;
- case ADD: os << "+"; break;
- case SUB: os << "-"; break;
- case RANGE: os << ".."; break;
- case RANGE_INC: os << "..."; break;
+ case MULTIPLY: os << "*"; break;
+ case DIVIDE: os << "/"; break;
+ case MODULO: os << "%"; break;
+ 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 << ")";
+},{
+ return NEWNODE(ExprNode_BinOp, m_type, OPT_CLONE(m_left), OPT_CLONE(m_right));
})
void operator%(::Serialiser& s, const ExprNode_UniOp::Type t) {
@@ -501,12 +611,14 @@ NODE(ExprNode_UniOp, {
case QMARK: os << "(" << *m_value << "?)"; return;
}
os << *m_value << ")";
+},{
+ return NEWNODE(ExprNode_UniOp, m_type, m_value->clone());
})
#define NV(type, actions)\
- void NodeVisitorDef::visit(type& node) { DEBUG("DEF - "#type); actions }
-// void NodeVisitorDef::visit(const type& node) { DEBUG("DEF - "#type" (const)"); actions }
+ void NodeVisitorDef::visit(type& node) { DEBUG("DEF - "#type); actions }
+// void NodeVisitorDef::visit(const type& node) { DEBUG("DEF - "#type" (const)"); actions }
NV(ExprNode_Block, {
INDENT();
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp
index 95f74505..eab6f260 100644
--- a/src/ast/expr.hpp
+++ b/src/ast/expr.hpp
@@ -28,8 +28,8 @@ public:
virtual ~ExprNode() = 0;
virtual void visit(NodeVisitor& nv) = 0;
- //virtual void visit(NodeVisitor& nv) const = 0;
virtual void print(::std::ostream& os) const = 0;
+ virtual ::std::unique_ptr<ExprNode> clone() const = 0;
void set_pos(Position p) { m_pos = ::std::move(p); }
const Position& get_pos() const { return m_pos; }
@@ -46,10 +46,10 @@ public:
};
#define NODE_METHODS() \
- virtual void visit(NodeVisitor& nv) override;\
- virtual void print(::std::ostream& os) const override; \
- SERIALISABLE_PROTOTYPES();/* \
- virtual void visit(NodeVisitor& nv) const override;*/
+ void visit(NodeVisitor& nv) override;\
+ void print(::std::ostream& os) const override; \
+ ::std::unique_ptr<ExprNode> clone() const override; \
+ SERIALISABLE_PROTOTYPES();
struct ExprNode_Block:
public ExprNode
diff --git a/src/ast/macro.hpp b/src/ast/macro.hpp
index 85f2dea2..5cd53e1f 100644
--- a/src/ast/macro.hpp
+++ b/src/ast/macro.hpp
@@ -18,6 +18,11 @@ class MacroInvocation:
::std::string m_ident;
TokenTree m_input;
public:
+ MacroInvocation(MacroInvocation&&) = default;
+ MacroInvocation& operator=(MacroInvocation&&) = default;
+ MacroInvocation(const MacroInvocation&) = delete;
+ MacroInvocation& operator=(const MacroInvocation&) = delete;
+
MacroInvocation()
{
}
@@ -30,6 +35,8 @@ public:
m_input( mv$(input) )
{
}
+
+ MacroInvocation clone() const;
static ::std::unique_ptr<MacroInvocation> from_deserialiser(Deserialiser& s) {
auto i = new MacroInvocation;
diff --git a/src/ast/path.cpp b/src/ast/path.cpp
index 1a1d3cc9..be8b5887 100644
--- a/src/ast/path.cpp
+++ b/src/ast/path.cpp
@@ -54,8 +54,8 @@ PathBinding PathBinding::clone() const
// --- AST::PathNode
PathNode::PathNode(::std::string name, ::std::vector<TypeRef> args):
- m_name(name),
- m_params(args)
+ m_name( mv$(name) ),
+ m_params( mv$(args) )
{
}
Ordering PathNode::ord(const PathNode& x) const
@@ -101,6 +101,9 @@ typename ::std::vector<Named<T> >::const_iterator find_named(const ::std::vector
}
// --- AST::Path
+AST::Path::~Path()
+{
+}
AST::Path::Path(TagUfcs, TypeRef type, ::std::vector<AST::PathNode> nodes):
m_class( AST::Path::Class::make_UFCS({box$(type), nullptr, nodes}) )
{
diff --git a/src/ast/path.hpp b/src/ast/path.hpp
index 7eb17aab..4029f655 100644
--- a/src/ast/path.hpp
+++ b/src/ast/path.hpp
@@ -140,6 +140,7 @@ public:
private:
PathBinding m_binding;
public:
+ virtual ~Path();
// INVALID
Path():
m_class()
diff --git a/src/ast/pattern.cpp b/src/ast/pattern.cpp
index c3373206..80665008 100644
--- a/src/ast/pattern.cpp
+++ b/src/ast/pattern.cpp
@@ -163,6 +163,79 @@ void operator%(::Deserialiser& s, Pattern::Data::Tag& c) {
s.item(n);
c = Pattern::Data::tag_from_str(n);
}
+
+Pattern::~Pattern()
+{
+}
+
+AST::Pattern AST::Pattern::clone() const
+{
+ AST::Pattern rv;
+ rv.m_span = m_span;
+ rv.m_binding = m_binding;
+ rv.m_binding_mut = m_binding_mut;
+
+ struct H {
+ static ::std::unique_ptr<Pattern> clone_sp(const ::std::unique_ptr<Pattern>& p) {
+ return ::std::make_unique<Pattern>( p->clone() );
+ }
+ static ::std::vector<Pattern> clone_list(const ::std::vector<Pattern>& list) {
+ ::std::vector<Pattern> rv;
+ rv.reserve(list.size());
+ for(const auto& p : list)
+ rv.push_back( p.clone() );
+ return rv;
+ }
+ static AST::Pattern::Value clone_val(const AST::Pattern::Value& v) {
+ TU_MATCH(::AST::Pattern::Value, (v), (e),
+ (Invalid, return Value(e);),
+ (Integer, return Value(e);),
+ (String, return Value(e);),
+ (Named, return Value::make_Named( AST::Path(e) );)
+ )
+ throw "";
+ }
+ };
+
+ TU_MATCH(Pattern::Data, (m_data), (e),
+ (Any,
+ rv.m_data = Data::make_Any(e);
+ ),
+ (MaybeBind,
+ rv.m_data = Data::make_MaybeBind(e);
+ ),
+ (Macro,
+ rv.m_data = Data::make_Macro({ ::std::make_unique<AST::MacroInvocation>( e.inv->clone() ) });
+ ),
+ (Box,
+ rv.m_data = Data::make_Box({ H::clone_sp(e.sub) });
+ ),
+ (Ref,
+ rv.m_data = Data::make_Ref({ e.mut, H::clone_sp(e.sub) });
+ ),
+ (Value,
+ rv.m_data = Data::make_Value({ H::clone_val(e.start), H::clone_val(e.end) });
+ ),
+ (Tuple,
+ rv.m_data = Data::make_Tuple({ H::clone_list(e.sub_patterns) });
+ ),
+ (StructTuple,
+ rv.m_data = Data::make_StructTuple({ ::AST::Path(e.path), H::clone_list(e.sub_patterns) });
+ ),
+ (Struct,
+ ::std::vector< ::std::pair< ::std::string, Pattern> > sps;
+ for(const auto& sp : e.sub_patterns)
+ sps.push_back( ::std::make_pair(sp.first, sp.second.clone()) );
+ rv.m_data = Data::make_Struct({ ::AST::Path(e.path), mv$(sps) });
+ ),
+ (Slice,
+ rv.m_data = Data::make_Slice({ H::clone_list(e.leading), e.extra_bind, H::clone_list(e.trailing) });
+ )
+ )
+
+ return rv;
+}
+
#define _D(VAR, ...) case Pattern::Data::TAG_##VAR: { m_data = Pattern::Data::make_##VAR({}); auto& ent = m_data.as_##VAR(); (void)&ent; __VA_ARGS__ } break;
SERIALISE_TYPE(Pattern::, "Pattern", {
s.item(m_binding);
diff --git a/src/ast/pattern.hpp b/src/ast/pattern.hpp
index 468bf306..a901ac89 100644
--- a/src/ast/pattern.hpp
+++ b/src/ast/pattern.hpp
@@ -52,8 +52,12 @@ private:
Data m_data;
public:
+ virtual ~Pattern();
+
Pattern()
{}
+ Pattern(Pattern&&) = default;
+ Pattern& operator=(Pattern&&) = default;
struct TagMaybeBind {};
Pattern(TagMaybeBind, ::std::string name):
@@ -128,6 +132,9 @@ public:
const Span& span() const { return m_span; }
void set_span(Span sp) { m_span = mv$(sp); }
+
+ Pattern clone() const;
+
// Accessors
const ::std::string& binding() const { return m_binding; }
const BindType& binding_type() const { assert(m_binding != ""); return m_binding_type; }
diff --git a/src/ast/types.cpp b/src/ast/types.cpp
index 8a3ee638..8cc9b4ea 100644
--- a/src/ast/types.cpp
+++ b/src/ast/types.cpp
@@ -98,11 +98,15 @@ Ordering Type_Function::ord(const Type_Function& x) const
return (*m_rettype).ord( *x.m_rettype );
}
+TypeRef::~TypeRef()
+{
+}
+
TypeRef::TypeRef(const TypeRef& other)
{
switch( other.m_data.tag() )
{
- case TypeData::TAGDEAD: throw "";
+ case TypeData::TAGDEAD: assert(!"Copying a destructed type");
#define _COPY(VAR) case TypeData::TAG_##VAR: m_data = TypeData::make_##VAR(other.m_data.as_##VAR()); break;
#define _CLONE(VAR, code...) case TypeData::TAG_##VAR: { auto& old = other.m_data.as_##VAR(); m_data = TypeData::make_##VAR(code); } break;
_COPY(None)
diff --git a/src/ast/types.hpp b/src/ast/types.hpp
index 72080723..a79a811d 100644
--- a/src/ast/types.hpp
+++ b/src/ast/types.hpp
@@ -108,6 +108,8 @@ class TypeRef:
public:
TypeData m_data;
+ virtual ~TypeRef();
+
TypeRef(TypeRef&& other) noexcept:
m_data( mv$(other.m_data) )
{