private void InferLambda(LambdaExpression le, TypeInferenceCache cache) { // lambda is the only one expression that can have its type set from outside if (!cache.ContainsKey(le)) { var lambdaType = Enumerable.Repeat(typeof(Variant), 1 + le.Args.Count()).ForgeFuncType(); cache.Add(le, new Lambda(le, lambdaType)); } // detect overlapping variables var closure = le.Parent == null ? null : le.Parent.GetClosure(); if (closure != null) { var overlapping = closure.Keys.Intersect(le.Args); if (overlapping.IsNotEmpty()) { throw new RedeclaredVariableException(Root, le, closure); } } // detect overriding keywords foreach (var arg in le.Args) { if (Integration.IsRegisteredJS(arg)) { throw new VariableOverridesKeywordException(Root, le, arg); } } InferTypes(le.Body, cache); }
public Lambda(LambdaExpression expression, Type type) { Expression = expression; Type = type; }
public RedeclaredVariableException(RelinqScriptExpression root, LambdaExpression le, Closure closure) : base(JSToCSharpExceptionType.RedeclaredVariable, root, le) { Closure = closure; Name = le.Args.Intersect(closure.Keys).First(); }
public VariableOverridesKeywordException(RelinqScriptExpression root, LambdaExpression le, String name) : base(JSToCSharpExceptionType.VariableOverridesKeyword, root, le) { Name = name; }
private LinqExpression CompileLambda(LambdaExpression le, CompilationContext ctx) { var lambda = ctx.Types[le] as Lambda; if (lambda == null) { throw new CSharpBuilderException( JSToCSharpExceptionType.UnexpectedInferredAst, Ast, le, ctx); } var @params = le.Args.Select((arg, i) => LinqExpression.Parameter(lambda.Type.GetFunctionDesc().Args.ElementAt(i), arg)). ToDictionary(param => param.Name); foreach (var name in @params.Keys) { if (Integration.IsRegisteredJS(name)) { throw new CSharpBuilderException( JSToCSharpExceptionType.UnexpectedInferredAst, Ast, le, ctx); } else if (ctx.Closure.ContainsKey(name)) { throw new CSharpBuilderException( JSToCSharpExceptionType.UnexpectedInferredAst, Ast, le, ctx); } else { ctx.Closure.Add(name, @params[name]); } } try { // todo. also yield cast to convert return types? return LinqExpression.Lambda(Compile(le.Body, ctx), @params.Values.ToArray()); } finally { ctx.Closure.RemoveRange(@params.Keys); } }