public override IPStmt VisitAssignStmt(PParser.AssignStmtContext context) { IPExpr variable = exprVisitor.Visit(context.lvalue()); IPExpr value = exprVisitor.Visit(context.rvalue()); // If we're doing a move/swap assignment if (value is ILinearRef linearRef) { Variable refVariable = linearRef.Variable; switch (linearRef.LinearType) { case LinearType.Move: // Moved values must be subtypes of their destinations if (!variable.Type.IsAssignableFrom(refVariable.Type)) { throw handler.TypeMismatch(context.rvalue(), refVariable.Type, variable.Type); } return(new MoveAssignStmt(context, variable, refVariable)); case LinearType.Swap: // Within a function, swaps must only be subtyped in either direction // the actual types are checked at runtime. This is to allow swapping // with the `any` type. if (!variable.Type.IsAssignableFrom(refVariable.Type) && !refVariable.Type.IsAssignableFrom(variable.Type)) { throw handler.TypeMismatch(context.rvalue(), refVariable.Type, variable.Type); } return(new SwapAssignStmt(context, variable, refVariable)); default: throw handler.InternalError(linearRef.SourceLocation, new ArgumentOutOfRangeException(nameof(context))); } } // If this is a value assignment, we just need subtyping if (!variable.Type.IsAssignableFrom(value.Type)) { throw handler.TypeMismatch(context.rvalue(), value.Type, variable.Type); } return(new AssignStmt(context, variable, value)); }
public override object VisitAssignStmt(PParser.AssignStmtContext context) { return(null); }