/* * => [captures...] expression * or * => [captures...] { code... } * or * (parameters...) => [captures...] expression * or * (parameters...) => [captures...] { code... } */ LambdaExpression ParseLambda(TupleExpression argumentList = null) { var lambda = LambdaExpression.Create(unit.Location); // Parse parameter list if (argumentList == null || argumentList.Count == 0) { if (unit.Match(LoreToken.OpenParen)) { var parameters = ParseDeclarationArgumentList(); lambda.SetParameters(parameters); } } else { var lst = new List <NamedParameter> (); foreach (var argument in argumentList.Items) { var name = argument as NameExpression; if (name == null) { throw LoreException.Create(unit.Location).Describe($"Invalid parameter list in lambda declaration."); } lst.Add(NamedParameter.Create(name)); } lambda.SetParameters(lst); } // Expect arrow operator unit.Expect(LoreToken.Operator, "=>"); // Create master code block CodeBlock master = CodeBlock.Create(unit.Location); // Parse captures if (unit.Match(LoreToken.OpenBracket)) { // Parse captures unit.Expect(LoreToken.OpenBracket); while (!unit.Match(LoreToken.CloseBracket)) { var lex = unit.Read(); var capture = Capture.Create(unit, lex); master.AddCapture(capture); } unit.Expect(LoreToken.CloseBracket); } // Parse block if (unit.Match(LoreToken.OpenBrace)) { var block = ParseBlockWithoutCaptures(); // Merge captures master.Merge(block); } // Or parse expression else { // Create return statement for the result of the expression var retstmt = ReturnStatement.Create(unit.Location); retstmt.SetExpression(ParseExpression()); // Create a new block with the return statement var block = CodeBlock.Create(unit.Location); block.AddChild(retstmt); // Merge captures master.Merge(block); } // Set the lambda body lambda.SetBody(master); Console.WriteLine(lambda); return(lambda); }
/* * fn name (parameters...) -> type [captures...] { * code... * } */ FunctionDeclaration ParseFunction() { var function = FunctionDeclaration.Create(unit.Location); unit.Expect(LoreToken.Keyword, "fn"); // Read the name of the function var name = unit.Expect(LoreToken.Identifier); function.SetName(name.Value); // Read the parameter list if (unit.Match(LoreToken.OpenParen)) { function.SetParameters(ParseDeclarationArgumentList()); } // Read the return type if (unit.Accept(LoreToken.Operator, "->")) { var names = new List <NameExpression> (); while (unit.Match(LoreToken.Identifier)) { names.Add(ParseName()); if (!unit.Accept(LoreToken.Comma)) { break; } } if (names.Count == 1) { function.SetReturnType(names [0]); } else { function.SetReturnTuple(names); } } // Create the function body CodeBlock body = CodeBlock.Create(unit.Location); // Parse captures if (unit.Accept(LoreToken.OpenBracket)) { while (!unit.Match(LoreToken.CloseBracket)) { var lex = unit.Read(); var capture = Capture.Create(unit, lex); body.AddCapture(capture); } unit.Expect(LoreToken.CloseBracket); } // Parse body if (unit.Match(LoreToken.OpenBrace)) { body = ParseBlock(); } else if (unit.Accept(LoreToken.Operator, "=>")) { body.AddChild(ParseExpression()); } // Return the function function.SetBody(body); return(function); }
/// <summary> /// Merge this code block with another one. /// </summary> /// <param name="other">The other code block.</param> public void Merge(CodeBlock other) { Captures.AddRange(other.Captures.GroupBy(c => c.Identifier).Select(g => g.First())); Children.AddRange(other.Children); }
/// <summary> /// Sets the body of the function. /// </summary> /// <returns>The body.</returns> /// <param name="body">Body.</param> public void SetBody(CodeBlock body) { this.body = body; }
public virtual void Accept(CodeBlock block) => Update(block);