diff options
author | John Hodge <tpg@mutabah.net> | 2016-05-15 21:39:25 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-05-15 21:39:25 +0800 |
commit | 2ef7be5dc9f455e5dd9d8753aa34e2bb5db7f587 (patch) | |
tree | c2fca4958681af9aec6536864aacf8dc59386cf3 | |
parent | 0eab78b913d79d4a5f3ddc015f1b5dc5fd21266f (diff) | |
download | mrust-2ef7be5dc9f455e5dd9d8753aa34e2bb5db7f587.tar.gz |
HIR - Expression conversion progressing
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | src/ast/expr.hpp | 2 | ||||
-rw-r--r-- | src/hir/expr.cpp | 26 | ||||
-rw-r--r-- | src/hir/expr.hpp | 218 | ||||
-rw-r--r-- | src/hir/expr_ptr.cpp | 17 | ||||
-rw-r--r-- | src/hir/expr_ptr.hpp | 8 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 8 | ||||
-rw-r--r-- | src/hir/from_ast.hpp | 9 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 237 | ||||
-rw-r--r-- | src/hir/hir.hpp | 4 | ||||
-rw-r--r-- | src/hir/pattern.hpp | 11 |
11 files changed, 526 insertions, 18 deletions
@@ -36,8 +36,8 @@ OBJ += expand/derive.o expand/lang_item.o OBJ += expand/std_prelude.o OBJ += resolve/use.o resolve/index.o resolve/absolute.o OBJ += hir/from_ast.o hir/from_ast_expr.o -OBJ += hir/crate_ptr.o hir/type_ptr.o -OBJ += hir/type.o hir/path.o +OBJ += hir/crate_ptr.o hir/type_ptr.o hir/expr_ptr.o +OBJ += hir/type.o hir/path.o hir/expr.o OBJ += dump_as_rust.o OBJ += convert/ast_iterate.o #OBJ += convert/decorators.o diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index 3bb849d5..00694962 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -573,6 +573,8 @@ struct ExprNode_UniOp: NODE_METHODS(); }; +#undef NODE_METHODS + class NodeVisitor { public: diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp new file mode 100644 index 00000000..724d1284 --- /dev/null +++ b/src/hir/expr.cpp @@ -0,0 +1,26 @@ +/* + */ +#include <hir/expr.hpp> + +::HIR::ExprNode::~ExprNode() +{ +} + +#define DEF_VISIT(nt) void ::HIR::nt::visit(ExprVisitor& nv) { nv.visit(*this); } + +DEF_VISIT(ExprNode_Block) +DEF_VISIT(ExprNode_Return) +DEF_VISIT(ExprNode_Let) +DEF_VISIT(ExprNode_Loop) +DEF_VISIT(ExprNode_LoopControl) +DEF_VISIT(ExprNode_Assign) +DEF_VISIT(ExprNode_BinOp) +DEF_VISIT(ExprNode_UniOp) +DEF_VISIT(ExprNode_Cast) + +DEF_VISIT(ExprNode_CallPath) + +DEF_VISIT(ExprNode_Literal) + +#undef DEF_VISIT + diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 634932a6..3d7abe1a 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -2,27 +2,233 @@ */ #pragma once +#include <memory> +#include <hir/pattern.hpp> +#include <hir/type.hpp> namespace HIR { -class Visitor; +class ExprVisitor; class ExprNode { public: - virtual void visit(Visitor& v) = 0; - virtual ~ExprNode() = 0; + virtual void visit(ExprVisitor& v) = 0; + virtual ~ExprNode(); }; -class ExprNode_Block: +typedef ::std::unique_ptr<ExprNode> ExprNodeP; + +#define NODE_METHODS() \ + virtual void visit(ExprVisitor& nv) override; + +struct ExprNode_Block: + public ExprNode +{ + bool m_is_unsafe; + ::std::vector< ExprNodeP > m_nodes; + + NODE_METHODS(); +}; +struct ExprNode_Return: + public ExprNode +{ + ::HIR::ExprNodeP m_value; + + ExprNode_Return(::HIR::ExprNodeP v): + m_value( mv$(m_value) ) + {} + + NODE_METHODS(); +}; +struct ExprNode_Loop: + public ExprNode +{ + ::std::string m_label; + ::HIR::ExprNodeP m_code; + + NODE_METHODS(); +}; +struct ExprNode_LoopControl: + public ExprNode +{ + ::std::string m_label; + bool m_continue; + //::HIR::ExprNodeP m_value; + + ExprNode_LoopControl(::std::string label, bool cont): + m_label( mv$(label) ), + m_continue( cont ) + {} + + NODE_METHODS(); +}; +struct ExprNode_Let: + public ExprNode +{ + ::HIR::Pattern m_pattern; + ::HIR::TypeRef m_type; + ::HIR::ExprNodeP m_value; + + ExprNode_Let(::HIR::Pattern pat, ::HIR::TypeRef ty, ::HIR::ExprNodeP val): + m_pattern( mv$(pat) ), + m_type( mv$(ty) ), + m_value( mv$(m_value) ) + {} + + NODE_METHODS(); +}; + +struct ExprNode_Assign: + public ExprNode +{ + enum class Op { + None, + Add, Sub, + Mul, Div, Mod, + And, Or , Xor, + Shr, Shl, + }; + + Op m_op; + ExprNodeP m_slot; + ExprNodeP m_value; + + ExprNode_Assign(Op op, ::HIR::ExprNodeP slot, ::HIR::ExprNodeP value): + m_op(op), + m_slot( mv$(slot) ), + m_value( mv$(value) ) + {} + + NODE_METHODS(); +}; +struct ExprNode_BinOp: public ExprNode { + enum class Op { + CmpEqu, + CmpNEqu, + CmpLt, + CmpLtE, + CmpGt, + CmpGtE, + + BoolAnd, + BoolOr, + + Add, Sub, + Mul, Div, Mod, + And, Or , Xor, + Shr, Shl, + }; + + Op m_op; + ::HIR::ExprNodeP m_left; + ::HIR::ExprNodeP m_right; + + ExprNode_BinOp() {} + ExprNode_BinOp(Op op, ::HIR::ExprNodeP left, ::HIR::ExprNodeP right): + m_op(op), + m_left( mv$(left) ), + m_right( mv$(right) ) + {} + + NODE_METHODS(); +}; +struct ExprNode_UniOp: + public ExprNode +{ + enum class Op { + Ref, // '& <expr>' + RefMut, // '&mut <expr>' + Invert, // '!<expr>' + Negate, // '-<expr>' + }; + + Op m_op; + ::HIR::ExprNodeP m_value; + + ExprNode_UniOp(Op op, ::HIR::ExprNodeP value): + m_op(op), + m_value( mv$(value) ) + {} + + NODE_METHODS(); +}; +struct ExprNode_Cast: + public ExprNode +{ + ::HIR::ExprNodeP m_value; + ::HIR::TypeRef m_type; + + ExprNode_Cast(::HIR::ExprNodeP value, ::HIR::TypeRef dst_type): + m_value( mv$(value) ), + m_type( mv$(dst_type) ) + {} + NODE_METHODS(); }; -class Visitor +struct ExprNode_CallPath: + public ExprNode +{ + ::HIR::Path m_path; + ::std::vector<ExprNodeP> m_args; + + ExprNode_CallPath(::HIR::Path path, ::std::vector< ::HIR::ExprNodeP> args): + m_path( mv$(path) ), + m_args( mv$(args) ) + {} + + NODE_METHODS(); +}; + +struct ExprNode_Literal: + public ExprNode +{ + TAGGED_UNION(Data, Integer, + (Integer, struct { + ::HIR::CoreType m_type; // if not an integer type, it's unknown + uint64_t m_value; + }), + (Float, struct { + ::HIR::CoreType m_type; // If not a float type, it's unknown + double m_value; + }), + (Boolean, bool), + (String, ::std::string), + (ByteString, ::std::vector<char>) + ); + + Data m_data; + + ExprNode_Literal(Data data): + m_data( mv$(data) ) + {} + + NODE_METHODS(); +}; + +#undef NODE_METHODS + +class ExprVisitor { public: - virtual void visit(ExprNode_Block& n) = 0; + #define NV(nt) virtual void visit(nt& n) = 0; + + NV(ExprNode_Block) + NV(ExprNode_Return) + NV(ExprNode_Let) + NV(ExprNode_Loop) + NV(ExprNode_LoopControl) + + NV(ExprNode_Assign) + NV(ExprNode_BinOp) + NV(ExprNode_UniOp) + NV(ExprNode_Cast) + + NV(ExprNode_CallPath); + + NV(ExprNode_Literal); }; } diff --git a/src/hir/expr_ptr.cpp b/src/hir/expr_ptr.cpp new file mode 100644 index 00000000..c8136097 --- /dev/null +++ b/src/hir/expr_ptr.cpp @@ -0,0 +1,17 @@ +/* + */ +#include <hir/expr_ptr.hpp> +#include <hir/expr.hpp> + +::HIR::ExprPtr::ExprPtr(): + node(nullptr) +{ +} +::HIR::ExprPtr::ExprPtr(::std::unique_ptr< ::HIR::ExprNode> v): + node( v.release() ) +{ +} +::HIR::ExprPtr::~ExprPtr() +{ + delete node; +} diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp index 2804136b..ba53b58f 100644 --- a/src/hir/expr_ptr.hpp +++ b/src/hir/expr_ptr.hpp @@ -1,7 +1,7 @@ /* */ #pragma once - +#include <memory> namespace HIR { @@ -13,6 +13,12 @@ class ExprPtr public: ExprPtr(); + ExprPtr(::std::unique_ptr< ::HIR::ExprNode> _); + ExprPtr(ExprPtr&& x): + node(x.node) + { + x.node = nullptr; + } ~ExprPtr(); }; diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index e93a3273..92ac3dc6 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -4,8 +4,7 @@ #include <main_bindings.hpp> #include <ast/ast.hpp> #include <ast/crate.hpp> - -extern ::HIR::ExprPtr LowerHIR_ExprNode(const ::AST::ExprNode& e); +#include "from_ast.hpp" ::HIR::Module LowerHIR_Module(const ::AST::Module& module, ::HIR::SimplePath path); @@ -39,6 +38,11 @@ extern ::HIR::ExprPtr LowerHIR_ExprNode(const ::AST::ExprNode& e); throw ::std::runtime_error("TODO: LowerHIR_GenericParams"); } +::HIR::Pattern LowerHIR_Pattern(const ::AST::Pattern& pat) +{ + throw ::std::runtime_error("TODO: LowerHIR_Pattern"); +} + ::HIR::ExprPtr LowerHIR_Expr(const ::std::shared_ptr< ::AST::ExprNode>& e) { if( e.get() ) { diff --git a/src/hir/from_ast.hpp b/src/hir/from_ast.hpp new file mode 100644 index 00000000..0dde55b0 --- /dev/null +++ b/src/hir/from_ast.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include <hir/expr_ptr.hpp> + +extern ::HIR::ExprPtr LowerHIR_ExprNode(const ::AST::ExprNode& e); +extern ::HIR::Path LowerHIR_Path(const ::AST::Path& path); +extern ::HIR::TypeRef LowerHIR_Type(const ::TypeRef& ty); +extern ::HIR::Pattern LowerHIR_Pattern(const ::AST::Pattern& pat); + diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index a5f29ce8..f0284f8a 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -4,16 +4,245 @@ #include <hir/expr.hpp> #include <ast/expr.hpp> #include <ast/ast.hpp> +#include "from_ast.hpp" +::std::unique_ptr< ::HIR::ExprNode> LowerHIR_ExprNode_Inner(const ::AST::ExprNode& e); +::std::unique_ptr< ::HIR::ExprNode> LowerHIR_ExprNode_Inner_Opt(const ::AST::ExprNode* e) { + if( e ) { + return LowerHIR_ExprNode_Inner(*e); + } + else { + return nullptr; + } +} -struct Visitor: +struct LowerHIR_ExprNode_Visitor: public ::AST::NodeVisitor { + ::std::unique_ptr< ::HIR::ExprNode> m_rv; + + virtual void visit(::AST::ExprNode_Block& v) override { + auto rv = new ::HIR::ExprNode_Block(); + for(const auto& n : v.m_nodes) + { + if( n ) { + rv->m_nodes.push_back( LowerHIR_ExprNode_Inner( *n ) ); + } + } + m_rv.reset( static_cast< ::HIR::ExprNode*>(rv) ); + } + virtual void visit(::AST::ExprNode_Macro& v) override { + BUG(v.get_pos(), "Hit ExprNode_Macro"); + } + virtual void visit(::AST::ExprNode_Flow& v) override { + switch( v.m_type ) + { + case ::AST::ExprNode_Flow::RETURN: + m_rv.reset( new ::HIR::ExprNode_Return( LowerHIR_ExprNode_Inner_Opt(v.m_value.get()) ) ); + break; + case ::AST::ExprNode_Flow::CONTINUE: + case ::AST::ExprNode_Flow::BREAK: + if( v.m_value ) + TODO(v.get_pos(), "Handle break/continue values in HIR"); + m_rv.reset( new ::HIR::ExprNode_LoopControl( v.m_target, (v.m_type == ::AST::ExprNode_Flow::CONTINUE) ) ); + break; + } + } + virtual void visit(::AST::ExprNode_LetBinding& v) override { + m_rv.reset( new ::HIR::ExprNode_Let( + LowerHIR_Pattern( v.m_pat ), + LowerHIR_Type( v.m_type ), + LowerHIR_ExprNode_Inner_Opt( v.m_value.get() ) + ) ); + } + virtual void visit(::AST::ExprNode_Assign& v) override { + struct H { + static ::HIR::ExprNode_Assign::Op get_op(::AST::ExprNode_Assign::Operation o) { + switch(o) + { + case ::AST::ExprNode_Assign::NONE: return ::HIR::ExprNode_Assign::Op::None; + case ::AST::ExprNode_Assign::ADD: return ::HIR::ExprNode_Assign::Op::Add; + case ::AST::ExprNode_Assign::SUB: return ::HIR::ExprNode_Assign::Op::Sub; + + case ::AST::ExprNode_Assign::DIV: return ::HIR::ExprNode_Assign::Op::Mul; + case ::AST::ExprNode_Assign::MUL: return ::HIR::ExprNode_Assign::Op::Div; + case ::AST::ExprNode_Assign::MOD: return ::HIR::ExprNode_Assign::Op::Mod; + + case ::AST::ExprNode_Assign::AND: return ::HIR::ExprNode_Assign::Op::And; + case ::AST::ExprNode_Assign::OR : return ::HIR::ExprNode_Assign::Op::Or ; + case ::AST::ExprNode_Assign::XOR: return ::HIR::ExprNode_Assign::Op::Xor; + + case ::AST::ExprNode_Assign::SHR: return ::HIR::ExprNode_Assign::Op::Shr; + case ::AST::ExprNode_Assign::SHL: return ::HIR::ExprNode_Assign::Op::Shl; + } + throw ""; + } + }; + m_rv.reset( new ::HIR::ExprNode_Assign( + H::get_op(v.m_op), + LowerHIR_ExprNode_Inner( *v.m_slot ), + LowerHIR_ExprNode_Inner( *v.m_value ) + ) ); + } + virtual void visit(::AST::ExprNode_BinOp& v) override { + ::HIR::ExprNode_BinOp::Op op; + switch(v.m_type) + { + case ::AST::ExprNode_BinOp::RANGE: + TODO(v.get_pos(), "Desugar range"); + break; + case ::AST::ExprNode_BinOp::RANGE_INC: + TODO(v.get_pos(), "Desugar range"); + break; + case ::AST::ExprNode_BinOp::PLACE_IN: + TODO(v.get_pos(), "Desugar placement syntax"); + break; + + case ::AST::ExprNode_BinOp::CMPEQU : op = ::HIR::ExprNode_BinOp::Op::CmpEqu ; if(0) + case ::AST::ExprNode_BinOp::CMPNEQU: op = ::HIR::ExprNode_BinOp::Op::CmpNEqu; if(0) + case ::AST::ExprNode_BinOp::CMPLT : op = ::HIR::ExprNode_BinOp::Op::CmpLt ; if(0) + case ::AST::ExprNode_BinOp::CMPLTE: op = ::HIR::ExprNode_BinOp::Op::CmpLtE; if(0) + case ::AST::ExprNode_BinOp::CMPGT : op = ::HIR::ExprNode_BinOp::Op::CmpGt ; if(0) + case ::AST::ExprNode_BinOp::CMPGTE: op = ::HIR::ExprNode_BinOp::Op::CmpGtE; if(0) + case ::AST::ExprNode_BinOp::BOOLAND: op = ::HIR::ExprNode_BinOp::Op::BoolAnd; if(0) + case ::AST::ExprNode_BinOp::BOOLOR : op = ::HIR::ExprNode_BinOp::Op::BoolOr ; if(0) + + case ::AST::ExprNode_BinOp::BITAND: op = ::HIR::ExprNode_BinOp::Op::And; if(0) + case ::AST::ExprNode_BinOp::BITOR : op = ::HIR::ExprNode_BinOp::Op::Or ; if(0) + case ::AST::ExprNode_BinOp::BITXOR: op = ::HIR::ExprNode_BinOp::Op::Xor; if(0) + case ::AST::ExprNode_BinOp::MULTIPLY: op = ::HIR::ExprNode_BinOp::Op::Mul; if(0) + case ::AST::ExprNode_BinOp::DIVIDE : op = ::HIR::ExprNode_BinOp::Op::Div; if(0) + case ::AST::ExprNode_BinOp::MODULO : op = ::HIR::ExprNode_BinOp::Op::Mod; if(0) + case ::AST::ExprNode_BinOp::ADD: op = ::HIR::ExprNode_BinOp::Op::Add; if(0) + case ::AST::ExprNode_BinOp::SUB: op = ::HIR::ExprNode_BinOp::Op::Sub; if(0) + case ::AST::ExprNode_BinOp::SHR: op = ::HIR::ExprNode_BinOp::Op::Shr; if(0) + case ::AST::ExprNode_BinOp::SHL: op = ::HIR::ExprNode_BinOp::Op::Shl; + + m_rv.reset( new ::HIR::ExprNode_BinOp( + op, + LowerHIR_ExprNode_Inner( *v.m_left ), + LowerHIR_ExprNode_Inner( *v.m_right ) + ) ); + break; + } + } + virtual void visit(::AST::ExprNode_UniOp& v) override { + ::HIR::ExprNode_UniOp::Op op; + switch(v.m_type) + { + case ::AST::ExprNode_UniOp::BOX: + TODO(v.get_pos(), "Desugar box"); + break; + case ::AST::ExprNode_UniOp::QMARK: + TODO(v.get_pos(), "Desugar question mark operator"); + break; + + case ::AST::ExprNode_UniOp::REF: op = ::HIR::ExprNode_UniOp::Op::Ref ; if(0) + case ::AST::ExprNode_UniOp::REFMUT: op = ::HIR::ExprNode_UniOp::Op::RefMut; if(0) + case ::AST::ExprNode_UniOp::INVERT: op = ::HIR::ExprNode_UniOp::Op::Invert; if(0) + case ::AST::ExprNode_UniOp::NEGATE: op = ::HIR::ExprNode_UniOp::Op::Negate; + m_rv.reset( new ::HIR::ExprNode_UniOp( + op, + LowerHIR_ExprNode_Inner( *v.m_value ) + ) ); + break; + } + } + virtual void visit(::AST::ExprNode_Cast & v) override { + m_rv.reset( new ::HIR::ExprNode_Cast( + LowerHIR_ExprNode_Inner( *v.m_value ), + LowerHIR_Type(v.m_type) + ) ); + } + + virtual void visit(::AST::ExprNode_CallPath& v) override { + ::std::vector< ::HIR::ExprNodeP> args; + for(const auto& arg : v.m_args) + args.push_back( LowerHIR_ExprNode_Inner(*arg) ); + m_rv.reset( new ::HIR::ExprNode_CallPath( + LowerHIR_Path(v.m_path), + mv$( args ) + ) ); + } + virtual void visit(::AST::ExprNode_CallMethod& v) override { + } + virtual void visit(::AST::ExprNode_CallObject& v) override { + } + virtual void visit(::AST::ExprNode_Loop& v) override { + } + virtual void visit(::AST::ExprNode_Match& v) override { + } + virtual void visit(::AST::ExprNode_If& v) override { + } + virtual void visit(::AST::ExprNode_IfLet& v) override { + } + + virtual void visit(::AST::ExprNode_Integer& v) override { + struct H { + static ::HIR::CoreType get_type(::eCoreType ct) { + switch(ct) + { + case CORETYPE_I8 : return ::HIR::CoreType::I8; + case CORETYPE_U8 : return ::HIR::CoreType::U8; + case CORETYPE_I16: return ::HIR::CoreType::I16; + case CORETYPE_U16: return ::HIR::CoreType::U16; + case CORETYPE_I32: return ::HIR::CoreType::I32; + case CORETYPE_U32: return ::HIR::CoreType::U32; + case CORETYPE_I64: return ::HIR::CoreType::I64; + case CORETYPE_U64: return ::HIR::CoreType::U64; + + case CORETYPE_INT: return ::HIR::CoreType::Isize; + case CORETYPE_UINT: return ::HIR::CoreType::Usize; + default: + return ::HIR::CoreType::Str; + } + } + }; + m_rv.reset( new ::HIR::ExprNode_Literal( + ::HIR::ExprNode_Literal::Data::make_Integer({ + H::get_type( v.m_datatype ), + v.m_value + }) + ) ); + } + virtual void visit(::AST::ExprNode_Float& v) override { + } + virtual void visit(::AST::ExprNode_Bool& v) override { + } + virtual void visit(::AST::ExprNode_String& v) override { + } + virtual void visit(::AST::ExprNode_Closure& v) override { + } + virtual void visit(::AST::ExprNode_StructLiteral& v) override { + } + virtual void visit(::AST::ExprNode_Array& v) override { + } + virtual void visit(::AST::ExprNode_Tuple& v) override { + } + virtual void visit(::AST::ExprNode_NamedValue& v) override { + } + + virtual void visit(::AST::ExprNode_Field& v) override { + } + virtual void visit(::AST::ExprNode_Index& v) override { + } + virtual void visit(::AST::ExprNode_Deref& v) override { + } }; +::std::unique_ptr< ::HIR::ExprNode> LowerHIR_ExprNode_Inner(const ::AST::ExprNode& e) +{ + LowerHIR_ExprNode_Visitor v; + + const_cast<::AST::ExprNode*>(&e)->visit( v ); + + if( ! v.m_rv ) { + BUG(e.get_pos(), typeid(e).name() << " - Yielded a nullptr HIR node"); + } + return mv$( v.m_rv ); +} + ::HIR::ExprPtr LowerHIR_ExprNode(const ::AST::ExprNode& e) { - //Visitor v; - //const_cast<::AST::ExprNode*>(&e)->visit( v ); - throw ::std::runtime_error("TODO: LowerHIR_ExprNode"); + return ::HIR::ExprPtr( LowerHIR_ExprNode_Inner(e) ); } diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index dba408bc..b55194e6 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -16,13 +16,11 @@ #include <hir/type.hpp> #include <hir/path.hpp> +#include <hir/pattern.hpp> #include <hir/expr_ptr.hpp> namespace HIR { -class Pattern { -}; - class Crate; class Module; diff --git a/src/hir/pattern.hpp b/src/hir/pattern.hpp new file mode 100644 index 00000000..4fa262ce --- /dev/null +++ b/src/hir/pattern.hpp @@ -0,0 +1,11 @@ +/* + */ +#pragma once + +namespace HIR { + +class Pattern { +}; + +} + |