// Copyright (C) 2020 Free Software Foundation, Inc. // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3, or (at your option) any later // version. // GCC is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // . #ifndef RUST_AST_LOWER_EXPR #define RUST_AST_LOWER_EXPR #include "rust-diagnostics.h" #include "rust-ast-lower-base.h" #include "rust-ast-lower-block.h" #include "rust-ast-lower-struct-field-expr.h" namespace Rust { namespace HIR { class ArrayCapacityConstant : public ASTLoweringBase { public: static bool fold (AST::Expr *expr, size_t *folded_result) { ArrayCapacityConstant folder; expr->accept_vis (folder); *folded_result = folder.result; return folder.ok; } virtual ~ArrayCapacityConstant () {} void visit (AST::LiteralExpr &expr) { switch (expr.get_lit_type ()) { case AST::Literal::LitType::INT: { ok = true; std::stringstream ss (expr.as_string ()); ss >> result; } break; default: return; } } private: ArrayCapacityConstant () : ok (false), result (-1) {} bool ok; size_t result; }; // namespace Resolver class ASTLowerPathInExpression : public ASTLoweringBase { public: static HIR::PathInExpression *translate (AST::PathInExpression *expr) { ASTLowerPathInExpression compiler; expr->accept_vis (compiler); rust_assert (compiler.translated); return compiler.translated; } ~ASTLowerPathInExpression () {} void visit (AST::PathInExpression &expr) { std::vector path_segments; expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool { rust_assert (s.has_generic_args () == false); // TODO HIR::PathIdentSegment is (s.get_ident_segment ().as_string ()); HIR::PathExprSegment seg (is, s.get_locus ()); path_segments.push_back (seg); return true; }); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::PathInExpression (mapping, std::move (path_segments), expr.get_locus (), expr.opening_scope_resolution ()); } private: ASTLowerPathInExpression () : translated (nullptr) {} HIR::PathInExpression *translated; }; class ASTLoweringExpr : public ASTLoweringBase { public: static HIR::Expr *translate (AST::Expr *expr) { ASTLoweringExpr resolver; expr->accept_vis (resolver); if (resolver.translated == nullptr) { rust_fatal_error (expr->get_locus_slow (), "Failed to lower expr: [%s]", expr->as_string ().c_str ()); return nullptr; } resolver.mappings->insert_hir_expr ( resolver.translated->get_mappings ().get_crate_num (), resolver.translated->get_mappings ().get_hirid (), resolver.translated); return resolver.translated; } virtual ~ASTLoweringExpr () {} void visit (AST::IfExpr &expr) { translated = ASTLoweringIfBlock::translate (&expr); } void visit (AST::IfExprConseqElse &expr) { translated = ASTLoweringIfBlock::translate (&expr); } void visit (AST::IfExprConseqIf &expr) { translated = ASTLoweringIfBlock::translate (&expr); } void visit (AST::BlockExpr &expr) { translated = ASTLoweringBlock::translate (&expr); } void visit (AST::PathInExpression &expr) { translated = ASTLowerPathInExpression::translate (&expr); } void visit (AST::ReturnExpr &expr) { HIR::Expr *return_expr = expr.has_returned_expr () ? ASTLoweringExpr::translate (expr.get_returned_expr ().get ()) : nullptr; auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::ReturnExpr (mapping, expr.get_locus (), std::unique_ptr (return_expr)); } void visit (AST::CallExpr &expr) { std::vector outer_attribs; HIR::Expr *func = ASTLoweringExpr::translate (expr.get_function_expr ().get ()); std::vector > params; expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { auto trans = ASTLoweringExpr::translate (p); params.push_back (std::unique_ptr (trans)); return true; }); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping ( crate_num, UNKNOWN_NODEID /* this can map back to the AST*/, mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::CallExpr (mapping, std::unique_ptr (func), std::move (params), std::move (outer_attribs), expr.get_locus ()); } void visit (AST::AssignmentExpr &expr) { HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ()); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::AssignmentExpr (mapping, std::unique_ptr (lhs), std::unique_ptr (rhs), expr.get_locus ()); } void visit (AST::IdentifierExpr &expr) { auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::IdentifierExpr (mapping, expr.as_string (), expr.get_locus ()); } void visit (AST::ArrayExpr &expr) { std::vector outer_attribs; std::vector inner_attribs; expr.get_array_elems ()->accept_vis (*this); rust_assert (translated_array_elems != nullptr); HIR::ArrayElems *elems = translated_array_elems; auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::ArrayExpr (mapping, std::unique_ptr (elems), inner_attribs, outer_attribs, expr.get_locus ()); } void visit (AST::ArrayIndexExpr &expr) { std::vector outer_attribs; HIR::Expr *array_expr = ASTLoweringExpr::translate (expr.get_array_expr ().get ()); HIR::Expr *array_index_expr = ASTLoweringExpr::translate (expr.get_index_expr ().get ()); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::ArrayIndexExpr (mapping, std::unique_ptr (array_expr), std::unique_ptr (array_index_expr), outer_attribs, expr.get_locus ()); } void visit (AST::ArrayElemsValues &elems) { std::vector > elements; elems.iterate ([&] (AST::Expr *elem) mutable -> bool { HIR::Expr *translated_elem = ASTLoweringExpr::translate (elem); elements.push_back (std::unique_ptr (translated_elem)); return true; }); translated_array_elems = new HIR::ArrayElemsValues (std::move (elements)); } void visit (AST::ArrayElemsCopied &elems) { HIR::Expr *element = ASTLoweringExpr::translate (elems.get_elem_to_copy ().get ()); HIR::Expr *num_copies = ASTLoweringExpr::translate (elems.get_num_copies ().get ()); size_t folded; if (!ArrayCapacityConstant::fold (elems.get_num_copies ().get (), &folded)) { rust_fatal_error (elems.get_num_copies ()->get_locus_slow (), "failed to fold capacity constant"); return; } translated_array_elems = new HIR::ArrayElemsCopied (std::unique_ptr (element), std::unique_ptr (num_copies), folded); } void visit (AST::LiteralExpr &expr) { HIR::Literal::LitType type = HIR::Literal::LitType::CHAR; switch (expr.get_lit_type ()) { case AST::Literal::LitType::CHAR: type = HIR::Literal::LitType::CHAR; break; case AST::Literal::LitType::STRING: type = HIR::Literal::LitType::STRING; break; case AST::Literal::LitType::RAW_STRING: type = HIR::Literal::LitType::RAW_STRING; break; case AST::Literal::LitType::BYTE: type = HIR::Literal::LitType::BYTE; break; case AST::Literal::LitType::BYTE_STRING: type = HIR::Literal::LitType::BYTE_STRING; break; case AST::Literal::LitType::RAW_BYTE_STRING: type = HIR::Literal::LitType::RAW_BYTE_STRING; break; case AST::Literal::LitType::INT: type = HIR::Literal::LitType::INT; break; case AST::Literal::LitType::FLOAT: type = HIR::Literal::LitType::FLOAT; break; case AST::Literal::LitType::BOOL: type = HIR::Literal::LitType::BOOL; break; } auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::LiteralExpr (mapping, expr.as_string (), type, expr.get_literal ().get_type_hint (), expr.get_locus ()); } void visit (AST::ArithmeticOrLogicalExpr &expr) { HIR::ArithmeticOrLogicalExpr::ExprType kind = HIR::ArithmeticOrLogicalExpr::ExprType::ADD; switch (expr.get_expr_type ()) { case AST::ArithmeticOrLogicalExpr::ExprType::ADD: kind = HIR::ArithmeticOrLogicalExpr::ExprType::ADD; break; case AST::ArithmeticOrLogicalExpr::ExprType::SUBTRACT: kind = HIR::ArithmeticOrLogicalExpr::ExprType::SUBTRACT; break; case AST::ArithmeticOrLogicalExpr::ExprType::MULTIPLY: kind = HIR::ArithmeticOrLogicalExpr::ExprType::MULTIPLY; break; case AST::ArithmeticOrLogicalExpr::ExprType::DIVIDE: kind = HIR::ArithmeticOrLogicalExpr::ExprType::DIVIDE; break; case AST::ArithmeticOrLogicalExpr::ExprType::MODULUS: kind = HIR::ArithmeticOrLogicalExpr::ExprType::MODULUS; break; case AST::ArithmeticOrLogicalExpr::ExprType::BITWISE_AND: kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_AND; break; case AST::ArithmeticOrLogicalExpr::ExprType::BITWISE_OR: kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_OR; break; case AST::ArithmeticOrLogicalExpr::ExprType::BITWISE_XOR: kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_XOR; break; case AST::ArithmeticOrLogicalExpr::ExprType::LEFT_SHIFT: kind = HIR::ArithmeticOrLogicalExpr::ExprType::LEFT_SHIFT; break; case AST::ArithmeticOrLogicalExpr::ExprType::RIGHT_SHIFT: kind = HIR::ArithmeticOrLogicalExpr::ExprType::RIGHT_SHIFT; break; } HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); rust_assert (lhs != nullptr); HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ()); rust_assert (rhs != nullptr); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::ArithmeticOrLogicalExpr (mapping, std::unique_ptr (lhs), std::unique_ptr (rhs), kind, expr.get_locus ()); } void visit (AST::ComparisonExpr &expr) { HIR::ComparisonExpr::ExprType kind; switch (expr.get_kind ()) { case AST::ComparisonExpr::ExprType::EQUAL: kind = HIR::ComparisonExpr::ExprType::EQUAL; break; case AST::ComparisonExpr::ExprType::NOT_EQUAL: kind = HIR::ComparisonExpr::ExprType::NOT_EQUAL; break; case AST::ComparisonExpr::ExprType::GREATER_THAN: kind = HIR::ComparisonExpr::ExprType::GREATER_THAN; break; case AST::ComparisonExpr::ExprType::LESS_THAN: kind = HIR::ComparisonExpr::ExprType::LESS_THAN; break; case AST::ComparisonExpr::ExprType::GREATER_OR_EQUAL: kind = HIR::ComparisonExpr::ExprType::GREATER_OR_EQUAL; break; case AST::ComparisonExpr::ExprType::LESS_OR_EQUAL: kind = HIR::ComparisonExpr::ExprType::LESS_OR_EQUAL; break; } HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); rust_assert (lhs != nullptr); HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ()); rust_assert (rhs != nullptr); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::ComparisonExpr (mapping, std::unique_ptr (lhs), std::unique_ptr (rhs), kind, expr.get_locus ()); } void visit (AST::LazyBooleanExpr &expr) { HIR::LazyBooleanExpr::ExprType kind; switch (expr.get_kind ()) { case AST::LazyBooleanExpr::ExprType::LOGICAL_AND: kind = HIR::LazyBooleanExpr::ExprType::LOGICAL_AND; break; case AST::LazyBooleanExpr::ExprType::LOGICAL_OR: kind = HIR::LazyBooleanExpr::ExprType::LOGICAL_OR; break; } HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); rust_assert (lhs != nullptr); HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ()); rust_assert (rhs != nullptr); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::LazyBooleanExpr (mapping, std::unique_ptr (lhs), std::unique_ptr (rhs), kind, expr.get_locus ()); } void visit (AST::StructExprStructFields &struct_expr) { std::vector inner_attribs; std::vector outer_attribs; // bit of a hack for now HIR::PathInExpression *path = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ()); HIR::PathInExpression copied_path (*path); delete path; HIR::StructBase *base = nullptr; if (struct_expr.has_struct_base ()) { HIR::Expr *translated_base = ASTLoweringExpr::translate ( struct_expr.get_struct_base ().get_base_struct ().get ()); base = new HIR::StructBase (std::unique_ptr (translated_base)); } std::vector > fields; struct_expr.iterate ([&] (AST::StructExprField *field) mutable -> bool { HIR::StructExprField *translated = ASTLowerStructExprField::translate (field); fields.push_back (std::unique_ptr (translated)); return true; }); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); translated = new HIR::StructExprStructFields (mapping, copied_path, std::move (fields), struct_expr.get_locus (), base, inner_attribs, outer_attribs); } private: ASTLoweringExpr () : translated (nullptr), translated_array_elems (nullptr) {} HIR::Expr *translated; HIR::ArrayElems *translated_array_elems; }; } // namespace HIR } // namespace Rust #endif // RUST_AST_LOWER_EXPR