diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-11-12 22:22:41 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-08 21:10:28 +0800 |
commit | f5ae2781823b3a2bcded1ac3446de83cc52403a9 (patch) | |
tree | e90b9876a23cd40e0da140aa62fb220ef22dfd58 /gcc | |
parent | 37bbf2b8cbd4578f0fbe7cbbd573493481f62a45 (diff) | |
download | gcc-f5ae2781823b3a2bcded1ac3446de83cc52403a9.zip gcc-f5ae2781823b3a2bcded1ac3446de83cc52403a9.tar.gz gcc-f5ae2781823b3a2bcded1ac3446de83cc52403a9.tar.bz2 |
Added more expression stripping
Fixed compile errors and started on enum expr stripping
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.cc | 14 | ||||
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.h | 4 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 84 | ||||
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 4 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 18 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 200 |
6 files changed, 264 insertions, 60 deletions
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 87cf828..fcf475e 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -427,15 +427,15 @@ TypeResolution::visit (AST::StructExprFieldIdentifier &field) void TypeResolution::visit (AST::StructExprFieldIdentifierValue &field) { - identifierBuffer = &field.field_name; - field.value->accept_vis (*this); + identifierBuffer = std::unique_ptr<std::string> (new std::string (field.get_field_name ())); + field.get_value ()->accept_vis (*this); } void TypeResolution::visit (AST::StructExprFieldIndexValue &field) { - tupleIndexBuffer = &field.index; - field.value->accept_vis (*this); + tupleIndexBuffer = std::unique_ptr<int> (new int (field.get_index ())); + field.get_value ()->accept_vis (*this); } void @@ -448,7 +448,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr) return; } - for (auto &field : expr.fields) + for (auto &field : expr.get_fields ()) { identifierBuffer = NULL; tupleIndexBuffer = NULL; @@ -1069,14 +1069,14 @@ TypeResolution::visit (AST::LetStmt &stmt) void TypeResolution::visit (AST::ExprStmtWithoutBlock &stmt) { - stmt.expr->accept_vis (*this); + stmt.get_expr ()->accept_vis (*this); } void TypeResolution::visit (AST::ExprStmtWithBlock &stmt) { scope.Push (); - stmt.expr->accept_vis (*this); + stmt.get_expr ()->accept_vis (*this); auto localMap = scope.PeekLocals (); for (auto &[_, value] : localMap) { diff --git a/gcc/rust/analysis/rust-type-resolution.h b/gcc/rust/analysis/rust-type-resolution.h index af4594e..0c6413b 100644 --- a/gcc/rust/analysis/rust-type-resolution.h +++ b/gcc/rust/analysis/rust-type-resolution.h @@ -301,8 +301,8 @@ private: bool isTypeInScope (AST::Type *type, Location locus); TypeScoping scope; - std::string *identifierBuffer; - int *tupleIndexBuffer; + std::unique_ptr<std::string> identifierBuffer; + std::unique_ptr<int> tupleIndexBuffer; }; } // namespace Analysis diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index a92a8ad..1cf8f9c 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1218,7 +1218,8 @@ class TupleExpr : public ExprWithoutBlock public: std::string as_string () const override; - std::vector<Attribute> get_inner_attrs () const { return inner_attrs; } + const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } + std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements, std::vector<Attribute> inner_attribs, @@ -1269,6 +1270,10 @@ public: void mark_for_strip () override { marked_for_strip = true; } bool is_marked_for_strip () const override { return marked_for_strip; } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const { return tuple_elems; } + std::vector<std::unique_ptr<Expr> > &get_tuple_elems () { return tuple_elems; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1340,6 +1345,12 @@ public: void mark_for_strip () override { tuple_expr = nullptr; } bool is_marked_for_strip () const override { return tuple_expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_tuple_expr () { + rust_assert (tuple_expr != nullptr); + return tuple_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1382,7 +1393,8 @@ class StructExprStruct : public StructExpr public: std::string as_string () const override; - std::vector<Attribute> get_inner_attrs () const { return inner_attrs; } + const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } + std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } // Constructor has to call protected constructor of base class StructExprStruct (PathInExpression struct_path, @@ -1410,9 +1422,10 @@ protected: * struct */ struct StructBase { -public: +private: std::unique_ptr<Expr> base_struct; +public: // TODO: should this store location data? StructBase (std::unique_ptr<Expr> base_struct_ptr) : base_struct (std::move (base_struct_ptr)) @@ -1453,6 +1466,12 @@ public: bool is_invalid () const { return base_struct == nullptr; } std::string as_string () const; + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_base_struct () { + rust_assert (base_struct != nullptr); + return base_struct; + } }; /* Base AST node for a single struct expression field (in struct instance @@ -1480,11 +1499,10 @@ protected: // Identifier-only variant of StructExprField AST node class StructExprFieldIdentifier : public StructExprField { -public: Identifier field_name; // TODO: should this store location data? - +public: StructExprFieldIdentifier (Identifier field_identifier) : field_name (std::move (field_identifier)) {} @@ -1506,7 +1524,6 @@ protected: * abstract */ class StructExprFieldWithVal : public StructExprField { -public: std::unique_ptr<Expr> value; protected: @@ -1533,16 +1550,21 @@ protected: public: std::string as_string () const override; + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_value () { + rust_assert (value != nullptr); + return value; + } }; // Identifier and value variant of StructExprField AST node class StructExprFieldIdentifierValue : public StructExprFieldWithVal { -public: Identifier field_name; // TODO: should this store location data? - +public: StructExprFieldIdentifierValue (Identifier field_identifier, std::unique_ptr<Expr> field_value) : StructExprFieldWithVal (std::move (field_value)), @@ -1553,6 +1575,8 @@ public: void accept_vis (ASTVisitor &vis) override; + std::string get_field_name () const { return field_name; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1565,11 +1589,10 @@ protected: // Tuple index and value variant of StructExprField AST node class StructExprFieldIndexValue : public StructExprFieldWithVal { -public: TupleIndex index; // TODO: should this store location data? - +public: StructExprFieldIndexValue (TupleIndex tuple_index, std::unique_ptr<Expr> field_value) : StructExprFieldWithVal (std::move (field_value)), index (tuple_index) @@ -1579,6 +1602,8 @@ public: void accept_vis (ASTVisitor &vis) override; + TupleIndex get_index () const { return index; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1591,25 +1616,17 @@ protected: // AST node of a struct creator with fields class StructExprStructFields : public StructExprStruct { -public: // std::vector<StructExprField> fields; std::vector<std::unique_ptr<StructExprField> > fields; // bool has_struct_base; StructBase struct_base; +public: 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(); - }*/ - // Constructor for StructExprStructFields when no struct base is used StructExprStructFields ( PathInExpression struct_path, @@ -1650,6 +1667,13 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<std::unique_ptr<StructExprField> > &get_fields () { return fields; } + const std::vector<std::unique_ptr<StructExprField> > &get_fields () const { return fields; } + + StructBase &get_struct_base () { return struct_base; } + const StructBase &get_struct_base () const { return struct_base; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1660,6 +1684,8 @@ protected: }; // AST node of the functional update struct creator +/* TODO: remove and replace with StructExprStructFields, except with empty + * vector of fields? */ class StructExprStructBase : public StructExprStruct { StructBase struct_base; @@ -1667,10 +1693,6 @@ class StructExprStructBase : public StructExprStruct public: std::string as_string () const override; - /*inline StructBase get_struct_base() const { - return struct_base; - }*/ - StructExprStructBase (PathInExpression struct_path, StructBase base_struct, std::vector<Attribute> inner_attribs, std::vector<Attribute> outer_attribs, Location locus) @@ -1681,6 +1703,9 @@ public: void accept_vis (ASTVisitor &vis) override; + StructBase &get_struct_base () { return struct_base; } + const StructBase &get_struct_base () const { return struct_base; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1702,10 +1727,7 @@ public: std::string as_string () const override; const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } - - /*inline std::vector<std::unique_ptr<Expr>> get_exprs() const { - return exprs; - }*/ + std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } StructExprTuple (PathInExpression struct_path, std::vector<std::unique_ptr<Expr> > tuple_exprs, @@ -1748,6 +1770,9 @@ public: void accept_vis (ASTVisitor &vis) override; + const std::vector<std::unique_ptr<Expr> > &get_elems () const { return exprs; } + std::vector<std::unique_ptr<Expr> > &get_elems () { return exprs; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1766,7 +1791,6 @@ public: std::string as_string () const override { return get_struct_name ().as_string (); - // return struct_name.as_string(); } StructExprUnit (PathInExpression struct_path, @@ -1990,6 +2014,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<std::unique_ptr<EnumExprField> > &get_fields () { return fields; } + const std::vector<std::unique_ptr<EnumExprField> > &get_fields () const { return fields; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index f7c47d7..0bb1021 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -160,7 +160,6 @@ protected: * difficulties, can only be guaranteed to hold an expression). */ class ExprStmtWithoutBlock : public ExprStmt { -public: // TODO: ensure that this works std::unique_ptr<ExprWithoutBlock> expr; /* HACK: cannot ensure type safety of ExprWithoutBlock due to Pratt parsing, @@ -168,6 +167,7 @@ public: * or redesign AST. */ // std::unique_ptr<Expr> expr; +public: std::string as_string () const override; ExprStmtWithoutBlock (std::unique_ptr<ExprWithoutBlock> expr, Location locus) @@ -232,9 +232,9 @@ protected: // Statement containing an expression with a block class ExprStmtWithBlock : public ExprStmt { -public: std::unique_ptr<ExprWithBlock> expr; +public: std::string as_string () const override; std::vector<LetStmt *> locals; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 0589347..ca310ca 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -538,7 +538,7 @@ Compilation::visit (AST::StructExprFieldIdentifierValue &field) bool found = false; for (auto &df : decl->get_fields ()) { - if (field.field_name.compare (df.field_name) == 0) + if (field.get_field_name ().compare (df.field_name) == 0) { found = true; break; @@ -546,16 +546,16 @@ Compilation::visit (AST::StructExprFieldIdentifierValue &field) } if (!found) { - rust_fatal_error (field.value->get_locus_slow (), + rust_fatal_error (field.get_value ()->get_locus_slow (), "failed to lookup field index"); return; } Bexpression *value = NULL; - VISIT_POP (field.value->get_locus_slow (), field.value.get (), value, exprs); + VISIT_POP (field.get_value ()->get_locus_slow (), field.get_value ().get (), value, exprs); if (value == NULL) { - rust_fatal_error (field.value->get_locus_slow (), + rust_fatal_error (field.get_value ()->get_locus_slow (), "failed to compile value to struct"); return; } @@ -566,10 +566,10 @@ void Compilation::visit (AST::StructExprFieldIndexValue &field) { Bexpression *value = NULL; - VISIT_POP (field.value->get_locus_slow (), field.value.get (), value, exprs); + VISIT_POP (field.get_value ()->get_locus_slow (), field.get_value ().get (), value, exprs); if (value == NULL) { - rust_fatal_error (field.value->get_locus_slow (), + rust_fatal_error (field.get_value ()->get_locus_slow (), "failed to compile value to struct"); return; } @@ -598,7 +598,7 @@ Compilation::visit (AST::StructExprStructFields &expr) // FIXME type resolution pass should ensures these are in correct order // and have defaults if required - for (auto &field : expr.fields) + for (auto &field : expr.get_fields ()) { Bexpression *value = NULL; VISIT_POP (expr.get_locus (), field, value, exprs); @@ -1332,7 +1332,7 @@ Compilation::visit (AST::LetStmt &stmt) void Compilation::visit (AST::ExprStmtWithoutBlock &stmt) { - stmt.expr->accept_vis (*this); + stmt.get_expr ()->accept_vis (*this); } void @@ -1348,7 +1348,7 @@ Compilation::visit (AST::ExprStmtWithBlock &stmt) start_location, end_location); scope.PushBlock (code_block); - stmt.expr->accept_vis (*this); + stmt.get_expr ()->accept_vis (*this); // get trailing if required for (auto &s : stmts) diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 164b5a5..65918db 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -345,20 +345,196 @@ namespace Rust { expr.get_array_expr()->accept_vis(*this); expr.get_index_expr()->accept_vis(*this); } - void visit(AST::TupleExpr& expr) override {} - void visit(AST::TupleIndexExpr& expr) override {} - void visit(AST::StructExprStruct& expr) override {} - void visit(AST::StructExprFieldIdentifier& field) override {} - void visit(AST::StructExprFieldIdentifierValue& field) override {} - void visit(AST::StructExprFieldIndexValue& field) override {} - void visit(AST::StructExprStructFields& expr) override {} - void visit(AST::StructExprStructBase& expr) override {} - void visit(AST::StructExprTuple& expr) override {} - void visit(AST::StructExprUnit& expr) override {} - void visit(AST::EnumExprFieldIdentifier& field) override {} + void visit(AST::TupleExpr& expr) override { + /* according to spec, outer attributes are allowed on "elements of + * tuple expressions" */ + + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* strip test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* apparently outer attributes are allowed in "elements of tuple + * expressions" according to spec */ + auto& values = expr.get_tuple_elems(); + for (int i = 0; i < values.size();) { + auto& value = values[i]; + + // mark for stripping if required + value->accept_vis(*this); + + if (value->is_marked_for_strip()) + values.erase(values.begin() + i); + else + i++; + } + } + void visit(AST::TupleIndexExpr& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* wouldn't strip this directly (as outer attrs should be + * associated with this level), but any sub-expressions would be + * stripped. Thus, no need to erase when strip check called. */ + expr.get_tuple_expr()->accept_vis(*this); + } + void visit(AST::StructExprStruct& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* strip test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + } + void visit(AST::StructExprFieldIdentifier& field) override { + // as no attrs (at moment, at least), no stripping possible + } + void visit(AST::StructExprFieldIdentifierValue& field) override { + /* as no attrs possible (at moment, at least), only sub-expression + * stripping is possible */ + field.get_value()->accept_vis(*this); + } + void visit(AST::StructExprFieldIndexValue& field) override { + /* as no attrs possible (at moment, at least), only sub-expression + * stripping is possible */ + field.get_value()->accept_vis(*this); + } + void visit(AST::StructExprStructFields& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* strip test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* spec does not specify whether expressions are allowed to be + * stripped at top level of struct fields, but I wouldn't think + * that they would be, so operating under the assumption that only + * sub-expressions can be stripped. */ + for (auto& field : expr.get_fields()) { + field->accept_vis(*this); + // shouldn't strip in this + } + + /* struct base presumably can't be stripped, as the '..' is before + * the expression. as such, can only strip sub-expressions. */ + if (expr.has_struct_base()) + expr.get_struct_base().get_base_struct()->accept_vis(*this); + } + void visit(AST::StructExprStructBase& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* strip test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* struct base presumably can't be stripped, as the '..' is before + * the expression. as such, can only strip sub-expressions. */ + rust_assert(!expr.get_struct_base().is_invalid()); + expr.get_struct_base().get_base_struct()->accept_vis(*this); + } + void visit(AST::StructExprTuple& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* strip test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* spec says outer attributes are specifically allowed for elements + * of tuple-style struct expressions, so full stripping possible */ + auto& values = expr.get_elems(); + for (int i = 0; i < values.size();) { + auto& value = values[i]; + + // mark for stripping if required + value->accept_vis(*this); + + if (value->is_marked_for_strip()) + values.erase(values.begin() + i); + else + i++; + } + } + void visit(AST::StructExprUnit& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + } + void visit(AST::EnumExprFieldIdentifier& field) override { + + } void visit(AST::EnumExprFieldIdentifierValue& field) override {} void visit(AST::EnumExprFieldIndexValue& field) override {} - void visit(AST::EnumExprStruct& expr) override {} + void visit(AST::EnumExprStruct& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + // supposedly spec doesn't allow inner attributes in enum exprs + + /* spec does not specify whether expressions are allowed to be + * stripped at top level of expression fields, but I wouldn't think + * that they would be, so operating under the assumption that only + * sub-expressions can be stripped. */ + for (auto& field : expr.get_fields()) { + field->accept_vis(*this); + // shouldn't strip in this + } + } void visit(AST::EnumExprTuple& expr) override {} void visit(AST::EnumExprFieldless& expr) override {} void visit(AST::CallExpr& expr) override {} |