public override object VisitAssignmentExpr([NotNull] ChessVCParser.AssignmentExprContext context) { string s = context.GetText(); var rhsNode = context.assignmentExpr(); if (rhsNode != null) { object lhs = Visit(context.conditionalExpr()); if (lhs == null || !(lhs is Reference)) { throw new Exception("Attempt to assign to object without l-value"); } object rhs = deref(Visit(rhsNode)); Type assignType = ((Reference)lhs).EffectiveType; if (rhs.GetType() != assignType && !rhs.GetType().IsSubclassOf(assignType)) { // First check - if we're assigning a string to a ChoiceVariable, we // will automatically assign it to it's Value member. This makes cleaner // code as we don't need to put ".Value" all over the place. if (assignType == typeof(ChoiceVariable) && rhs is string) { return(((ChoiceVariable)(((Reference)lhs).GetValue())).Value = (string)rhs); } // We can't directly assign = however, we may be able to construct a new object // if the type to be assigned contains a constructor with a single argument // of the type supplied on the right-hand-side. var constructors = assignType.GetConstructors(); foreach (ConstructorInfo ci in constructors) { var parameters = ci.GetParameters(); if (parameters.Length == 1) { if (rhs.GetType() == parameters[0].ParameterType || parameters[0].ParameterType.IsSubclassOf(assignType)) { // types compatible - we can perform constructon ((Reference)lhs).SetValue(ci.Invoke(new object[] { rhs })); return(lhs); } } } throw new Exception("Incompatable types for assignment"); } ((Reference)lhs).SetValue(rhs); return(lhs); } return(base.VisitAssignmentExpr(context)); }
/// <summary> /// Visit a parse tree produced by <see cref="ChessVCParser.assignmentExpr"/>. /// <para> /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/> /// on <paramref name="context"/>. /// </para> /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public virtual Result VisitAssignmentExpr([NotNull] ChessVCParser.AssignmentExprContext context) { return(VisitChildren(context)); }
/// <summary> /// Exit a parse tree produced by <see cref="ChessVCParser.assignmentExpr"/>. /// <para>The default implementation does nothing.</para> /// </summary> /// <param name="context">The parse tree.</param> public virtual void ExitAssignmentExpr([NotNull] ChessVCParser.AssignmentExprContext context) { }