@@ -230,8 +230,26 @@ class Var : public Expr {
230230 TVM_DLL Var (Id vid, Type type_annotation, Span span = Span());
231231
232232 TVM_DEFINE_OBJECT_REF_METHODS (Var, RelayExpr, VarNode);
233+ TVM_DEFINE_OBJECT_REF_COW_METHOD (VarNode);
233234};
234235
236+ /* !
237+ * \brief Returns the var with given properties. A null property denotes 'no change'.
238+ * Returns var if all properties are unchanged. Otherwise, returns a copy with the new fields.
239+ * \param var The var to copy.
240+ * \param opt_vid The (optional) vid for the copied var. If none, ret_var->vid = var->vid.
241+ * \param opt_type_annotation The (optional) type_annotation for the copied var. If none,
242+ * ret_var->type_annotation = var->type_annotation.
243+ * \param opt_span The (optional) span for the copied var. If none, ret_var->span = var->span.
244+ * \return If all properties are null or the same as the property in the input var
245+ * (i.e., opt_vid is null or opt_vid.value() == var->vid, etc.), then we return var. Otherwise,
246+ * we return a copy of call with the different fields overwritten. (i.e., if
247+ * opt_vid.value() != var->vid, then ret_var->vid = opt_.value()).
248+ */
249+ Var WithFields (Var var, Optional<Id> opt_vid = Optional<Id>(),
250+ Optional<Type> opt_type_annotation = Optional<Type>(),
251+ Optional<Span> opt_span = Optional<Span>());
252+
235253/* !
236254 * \brief Call corresponds to operator invocation.
237255 * Corresponds to the operator in computational graph terminology.
@@ -331,8 +349,31 @@ class Call : public Expr {
331349 Array<Type> type_args = Array<Type>(), Span span = Span());
332350
333351 TVM_DEFINE_OBJECT_REF_METHODS (Call, RelayExpr, CallNode);
352+ TVM_DEFINE_OBJECT_REF_COW_METHOD (CallNode);
334353};
335354
355+ /* !
356+ * \brief Returns the call with given properties. A null property denotes 'no change'.
357+ * Returns call if all properties are unchanged. Otherwise, returns a copy with the new fields.
358+ * \param call The call to copy.
359+ * \param opt_op The (optional) op for the copied call. If none, ret_call->op = call->op.
360+ * \param opt_args The (optional) args for the copied call. If none, ret_call->args = call->args.
361+ * \param opt_attrs The (optional) attrs for the copied call. If none, ret_call->attrs =
362+ * call->attrs.
363+ * \param opt_type_args The (optional) type args for the copied call. If none,
364+ * ret_call->type_args = call->type_args.
365+ * \param opt_span The (optional) span for the copied call. If none, ret_call->span = call->span.
366+ * \return If all properties are null or the same as the property in the input call
367+ * (i.e., opt_op is null or opt_op.value() == call->op, etc.), then we return call. Otherwise, we
368+ * return a copy of call with the different fields overwritten. (i.e., if opt_op.value() !=
369+ * call->op, then ret_call->op = opt_op.value()).
370+ */
371+ Call WithFields (Call call, Optional<Expr> opt_op = Optional<Expr>(),
372+ Optional<Array<Expr>> opt_args = Optional<Array<Expr>>(),
373+ Optional<Attrs> opt_attrs = Optional<Attrs>(),
374+ Optional<Array<Type>> opt_type_args = Optional<Array<Type>>(),
375+ Optional<Span> opt_span = Optional<Span>());
376+
336377/* !
337378 * \brief Let binding that binds a local var and optionally a type annotation.
338379 *
@@ -405,8 +446,27 @@ class Let : public Expr {
405446 TVM_DLL Let (Var var, Expr value, Expr body, Span span = Span());
406447
407448 TVM_DEFINE_OBJECT_REF_METHODS (Let, RelayExpr, LetNode);
449+ TVM_DEFINE_OBJECT_REF_COW_METHOD (LetNode);
408450};
409451
452+ /* !
453+ * \brief Returns the let with given properties. A null property denotes 'no change'.
454+ * Returns let if all properties are unchanged. Otherwise, returns a copy with the new fields.
455+ * \param let The let to copy.
456+ * \param opt_var The (optional) var for the copied let. If none, ret_let->op = let->op.
457+ * \param opt_value The (optional) value for the copied let. If none, ret_let->args = let->args.
458+ * \param opt_body The (optional) body for the copied let. If none, ret_let->attrs = let->attrs.
459+ * \param opt_span The (optional) span for the copied let. If none, ret_let->span = let->span.
460+ * \return If all properties are null or the same as the property in the input let (i.e., opt_var is
461+ * null or opt_var.value() == let->var, etc.), then we return let. Otherwise, we return a copy of
462+ * let with the different fields overwritten. (i.e., if opt_var.value() != let->var, then
463+ * ret_let->var = opt_var.value()).
464+ */
465+ Let WithFields (Let let, Optional<Var> opt_var = Optional<Var>(),
466+ Optional<Expr> opt_value = Optional<Expr>(),
467+ Optional<Expr> opt_body = Optional<Expr>(),
468+ Optional<Span> opt_span = Optional<Span>());
469+
410470/* !
411471 * \brief Condition expression
412472 *
@@ -466,8 +526,32 @@ class If : public Expr {
466526 TVM_DLL If (Expr cond, Expr true_branch, Expr false_branch, Span span = Span());
467527
468528 TVM_DEFINE_OBJECT_REF_METHODS (If, RelayExpr, IfNode);
529+ TVM_DEFINE_OBJECT_REF_COW_METHOD (IfNode);
469530};
470531
532+ /* !
533+ * \brief Returns the if_expr with given properties. A null property denotes 'no change'.
534+ * Returns if_expr if all properties are unchanged. Otherwise, returns a copy with the new fields.
535+ * \param if_expr The if expression to copy.
536+ * \param opt_cond The (optional) cond for the copied if_expr. If none, ret_if->cond =
537+ * if_expr->cond.
538+ * \param opt_true_branch The (optional) true_branch for the copied if_expr. If none,
539+ * ret_if->true_branch = ret_if->false_branch.
540+ * \param opt_false_branch The (optional) false_branch
541+ * for the copied if_expr. If none, ret_if->false_branch = if_expr->false_branch.
542+ * \param opt_span
543+ * The (optional) span for the copied if_expr. If none, ret_if->span = if_expr->span.
544+ * \return If all
545+ * properties are null or the same as the property in the input if_expr (i.e., opt_cond is null or
546+ * opt_cond.value() == if_expr->cond, etc.), then we return if_expr. Otherwise, we return a copy of
547+ * if_expr with the different fields overwritten. (i.e., if opt_cond.value() != if_expr->cond, then
548+ * ret_if->cond = opt_cond.value()).
549+ */
550+ If WithFields (If if_expr, Optional<Expr> opt_cond = Optional<Expr>(),
551+ Optional<Expr> opt_true_branch = Optional<Expr>(),
552+ Optional<Expr> opt_false_branch = Optional<Expr>(),
553+ Optional<Span> opt_span = Optional<Span>());
554+
471555/* ! \brief Get index-th field out of a tuple. */
472556class TupleGetItem ;
473557class TupleGetItemNode : public ExprNode {
@@ -508,8 +592,30 @@ class TupleGetItem : public Expr {
508592 TVM_DLL TupleGetItem (Expr tuple, int index, Span span = Span());
509593
510594 TVM_DEFINE_OBJECT_REF_METHODS (TupleGetItem, RelayExpr, TupleGetItemNode);
595+ TVM_DEFINE_OBJECT_REF_COW_METHOD (TupleGetItemNode);
511596};
512597
598+ /* !
599+ * \brief Returns the tuple_get_item with given properties. A null property denotes 'no change'.
600+ * Returns if_expr if all properties are unchanged. Otherwise, returns a copy with the new fields.
601+ * \param tuple_get_item The tuple_get_item to copy.
602+ * \param opt_tuple The (optional) tuple for the copied tuple_get_item. If none,
603+ * ret_tuple_get_item->tuple = tuple_get_item->tuple.
604+ * \param opt_index The (optional) index for the copied tuple_get_item. If none,
605+ * ret_tuple_get_item->index = tuple_get_item->index.
606+ * \param
607+ * opt_span The (optional) span for the copied tuple_get_item. If none,
608+ * ret_tuple_get_item->span = tuple_get_item->span.
609+ * \return If all properties are null or the same as the property in the input tuple_get_item
610+ * (i.e., opt_tuple is null or opt_tuple.value() == tuple_get_item->tuple, etc.), then we return
611+ * tuple_get_item. Otherwise, we return a copy of tuple_get_item with the different fields
612+ * overwritten. (i.e., if opt_tuple.value() != tuple_get_item->tuple, then
613+ * ret_tuple_get_item->tuple = opt_tuple.value()).
614+ */
615+ TupleGetItem WithFields (TupleGetItem tuple_get_item, Optional<Expr> opt_tuple = Optional<Expr>(),
616+ Optional<Integer> opt_index = Optional<Integer>(),
617+ Optional<Span> opt_span = Optional<Span>());
618+
513619/* ! \brief Create a new Reference out of initial value. */
514620class RefCreate ;
515621class RefCreateNode : public ExprNode {
@@ -547,8 +653,27 @@ class RefCreate : public Expr {
547653 TVM_DLL explicit RefCreate (Expr value, Span span = Span());
548654
549655 TVM_DEFINE_OBJECT_REF_METHODS (RefCreate, RelayExpr, RefCreateNode);
656+ TVM_DEFINE_OBJECT_REF_COW_METHOD (RefCreateNode);
550657};
551658
659+ /* !
660+ * \brief Returns the ref create with given properties. A null property denotes 'no change'.
661+ * Returns ref_create if all properties are unchanged. Otherwise, returns a copy with the new
662+ * fields.
663+ * \param ref_create The ref_create to copy.
664+ * \param opt_value The (optional) value for the copied ref_create. If none,
665+ * ret_ref_create->value = ref_create->value.
666+ * \param opt_span The (optional) span for the copied ref_create. If none,
667+ * ret_ref_create->span = ref_create->span.
668+ * \return If all properties are null or the same as the property in the input ref_create
669+ * (i.e., opt_value is null or opt_value.value() == ref_create->value, etc.), then we return
670+ * ref_create. Otherwise, we return a copy of ref_create with the different fields overwritten.
671+ * (i.e., if opt_value.value() != ref_create->value, then
672+ * ret_ref_create->value = opt_value.value()).
673+ */
674+ RefCreate WithFields (RefCreate ref_create, Optional<Expr> opt_value = Optional<Expr>(),
675+ Optional<Span> opt_span = Optional<Span>());
676+
552677/* ! \brief Get value out of Reference. */
553678class RefRead ;
554679class RefReadNode : public ExprNode {
@@ -586,7 +711,26 @@ class RefRead : public Expr {
586711 TVM_DLL explicit RefRead (Expr ref, Span span = Span());
587712
588713 TVM_DEFINE_OBJECT_REF_METHODS (RefRead, RelayExpr, RefReadNode);
714+ TVM_DEFINE_OBJECT_REF_COW_METHOD (RefReadNode);
589715};
716+
717+ /* !
718+ * \brief Returns the ref read with given properties. A null property denotes 'no change'.
719+ * Returns ref_read if all properties are unchanged. Otherwise, returns a copy with the new fields.
720+ * \param ref_read The ref_read to copy.
721+ * \param opt_ref The (optional) ref for the copied ref_read. If none, ret_ref_read->ref =
722+ * ref_read->ref.
723+ * \param opt_span
724+ * The (optional) span for the copied ref_read. If none, ret_ref_read->span = ref_read->span.
725+ * \return If all properties are null or the same as the property in the input ref_read
726+ * (i.e., opt_ref is null or opt_ref.value() == ref_read->ref, etc.), then we return ref_read.
727+ * Otherwise, we return a copy of ref_read with the different fields overwritten.
728+ * (i.e., if opt_ref.value() != ref_read->ref, then
729+ * ret_ref_read->ref = opt_ref.value()).
730+ */
731+ RefRead WithFields (RefRead ref_read, Optional<Expr> opt_ref = Optional<Expr>(),
732+ Optional<Span> opt_span = Optional<Span>());
733+
590734/* ! \brief Set value of Reference. The whole expression evaluates to an Empty Tuple. */
591735class RefWrite ;
592736class RefWriteNode : public ExprNode {
@@ -629,8 +773,29 @@ class RefWrite : public Expr {
629773 TVM_DLL RefWrite (Expr ref, Expr value, Span span = Span());
630774
631775 TVM_DEFINE_OBJECT_REF_METHODS (RefWrite, RelayExpr, RefWriteNode);
776+ TVM_DEFINE_OBJECT_REF_COW_METHOD (RefWriteNode);
632777};
633778
779+ /* !
780+ * \brief Returns the ref write with given properties. A null property denotes 'no change'.
781+ * Returns ref_write if all properties are unchanged. Otherwise, returns a copy with the new fields.
782+ * \param ref_write The ref_write to copy.
783+ * \param opt_ref The (optional) ref for the copied ref_write. If none,
784+ * ret_ref_write->ref = ref_write->ref.
785+ * \param opt_value The (optional) value for the copied ref_write. If none,
786+ * ret_ref_write->value = ref_write->value.
787+ * \param opt_span
788+ * The (optional) span for the copied ref_write. If none, ret_ref_write->span = ref_write->span.
789+ * \return If all properties are null or the same as the property in the input ref_write
790+ * (i.e., opt_ref is null or opt_ref.value() == ref_write->ref, etc.), then we return ref_write.
791+ * Otherwise, we return a copy of ref_write with the different fields overwritten.
792+ * (i.e., if ref_write.value() != ref_write->ref, then
793+ * ret_ref_write->ref = opt_ref.value()).
794+ */
795+ RefWrite WithFields (RefWrite ref_write, Optional<Expr> opt_ref = Optional<Expr>(),
796+ Optional<Expr> opt_value = Optional<Expr>(),
797+ Optional<Span> opt_span = Optional<Span>());
798+
634799/* !
635800 * \brief Base class of the temporary expression.
636801 *
0 commit comments