public Expression Visit(ParserRec rec) { Expression input = rec.Input.Accept(this); Expression start = rec.Start.Accept(this); Expression step = rec.Step.Accept(this); if (rec.Start.Type is ParserNumType) { return(new RecNumExpression(input as NumExpression, start as NumExpression, rec.NumVariableName, rec.AccVariableName, step as NumExpression)); } if (rec.Start.Type is ParserLogicType) { return(new RecLogicExpression(input as NumExpression, start as LogicExpression, rec.NumVariableName, rec.AccVariableName, step as LogicExpression)); } if (rec.Start.Type is ParserLambdaType) { return(new RecLambdaExpression(input as NumExpression, start as AbstractLambdaExpression, rec.NumVariableName, rec.AccVariableName, step as AbstractLambdaExpression)); } if (rec.Start.Type is ParserProdType) { return(new RecPairExpression(input as NumExpression, start as AbstractPairExpression, rec.NumVariableName, rec.AccVariableName, step as AbstractPairExpression)); } throw new ArgumentException("Unknown Rec type"); }
public ParserType Visit(ParserRec rec) { var inputType = rec.Input.Accept(this); if (!(inputType is ParserNumType)) { throw new ArgumentException("The input to a Rec expression must be numeric. Type: " + inputType.ToString()); } var startType = rec.Start.Accept(this); // In order to type check the step clone our current context, add two new variables, run // the type check, remove the bound variables, then join the new context with the old var newCtx = CloneContext(); newCtx[rec.NumVariableName] = new ParserNumType(); newCtx[rec.AccVariableName] = rec.AccType; var visitor = new TypeVisitor(newCtx); ParserType stepType = rec.Step.Accept(visitor); newCtx.Remove(rec.AccVariableName); newCtx.Remove(rec.NumVariableName); JoinContext(newCtx); if (!startType.Equivalent(stepType)) { throw new ArgumentException(String.Format( "Start type and step type in Rec must be equivalent. Start Type: {0} Step Type: {1}", startType.ToString(), stepType.ToString())); } rec.Type = startType; return(startType); }