From 88ae396cad97000c2894e6467af249a207cb27b2 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 3 Dec 2023 19:19:47 +0800 Subject: [PATCH] AST/HIR - Draft `const` blocks --- src/ast/dump.cpp | 9 ++++- src/ast/expr.cpp | 2 +- src/ast/expr.hpp | 13 ++++--- src/expand/derive.cpp | 2 +- src/expand/proc_macro.cpp | 10 +++++- src/hir/dump.cpp | 5 +++ src/hir/expr.cpp | 4 +++ src/hir/expr.hpp | 16 +++++++++ src/hir/from_ast_expr.cpp | 22 ++++++++++++ src/hir_expand/annotate_value_usage.cpp | 5 +++ src/hir_expand/lifetime_infer.cpp | 1 + src/hir_expand/static_borrow_constants.cpp | 5 +++ src/hir_typeck/expr_check.cpp | 6 ++++ src/hir_typeck/expr_cs.cpp | 6 ++++ src/hir_typeck/expr_cs__enum.cpp | 10 ++++++ src/mir/from_hir.cpp | 4 +++ src/parse/common.hpp | 3 +- src/parse/expr.cpp | 42 +++++++++++++++++----- 18 files changed, 147 insertions(+), 18 deletions(-) diff --git a/src/ast/dump.cpp b/src/ast/dump.cpp index 8682aff5..595ebf14 100644 --- a/src/ast/dump.cpp +++ b/src/ast/dump.cpp @@ -41,8 +41,15 @@ class RustPrinter: virtual bool is_const() const override { return true; } virtual void visit(AST::ExprNode_Block& n) override { - if( n.m_is_unsafe ) { + switch(n.m_block_type) { + case AST::ExprNode_Block::Type::Bare: + break; + case AST::ExprNode_Block::Type::Unsafe: m_os << "unsafe "; + break; + case AST::ExprNode_Block::Type::Const: + m_os << "const "; + break; } m_os << "{"; inc_indent(); diff --git a/src/ast/expr.cpp b/src/ast/expr.cpp index 66dfe64d..791d8e59 100644 --- a/src/ast/expr.cpp +++ b/src/ast/expr.cpp @@ -105,7 +105,7 @@ NODE(ExprNode_Block, { ::std::vector nodes; for(const auto& n : m_nodes) nodes.push_back( n->clone() ); - return NEWNODE(ExprNode_Block, m_is_unsafe, m_yields_final_value, mv$(nodes), m_local_mod); + return NEWNODE(ExprNode_Block, m_block_type, m_yields_final_value, mv$(nodes), m_local_mod); }) NODE(ExprNode_Try, { diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp index d576d881..545c2a9a 100644 --- a/src/ast/expr.hpp +++ b/src/ast/expr.hpp @@ -53,21 +53,26 @@ class ExprNode struct ExprNode_Block: public ExprNode { - bool m_is_unsafe; + enum class Type { + Bare, + Unsafe, + Const, + }; + Type m_block_type; bool m_yields_final_value; Ident m_label; ::std::shared_ptr m_local_mod; ::std::vector m_nodes; ExprNode_Block(::std::vector nodes={}): - m_is_unsafe(false), + m_block_type(Type::Bare), m_yields_final_value(true), m_label(""), m_local_mod(), m_nodes( mv$(nodes) ) {} - ExprNode_Block(bool is_unsafe, bool yields_final_value, ::std::vector nodes, ::std::shared_ptr local_mod): - m_is_unsafe(is_unsafe), + ExprNode_Block(Type type, bool yields_final_value, ::std::vector nodes, ::std::shared_ptr local_mod): + m_block_type(type), m_yields_final_value(yields_final_value), m_label(""), m_local_mod( move(local_mod) ), diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index 50493b24..1ec87df2 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -448,7 +448,7 @@ class Deriver_Debug: )); } nodes.push_back(NEWNODE(CallMethod, NEWNODE(NamedValue, AST::Path("s")), AST::PathNode("finish",{}), {})); - node = NEWNODE(Block, false, /*yields_final_value*/true, mv$(nodes), {}); + node = NEWNODE(Block, AST::ExprNode_Block::Type::Bare, /*yields_final_value*/true, mv$(nodes), {}); } TU_ARMA(Tuple, e) { node = NEWNODE(NamedValue, AST::Path("f")); diff --git a/src/expand/proc_macro.cpp b/src/expand/proc_macro.cpp index 331e47cc..36f8bc1b 100644 --- a/src/expand/proc_macro.cpp +++ b/src/expand/proc_macro.cpp @@ -931,8 +931,16 @@ namespace { // === Expressions ==== void visit(::AST::ExprNode_Block& node) { - if( node.m_is_unsafe ) + switch(node.m_block_type) { + case AST::ExprNode_Block::Type::Bare: + break; + case AST::ExprNode_Block::Type::Unsafe: m_pmi.send_ident("unsafe"); + break; + case AST::ExprNode_Block::Type::Const: + m_pmi.send_ident("const"); + break; + } m_pmi.send_symbol("{"); TODO(sp, ""); m_pmi.send_symbol("}"); diff --git a/src/hir/dump.cpp b/src/hir/dump.cpp index e95072d3..3326a7b3 100644 --- a/src/hir/dump.cpp +++ b/src/hir/dump.cpp @@ -364,6 +364,11 @@ namespace { dec_indent(); m_os << indent() << "}"; } + void visit(::HIR::ExprNode_ConstBlock& node) override + { + m_os << "const "; + node.m_inner->visit(*this); + } void visit(::HIR::ExprNode_Asm& node) override { diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp index 2c7af8bc..2c4e0c00 100644 --- a/src/hir/expr.cpp +++ b/src/hir/expr.cpp @@ -39,6 +39,10 @@ DEF_VISIT_H(ExprNode_Block, node) { if( node.m_value_node ) visit_node_ptr(node.m_value_node); } +DEF_VISIT_H(ExprNode_ConstBlock, node) { + TRACE_FUNCTION_F("_ConstBlock"); + visit_node_ptr(node.m_inner); +} DEF_VISIT_H(ExprNode_Asm, node) { TRACE_FUNCTION_F("_Asm"); for(auto& v : node.m_outputs) diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 3c12c73a..e2c119a8 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -92,6 +92,18 @@ struct ExprNode_Block: NODE_METHODS(); }; +struct ExprNode_ConstBlock: + public ExprNode +{ + ExprNodeP m_inner; + + ExprNode_ConstBlock(Span sp, ExprNodeP inner) + : ExprNode(mv$(sp)) + , m_inner(mv$(inner)) + {} + + NODE_METHODS(); +}; struct ExprNode_Asm: public ExprNode { @@ -929,6 +941,8 @@ class ExprVisitor #define NV(nt) virtual void visit(nt& n) = 0; NV(ExprNode_Block) + NV(ExprNode_ConstBlock) + //NV(ExprNode_AsyncBlock) NV(ExprNode_Asm) NV(ExprNode_Asm2) NV(ExprNode_Return) @@ -982,6 +996,8 @@ class ExprVisitorDef: virtual void visit_node_ptr(::std::unique_ptr& node_ptr) override; NV(ExprNode_Block) + NV(ExprNode_ConstBlock) + //NV(ExprNode_AsyncBlock) NV(ExprNode_Asm) NV(ExprNode_Asm2) NV(ExprNode_Return) diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index 6c63809b..6ff66ed6 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -55,6 +55,17 @@ struct LowerHIR_ExprNode_Visitor: rv->m_local_mod = ::HIR::SimplePath(g_crate_name, v.m_local_mod->path().nodes); } + switch(v.m_block_type) + { + case AST::ExprNode_Block::Type::Bare: + break; + case AST::ExprNode_Block::Type::Unsafe: + rv->m_is_unsafe = true; + break; + case AST::ExprNode_Block::Type::Const: + break; + } + if( v.m_label != "" ) { if(rv->m_value_node) @@ -72,6 +83,17 @@ struct LowerHIR_ExprNode_Visitor: { m_rv.reset( static_cast< ::HIR::ExprNode*>(rv) ); } + + switch(v.m_block_type) + { + case AST::ExprNode_Block::Type::Bare: + break; + case AST::ExprNode_Block::Type::Unsafe: + break; + case AST::ExprNode_Block::Type::Const: + m_rv.reset( new ::HIR::ExprNode_ConstBlock(v.span(), std::move(m_rv)) ); + break; + } } virtual void visit(::AST::ExprNode_Try& v) override { TODO(v.span(), "Handle _Try"); diff --git a/src/hir_expand/annotate_value_usage.cpp b/src/hir_expand/annotate_value_usage.cpp index a99c5f94..56cb78b6 100644 --- a/src/hir_expand/annotate_value_usage.cpp +++ b/src/hir_expand/annotate_value_usage.cpp @@ -164,6 +164,11 @@ namespace { scope->yield_stack.pop_back(); } } + void visit(::HIR::ExprNode_ConstBlock& node) override + { + auto _ = this->push_usage( ::HIR::ValueUsage::Move ); + this->visit_node_ptr(node.m_inner); + } void visit(::HIR::ExprNode_Asm& node) override { diff --git a/src/hir_expand/lifetime_infer.cpp b/src/hir_expand/lifetime_infer.cpp index c226e6ae..f165787f 100644 --- a/src/hir_expand/lifetime_infer.cpp +++ b/src/hir_expand/lifetime_infer.cpp @@ -902,6 +902,7 @@ namespace { #define NV(nt) void visit(HIR::nt& node) override { local(node); } NV(ExprNode_Block) + NV(ExprNode_ConstBlock) NV(ExprNode_Asm) NV(ExprNode_Asm2) NV(ExprNode_Return) diff --git a/src/hir_expand/static_borrow_constants.cpp b/src/hir_expand/static_borrow_constants.cpp index d7120ac3..28d7296c 100644 --- a/src/hir_expand/static_borrow_constants.cpp +++ b/src/hir_expand/static_borrow_constants.cpp @@ -327,6 +327,11 @@ namespace static_borrow_constants { ::HIR::ExprVisitorDef::visit(node); m_is_constant = m_all_constant; } + void visit(::HIR::ExprNode_ConstBlock& node) override { + ::HIR::ExprVisitorDef::visit(node); + ASSERT_BUG(node.span(),m_all_constant, "const block wasn't constant"); + m_is_constant = m_all_constant; + } // - Root values void visit(::HIR::ExprNode_Literal& node) override { ::HIR::ExprVisitorDef::visit(node); diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 2e6b6eeb..36a374e7 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -82,6 +82,12 @@ namespace { check_types_equal(node.span(), node.m_res_type, node.m_value_node->m_res_type); } } + void visit(::HIR::ExprNode_ConstBlock& node) override + { + TRACE_FUNCTION_F(&node << " const { ... }"); + node.m_inner->visit(*this); + check_types_equal(node.span(), node.m_res_type, node.m_inner->m_res_type); + } void visit(::HIR::ExprNode_Asm& node) override { TRACE_FUNCTION_F(&node << " llvm_asm! ..."); diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 7a6b9af4..1d10e837 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -131,6 +131,9 @@ namespace { } this->m_completed = true; } + void visit(::HIR::ExprNode_ConstBlock& node) override { + no_revisit(node); + } void visit(::HIR::ExprNode_Asm& node) override { // TODO: Revisit for validation no_revisit(node); @@ -1662,6 +1665,9 @@ namespace { void visit(::HIR::ExprNode_Block& node) override { m_os << "_Block {" << context.m_ivars.fmt_type(node.m_nodes.back()->m_res_type) << "}"; } + void visit(::HIR::ExprNode_ConstBlock& node) override { + no_revisit(node); + } void visit(::HIR::ExprNode_Asm& node) override { no_revisit(node); } diff --git a/src/hir_typeck/expr_cs__enum.cpp b/src/hir_typeck/expr_cs__enum.cpp index 3c2f1437..14608977 100644 --- a/src/hir_typeck/expr_cs__enum.cpp +++ b/src/hir_typeck/expr_cs__enum.cpp @@ -656,6 +656,16 @@ namespace typecheck } this->pop_traits( node.m_traits ); } + void visit(::HIR::ExprNode_ConstBlock& node) override + { + TRACE_FUNCTION_F(&node << " const { ... }"); + this->context.add_ivars( node.m_inner->m_res_type ); + + //this->push_inner_coerce( true ); + node.m_inner->visit( *this ); + //this->pop_inner_coerce(); + this->context.equate_types(node.span(), node.m_res_type, node.m_inner->m_res_type); + } void visit(::HIR::ExprNode_Asm& node) override { TRACE_FUNCTION_F(&node << " asm! ..."); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 7e7a5895..140f7bdd 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -475,6 +475,10 @@ namespace { } } } + void visit(::HIR::ExprNode_ConstBlock& node) override + { + BUG(node.span(), "Const block shouldn't have reached MIR generation"); + } void visit(::HIR::ExprNode_Asm& node) override { TRACE_FUNCTION_F("_Asm"); diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 512b2766..4e41e23e 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -66,7 +66,8 @@ extern AST::Expr Parse_Expr(TokenStream& lex); extern AST::Expr Parse_ExprBlock(TokenStream& lex); extern AST::ExprNodeP Parse_Expr0(TokenStream& lex); extern AST::ExprNodeP Parse_ExprVal(TokenStream& lex); -extern AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false, Ident label=Ident("")); +//extern AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex, AST::ExprNode_Block::Type ty=AST::ExprNode_Block::Type::Bare, Ident label=Ident("")); +extern AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex); extern AST::ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence); extern AST::ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr& local_mod, bool& add_silence_if_end); extern AST::ExprNodeP Parse_Stmt(TokenStream& lex); diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 5950dc28..bfb43aae 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -24,7 +24,7 @@ using AST::ExprNodeP; static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){en->set_span(lex.point_span()); return ExprNodeP(en); } #define NEWNODE(type, ...) mk_exprnodep(lex, new type(__VA_ARGS__)) -//ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe=false, Ident label=RcString()); // common.hpp +ExprNodeP Parse_ExprBlockNode(TokenStream& lex, AST::ExprNode_Block::Type ty, Ident label=Ident("")); //ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr& local_mod, bool& add_silence_if_end); //ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence); ExprNodeP Parse_ExprBlockLine_Stmt(TokenStream& lex, bool& has_semicolon); @@ -47,8 +47,11 @@ AST::Expr Parse_ExprBlock(TokenStream& lex) { return ::AST::Expr( Parse_ExprBlockNode(lex) ); } - -ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe/*=false*/, Ident label/*=RcString()*/) +AST::ExprNodeP Parse_ExprBlockNode(TokenStream& lex) +{ + return Parse_ExprBlockNode(lex, AST::ExprNode_Block::Type::Bare, RcString()); +} +ExprNodeP Parse_ExprBlockNode(TokenStream& lex, AST::ExprNode_Block::Type ty/*=Bare*/, Ident label/*=RcString()*/) { TRACE_FUNCTION; Token tok; @@ -97,7 +100,7 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe/*=false*/, Ident DEBUG("Restore module from " << lex.parse_state().module->path() << " to " << orig_module->path() ); lex.parse_state().module = orig_module; } - auto* rv_blk = new ::AST::ExprNode_Block(is_unsafe, last_value_yielded, mv$(nodes), mv$(local_mod) ); + auto* rv_blk = new ::AST::ExprNode_Block(ty, last_value_yielded, mv$(nodes), mv$(local_mod) ); rv_blk->m_label = label; auto rv = ExprNodeP(rv_blk); rv->set_attrs( mv$(attrs) ); @@ -151,7 +154,6 @@ ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptrpath() << " to " << local_mod->path() ); + lex.parse_state().module = local_mod.get(); + } + Parse_Mod_Item(lex, *local_mod, mv$(item_attrs)); + return ExprNodeP(); + } + break; // 'unsafe' - Check if the next token isn't a `{`, if so it's an item. Otherwise, fall through case TOK_RWORD_UNSAFE: if( LOOK_AHEAD(lex) != TOK_BRACE_OPEN ) @@ -226,10 +242,13 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence) // NOTE: 1.39's libsyntax uses labelled block case TOK_BRACE_OPEN: PUTBACK(tok, lex); - ret = Parse_ExprBlockNode(lex, /*is_unsafe*/false, lifetime); + ret = Parse_ExprBlockNode(lex, /*is_unsafe*/AST::ExprNode_Block::Type::Bare, lifetime); return ret; case TOK_RWORD_UNSAFE: - ret = Parse_ExprBlockNode(lex, /*is_unsafe*/true, lifetime); + ret = Parse_ExprBlockNode(lex, /*is_unsafe*/AST::ExprNode_Block::Type::Unsafe, lifetime); + return ret; + case TOK_RWORD_CONST: + ret = Parse_ExprBlockNode(lex, /*is_unsafe*/AST::ExprNode_Block::Type::Const, lifetime); return ret; // TODO: Can these have labels? //case TOK_RWORD_IF: @@ -299,7 +318,10 @@ ExprNodeP Parse_ExprBlockLine(TokenStream& lex, bool *add_silence) ret = Parse_Expr_Match(lex); if(0) case TOK_RWORD_UNSAFE: - ret = Parse_ExprBlockNode(lex, true); + ret = Parse_ExprBlockNode(lex, AST::ExprNode_Block::Type::Unsafe); + if(0) + case TOK_RWORD_CONST: + ret = Parse_ExprBlockNode(lex, AST::ExprNode_Block::Type::Const); if(0) case TOK_BRACE_OPEN: { PUTBACK(tok, lex); ret = Parse_ExprBlockNode(lex); } @@ -1282,7 +1304,9 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) case TOK_RWORD_IF: return Parse_IfStmt(lex); case TOK_RWORD_UNSAFE: - return Parse_ExprBlockNode(lex, true); + return Parse_ExprBlockNode(lex, AST::ExprNode_Block::Type::Unsafe); + case TOK_RWORD_CONST: + return Parse_ExprBlockNode(lex, AST::ExprNode_Block::Type::Const); // Paths // `self` can be a value, or start a path