summaryrefslogtreecommitdiff
path: root/src/mir/from_hir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mir/from_hir.cpp')
-rw-r--r--src/mir/from_hir.cpp119
1 files changed, 85 insertions, 34 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 3787f4aa..b2858946 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -228,40 +228,39 @@ namespace {
}
auto& be = m_branches.as_Variant();
auto it = ::std::find_if( be.begin(), be.end(), [&](const auto& x){ return x.first >= e.idx; });
- // Not found? Insert a new branch
+ // If this variant isn't yet processed, add a new subtree for it
if( it == be.end() || it->first != e.idx ) {
it = be.insert(it, ::std::make_pair(e.idx, Branch( box$(DecisionTreeNode()) )));
- auto& subtree = *it->second.as_Subtree();
-
- if( e.sub_rules.size() > 0 && rule_count > 1 )
- {
- subtree.populate_tree_from_rule(sp, e.sub_rules.data(), e.sub_rules.size(), [&](auto& branch){
- ASSERT_BUG(sp, branch.is_Unset(), "Duplicate terminator");
- branch.as_Subtree()->populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then);
- });
- }
- else if( e.sub_rules.size() > 0)
- {
- subtree.populate_tree_from_rule(sp, e.sub_rules.data(), e.sub_rules.size(), and_then);
- }
- else if( rule_count > 1 )
- {
- subtree.populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then);
- }
- else
- {
- and_then(it->second);
- }
+ assert( it->second.is_Subtree() );
}
else {
- assert( !it->second.is_Unset() );
- TU_IFLET(Branch, it->second, Subtree, subtree_ptr,
- assert(subtree_ptr);
- subtree_ptr->populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then);
- )
- else {
+ if( it->second.is_Terminal() ) {
BUG(sp, "Duplicate terminal rule - " << it->second.as_Terminal());
}
+ assert( !it->second.is_Unset() );
+ assert( it->second.is_Subtree() );
+ }
+ auto& subtree = *it->second.as_Subtree();
+
+ if( e.sub_rules.size() > 0 && rule_count > 1 )
+ {
+ subtree.populate_tree_from_rule(sp, e.sub_rules.data(), e.sub_rules.size(), [&](auto& branch){
+ ASSERT_BUG(sp, branch.is_Unset(), "Duplicate terminator");
+ branch = Branch( box$(DecisionTreeNode()) );
+ branch.as_Subtree()->populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then);
+ });
+ }
+ else if( e.sub_rules.size() > 0)
+ {
+ subtree.populate_tree_from_rule(sp, e.sub_rules.data(), e.sub_rules.size(), and_then);
+ }
+ else if( rule_count > 1 )
+ {
+ subtree.populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then);
+ }
+ else
+ {
+ and_then(it->second);
}
}),
(Value,
@@ -551,7 +550,6 @@ namespace {
}
this->visit_node_ptr(node.m_nodes.back());
- //auto ret = m_builder.get_result(node.m_nodes.back()->span());
auto bd = mv$( m_block_stack.back() );
m_block_stack.pop_back();
@@ -565,11 +563,11 @@ namespace {
}
}
- //m_builder.set_result(node.span(), mv$(ret));
+ // Result maintained from last node
}
else
{
- TODO(node.span(), "Lower empty blocks");
+ m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({}));
}
}
void visit(::HIR::ExprNode_Return& node) override
@@ -989,6 +987,7 @@ namespace {
),
(Enum,
const auto& enum_path = e.path.m_data.as_Generic();
+ ASSERT_BUG(sp, node.m_branches.is_Variant(), "Tree for enum isn't a Variant - node="<<node);
const auto& branches = node.m_branches.as_Variant();
const auto& variants = pbe->m_variants;
auto variant_count = pbe->m_variants.size();
@@ -1162,13 +1161,65 @@ namespace {
if( node.m_op != ::HIR::ExprNode_Assign::Op::None )
{
- // TODO: What about += on primitives?
- ASSERT_BUG(sp, node.m_op == ::HIR::ExprNode_Assign::Op::None, "Operator overload assignments should already be eliminated");
+ ASSERT_BUG(sp, node.m_slot->m_res_type == node.m_value->m_res_type, "Types must match for op-assign");
+
+ TU_IFLET(::HIR::TypeRef::Data, node.m_slot->m_res_type.m_data, Primitive, e,
+ switch(e)
+ {
+ case ::HIR::CoreType::Char:
+ case ::HIR::CoreType::Str:
+ case ::HIR::CoreType::Bool:
+ BUG(sp, "Unsupported type for op-assign - " << node.m_slot->m_res_type);
+ break;
+ default:
+ // Good.
+ break;
+ }
+ )
+ else {
+ BUG(sp, "Unsupported type for op-assign - " << node.m_slot->m_res_type);
+ }
+
+ auto val_lv = m_builder.lvalue_or_temp( node.m_value->m_res_type, mv$(val) );
+
+ ::MIR::RValue res;
+ #define _(v) ::HIR::ExprNode_Assign::Op::v
+ ::MIR::eBinOp op;
+ switch(node.m_op)
+ {
+ case _(None): throw "";
+ case _(Add): op = ::MIR::eBinOp::ADD; if(0)
+ case _(Sub): op = ::MIR::eBinOp::SUB; if(0)
+ case _(Mul): op = ::MIR::eBinOp::MUL; if(0)
+ case _(Div): op = ::MIR::eBinOp::DIV; if(0)
+ ;
+ // TODO: Overflow check
+ res = ::MIR::RValue::make_BinOp({ dst.clone(), op, mv$(val_lv) });
+ break;
+ case _(Mod):
+ res = ::MIR::RValue::make_BinOp({ dst.clone(), ::MIR::eBinOp::MOD, mv$(val_lv) });
+ break;
+ case _(Xor): op = ::MIR::eBinOp::BIT_XOR; if(0)
+ case _(Or ): op = ::MIR::eBinOp::BIT_OR ; if(0)
+ case _(And): op = ::MIR::eBinOp::BIT_AND; if(0)
+ ;
+ res = ::MIR::RValue::make_BinOp({ dst.clone(), op, mv$(val_lv) });
+ break;
+ case _(Shl): op = ::MIR::eBinOp::BIT_SHL; if(0)
+ case _(Shr): op = ::MIR::eBinOp::BIT_SHR; if(0)
+ ;
+ // TODO: Overflow check
+ res = ::MIR::RValue::make_BinOp({ dst.clone(), op, mv$(val_lv) });
+ break;
+ }
+
+ m_builder.push_stmt_assign(mv$(dst), mv$(res));
}
else
{
m_builder.push_stmt_assign(mv$(dst), mv$(val));
}
+ m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({}));
}
void visit(::HIR::ExprNode_BinOp& node) override
@@ -1616,7 +1667,7 @@ namespace {
{}
// NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
- void visit_expr(::HIR::ExprPtr& exp) {
+ void visit_expr(::HIR::ExprPtr& exp) override {
BUG(Span(), "visit_expr hit in OuterVisitor");
}