diff --git a/api/slice.hpp b/api/slice.hpp index 9ffcf14bb..c7cca9cd5 100644 --- a/api/slice.hpp +++ b/api/slice.hpp @@ -407,15 +407,6 @@ namespace jule Slice &operator=(const jule::Slice &src) noexcept { - // Assignment to itself. - if (this->data.alloc != nullptr && this->data.alloc == src.data.alloc) - { - this->_len = src._len; - this->_cap = src._cap; - this->_slice = src._slice; - return *this; - } - this->dealloc(); this->__get_copy(src); return *this; diff --git a/src/julec/obj/cxx/expr.jule b/src/julec/obj/cxx/expr.jule index 3eb8d1aee..80780c575 100644 --- a/src/julec/obj/cxx/expr.jule +++ b/src/julec/obj/cxx/expr.jule @@ -1194,15 +1194,53 @@ impl exprCoder { self.oc.write("{ ") self.oc.write(self.oc.tc.asSlice(m.Elems.ElemKind)) - self.oc.write(" &" + destIdent + " = ") - self.possibleRefExpr(m.Dest) - self.oc.write("; " + destIdent + ".alloc_for_append(") + + let mut ptr = false + match type m.Dest { + | &UnaryExprModel: + // Use raw pointer directly if exist. + let mut u = (&UnaryExprModel)(m.Dest) + if u.Expr.Kind.Ptr() != nil { + self.oc.write(" *" + destIdent + " = ") + self.possibleRefExpr(u.Expr.Model) + self.oc.write("; ") + ptr = true + break + } + fall + |: + self.oc.write(" &" + destIdent + " = ") + self.possibleRefExpr(m.Dest) + self.oc.write("; ") + } + // Pushed single item. + if len(m.Elems.Elems) == 1 { + if ptr { + self.oc.write(destIdent + "->push(") + } else { + self.oc.write(destIdent + ".push(") + } + self.possibleRefExpr(m.Elems.Elems[0]) + self.oc.write("); }") + ret + } + // Pushed more than single item. + // Pre-allocate enough capacity if not exist for appendation. + if ptr { + self.oc.write(destIdent + "->alloc_for_append(") + } else { + self.oc.write(destIdent + ".alloc_for_append(") + } self.oc.write(conv::Itoa(len(m.Elems.Elems))) self.oc.write("); ") for (_, mut e) in m.Elems.Elems { self.oc.write(destIdent) // Use the "__push" method to skip allocation boundary checking. - self.oc.write(".__push(") + if ptr { + self.oc.write("->__push(") + } else { + self.oc.write(".__push(") + } self.possibleRefExpr(e) self.oc.write("); ") } diff --git a/src/julec/opt/expr.jule b/src/julec/opt/expr.jule index 2c5ee3a51..50e0dea92 100644 --- a/src/julec/opt/expr.jule +++ b/src/julec/opt/expr.jule @@ -486,7 +486,7 @@ fn checkForBitShiftOpt(&l: &OperandExprModel, &r: &OperandExprModel): (ok: bool, } // Reports l and r the same lvalue expression. -fn areSameLvalueExprModel(mut &l: ExprModel, &r: ExprModel): bool { +fn areSameLvalueExprModel(&l: ExprModel, &r: ExprModel): bool { match type l { | &Var: // Compare values directly. @@ -499,7 +499,7 @@ fn areSameLvalueExprModel(mut &l: ExprModel, &r: ExprModel): bool { |: ret false } - let mut lsi = (&StructSubIdentExprModel)(l) + let lsi = (&StructSubIdentExprModel)(l) let rsi = (&StructSubIdentExprModel)(r) // Compare fields directly. // If the l and r have same pointers, @@ -509,6 +509,19 @@ fn areSameLvalueExprModel(mut &l: ExprModel, &r: ExprModel): bool { } // Check head expressions used for field access. ret areSameLvalueExprModel(lsi.Expr.Model, rsi.Expr.Model) + | &UnaryExprModel: + match type r { + | &UnaryExprModel: + let ul = (&UnaryExprModel)(l) + let ur = (&UnaryExprModel)(r) + // Unary operators should have the same operator. + // The operator does not matter. + if ul.Op.Id != ur.Op.Id || ul.Op.Kind != ur.Op.Kind { + ret false + } + // Check expressions used for unary. + ret areSameLvalueExprModel(ul.Expr.Model, ur.Expr.Model) + } } ret false } \ No newline at end of file