diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2021-01-08 15:09:08 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2021-01-08 15:09:08 +0800 |
commit | 238a31b33f79cddfaa40c5fd748495a5f2b34630 (patch) | |
tree | bc217d37b5e3ee41b0a69265341945389d1f4dfb /gcc | |
parent | b5f86dca7e6b53ca3701ef01ae36070a760dff78 (diff) | |
parent | af04ea2222b6407fb3e83759ae332d600495380c (diff) | |
download | gcc-238a31b33f79cddfaa40c5fd748495a5f2b34630.zip gcc-238a31b33f79cddfaa40c5fd748495a5f2b34630.tar.gz gcc-238a31b33f79cddfaa40c5fd748495a5f2b34630.tar.bz2 |
Merge branch 'master' of https://github.com/redbrain/gccrs
Diffstat (limited to 'gcc')
44 files changed, 1496 insertions, 174 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 1329978..092ab00 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -437,7 +437,7 @@ StaticItem::as_string () const str += " mut"; } - str += name; + str += " " + name; // DEBUG: null pointer check if (type == nullptr) @@ -4947,28 +4947,30 @@ MacroParser::parse_literal () { case CHAR_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::CHAR); + return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ()); case STRING_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::STRING); + return Literal (tok->as_string (), Literal::STRING, + tok->get_type_hint ()); case BYTE_CHAR_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::BYTE); + return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ()); case BYTE_STRING_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::BYTE_STRING); + return Literal (tok->as_string (), Literal::BYTE_STRING, + tok->get_type_hint ()); case INT_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::INT); + return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ()); case FLOAT_LITERAL: skip_token (); - return Literal (tok->as_string (), Literal::FLOAT); + return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ()); case TRUE_LITERAL: skip_token (); - return Literal ("true", Literal::BOOL); + return Literal ("true", Literal::BOOL, tok->get_type_hint ()); case FALSE_LITERAL: skip_token (); - return Literal ("false", Literal::BOOL); + return Literal ("false", Literal::BOOL, tok->get_type_hint ()); default: rust_error_at (tok->get_locus (), "expected literal - found '%s'", get_token_description (tok->get_id ())); @@ -5291,7 +5293,8 @@ Token::to_token_stream () const Attribute MetaNameValueStr::to_attribute () const { - LiteralExpr lit_expr (str, Literal::LitType::STRING, Location ()); + LiteralExpr lit_expr (str, Literal::LitType::STRING, + PrimitiveCoreType::CORETYPE_UNKNOWN, Location ()); return Attribute (SimplePath::from_str (ident), std::unique_ptr<AttrInputLiteral> ( new AttrInputLiteral (std::move (lit_expr)))); diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 7700bf3..b7baab4 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -212,6 +212,8 @@ public: Location get_locus () const { return locus; } + PrimitiveCoreType get_type_hint () const { return type_hint; } + protected: // No virtual for now as not polymorphic but can be in future /*virtual*/ Token *clone_token_impl () const { return new Token (*this); } @@ -250,17 +252,25 @@ private: * (or generics) */ std::string value_as_string; LitType type; + PrimitiveCoreType type_hint; public: std::string as_string () const { return value_as_string; } LitType get_lit_type () const { return type; } - Literal (std::string value_as_string, LitType type) - : value_as_string (std::move (value_as_string)), type (type) + PrimitiveCoreType get_type_hint () const { return type_hint; } + + Literal (std::string value_as_string, LitType type, + PrimitiveCoreType type_hint) + : value_as_string (std::move (value_as_string)), type (type), + type_hint (type_hint) {} - static Literal create_error () { return Literal ("", CHAR); } + static Literal create_error () + { + return Literal ("", CHAR, PrimitiveCoreType::CORETYPE_UNKNOWN); + } // Returns whether literal is in an invalid state. bool is_error () const { return value_as_string == ""; } diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index d531342..eee654b 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -50,10 +50,10 @@ public: Literal::LitType get_lit_type () const { return literal.get_lit_type (); } LiteralExpr (std::string value_as_string, Literal::LitType type, - Location locus, + PrimitiveCoreType type_hint, Location locus, std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : ExprWithoutBlock (std::move (outer_attrs)), - literal (std::move (value_as_string), type), locus (locus) + literal (std::move (value_as_string), type, type_hint), locus (locus) {} LiteralExpr (Literal literal, Location locus, @@ -1572,9 +1572,16 @@ public: virtual Location get_locus_slow () const = 0; + NodeId get_node_id () const { return node_id; } + protected: // pure virtual clone implementation virtual StructExprField *clone_struct_expr_field_impl () const = 0; + + StructExprField () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + NodeId node_id; }; // Identifier-only variant of StructExprField AST node @@ -1585,7 +1592,8 @@ class StructExprFieldIdentifier : public StructExprField public: StructExprFieldIdentifier (Identifier field_identifier, Location locus) - : field_name (std::move (field_identifier)), locus (locus) + : StructExprField (), field_name (std::move (field_identifier)), + locus (locus) {} std::string as_string () const override { return field_name; } @@ -1612,7 +1620,7 @@ class StructExprFieldWithVal : public StructExprField protected: StructExprFieldWithVal (std::unique_ptr<Expr> field_value) - : value (std::move (field_value)) + : StructExprField (), value (std::move (field_value)) {} // Copy constructor requires clone @@ -1770,6 +1778,15 @@ public: return fields; } + void iterate (std::function<bool (StructExprField *)> cb) + { + for (auto &field : fields) + { + if (!cb (field.get ())) + return; + } + } + StructBase &get_struct_base () { return struct_base; } const StructBase &get_struct_base () const { return struct_base; } diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index fc34670..f558195 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1748,6 +1748,8 @@ public: return where_clause; } + Identifier get_identifier () const { return struct_name; } + protected: Struct (Identifier struct_name, std::vector<std::unique_ptr<GenericParam> > generic_params, @@ -1804,6 +1806,8 @@ private: // should this store location info? + NodeId node_id; + public: // Returns whether struct field has any outer attributes. bool has_outer_attributes () const { return !outer_attrs.empty (); } @@ -1879,6 +1883,8 @@ public: } Visibility get_visibility () const { return visibility; } + + NodeId get_node_id () const { return node_id; } }; // Rust struct declaration with true struct type AST node @@ -1924,6 +1930,15 @@ public: std::vector<StructField> &get_fields () { return fields; } const std::vector<StructField> &get_fields () const { return fields; } + void iterate (std::function<bool (StructField &)> cb) + { + for (auto &field : fields) + { + if (!cb (field)) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2533,6 +2548,8 @@ public: return type; } + std::string get_identifier () const { return identifier; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2643,6 +2660,10 @@ public: return type; } + bool is_mutable () const { return has_mut; } + + Identifier get_identifier () const { return name; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 79beebb..e89fc62 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -47,8 +47,8 @@ public: LiteralPattern (std::string val, Literal::LitType type, Location locus, bool has_minus = false) - : lit (Literal (std::move (val), type)), has_minus (has_minus), - locus (locus) + : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)), + has_minus (has_minus), locus (locus) {} Location get_locus () const { return locus; } diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 5736bf2..d241921 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -141,6 +141,21 @@ public: return true; } + void insert_const_decl (HirId id, ::Bexpression *expr) + { + compiled_consts[id] = expr; + } + + bool lookup_const_decl (HirId id, ::Bexpression **expr) + { + auto it = compiled_consts.find (id); + if (it == compiled_consts.end ()) + return false; + + *expr = it->second; + return true; + } + void push_fn (::Bfunction *fn, ::Bvariable *ret_addr) { fn_stack.push_back (fncontext{fn, ret_addr}); @@ -183,6 +198,7 @@ private: std::map<HirId, ::Bvariable *> compiled_var_decls; std::map<HirId, ::Btype *> compiled_type_map; std::map<HirId, ::Bfunction *> compiled_fn_map; + std::map<HirId, ::Bexpression *> compiled_consts; std::vector< ::std::vector<Bstatement *> > statements; std::vector< ::Bblock *> scope_stack; @@ -211,6 +227,14 @@ public: void visit (TyTy::FnType &type) override { gcc_unreachable (); } + void visit (TyTy::ADTType &type) override + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + void visit (TyTy::ArrayType &type) override { mpz_t ival; @@ -248,6 +272,14 @@ public: translated = compiled_type; } + void visit (TyTy::FloatType &type) override + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + private: TyTyResolveCompile (Context *ctx) : ctx (ctx) {} diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 5c3206a..9081000 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -23,6 +23,7 @@ #include "rust-compile-tyty.h" #include "rust-compile-resolve-path.h" #include "rust-compile-block.h" +#include "rust-compile-struct-field-expr.h" namespace Rust { namespace Compile { @@ -56,7 +57,7 @@ public: void visit (HIR::CallExpr &expr) { - Bexpression *fn = ResolvePath::Compile (expr.get_fnexpr (), ctx); + Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx); rust_assert (fn != nullptr); std::vector<Bexpression *> args; @@ -105,6 +106,11 @@ public: return; } + // this could be a constant reference + if (ctx->lookup_const_decl (ref, &translated)) + return; + + // must be an identifier Bvariable *var = nullptr; if (!ctx->lookup_var_decl (ref, &var)) { @@ -149,6 +155,36 @@ public: } return; + case HIR::Literal::FLOAT: { + printf ("FLOATY BOYO: [%s]\n", expr.as_string ().c_str ()); + + mpfr_t fval; + if (mpfr_init_set_str (fval, expr.as_string ().c_str (), 10, + MPFR_RNDN) + != 0) + { + rust_fatal_error (expr.get_locus (), + "bad float number in literal"); + return; + } + + TyTy::TyBase *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_mappings ().get_hirid (), &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this literal expr"); + return; + } + + printf ("tyty float is [%s]\n", tyty->as_string ().c_str ()); + + Btype *type = TyTyResolveCompile::compile (ctx, tyty); + translated + = ctx->get_backend ()->float_constant_expression (type, fval); + } + return; + default: rust_fatal_error (expr.get_locus (), "unknown literal"); return; @@ -350,6 +386,25 @@ public: ctx->add_statement (block_stmt); } + void visit (HIR::StructExprStructFields &struct_expr) + { + Btype *type + = ResolvePathType::Compile (&struct_expr.get_struct_name (), ctx); + + // this assumes all fields are in order from type resolution and if a base + // struct was specified those fields are filed via accesors + std::vector<Bexpression *> vals; + struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool { + Bexpression *expr = CompileStructExprField::Compile (field, ctx); + vals.push_back (expr); + return true; + }); + + translated + = ctx->get_backend ()->constructor_expression (type, vals, + struct_expr.get_locus ()); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index f131a89..90630bb 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -23,6 +23,7 @@ #include "rust-compile-tyty.h" #include "rust-compile-var-decl.h" #include "rust-compile-stmt.h" +#include "rust-compile-expr.h" namespace Rust { namespace Compile { @@ -38,6 +39,81 @@ public: virtual ~CompileItem () {} + void visit (HIR::StructStruct &struct_decl) + { + std::vector<Backend::Btyped_identifier> fields; + struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool { + TyTy::TyBase *resolved_type = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (field.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + Btype *compiled_field_ty + = TyTyCompile::compile (ctx->get_backend (), resolved_type); + + Backend::Btyped_identifier f (field.field_name, compiled_field_ty, + field.get_locus ()); + fields.push_back (std::move (f)); + return true; + }); + + Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); + Btype *named_struct + = ctx->get_backend ()->named_type (struct_decl.get_identifier (), + struct_type_record, + struct_decl.get_locus ()); + ctx->push_type (named_struct); + ctx->insert_compiled_type (struct_decl.get_mappings ().get_hirid (), + named_struct); + } + + void visit (HIR::StaticItem &var) + { + TyTy::TyBase *resolved_type = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type (var.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); + Bexpression *value = CompileExpr::Compile (var.get_expr (), ctx); + + std::string name = var.get_identifier (); + // FIXME need name mangling + std::string asm_name = "__" + var.get_identifier (); + + bool is_external = false; + bool is_hidden = false; + bool in_unique_section = true; + + Bvariable *static_global + = ctx->get_backend ()->global_variable (name, asm_name, type, is_external, + is_hidden, in_unique_section, + var.get_locus ()); + ctx->get_backend ()->global_variable_set_init (static_global, value); + + ctx->insert_var_decl (var.get_mappings ().get_hirid (), static_global); + ctx->push_var (static_global); + } + + void visit (HIR::ConstantItem &constant) + { + TyTy::TyBase *resolved_type = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (constant.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); + Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx); + + Bexpression *const_expr = ctx->get_backend ()->named_constant_expression ( + type, constant.get_identifier (), value, constant.get_locus ()); + + ctx->push_const (const_expr); + ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); + } + void visit (HIR::Function &function) { // items can be forward compiled which means we may not need to invoke this diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index c5c646d..c24005e 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -25,7 +25,7 @@ namespace Rust { namespace Compile { void -ResolvePath::visit (HIR::PathInExpression &expr) +ResolvePathRef::visit (HIR::PathInExpression &expr) { // need to look up the reference for this identifier NodeId ref_node_id; @@ -70,5 +70,33 @@ ResolvePath::visit (HIR::PathInExpression &expr) = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); } +void +ResolvePathType::visit (HIR::PathInExpression &expr) +{ + // need to look up the reference for this identifier + NodeId ref_node_id; + if (!ctx->get_resolver ()->lookup_resolved_name ( + expr.get_mappings ().get_nodeid (), &ref_node_id)) + { + rust_fatal_error (expr.get_locus (), "failed to look up resolved name"); + return; + } + + HirId ref; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + return; + } + + // assumes paths are functions for now + if (!ctx->lookup_compiled_types (ref, &resolved)) + { + rust_fatal_error (expr.get_locus (), "forward decl was not compiled"); + return; + } +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h index d8f393d..a5543d2 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.h +++ b/gcc/rust/backend/rust-compile-resolve-path.h @@ -25,27 +25,44 @@ namespace Rust { namespace Compile { -class ResolvePath : public HIRCompileBase +class ResolvePathRef : public HIRCompileBase { public: static Bexpression *Compile (HIR::Expr *expr, Context *ctx) { - ResolvePath resolver (ctx); + ResolvePathRef resolver (ctx); expr->accept_vis (resolver); rust_assert (resolver.resolved != nullptr); return resolver.resolved; } - virtual ~ResolvePath () {} - void visit (HIR::PathInExpression &expr); private: - ResolvePath (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {} + ResolvePathRef (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {} Bexpression *resolved; }; +class ResolvePathType : public HIRCompileBase +{ +public: + static Btype *Compile (HIR::Expr *expr, Context *ctx) + { + ResolvePathType resolver (ctx); + expr->accept_vis (resolver); + rust_assert (resolver.resolved != nullptr); + return resolver.resolved; + } + + void visit (HIR::PathInExpression &expr); + +private: + ResolvePathType (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {} + + Btype *resolved; +}; + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h new file mode 100644 index 0000000..a394f7a --- /dev/null +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -0,0 +1,52 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_STRUCT_FIELD_EXPR +#define RUST_COMPILE_STRUCT_FIELD_EXPR + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" + +namespace Rust { +namespace Compile { + +class CompileStructExprField : public HIRCompileBase +{ +public: + static Bexpression *Compile (HIR::StructExprField *field, Context *ctx) + { + CompileStructExprField compiler (ctx); + field->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + return compiler.translated; + } + + void visit (HIR::StructExprFieldIdentifierValue &field); + +private: + CompileStructExprField (Context *ctx) + : HIRCompileBase (ctx), translated (nullptr) + {} + + Bexpression *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_STRUCT_FIELD_EXPR diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 66d2472..528f90e 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -111,6 +111,18 @@ public: = backend->named_type ("i32", backend->integer_type (false, 32), Linemap::predeclared_location ()); return; + + case TyTy::IntType::I64: + translated + = backend->named_type ("i64", backend->integer_type (false, 64), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I128: + translated + = backend->named_type ("i128", backend->integer_type (false, 128), + Linemap::predeclared_location ()); + return; } gcc_unreachable (); } @@ -135,7 +147,37 @@ public: = backend->named_type ("i32", backend->integer_type (true, 32), Linemap::predeclared_location ()); return; + + case TyTy::UintType::U64: + translated + = backend->named_type ("u64", backend->integer_type (true, 64), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U128: + translated + = backend->named_type ("u128", backend->integer_type (true, 128), + Linemap::predeclared_location ()); + return; + } + gcc_unreachable (); + } + + void visit (TyTy::FloatType &type) override + { + switch (type.get_kind ()) + { + case TyTy::FloatType::F32: + translated = backend->named_type ("f32", backend->float_type (32), + Linemap::predeclared_location ()); + return; + + case TyTy::FloatType::F64: + translated = backend->named_type ("f64", backend->float_type (64), + Linemap::predeclared_location ()); + return; } + gcc_unreachable (); } diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 02fa3a0..24b45ee 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -19,6 +19,7 @@ #include "rust-compile.h" #include "rust-compile-item.h" #include "rust-compile-expr.h" +#include "rust-compile-struct-field-expr.h" namespace Rust { namespace Compile { @@ -152,5 +153,13 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) else_block, expr.get_locus ()); } +// rust-compile-struct-field-expr.h + +void +CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field) +{ + translated = CompileExpr::Compile (field.get_value (), ctx); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index a165eaf..87ba0dc 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -22,6 +22,7 @@ #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 { @@ -62,6 +63,47 @@ private: 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<HIR::PathExprSegment> 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: @@ -107,24 +149,7 @@ public: void visit (AST::PathInExpression &expr) { - std::vector<HIR::PathExprSegment> 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 ()); + translated = ASTLowerPathInExpression::translate (&expr); } void visit (AST::ReturnExpr &expr) @@ -303,6 +328,7 @@ public: UNKNOWN_LOCAL_DEFID); translated = new HIR::LiteralExpr (mapping, expr.as_string (), type, + expr.get_literal ().get_type_hint (), expr.get_locus ()); } @@ -431,6 +457,46 @@ public: expr.get_locus ()); } + void visit (AST::StructExprStructFields &struct_expr) + { + std::vector<HIR::Attribute> inner_attribs; + std::vector<HIR::Attribute> 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<HIR::Expr> (translated_base)); + } + + std::vector<std::unique_ptr<HIR::StructExprField> > fields; + struct_expr.iterate ([&] (AST::StructExprField *field) mutable -> bool { + HIR::StructExprField *translated + = ASTLowerStructExprField::translate (field); + fields.push_back (std::unique_ptr<HIR::StructExprField> (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) {} diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index f57ac86..2a17880 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -24,6 +24,7 @@ #include "rust-ast-lower-base.h" #include "rust-ast-lower-type.h" #include "rust-ast-lower-stmt.h" +#include "rust-ast-lower-expr.h" #include "rust-ast-lower-pattern.h" #include "rust-ast-lower-block.h" @@ -42,6 +43,108 @@ public: virtual ~ASTLoweringItem () {} + void visit (AST::StructStruct &struct_decl) + { + std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; + HIR::WhereClause where_clause (std::move (where_clause_items)); + HIR::Visibility vis = HIR::Visibility::create_public (); + std::vector<HIR::Attribute> outer_attrs; + + bool is_unit = false; + std::vector<HIR::StructField> fields; + struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool { + std::vector<HIR::Attribute> outer_attrs; + HIR::Visibility vis = HIR::Visibility::create_public (); + HIR::Type *type + = ASTLoweringType::translate (field.get_field_type ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, field.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id ( + crate_num)); + + // FIXME + // AST::StructField is missing Location info + Location field_locus; + HIR::StructField translated_field (mapping, field.get_field_name (), + std::unique_ptr<HIR::Type> (type), vis, + field_locus, outer_attrs); + fields.push_back (std::move (translated_field)); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::StructStruct (mapping, std::move (fields), + struct_decl.get_identifier (), + std::move (generic_params), + std::move (where_clause), is_unit, vis, + std::move (outer_attrs), + struct_decl.get_locus ()); + + mappings->insert_defid_mapping (mapping.get_defid (), translated); + mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), + translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + struct_decl.get_locus ()); + } + + void visit (AST::StaticItem &var) + { + std::vector<HIR::Attribute> outer_attrs; + HIR::Visibility vis = HIR::Visibility::create_public (); + + HIR::Type *type = ASTLoweringType::translate (var.get_type ().get ()); + HIR::Expr *expr = ASTLoweringExpr::translate (var.get_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, var.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated + = new HIR::StaticItem (mapping, var.get_identifier (), var.is_mutable (), + std::unique_ptr<HIR::Type> (type), + std::unique_ptr<HIR::Expr> (expr), vis, + outer_attrs, var.get_locus ()); + + mappings->insert_defid_mapping (mapping.get_defid (), translated); + mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), + translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + var.get_locus ()); + } + + void visit (AST::ConstantItem &constant) + { + std::vector<HIR::Attribute> outer_attrs; + HIR::Visibility vis = HIR::Visibility::create_public (); + + HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ()); + HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, constant.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::ConstantItem (mapping, constant.get_identifier (), + vis, std::unique_ptr<HIR::Type> (type), + std::unique_ptr<HIR::Expr> (expr), + outer_attrs, constant.get_locus ()); + + mappings->insert_defid_mapping (mapping.get_defid (), translated); + mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), + translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + constant.get_locus ()); + } + void visit (AST::Function &function) { // ignore for now and leave empty diff --git a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h new file mode 100644 index 0000000..1b444a5 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h @@ -0,0 +1,58 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_LOWER_STRUCT_FIELD_EXPR +#define RUST_AST_LOWER_STRUCT_FIELD_EXPR + +#include "rust-diagnostics.h" +#include "rust-ast-lower-base.h" + +namespace Rust { +namespace HIR { + +class ASTLowerStructExprField : public ASTLoweringBase +{ +public: + static HIR::StructExprField *translate (AST::StructExprField *field) + { + ASTLowerStructExprField compiler; + field->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + + // compiler.mappings->insert_hir_expr ( + // compiler.translated->get_mappings ().get_crate_num (), + // compiler.translated->get_mappings ().get_hirid (), + // compiler.translated); + + return compiler.translated; + } + + ~ASTLowerStructExprField () {} + + void visit (AST::StructExprFieldIdentifierValue &field); + +private: + ASTLowerStructExprField () : translated (nullptr) {} + + HIR::StructExprField *translated; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_STRUCT_FIELD_EXPR diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 93288c3..8dd8800 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -149,5 +149,22 @@ ASTLoweringIfBlock::visit (AST::IfExprConseqIf &expr) expr.get_locus ()); } +// rust-ast-lower-struct-field-expr.h + +void +ASTLowerStructExprField::visit (AST::StructExprFieldIdentifierValue &field) +{ + HIR::Expr *value = ASTLoweringExpr::translate (field.get_value ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, field.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::StructExprFieldIdentifierValue ( + mapping, field.get_field_name (), std::unique_ptr<HIR::Expr> (value), + field.get_locus ()); +} + } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 1110f98..dc7ab5a 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -66,10 +66,11 @@ public: Literal::LitType get_lit_type () const { return literal.get_lit_type (); } LiteralExpr (Analysis::NodeMapping mappings, std::string value_as_string, - Literal::LitType type, Location locus, + Literal::LitType type, PrimitiveCoreType type_hint, + Location locus, std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), - literal (std::move (value_as_string), type), locus (locus) + literal (std::move (value_as_string), type, type_hint), locus (locus) {} LiteralExpr (Analysis::NodeMapping mappings, Literal literal, Location locus, @@ -1315,9 +1316,9 @@ protected: // Base struct/tuple/union value creator HIR node (abstract) class StructExpr : public ExprWithoutBlock { +protected: PathInExpression struct_name; -protected: // Protected constructor to allow initialising struct_name StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path, std::vector<Attribute> outer_attribs) @@ -1326,7 +1327,7 @@ protected: {} public: - const PathInExpression &get_struct_name () const { return struct_name; } + PathInExpression &get_struct_name () { return struct_name; } std::string as_string () const override; }; @@ -1417,6 +1418,8 @@ public: bool is_invalid () const { return base_struct == nullptr; } std::string as_string () const; + + Expr *get_base () { return base_struct.get (); } }; /* Base HIR node for a single struct expression field (in struct instance @@ -1436,9 +1439,20 @@ public: virtual void accept_vis (HIRVisitor &vis) = 0; + Analysis::NodeMapping &get_mappings () { return mappings; } + + Location get_locus () { return locus; } + protected: // pure virtual clone implementation virtual StructExprField *clone_struct_expr_field_impl () const = 0; + + StructExprField (Analysis::NodeMapping mapping, Location locus) + : mappings (mapping), locus (locus) + {} + + Analysis::NodeMapping mappings; + Location locus; }; // Identifier-only variant of StructExprField HIR node @@ -1449,8 +1463,10 @@ public: // TODO: should this store location data? - StructExprFieldIdentifier (Identifier field_identifier) - : field_name (std::move (field_identifier)) + StructExprFieldIdentifier (Analysis::NodeMapping mapping, + Identifier field_identifier, Location locus) + : StructExprField (mapping, locus), + field_name (std::move (field_identifier)) {} std::string as_string () const override { return field_name; } @@ -1470,23 +1486,26 @@ protected: * abstract */ class StructExprFieldWithVal : public StructExprField { -public: std::unique_ptr<Expr> value; protected: - StructExprFieldWithVal (std::unique_ptr<Expr> field_value) - : value (std::move (field_value)) + StructExprFieldWithVal (Analysis::NodeMapping mapping, + std::unique_ptr<Expr> field_value, Location locus) + : StructExprField (mapping, locus), value (std::move (field_value)) {} // Copy constructor requires clone StructExprFieldWithVal (StructExprFieldWithVal const &other) - : value (other.value->clone_expr ()) + : StructExprField (other.mappings, other.locus), + value (other.value->clone_expr ()) {} // Overload assignment operator to clone unique_ptr StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other) { value = other.value->clone_expr (); + mappings = other.mappings; + locus = other.locus; return *this; } @@ -1497,6 +1516,8 @@ protected: public: std::string as_string () const override; + + Expr *get_value () { return value.get (); } }; // Identifier and value variant of StructExprField HIR node @@ -1507,9 +1528,11 @@ public: // TODO: should this store location data? - StructExprFieldIdentifierValue (Identifier field_identifier, - std::unique_ptr<Expr> field_value) - : StructExprFieldWithVal (std::move (field_value)), + StructExprFieldIdentifierValue (Analysis::NodeMapping mapping, + Identifier field_identifier, + std::unique_ptr<Expr> field_value, + Location locus) + : StructExprFieldWithVal (mapping, std::move (field_value), locus), field_name (std::move (field_identifier)) {} @@ -1534,9 +1557,11 @@ public: // TODO: should this store location data? - StructExprFieldIndexValue (TupleIndex tuple_index, - std::unique_ptr<Expr> field_value) - : StructExprFieldWithVal (std::move (field_value)), index (tuple_index) + StructExprFieldIndexValue (Analysis::NodeMapping mapping, + TupleIndex tuple_index, + std::unique_ptr<Expr> field_value, Location locus) + : StructExprFieldWithVal (mapping, std::move (field_value), locus), + index (tuple_index) {} std::string as_string () const override; @@ -1560,31 +1585,24 @@ public: std::vector<std::unique_ptr<StructExprField> > fields; // bool has_struct_base; - StructBase struct_base; + // FIXME make unique_ptr + StructBase *struct_base; std::string as_string () const override; - bool has_struct_base () const { return !struct_base.is_invalid (); } - - /*inline std::vector<std::unique_ptr<StructExprField>> get_fields() - const { return fields; - }*/ - - /*inline StructBase get_struct_base() const { - return has_struct_base ? struct_base : StructBase::error(); - }*/ + bool has_struct_base () const { return struct_base != nullptr; } // Constructor for StructExprStructFields when no struct base is used StructExprStructFields ( Analysis::NodeMapping mappings, PathInExpression struct_path, std::vector<std::unique_ptr<StructExprField> > expr_fields, Location locus, - StructBase base_struct = StructBase::error (), + StructBase *base_struct, std::vector<Attribute> inner_attribs = std::vector<Attribute> (), std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : StructExprStruct (std::move (mappings), std::move (struct_path), std::move (inner_attribs), std::move (outer_attribs), locus), - fields (std::move (expr_fields)), struct_base (std::move (base_struct)) + fields (std::move (expr_fields)), struct_base (base_struct) {} // copy constructor with vector clone @@ -1615,6 +1633,15 @@ public: void accept_vis (HIRVisitor &vis) override; + void iterate (std::function<bool (StructExprField *)> cb) + { + for (auto &field : fields) + { + if (!cb (field.get ())) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1752,11 +1779,7 @@ class StructExprUnit : public StructExpr Location locus; public: - std::string as_string () const override - { - return get_struct_name ().as_string (); - // return struct_name.as_string(); - } + std::string as_string () const override { return struct_name.as_string (); } StructExprUnit (Analysis::NodeMapping mappings, PathInExpression struct_path, std::vector<Attribute> outer_attribs, Location locus) diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index 2e30b59..b935376 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -3683,7 +3683,7 @@ StructExprStruct::as_string () const { std::string str ("StructExprStruct (or subclass): "); - str += "\n Path: " + get_struct_name ().as_string (); + str += "\n Path: " + struct_name.as_string (); // inner attributes str += "\n inner attributes: "; @@ -3761,7 +3761,7 @@ StructExprStructFields::as_string () const } else { - str += struct_base.as_string (); + str += struct_base->as_string (); } return str; @@ -4904,38 +4904,8 @@ DelimTokenTree::to_token_stream () const Literal MacroParser::parse_literal () { - const std::unique_ptr<Token> &tok = peek_token (); - switch (tok->get_id ()) - { - case CHAR_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::CHAR); - case STRING_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::STRING); - case BYTE_CHAR_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::BYTE); - case BYTE_STRING_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::BYTE_STRING); - case INT_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::INT); - case FLOAT_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::FLOAT); - case TRUE_LITERAL: - skip_token (); - return Literal ("true", Literal::BOOL); - case FALSE_LITERAL: - skip_token (); - return Literal ("false", Literal::BOOL); - default: - rust_error_at (tok->get_locus (), "expected literal - found '%s'", - get_token_description (tok->get_id ())); - return Literal::create_error (); - } + // marcos need to be removed from HIR + gcc_unreachable (); } SimplePath @@ -5037,7 +5007,8 @@ Attribute MetaNameValueStr::to_attribute () const { LiteralExpr lit_expr (Analysis::NodeMapping::get_error (), str, - Literal::LitType::STRING, Location ()); + Literal::LitType::STRING, + PrimitiveCoreType::CORETYPE_STR, Location ()); return Attribute (SimplePath::from_str (ident), std::unique_ptr<AttrInputLiteral> ( new AttrInputLiteral (std::move (lit_expr)))); diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index e0477f4..69e39c8 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -1390,7 +1390,7 @@ protected: // Rust base struct declaration HIR node - abstract base class class Struct : public VisItem { -public: +protected: // protected to enable access by derived classes - allows better as_string Identifier struct_name; @@ -1403,6 +1403,9 @@ public: Location locus; +public: + Identifier get_identifier () const { return struct_name; } + // Returns whether struct has generic parameters. bool has_generics () const { return !generic_params.empty (); } @@ -1465,6 +1468,10 @@ public: Identifier field_name; std::unique_ptr<Type> field_type; + Analysis::NodeMapping mappings; + + Location locus; + // should this store location info? // Returns whether struct field has any outer attributes. @@ -1473,18 +1480,19 @@ public: // Returns whether struct field has a non-private (non-default) visibility. bool has_visibility () const { return !visibility.is_error (); } - StructField (Identifier field_name, std::unique_ptr<Type> field_type, - Visibility vis, + StructField (Analysis::NodeMapping mappings, Identifier field_name, + std::unique_ptr<Type> field_type, Visibility vis, Location locus, std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), - field_name (std::move (field_name)), field_type (std::move (field_type)) + field_name (std::move (field_name)), field_type (std::move (field_type)), + mappings (mappings), locus (locus) {} // Copy constructor StructField (StructField const &other) : outer_attrs (other.outer_attrs), visibility (other.visibility), field_name (other.field_name), - field_type (other.field_type->clone_type ()) + field_type (other.field_type->clone_type ()), mappings (other.mappings) {} ~StructField () = default; @@ -1496,6 +1504,7 @@ public: field_type = other.field_type->clone_type (); visibility = other.visibility; outer_attrs = other.outer_attrs; + mappings = other.mappings; return *this; } @@ -1504,20 +1513,19 @@ public: StructField (StructField &&other) = default; StructField &operator= (StructField &&other) = default; - // Returns whether struct field is in an error state. - bool is_error () const - { - return field_name.empty () && field_type == nullptr; - // this should really be an or since neither are allowed - } + std::string as_string () const; - // Creates an error state struct field. - static StructField create_error () + Identifier get_field_name () const { return field_name; } + + std::unique_ptr<Type> &get_field_type () { - return StructField (std::string (""), nullptr, Visibility::create_error ()); + rust_assert (field_type != nullptr); + return field_type; } - std::string as_string () const; + Analysis::NodeMapping get_mappings () const { return mappings; } + + Location get_locus () { return locus; } }; // Rust struct declaration with true struct type HIR node @@ -1560,6 +1568,15 @@ public: void accept_vis (HIRVisitor &vis) override; + void iterate (std::function<bool (StructField &)> cb) + { + for (auto &field : fields) + { + if (!cb (field)) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2055,6 +2072,12 @@ public: void accept_vis (HIRVisitor &vis) override; + Type *get_type () { return type.get (); } + + Expr *get_expr () { return const_expr.get (); } + + std::string get_identifier () { return identifier; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2134,6 +2157,14 @@ public: void accept_vis (HIRVisitor &vis) override; + Identifier get_identifier () const { return name; } + + bool is_mutable () const { return has_mut; } + + Expr *get_expr () { return expr.get (); } + + Type *get_type () { return type.get (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 3ff13d2..d18d8db 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -47,8 +47,8 @@ public: LiteralPattern (std::string val, Literal::LitType type, Location locus, bool has_minus = false) - : lit (Literal (std::move (val), type)), has_minus (has_minus), - locus (locus) + : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)), + has_minus (has_minus), locus (locus) {} Location get_locus () const { return locus; } diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index cbaa2e9..7417a32 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -235,21 +235,27 @@ public: }; private: - /* TODO: maybe make subclasses of each type of literal with their typed values - * (or generics) */ std::string value_as_string; LitType type; + PrimitiveCoreType type_hint; public: std::string as_string () const { return value_as_string; } LitType get_lit_type () const { return type; } - Literal (std::string value_as_string, LitType type) - : value_as_string (std::move (value_as_string)), type (type) + PrimitiveCoreType get_type_hint () const { return type_hint; } + + Literal (std::string value_as_string, LitType type, + PrimitiveCoreType type_hint) + : value_as_string (std::move (value_as_string)), type (type), + type_hint (type_hint) {} - static Literal create_error () { return Literal ("", CHAR); } + static Literal create_error () + { + return Literal ("", CHAR, PrimitiveCoreType::CORETYPE_UNKNOWN); + } // Returns whether literal is in an invalid state. bool is_error () const { return value_as_string == ""; } diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index cc89ad5..87e02dd 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -791,7 +791,8 @@ Parser<ManagedTokenSource>::parse_attr_input () } // create actual LiteralExpr - AST::LiteralExpr lit_expr (t->get_str (), lit_type, t->get_locus ()); + AST::LiteralExpr lit_expr (t->get_str (), lit_type, t->get_type_hint (), + t->get_locus ()); std::unique_ptr<AST::AttrInputLiteral> attr_input_lit ( new AST::AttrInputLiteral (std::move (lit_expr))); @@ -7376,7 +7377,8 @@ Parser<ManagedTokenSource>::parse_literal_expr ( // create literal based on stuff in switch return std::unique_ptr<AST::LiteralExpr> ( new AST::LiteralExpr (std::move (literal_value), std::move (type), - t->get_locus (), std::move (outer_attrs))); + t->get_type_hint (), t->get_locus (), + std::move (outer_attrs))); } // Parses a return expression (including any expression to return). @@ -9952,7 +9954,8 @@ Parser<ManagedTokenSource>::parse_literal_or_range_pattern () lexer.skip_token (); std::unique_ptr<AST::RangePatternBound> lower ( new AST::RangePatternBoundLiteral ( - AST::Literal (range_lower->get_str (), type), + AST::Literal (range_lower->get_str (), type, + PrimitiveCoreType::CORETYPE_UNKNOWN), range_lower->get_locus (), has_minus)); std::unique_ptr<AST::RangePatternBound> upper @@ -9993,26 +9996,30 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound () lexer.skip_token (); return std::unique_ptr<AST::RangePatternBoundLiteral> ( new AST::RangePatternBoundLiteral ( - AST::Literal (range_lower->get_str (), AST::Literal::CHAR), + AST::Literal (range_lower->get_str (), AST::Literal::CHAR, + range_lower->get_type_hint ()), range_lower_locus)); case BYTE_CHAR_LITERAL: lexer.skip_token (); return std::unique_ptr<AST::RangePatternBoundLiteral> ( new AST::RangePatternBoundLiteral ( - AST::Literal (range_lower->get_str (), AST::Literal::BYTE), + AST::Literal (range_lower->get_str (), AST::Literal::BYTE, + range_lower->get_type_hint ()), range_lower_locus)); case INT_LITERAL: lexer.skip_token (); return std::unique_ptr<AST::RangePatternBoundLiteral> ( new AST::RangePatternBoundLiteral ( - AST::Literal (range_lower->get_str (), AST::Literal::INT), + AST::Literal (range_lower->get_str (), AST::Literal::INT, + range_lower->get_type_hint ()), range_lower_locus)); case FLOAT_LITERAL: lexer.skip_token (); fprintf (stderr, "warning: used deprecated float range pattern bound"); return std::unique_ptr<AST::RangePatternBoundLiteral> ( new AST::RangePatternBoundLiteral ( - AST::Literal (range_lower->get_str (), AST::Literal::FLOAT), + AST::Literal (range_lower->get_str (), AST::Literal::FLOAT, + range_lower->get_type_hint ()), range_lower_locus)); case MINUS: // branch on next token @@ -10023,7 +10030,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound () lexer.skip_token (1); return std::unique_ptr<AST::RangePatternBoundLiteral> ( new AST::RangePatternBoundLiteral ( - AST::Literal (range_lower->get_str (), AST::Literal::INT), + AST::Literal (range_lower->get_str (), AST::Literal::INT, + range_lower->get_type_hint ()), range_lower_locus, true)); case FLOAT_LITERAL: lexer.skip_token (1); @@ -10031,7 +10039,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound () "warning: used deprecated float range pattern bound"); return std::unique_ptr<AST::RangePatternBoundLiteral> ( new AST::RangePatternBoundLiteral ( - AST::Literal (range_lower->get_str (), AST::Literal::FLOAT), + AST::Literal (range_lower->get_str (), AST::Literal::FLOAT, + range_lower->get_type_hint ()), range_lower_locus, true)); default: rust_error_at (range_lower->get_locus (), @@ -12105,22 +12114,24 @@ Parser<ManagedTokenSource>::null_denotation ( // encode as int? return std::unique_ptr<AST::LiteralExpr> ( new AST::LiteralExpr (tok->get_str (), AST::Literal::INT, - tok->get_locus ())); + tok->get_type_hint (), tok->get_locus ())); case FLOAT_LITERAL: // encode as float? return std::unique_ptr<AST::LiteralExpr> ( new AST::LiteralExpr (tok->get_str (), AST::Literal::FLOAT, - tok->get_locus ())); + tok->get_type_hint (), tok->get_locus ())); case STRING_LITERAL: return std::unique_ptr<AST::LiteralExpr> ( new AST::LiteralExpr (tok->get_str (), AST::Literal::STRING, - tok->get_locus ())); + tok->get_type_hint (), tok->get_locus ())); case TRUE_LITERAL: return std::unique_ptr<AST::LiteralExpr> ( - new AST::LiteralExpr ("true", AST::Literal::BOOL, tok->get_locus ())); + new AST::LiteralExpr ("true", AST::Literal::BOOL, tok->get_type_hint (), + tok->get_locus ())); case FALSE_LITERAL: return std::unique_ptr<AST::LiteralExpr> ( - new AST::LiteralExpr ("false", AST::Literal::BOOL, tok->get_locus ())); + new AST::LiteralExpr ("false", AST::Literal::BOOL, + tok->get_type_hint (), tok->get_locus ())); case LEFT_PAREN: { // have to parse whole expression if inside brackets /* recursively invoke parse_expression with lowest priority possible as * it it were a top-level expression. */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index d86866c..2292d16 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -21,6 +21,7 @@ #include "rust-ast-resolve-base.h" #include "rust-ast-full.h" +#include "rust-ast-resolve-struct-expr-field.h" namespace Rust { namespace Resolver { @@ -38,19 +39,22 @@ public: void visit (AST::PathInExpression &expr) { + // name scope first if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) { - rust_error_at (expr.get_locus (), "unknown path %s", - expr.as_string ().c_str ()); - return; - } - else - { - resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - resolver->insert_new_definition (expr.get_node_id (), - Definition{expr.get_node_id (), - parent}); + // check the type scope + if (!resolver->get_type_scope ().lookup (expr.as_string (), + &resolved_node)) + { + rust_error_at (expr.get_locus (), "unknown path %s", + expr.as_string ().c_str ()); + return; + } } + + resolver->insert_resolved_name (expr.get_node_id (), resolved_node); + resolver->insert_new_definition (expr.get_node_id (), + Definition{expr.get_node_id (), parent}); } void visit (AST::ReturnExpr &expr) @@ -154,6 +158,17 @@ public: ResolveExpr::go (elems.get_elem_to_copy ().get (), elems.get_node_id ()); } + void visit (AST::StructExprStructFields &struct_expr) + { + ResolveExpr::go (&struct_expr.get_struct_name (), + struct_expr.get_node_id ()); + struct_expr.iterate ( + [&] (AST::StructExprField *struct_field) mutable -> bool { + ResolveStructExprField::go (struct_field, struct_expr.get_node_id ()); + return true; + }); + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 2c21a52..c3b2312 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -39,6 +39,26 @@ public: ~ResolveItem () {} + void visit (AST::StructStruct &struct_decl) + { + struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool { + ResolveType::go (field.get_field_type ().get (), field.get_node_id ()); + return true; + }); + } + + void visit (AST::StaticItem &var) + { + ResolveType::go (var.get_type ().get (), var.get_node_id ()); + ResolveExpr::go (var.get_expr ().get (), var.get_node_id ()); + } + + void visit (AST::ConstantItem &constant) + { + ResolveType::go (constant.get_type ().get (), constant.get_node_id ()); + ResolveExpr::go (constant.get_expr ().get (), constant.get_node_id ()); + } + void visit (AST::Function &function) { if (function.has_return_type ()) diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h new file mode 100644 index 0000000..c705a03 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h @@ -0,0 +1,53 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_STRUCT_EXPR_FIELD +#define RUST_AST_RESOLVE_STRUCT_EXPR_FIELD + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +// this resolves values being assigned not that the field actually exists yet. +// We cant resolve the field to struct until type resolution since the HIR +// Mappings don't exist yet. +class ResolveStructExprField : public ResolverBase +{ +public: + static void go (AST::StructExprField *field, NodeId parent) + { + ResolveStructExprField resolver (parent); + field->accept_vis (resolver); + } + + virtual ~ResolveStructExprField () {} + + void visit (AST::StructExprFieldIdentifierValue &field); + + // TODO + +private: + ResolveStructExprField (NodeId parent) : ResolverBase (parent) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_STRUCT_EXPR_FIELD diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index fcc9663..6a4395f 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -36,6 +36,30 @@ public: ~ResolveTopLevel () {} + void visit (AST::StructStruct &struct_decl) + { + resolver->get_type_scope ().insert (struct_decl.get_identifier (), + struct_decl.get_node_id ()); + } + + void visit (AST::StaticItem &var) + { + resolver->get_name_scope ().insert (var.get_identifier (), + var.get_node_id ()); + resolver->insert_new_definition (var.get_node_id (), + Definition{var.get_node_id (), + var.get_node_id ()}); + } + + void visit (AST::ConstantItem &constant) + { + resolver->get_name_scope ().insert (constant.get_identifier (), + constant.get_node_id ()); + resolver->insert_new_definition (constant.get_node_id (), + Definition{constant.get_node_id (), + constant.get_node_id ()}); + } + void visit (AST::Function &function) { // function_names are simple std::String identifiers so this can be a diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 8370a5b..fe8d7e0 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -126,20 +126,38 @@ Resolver::generate_builtins () = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U16); auto u32 = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U32); + auto u64 + = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U64); + auto u128 + = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U128); auto i8 = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I8); auto i16 = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I16); auto i32 = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I32); + auto i64 + = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I64); + auto i128 + = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I128); auto rbool = new TyTy::BoolType (mappings->get_next_hir_id ()); + auto f32 + = new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F32); + auto f64 + = new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F64); MKBUILTIN_TYPE ("u8", builtins, u8); MKBUILTIN_TYPE ("u16", builtins, u16); MKBUILTIN_TYPE ("u32", builtins, u32); + MKBUILTIN_TYPE ("u64", builtins, u64); + MKBUILTIN_TYPE ("u128", builtins, u128); MKBUILTIN_TYPE ("i8", builtins, i8); MKBUILTIN_TYPE ("i16", builtins, i16); MKBUILTIN_TYPE ("i32", builtins, i32); + MKBUILTIN_TYPE ("i64", builtins, i64); + MKBUILTIN_TYPE ("i128", builtins, i128); MKBUILTIN_TYPE ("bool", builtins, rbool); + MKBUILTIN_TYPE ("f32", builtins, f32); + MKBUILTIN_TYPE ("f64", builtins, f64); } void @@ -271,5 +289,13 @@ ResolveExpr::visit (AST::BlockExpr &expr) resolver->get_type_scope ().pop (); } +// rust-ast-resolve-struct-expr-field.h + +void +ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field) +{ + ResolveExpr::go (field.get_value ().get (), field.get_node_id ()); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 474986d..bfa7609 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -2527,7 +2527,7 @@ Gcc_backend::global_variable_set_init (Bvariable *var, Bexpression *expr) return; DECL_INITIAL (var_decl) = expr_tree; - // If this variable rustes in a unique section, it may need to rust into + // If this variable goes in a unique section, it may need to go into // a different one now that DECL_INITIAL is set. if (symtab_node::get (var_decl) && symtab_node::get (var_decl)->implicit_section) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 17ff24a..c1df913 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -359,9 +359,10 @@ Session::enable_dump (std::string arg) * created */ if (arg == "all") { - rust_error_at (Location (), - "dumping all is not supported as of now. choose %<lex%>, %<parse%>, " - "or %<target_options%>"); + rust_error_at ( + Location (), + "dumping all is not supported as of now. choose %<lex%>, %<parse%>, " + "or %<target_options%>"); return false; } else if (arg == "lex") @@ -409,10 +410,11 @@ Session::enable_dump (std::string arg) } else { - rust_error_at (Location (), - "dump option %qs was unrecognised. choose %<lex%>, %<parse%>, or " - "%<target_options%>", - arg.c_str ()); + rust_error_at ( + Location (), + "dump option %qs was unrecognised. choose %<lex%>, %<parse%>, or " + "%<target_options%>", + arg.c_str ()); return false; } return true; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 116fab7..a5440c0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -24,6 +24,7 @@ #include "rust-tyty.h" #include "rust-tyty-call.h" #include "rust-tyty-resolver.h" +#include "rust-hir-type-check-struct-field.h" namespace Rust { namespace Resolver { @@ -136,9 +137,8 @@ public: TyTy::TyBase *lookup; if (!context->lookup_type (ref, &lookup)) { - // FIXME we need to be able to lookup the location info for the - // reference here - rust_error_at (expr.get_locus (), "consider giving this a type: %s", + rust_error_at (mappings->lookup_location (ref), + "consider giving this a type: %s", expr.as_string ().c_str ()); return; } @@ -152,10 +152,53 @@ public: switch (expr.get_lit_type ()) { case HIR::Literal::LitType::INT: { - // FIXME: - // assume i32 let the combiner functions figure it out - // this should look at the suffix of the literal value to check - auto ok = context->lookup_builtin ("i32", &infered); + bool ok = false; + + switch (expr.get_literal ()->get_type_hint ()) + { + case CORETYPE_I8: + ok = context->lookup_builtin ("i8", &infered); + break; + case CORETYPE_I16: + ok = context->lookup_builtin ("i16", &infered); + break; + case CORETYPE_I32: + ok = context->lookup_builtin ("i32", &infered); + break; + case CORETYPE_I64: + ok = context->lookup_builtin ("i64", &infered); + break; + case CORETYPE_I128: + ok = context->lookup_builtin ("i128", &infered); + break; + + case CORETYPE_U8: + ok = context->lookup_builtin ("u8", &infered); + break; + case CORETYPE_U16: + ok = context->lookup_builtin ("u16", &infered); + break; + case CORETYPE_U32: + ok = context->lookup_builtin ("u32", &infered); + break; + case CORETYPE_U64: + ok = context->lookup_builtin ("u64", &infered); + break; + case CORETYPE_U128: + ok = context->lookup_builtin ("u128", &infered); + break; + + default: + ok = context->lookup_builtin ("i32", &infered); + break; + } + rust_assert (ok); + } + break; + + case HIR::Literal::LitType::FLOAT: { + // FIXME need to respect the suffix if applicable + auto ok = context->lookup_builtin ("f32", &infered); rust_assert (ok); } break; @@ -269,6 +312,11 @@ public: infered_array_elems = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); } + void visit (HIR::StructExprStructFields &struct_expr) + { + infered = TypeCheckStructExpr::Resolve (&struct_expr); + } + private: TypeCheckExpr () : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h new file mode 100644 index 0000000..727569d --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -0,0 +1,61 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_STRUCT_FIELD +#define RUST_HIR_TYPE_CHECK_STRUCT_FIELD + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckStructExpr : public TypeCheckBase +{ +public: + static TyTy::TyBase *Resolve (HIR::StructExprStructFields *expr) + { + TypeCheckStructExpr resolver; + expr->accept_vis (resolver); + rust_assert (resolver.resolved != nullptr); + return resolver.resolved; + } + + void visit (HIR::StructExprStructFields &struct_expr); + + void visit (HIR::PathInExpression &path); + + void visit (HIR::StructExprFieldIdentifierValue &field); + +private: + TypeCheckStructExpr () + : TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr) + {} + + TyTy::TyBase *resolved; + TyTy::ADTType *struct_path_resolved; + TyTy::TyBase *resolved_field; + std::set<std::string> fields_assigned; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_STRUCT_FIELD diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 25e6c0b..34e7020 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -22,6 +22,7 @@ #include "rust-hir-type-check-base.h" #include "rust-hir-full.h" #include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" #include "rust-tyty.h" namespace Rust { @@ -36,6 +37,46 @@ public: item->accept_vis (resolver); } + void visit (HIR::StructStruct &struct_decl) + { + std::vector<TyTy::StructFieldType *> fields; + struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool { + TyTy::TyBase *field_type + = TypeCheckType::Resolve (field.get_field_type ().get ()); + TyTy::StructFieldType *ty_field + = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), + field.get_field_name (), field_type); + fields.push_back (ty_field); + context->insert_type (field.get_mappings ().get_hirid (), + ty_field->get_field_type ()); + return true; + }); + + TyTy::TyBase *type + = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), + struct_decl.get_identifier (), std::move (fields)); + + context->insert_type (struct_decl.get_mappings ().get_hirid (), type); + } + + void visit (HIR::StaticItem &var) + { + TyTy::TyBase *type = TypeCheckType::Resolve (var.get_type ()); + TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (var.get_expr ()); + + context->insert_type (var.get_mappings ().get_hirid (), + type->combine (expr_type)); + } + + void visit (HIR::ConstantItem &constant) + { + TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ()); + TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + + context->insert_type (constant.get_mappings ().get_hirid (), + type->combine (expr_type)); + } + void visit (HIR::Function &function) { TyTy::TyBase *ret_type = nullptr; diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 21d6c23..8ff4c44 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -87,7 +87,8 @@ public: if (!resolver->lookup_resolved_type (path.get_mappings ().get_nodeid (), &ref)) { - rust_error_at (path.get_locus (), "Type was not resolved"); + rust_fatal_error (path.get_locus (), + "Failed to resolve node id to HIR"); return; } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 79e0190..e7d3366 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -21,6 +21,7 @@ #include "rust-hir-type-check-toplevel.h" #include "rust-hir-type-check-item.h" #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-struct-field.h" namespace Rust { namespace Resolver { @@ -45,5 +46,123 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) }); } +// RUST_HIR_TYPE_CHECK_STRUCT_FIELD + +void +TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) +{ + struct_expr.get_struct_name ().accept_vis (*this); + if (struct_path_resolved == nullptr) + { + rust_fatal_error (struct_expr.get_struct_name ().get_locus (), + "Failed to resolve type"); + return; + } + + struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool { + resolved_field = nullptr; + field->accept_vis (*this); + if (resolved_field == nullptr) + { + rust_fatal_error (field->get_locus (), + "failed to resolve type for field"); + return false; + } + + context->insert_type (field->get_mappings ().get_hirid (), resolved_field); + return true; + }); + + TyTy::TyBase *expr_type = struct_path_resolved; + if (struct_expr.has_struct_base ()) + { + TyTy::TyBase *base_resolved + = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ()); + expr_type = expr_type->combine (base_resolved); + if (resolved == nullptr) + { + rust_fatal_error ( + struct_expr.struct_base->base_struct->get_locus_slow (), + "incompatible types for base struct reference"); + return; + } + } + else if (fields_assigned.size () != struct_path_resolved->num_fields ()) + { + rust_fatal_error (struct_expr.get_locus (), + "some fields are not fully assigned"); + return; + } + + resolved = expr_type; +} + +void +TypeCheckStructExpr::visit (HIR::PathInExpression &expr) +{ + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup reference for node: %s", + expr.as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + ref_node_id, &ref)) + { + rust_error_at (expr.get_locus (), "reverse lookup failure"); + return; + } + + // the base reference for this name _must_ have a type set + TyTy::TyBase *lookup; + if (!context->lookup_type (ref, &lookup)) + { + rust_error_at (mappings->lookup_location (ref), + "consider giving this a type: %s", + expr.as_string ().c_str ()); + return; + } + + if (lookup->get_kind () != TyTy::TypeKind::ADT) + { + rust_fatal_error (mappings->lookup_location (ref), + "expected an ADT type"); + return; + } + struct_path_resolved = (TyTy::ADTType *) lookup; +} + +void +TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) +{ + auto it = fields_assigned.find (field.field_name); + if (it != fields_assigned.end ()) + { + rust_fatal_error (field.get_locus (), "used more than once"); + return; + } + + TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); + TyTy::StructFieldType *field_type + = struct_path_resolved->get_field (field.field_name); + if (field_type == nullptr) + { + rust_error_at (field.get_locus (), "unknown field"); + return; + } + + resolved_field = field_type->get_field_type ()->combine (value); + if (resolved_field != nullptr) + fields_assigned.insert (field.field_name); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 97ee895..615ef80 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -134,6 +134,24 @@ private: TyBase *resolved; }; +class StructFieldTypeRules : protected BaseRules +{ +public: + StructFieldTypeRules (StructFieldType *base) + : BaseRules (base), base (base), resolved (nullptr) + {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + StructFieldType *base; + TyBase *resolved; +}; + class UnitRules : protected BaseRules { public: @@ -298,6 +316,31 @@ private: TyBase *resolved; }; +class FloatRules : protected BaseRules +{ +public: + FloatRules (FloatType *base) + : BaseRules (base), base (base), resolved (nullptr) + {} + ~FloatRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + + void visit (FloatType &type) override + { + // FIXME we should look at the FloatKind and respect it + resolved = new FloatType (type.get_ref (), type.get_kind ()); + } + +private: + FloatType *base; + TyBase *resolved; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 427190f..40998ca 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -29,12 +29,15 @@ class TyVisitor public: virtual void visit (UnitType &type) {} virtual void visit (InferType &type) {} + virtual void visit (StructFieldType &type) {} + virtual void visit (ADTType &type) {} virtual void visit (FnType &type) {} virtual void visit (ParamType &type) {} virtual void visit (ArrayType &type) {} virtual void visit (BoolType &type) {} virtual void visit (IntType &type) {} virtual void visit (UintType &type) {} + virtual void visit (FloatType &type) {} }; } // namespace TyTy diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 2023523..0cefab6 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -64,6 +64,47 @@ InferType::combine (TyBase *other) } void +StructFieldType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +StructFieldType::as_string () const +{ + return name + ":" + ty->as_string (); +} + +TyBase * +StructFieldType::combine (TyBase *other) +{ + StructFieldTypeRules r (this); + return r.combine (other); +} + +void +ADTType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +ADTType::as_string () const +{ + std::string fields_buffer; + for (auto &field : fields) + fields_buffer += field->as_string () + "\n"; + + return identifier + "{\n" + fields_buffer + "\n}"; +} + +TyBase * +ADTType::combine (TyBase *other) +{ + return nullptr; +} + +void FnType::accept_vis (TyVisitor &vis) { vis.visit (*this); @@ -164,6 +205,10 @@ IntType::as_string () const return "i16"; case I32: return "i32"; + case I64: + return "i64"; + case I128: + return "i128"; } gcc_unreachable (); return "__unknown_int_type"; @@ -193,6 +238,10 @@ UintType::as_string () const return "u16"; case U32: return "u32"; + case U64: + return "u64"; + case U128: + return "u128"; } gcc_unreachable (); return "__unknown_uint_type"; @@ -206,6 +255,33 @@ UintType::combine (TyBase *other) } void +FloatType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +FloatType::as_string () const +{ + switch (float_kind) + { + case F32: + return "f32"; + case F64: + return "f64"; + } + gcc_unreachable (); + return "__unknown_float_type"; +} + +TyBase * +FloatType::combine (TyBase *other) +{ + FloatRules r (this); + return r.combine (other); +} + +void TypeCheckCallExpr::visit (FnType &type) { if (call.num_params () != type.num_params ()) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index b9dc268..59c4bcb 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -41,6 +41,7 @@ enum TypeKind UINT, FLOAT, UNIT, + FIELD, // there are more to add... }; @@ -60,6 +61,8 @@ public: virtual bool is_unit () const { return kind == TypeKind::UNIT; } + TypeKind get_kind () const { return kind; } + protected: TyBase (HirId ref, TypeKind kind) : kind (kind), ref (ref) {} @@ -95,6 +98,65 @@ public: TyBase *combine (TyBase *other) override; }; +class StructFieldType : public TyBase +{ +public: + StructFieldType (HirId ref, std::string name, TyBase *ty) + : TyBase (ref, TypeKind::FIELD), name (name), ty (ty) + {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return ty->is_unit (); } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + std::string get_name () const { return name; } + + TyBase *get_field_type () { return ty; } + +private: + std::string name; + TyBase *ty; +}; + +class ADTType : public TyBase +{ +public: + ADTType (HirId ref, std::string identifier, + std::vector<StructFieldType *> fields) + : TyBase (ref, TypeKind::ADT), identifier (identifier), fields (fields) + {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return false; } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + size_t num_fields () const { return fields.size (); } + + StructFieldType *get_field (size_t index) { return fields.at (index); } + + StructFieldType *get_field (const std::string &lookup) + { + for (auto &field : fields) + { + if (field->get_name ().compare (lookup) == 0) + return field; + } + return nullptr; + } + +private: + std::string identifier; + std::vector<StructFieldType *> fields; +}; + class ParamType : public TyBase { public: @@ -185,6 +247,8 @@ public: I8, I16, I32, + I64, + I128 }; IntType (HirId ref, IntKind kind) @@ -211,6 +275,8 @@ public: U8, U16, U32, + U64, + U128 }; UintType (HirId ref, UintKind kind) @@ -229,6 +295,31 @@ private: UintKind uint_kind; }; +class FloatType : public TyBase +{ +public: + enum FloatKind + { + F32, + F64 + }; + + FloatType (HirId ref, FloatKind kind) + : TyBase (ref, TypeKind::FLOAT), float_kind (kind) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + FloatKind get_kind () const { return float_kind; } + +private: + FloatKind float_kind; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/testsuite/rust.test/compilable/constant1.rs b/gcc/testsuite/rust.test/compilable/constant1.rs new file mode 100644 index 0000000..e8ef96b --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/constant1.rs @@ -0,0 +1,8 @@ +const TEST_CONST:i32 = 10; + +fn main() { + let mut x = TEST_CONST; + x = x + 1; + + let mut y = x + TEST_CONST; +} diff --git a/gcc/testsuite/rust.test/compilable/float1.rs b/gcc/testsuite/rust.test/compilable/float1.rs new file mode 100644 index 0000000..57a746f --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/float1.rs @@ -0,0 +1,8 @@ +fn test(x: f32) -> f32 { + return x + 1.0; +} + +fn main() { + let a_float = 5.123; + let call_test = test(a_float + 1.0); +} diff --git a/gcc/testsuite/rust.test/compilable/integer_types.rs b/gcc/testsuite/rust.test/compilable/integer_types.rs new file mode 100644 index 0000000..22a9164 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/integer_types.rs @@ -0,0 +1,25 @@ +fn main() { + let a1: i8 = 1i8; + let a2: i16 = 2i16; + let a3: i32 = 3i32; + let a4: i64 = 4i64; + let a5: i128 = 5i128; + + let b1 = 1i8; + let b2 = 2i16; + let b3 = 3i32; + let b4 = 4i64; + let b5 = 5i128; + + let c1: u8 = 1u8; + let c2: u16 = 2u16; + let c3: u32 = 3u32; + let c4: u64 = 4u64; + let c5: u128 = 5u128; + + let d1 = 1u8; + let d2 = 2u16; + let d3 = 3u32; + let d4 = 4u64; + let d5 = 5u128; +} diff --git a/gcc/testsuite/rust.test/compilable/static_var1.rs b/gcc/testsuite/rust.test/compilable/static_var1.rs new file mode 100644 index 0000000..8464f41 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/static_var1.rs @@ -0,0 +1,5 @@ +static x:i32 = 3; + +fn main() { + let y = x +1; +} diff --git a/gcc/testsuite/rust.test/fail_compilation/static_var1.rs b/gcc/testsuite/rust.test/fail_compilation/static_var1.rs new file mode 100644 index 0000000..d94c8c1 --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/static_var1.rs @@ -0,0 +1,5 @@ +static x = 3; + +fn main() { + let y = x +1; +} |