@@ -218,8 +218,26 @@ class Var : public Expr {
218218 TVM_DLL Var (Id vid, Type type_annotation, Span span = Span());
219219
220220 TVM_DEFINE_OBJECT_REF_METHODS (Var, RelayExpr, VarNode);
221+ TVM_DEFINE_OBJECT_REF_COW_METHOD (VarNode);
221222};
222223
224+ /* !
225+ * \brief Returns the var with given properties. A null property denotes 'no change'.
226+ * Returns var if all properties are unchanged. Otherwise, returns a copy with the new fields.
227+ * \param var The var to copy.
228+ * \param opt_vid The (optional) vid for the copied var. If none, ret_var->vid = var->vid.
229+ * \param opt_type_annotation The (optional) type_annotation for the copied var. If none,
230+ * ret_var->type_annotation = var->type_annotation.
231+ * \param opt_span The (optional) span for the copied var. If none, ret_var->span = var->span.
232+ * \return If all properties are null or the same as the property in the input var
233+ * (i.e., opt_vid is null or opt_vid.value() == var->vid, etc.), then we return var. Otherwise,
234+ * we return a copy of call with the different fields overwritten. (i.e., if
235+ * opt_vid.value() != var->vid, then ret_var->vid = opt_.value()).
236+ */
237+ Var WithFields (Var var, Optional<Id> opt_vid = Optional<Id>(),
238+ Optional<Type> opt_type_annotation = Optional<Type>(),
239+ Optional<Span> opt_span = Optional<Span>());
240+
223241/* !
224242 * \brief Call corresponds to operator invocation.
225243 * Corresponds to the operator in computational graph terminology.
@@ -319,8 +337,31 @@ class Call : public Expr {
319337 Array<Type> type_args = Array<Type>(), Span span = Span());
320338
321339 TVM_DEFINE_OBJECT_REF_METHODS (Call, RelayExpr, CallNode);
340+ TVM_DEFINE_OBJECT_REF_COW_METHOD (CallNode);
322341};
323342
343+ /* !
344+ * \brief Returns the call with given properties. A null property denotes 'no change'.
345+ * Returns call if all properties are unchanged. Otherwise, returns a copy with the new fields.
346+ * \param call The call to copy.
347+ * \param opt_op The (optional) op for the copied call. If none, ret_call->op = call->op.
348+ * \param opt_args The (optional) args for the copied call. If none, ret_call->args = call->args.
349+ * \param opt_attrs The (optional) attrs for the copied call. If none, ret_call->attrs =
350+ * call->attrs.
351+ * \param opt_type_args The (optional) type args for the copied call. If none,
352+ * ret_call->type_args = call->type_args.
353+ * \param opt_span The (optional) span for the copied call. If none, ret_call->span = call->span.
354+ * \return If all properties are null or the same as the property in the input call
355+ * (i.e., opt_op is null or opt_op.value() == call->op, etc.), then we return call. Otherwise, we
356+ * return a copy of call with the different fields overwritten. (i.e., if opt_op.value() !=
357+ * call->op, then ret_call->op = opt_op.value()).
358+ */
359+ Call WithFields (Call call, Optional<Expr> opt_op = Optional<Expr>(),
360+ Optional<Array<Expr>> opt_args = Optional<Array<Expr>>(),
361+ Optional<Attrs> opt_attrs = Optional<Attrs>(),
362+ Optional<Array<Type>> opt_type_args = Optional<Array<Type>>(),
363+ Optional<Span> opt_span = Optional<Span>());
364+
324365/* !
325366 * \brief Let binding that binds a local var and optionally a type annotation.
326367 *
@@ -393,8 +434,27 @@ class Let : public Expr {
393434 TVM_DLL Let (Var var, Expr value, Expr body, Span span = Span());
394435
395436 TVM_DEFINE_OBJECT_REF_METHODS (Let, RelayExpr, LetNode);
437+ TVM_DEFINE_OBJECT_REF_COW_METHOD (LetNode);
396438};
397439
440+ /* !
441+ * \brief Returns the let with given properties. A null property denotes 'no change'.
442+ * Returns let if all properties are unchanged. Otherwise, returns a copy with the new fields.
443+ * \param let The let to copy.
444+ * \param opt_var The (optional) var for the copied let. If none, ret_let->op = let->op.
445+ * \param opt_value The (optional) value for the copied let. If none, ret_let->args = let->args.
446+ * \param opt_body The (optional) body for the copied let. If none, ret_let->attrs = let->attrs.
447+ * \param opt_span The (optional) span for the copied let. If none, ret_let->span = let->span.
448+ * \return If all properties are null or the same as the property in the input let (i.e., opt_var is
449+ * null or opt_var.value() == let->var, etc.), then we return let. Otherwise, we return a copy of
450+ * let with the different fields overwritten. (i.e., if opt_var.value() != let->var, then
451+ * ret_let->var = opt_var.value()).
452+ */
453+ Let WithFields (Let let, Optional<Var> opt_var = Optional<Var>(),
454+ Optional<Expr> opt_value = Optional<Expr>(),
455+ Optional<Expr> opt_body = Optional<Expr>(),
456+ Optional<Span> opt_span = Optional<Span>());
457+
398458/* !
399459 * \brief Condition expression
400460 *
@@ -454,8 +514,32 @@ class If : public Expr {
454514 TVM_DLL If (Expr cond, Expr true_branch, Expr false_branch, Span span = Span());
455515
456516 TVM_DEFINE_OBJECT_REF_METHODS (If, RelayExpr, IfNode);
517+ TVM_DEFINE_OBJECT_REF_COW_METHOD (IfNode);
457518};
458519
520+ /* !
521+ * \brief Returns the if_expr with given properties. A null property denotes 'no change'.
522+ * Returns if_expr if all properties are unchanged. Otherwise, returns a copy with the new fields.
523+ * \param if_expr The if expression to copy.
524+ * \param opt_cond The (optional) cond for the copied if_expr. If none, ret_if->cond =
525+ * if_expr->cond.
526+ * \param opt_true_branch The (optional) true_branch for the copied if_expr. If none,
527+ * ret_if->true_branch = ret_if->false_branch.
528+ * \param opt_false_branch The (optional) false_branch
529+ * for the copied if_expr. If none, ret_if->false_branch = if_expr->false_branch.
530+ * \param opt_span
531+ * The (optional) span for the copied if_expr. If none, ret_if->span = if_expr->span.
532+ * \return If all
533+ * properties are null or the same as the property in the input if_expr (i.e., opt_cond is null or
534+ * opt_cond.value() == if_expr->cond, etc.), then we return if_expr. Otherwise, we return a copy of
535+ * if_expr with the different fields overwritten. (i.e., if opt_cond.value() != if_expr->cond, then
536+ * ret_if->cond = opt_cond.value()).
537+ */
538+ If WithFields (If if_expr, Optional<Expr> opt_cond = Optional<Expr>(),
539+ Optional<Expr> opt_true_branch = Optional<Expr>(),
540+ Optional<Expr> opt_false_branch = Optional<Expr>(),
541+ Optional<Span> opt_span = Optional<Span>());
542+
459543/* ! \brief Get index-th field out of a tuple. */
460544class TupleGetItem ;
461545class TupleGetItemNode : public ExprNode {
@@ -496,8 +580,30 @@ class TupleGetItem : public Expr {
496580 TVM_DLL TupleGetItem (Expr tuple, int index, Span span = Span());
497581
498582 TVM_DEFINE_OBJECT_REF_METHODS (TupleGetItem, RelayExpr, TupleGetItemNode);
583+ TVM_DEFINE_OBJECT_REF_COW_METHOD (TupleGetItemNode);
499584};
500585
586+ /* !
587+ * \brief Returns the tuple_get_item with given properties. A null property denotes 'no change'.
588+ * Returns if_expr if all properties are unchanged. Otherwise, returns a copy with the new fields.
589+ * \param tuple_get_item The tuple_get_item to copy.
590+ * \param opt_tuple The (optional) tuple for the copied tuple_get_item. If none,
591+ * ret_tuple_get_item->tuple = tuple_get_item->tuple.
592+ * \param opt_index The (optional) index for the copied tuple_get_item. If none,
593+ * ret_tuple_get_item->index = tuple_get_item->index.
594+ * \param
595+ * opt_span The (optional) span for the copied tuple_get_item. If none,
596+ * ret_tuple_get_item->span = tuple_get_item->span.
597+ * \return If all properties are null or the same as the property in the input tuple_get_item
598+ * (i.e., opt_tuple is null or opt_tuple.value() == tuple_get_item->tuple, etc.), then we return
599+ * tuple_get_item. Otherwise, we return a copy of tuple_get_item with the different fields
600+ * overwritten. (i.e., if opt_tuple.value() != tuple_get_item->tuple, then
601+ * ret_tuple_get_item->tuple = opt_tuple.value()).
602+ */
603+ TupleGetItem WithFields (TupleGetItem tuple_get_item, Optional<Expr> opt_tuple = Optional<Expr>(),
604+ Optional<Integer> opt_index = Optional<Integer>(),
605+ Optional<Span> opt_span = Optional<Span>());
606+
501607/* ! \brief Create a new Reference out of initial value. */
502608class RefCreate ;
503609class RefCreateNode : public ExprNode {
@@ -535,8 +641,27 @@ class RefCreate : public Expr {
535641 TVM_DLL explicit RefCreate (Expr value, Span span = Span());
536642
537643 TVM_DEFINE_OBJECT_REF_METHODS (RefCreate, RelayExpr, RefCreateNode);
644+ TVM_DEFINE_OBJECT_REF_COW_METHOD (RefCreateNode);
538645};
539646
647+ /* !
648+ * \brief Returns the ref create with given properties. A null property denotes 'no change'.
649+ * Returns ref_create if all properties are unchanged. Otherwise, returns a copy with the new
650+ * fields.
651+ * \param ref_create The ref_create to copy.
652+ * \param opt_value The (optional) value for the copied ref_create. If none,
653+ * ret_ref_create->value = ref_create->value.
654+ * \param opt_span The (optional) span for the copied ref_create. If none,
655+ * ret_ref_create->span = ref_create->span.
656+ * \return If all properties are null or the same as the property in the input ref_create
657+ * (i.e., opt_value is null or opt_value.value() == ref_create->value, etc.), then we return
658+ * ref_create. Otherwise, we return a copy of ref_create with the different fields overwritten.
659+ * (i.e., if opt_value.value() != ref_create->value, then
660+ * ret_ref_create->value = opt_value.value()).
661+ */
662+ RefCreate WithFields (RefCreate ref_create, Optional<Expr> opt_value = Optional<Expr>(),
663+ Optional<Span> opt_span = Optional<Span>());
664+
540665/* ! \brief Get value out of Reference. */
541666class RefRead ;
542667class RefReadNode : public ExprNode {
@@ -574,7 +699,26 @@ class RefRead : public Expr {
574699 TVM_DLL explicit RefRead (Expr ref, Span span = Span());
575700
576701 TVM_DEFINE_OBJECT_REF_METHODS (RefRead, RelayExpr, RefReadNode);
702+ TVM_DEFINE_OBJECT_REF_COW_METHOD (RefReadNode);
577703};
704+
705+ /* !
706+ * \brief Returns the ref read with given properties. A null property denotes 'no change'.
707+ * Returns ref_read if all properties are unchanged. Otherwise, returns a copy with the new fields.
708+ * \param ref_read The ref_read to copy.
709+ * \param opt_ref The (optional) ref for the copied ref_read. If none, ret_ref_read->ref =
710+ * ref_read->ref.
711+ * \param opt_span
712+ * The (optional) span for the copied ref_read. If none, ret_ref_read->span = ref_read->span.
713+ * \return If all properties are null or the same as the property in the input ref_read
714+ * (i.e., opt_ref is null or opt_ref.value() == ref_read->ref, etc.), then we return ref_read.
715+ * Otherwise, we return a copy of ref_read with the different fields overwritten.
716+ * (i.e., if opt_ref.value() != ref_read->ref, then
717+ * ret_ref_read->ref = opt_ref.value()).
718+ */
719+ RefRead WithFields (RefRead ref_read, Optional<Expr> opt_ref = Optional<Expr>(),
720+ Optional<Span> opt_span = Optional<Span>());
721+
578722/* ! \brief Set value of Reference. The whole expression evaluates to an Empty Tuple. */
579723class RefWrite ;
580724class RefWriteNode : public ExprNode {
@@ -617,8 +761,29 @@ class RefWrite : public Expr {
617761 TVM_DLL RefWrite (Expr ref, Expr value, Span span = Span());
618762
619763 TVM_DEFINE_OBJECT_REF_METHODS (RefWrite, RelayExpr, RefWriteNode);
764+ TVM_DEFINE_OBJECT_REF_COW_METHOD (RefWriteNode);
620765};
621766
767+ /* !
768+ * \brief Returns the ref write with given properties. A null property denotes 'no change'.
769+ * Returns ref_write if all properties are unchanged. Otherwise, returns a copy with the new fields.
770+ * \param ref_write The ref_write to copy.
771+ * \param opt_ref The (optional) ref for the copied ref_write. If none,
772+ * ret_ref_write->ref = ref_write->ref.
773+ * \param opt_value The (optional) value for the copied ref_write. If none,
774+ * ret_ref_write->value = ref_write->value.
775+ * \param opt_span
776+ * The (optional) span for the copied ref_write. If none, ret_ref_write->span = ref_write->span.
777+ * \return If all properties are null or the same as the property in the input ref_write
778+ * (i.e., opt_ref is null or opt_ref.value() == ref_write->ref, etc.), then we return ref_write.
779+ * Otherwise, we return a copy of ref_write with the different fields overwritten.
780+ * (i.e., if ref_write.value() != ref_write->ref, then
781+ * ret_ref_write->ref = opt_ref.value()).
782+ */
783+ RefWrite WithFields (RefWrite ref_write, Optional<Expr> opt_ref = Optional<Expr>(),
784+ Optional<Expr> opt_value = Optional<Expr>(),
785+ Optional<Span> opt_span = Optional<Span>());
786+
622787/* !
623788 * \brief Base class of the temporary expression.
624789 *
0 commit comments