/// <summary> /// Creates an appropriate setter for GetMemberNode. /// From: expr.a /// To: expr.a = ... /// </summary> private SetMemberNode SetterOf(GetMemberNode node) { return(new SetMemberNode { Expression = node.Expression, StaticType = node.StaticType, MemberName = node.MemberName }); }
public void FieldWithTypeParameters() { var src = "Enumerable::Empty<int>"; var result = new GetMemberNode { StaticType = new TypeSignature("Enumerable"), MemberName = "Empty", TypeHints = { new TypeSignature("int") } }; TestParser(src, result); }
/// <summary> /// Resolves the method if the expression was a member getter (obj.field or type::field). /// </summary> private void resolveGetMember(Context ctx, GetMemberNode node) { _InvocationSource = node.Expression; var type = _InvocationSource != null ? _InvocationSource.Resolve(ctx) : ctx.ResolveType(node.StaticType); checkTypeInSafeMode(ctx, type); if (node.TypeHints != null && node.TypeHints.Count > 0) _TypeHints = node.TypeHints.Select(x => ctx.ResolveType(x, true)).ToArray(); try { // resolve a normal method try { _Method = ctx.ResolveMethod( type, node.MemberName, _ArgTypes, _TypeHints, (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); if (_Method.IsStatic) _InvocationSource = null; return; } catch (KeyNotFoundException) { if (_InvocationSource == null) throw; } // resolve a callable field try { ctx.ResolveField(type, node.MemberName); resolveExpression(ctx, node); return; } catch (KeyNotFoundException) { } // resolve a callable property try { ctx.ResolveProperty(type, node.MemberName); resolveExpression(ctx, node); return; } catch (KeyNotFoundException) { } Arguments = (Arguments[0] is UnitNode) ? new List<NodeBase> {_InvocationSource} : new[] {_InvocationSource}.Union(Arguments).ToList(); var oldArgTypes = _ArgTypes; _ArgTypes = Arguments.Select(a => a.Resolve(ctx)).ToArray(); _InvocationSource = null; try { // resolve a local function that is implicitly used as an extension method _Method = ctx.ResolveMethod( ctx.MainType.TypeInfo, node.MemberName, _ArgTypes, resolver: (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); return; } catch (KeyNotFoundException) { } // resolve a declared extension method // most time-consuming operation, therefore is last checked try { if(!ctx.Options.AllowExtensionMethods) throw new KeyNotFoundException(); _Method = ctx.ResolveExtensionMethod( type, node.MemberName, oldArgTypes, _TypeHints, (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); } catch (KeyNotFoundException) { var msg = node.StaticType != null ? CompilerMessages.TypeStaticMethodNotFound : CompilerMessages.TypeMethodNotFound; error(msg, type, node.MemberName); } } catch (AmbiguousMatchException) { error(CompilerMessages.TypeMethodInvocationAmbiguous, type, node.MemberName); } }
/// <summary> /// Resolves the method if the expression was a member getter (obj.field or type::field). /// </summary> private void ResolveGetMember(Context ctx, GetMemberNode node) { _invocationSource = node.Expression; var type = _invocationSource != null ? _invocationSource.Resolve(ctx) : ctx.ResolveType(node.StaticType); CheckTypeInSafeMode(ctx, type); if (node.TypeHints != null && node.TypeHints.Count > 0) { _typeHints = node.TypeHints.Select(x => ctx.ResolveType(x, true)).ToArray(); } try { // resolve a normal method try { _method = ctx.ResolveMethod( type, node.MemberName, ArgTypes, _typeHints, (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); if (_method.IsStatic) { _invocationSource = null; } return; } catch (KeyNotFoundException) { if (_invocationSource == null) { throw; } } // resolve a callable field try { ctx.ResolveField(type, node.MemberName); ResolveExpression(ctx, node); return; } catch (KeyNotFoundException) { } // resolve a callable property try { ctx.ResolveProperty(type, node.MemberName); ResolveExpression(ctx, node); return; } catch (KeyNotFoundException) { } Arguments = (Arguments[0] is UnitNode) ? new List <NodeBase> { _invocationSource } : new[] { _invocationSource }.Union(Arguments).ToList(); var oldArgTypes = ArgTypes; ArgTypes = Arguments.Select(a => a.Resolve(ctx)).ToArray(); _invocationSource = null; try { // resolve a local function that is implicitly used as an extension method _method = ctx.ResolveMethod( ctx.MainType.TypeInfo, node.MemberName, ArgTypes, resolver: (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); return; } catch (KeyNotFoundException) { } // resolve a declared extension method // most time-consuming operation, therefore is last checked try { if (!ctx.Options.AllowExtensionMethods) { throw new KeyNotFoundException(); } _method = ctx.ResolveExtensionMethod( type, node.MemberName, oldArgTypes, _typeHints, (idx, types) => ctx.ResolveLambda(Arguments[idx] as LambdaNode, types) ); } catch (KeyNotFoundException) { var msg = node.StaticType != null ? CompilerMessages.TypeStaticMethodNotFound : CompilerMessages.TypeMethodNotFound; Error(msg, type, node.MemberName); } } catch (AmbiguousMatchException) { Error(CompilerMessages.TypeMethodInvocationAmbiguous, type, node.MemberName); } }
/// <summary> /// accessor_mbr = "." identifier [ type_args ] /// </summary> private GetMemberNode parseAccessorMbr() { if (!check(LexemType.Dot)) return null; var node = new GetMemberNode(); node.MemberName = ensure(LexemType.Identifier, ParserMessages.MemberNameExpected).Value; var args = attempt(parseTypeArgs); if (args != null) node.TypeHints = args; return node; }
/// <summary> /// invoke_pass = "******" identifier [ type_args ] ( invoke_block_args | invoke_line_args ) /// </summary> private InvocationNode parseInvokePass() { if (!check(LexemType.PassRight)) return null; var getter = new GetMemberNode(); var invoker = new InvocationNode { Expression = getter }; getter.MemberName = ensure(LexemType.Identifier, ParserMessages.MemberNameExpected).Value; var hints = attempt(parseTypeArgs); if(hints != null) getter.TypeHints = hints; var lambda = attempt(parseLambdaLineExpr); if (lambda != null) { invoker.Arguments = new List<NodeBase> { lambda }; } else { invoker.Arguments = parseInvokeBlockArgs().ToList(); if (invoker.Arguments.Count == 0) invoker.Arguments = parseInvokeLineArgs().ToList(); if (invoker.Arguments.Count == 0) error(ParserMessages.ArgumentsExpected); } return invoker; }
/// <summary> /// lvalue_stmbr_expr = type "::" identifier /// </summary> private GetMemberNode parseLvalueStmbrExpr() { var type = attempt(parseType); if (type == null || !check(LexemType.DoubleŠ”olon)) return null; var node = new GetMemberNode(); node.StaticType = type; node.MemberName = ensure(LexemType.Identifier, ParserMessages.MemberNameExpected).Value; return node; }