public LambdaAction(ParseInfo parseInfo, Scope scope, DeltinScriptParser.LambdaContext context) { Scope lambdaScope = scope.Child(); RecursiveCallHandler = new LambdaRecursionHandler(this); CallInfo = new CallInfo(RecursiveCallHandler, parseInfo.Script); // Get the lambda parameters. Parameters = new Var[context.define().Length]; InvokedState = new SubLambdaInvoke[Parameters.Length]; for (int i = 0; i < Parameters.Length; i++) { InvokedState[i] = new SubLambdaInvoke(); // TODO: Make custom builder. Parameters[i] = new ParameterVariable(lambdaScope, new DefineContextHandler(parseInfo, context.define(i)), InvokedState[i]); } CodeType[] argumentTypes = Parameters.Select(arg => arg.CodeType).ToArray(); // context.block() will not be null if the lambda is a block. // () => {} if (context.block() != null) { // Parse the block. Block = new BlockAction(parseInfo.SetCallInfo(CallInfo), lambdaScope, context.block()); // Validate the block. BlockTreeScan validation = new BlockTreeScan(parseInfo, Block, "lambda", DocRange.GetRange(context.INS())); validation.ValidateReturns(); if (validation.ReturnsValue) { LambdaType = new ValueBlockLambda(validation.ReturnType, argumentTypes); MultiplePaths = validation.MultiplePaths; } else { LambdaType = new BlockLambda(argumentTypes); } } // context.expr() will not be null if the lambda is an expression. // () => 2 * x else if (context.expr() != null) { // Get the lambda expression. Expression = parseInfo.SetCallInfo(CallInfo).GetExpression(lambdaScope, context.expr()); LambdaType = new MacroLambda(Expression.Type(), argumentTypes); } // Add so the lambda can be recursive-checked. parseInfo.TranslateInfo.RecursionCheck(CallInfo); // Add hover info parseInfo.Script.AddHover(DocRange.GetRange(context.INS()), new MarkupBuilder().StartCodeLine().Add(LambdaType.GetName()).EndCodeLine().ToString()); }
public LambdaAction(ParseInfo parseInfo, Scope scope, LambdaExpression context) { _context = context; _lambdaScope = scope.Child(); _parseInfo = parseInfo; _contextualParameterTypesKnown = _parseInfo.ExpectingLambda != null && _parseInfo.ExpectingLambda.Type.ParameterTypesKnown; RecursiveCallHandler = new LambdaRecursionHandler(this); CallInfo = new CallInfo(RecursiveCallHandler, parseInfo.Script); This = scope.GetThis(); _isExplicit = context.Parameters.Any(p => p.Type != null); var parameterState = context.Parameters.Count == 0 || _isExplicit ? ParameterState.CountAndTypesKnown : ParameterState.CountKnown; // Get the lambda parameters. Parameters = new Var[context.Parameters.Count]; InvokedState = new SubLambdaInvoke[Parameters.Length]; _argumentTypes = new CodeType[Parameters.Length]; for (int i = 0; i < Parameters.Length; i++) { if (_isExplicit && context.Parameters[i].Type == null) { parseInfo.Script.Diagnostics.Error("Inconsistent lambda parameter usage; parameter types must be all explicit or all implicit", context.Parameters[i].Range); } InvokedState[i] = new SubLambdaInvoke(); Parameters[i] = new LambdaVariable(i, _parseInfo.ExpectingLambda?.Type, _lambdaScope, new LambdaContextHandler(parseInfo, context.Parameters[i]), InvokedState[i]); _argumentTypes[i] = Parameters[i].CodeType; } new CheckLambdaContext( parseInfo, this, "Cannot determine lambda in the current context", context.Range, parameterState ).Check(); // Add hover info // parseInfo.Script.AddHover(context.Arrow.Range, new MarkupBuilder().StartCodeLine().Add(LambdaType.GetName()).EndCodeLine().ToString()); }
public void GetLambdaContent(PortableLambdaType expectingType) { _resolved = true; // Get the lambda parameters. Parameters = new Var[_context.Parameters.Count]; InvokedState = new SubLambdaInvoke[Parameters.Length]; _argumentTypes = new CodeType[Parameters.Length]; for (int i = 0; i < Parameters.Length; i++) { if (_isExplicit && _context.Parameters[i].Type == null) { _parseInfo.Script.Diagnostics.Error("Inconsistent lambda parameter usage; parameter types must be all explicit or all implicit", _context.Parameters[i].Range); } InvokedState[i] = new SubLambdaInvoke(); Parameters[i] = (Var) new LambdaVariable(i, expectingType, _lambdaScope, new LambdaContextHandler(_parseInfo, _context.Parameters[i]), InvokedState[i]).GetVar(); _argumentTypes[i] = Parameters[i].GetDefaultInstance(null).CodeType.GetCodeType(_parseInfo.TranslateInfo); } ParseInfo parser = _parseInfo.SetCallInfo(CallInfo).AddVariableTracker(this).SetExpectType(expectingType?.ReturnType).SetReturnType(expectingType?.ReturnType); bool returnsValue = false; // Get the statements. if (_context.Statement is Block block) { var returnTracker = new ReturnTracker(); // Parse the block. Statement = new BlockAction(parser.SetReturnTracker(returnTracker), _lambdaScope, block); if (returnTracker.ReturnsValue) { ReturnType = returnTracker.InferredType; MultiplePaths = returnTracker.IsMultiplePaths; returnsValue = true; } } else if (_context.Statement is ExpressionStatement exprStatement) { // Get the lambda expression. Expression = parser.GetExpression(_lambdaScope, exprStatement.Expression); ReturnType = Expression.Type(); returnsValue = true; } else { // Statement Statement = parser.GetStatement(_lambdaScope, _context.Statement); if (Statement is IExpression expr) { Expression = expr; ReturnType = expr.Type(); if (ReturnType != null) { returnsValue = true; } } } LambdaType = new PortableLambdaType(new PortableLambdaTypeBuilder( kind: expectingType?.LambdaKind ?? LambdaKind.Anonymous, parameters: _argumentTypes, returnType: ReturnType, returnsValue: returnsValue, parameterTypesKnown: _isExplicit)); // Add so the lambda can be recursive-checked. _parseInfo.TranslateInfo.GetComponent <RecursionCheckComponent>().AddCheck(CallInfo); }