public static IUnboundExpr Match(BindingContext context, MatchExpr expr, IBoundExpr boundValue) { // validate the patterns ShapeChecker.Validate(expr, boundValue.Type); Coverage.Validate(expr, boundValue.Type); // convert the cases to vanilla if/then blocks var valueName = context.NameGenerator.Generate(); var defineValueExpr = new DefineExpr(expr.Value.Position, valueName, expr.Value, false); var valueExpr = new NameExpr(expr.Value.Position, valueName); var conditions = new List <DesugaredMatchCase>(); foreach (var matchCase in expr.Cases) { var result = new DesugaredMatchCase(); result.Condition = Match(context, boundValue.Type, matchCase.Pattern, valueExpr, result.Variables); conditions.Add(result); } // build a single compound "if" expression var ifExpr = (IUnboundExpr)null; if (expr.Cases.Count == 0) { throw new CompileException(expr.Position, "Match expression has no cases."); } else if (expr.Cases.Count == 1) { // if there is only a since case, and we've ensured exhaustivity already, // then it must match all values, so just use the body directly ifExpr = CreateCaseBody(conditions[0].Variables, expr.Cases[0].Body); } else { // go in reverse order so that we start with the trailing else and build // forward for (int i = expr.Cases.Count - 1; i >= 0; i--) { if (ifExpr == null) { // for the first popped (i.e. last appearing) case, we know it must // match because the match expression is exhaustive, so just use its // body directly ifExpr = CreateCaseBody(conditions[i].Variables, expr.Cases[i].Body); } else { var body = CreateCaseBody(conditions[i].Variables, expr.Cases[i].Body); ifExpr = new IfExpr(expr.Cases[i].Position, conditions[i].Condition, body, ifExpr); } } } return(new BlockExpr(new IUnboundExpr[] { defineValueExpr, ifExpr })); }
// <-- Name // | FN Name TupleType // | BOOL_LITERAL // | INT_LITERAL // | STRING_LITERAL // | LPAREN (Expression)? RPAREN private IUnboundExpr PrimaryExpr() { IUnboundExpr expression; if (CurrentIs(TokenType.Name)) { var name = Consume(); expression = new NameExpr(name.Position, name.StringValue, TypeArgs()); } else if (CurrentIs(TokenType.Fn)) { expression = FuncExpr(); } else if (CurrentIs(TokenType.Bool)) { expression = new BoolExpr(Consume(TokenType.Bool)); } else if (CurrentIs(TokenType.Int)) { expression = new IntExpr(Consume(TokenType.Int)); } else if (CurrentIs(TokenType.String)) { expression = new StringExpr(Consume(TokenType.String)); } else if (CurrentIs(TokenType.LeftParen)) { Token leftParen = Consume(TokenType.LeftParen); if (CurrentIs(TokenType.RightParen)) { // () -> unit expression = new UnitExpr(leftParen.Position); } else if (CurrentIs(TokenType.Operator)) { // ( OPERATOR ) -> an operator in prefix form Token op = Consume(TokenType.Operator); expression = new NameExpr(op.Position, op.StringValue); } else { // anything else is a regular parenthesized expression expression = Expression(); } Consume(TokenType.RightParen); } else { expression = null; } return(expression); }
IBoundExpr IUnboundExprVisitor<IBoundExpr>.Visit(NameExpr expr) { //### bob: handle array constructors. hack! should be intrinsic if (expr.Name == "ArrayOf") { // handle ArrayOf[Int] if (expr.TypeArgs.Count == 1) { return new ArrayExpr(expr.Position, expr.TypeArgs[0]).Accept(this); } } return mContext.ResolveName(mFunction, Scope, expr.Position, expr.Name, expr.TypeArgs, null); }
// <-- FN ((Name | Operator) TupleType) // | (LPAREN ParamDecl RPAREN) private IUnboundExpr FuncExpr() { Position position = Consume(TokenType.Fn).Position; if (CurrentIs(TokenType.LeftParen)) { // local function var paramNames = new List <string>(); var funcType = FnArgsDecl(paramNames); var body = Block(); return(new LocalFuncExpr(position, paramNames, funcType, body)); } else { // function reference NameExpr name; if (CurrentIs(TokenType.Operator)) { Token op = Consume(TokenType.Operator); name = new NameExpr(op.Position, op.StringValue); } else { var token = Consume(TokenType.Name); name = new NameExpr(token.Position, token.StringValue, TypeArgs()); } var parameters = TupleType().ToArray(); IUnboundDecl parameter; if (parameters.Length == 0) { parameter = Decl.Unit; } else if (parameters.Length == 1) { parameter = parameters[0]; } else { parameter = new TupleType(parameters); } return(new FuncRefExpr(position, name, parameter)); } }
public FuncRefExpr(Position position, NameExpr name, IUnboundDecl paramType) { Position = position; Name = name; ParamType = paramType; }
public virtual IUnboundExpr Transform(NameExpr expr) { return(expr); }
IUnboundExpr IUnboundExprVisitor <IUnboundExpr> .Visit(NameExpr expr) { return(Call("NameExpr", String(expr.Name))); }