public override TypeSpec ResolveAsType(IMemberContext mc, bool allowUnboundTypeArguments = false) { var length = elements.Count; if (length > 7) { throw new NotImplementedException("tuples > 7"); } eclass = ExprClass.Type; var otype = mc.Module.PredefinedTypes.Tuples [length - 1].Resolve(); if (otype == null) { return(null); } GenericTypeExpr ctype = new GenericTypeExpr(otype, elements, loc); type = ctype.ResolveAsType(mc); if (names != null && CheckElementNames(mc) && type != null) { type = NamedTupleSpec.MakeType(mc.Module, (InflatedTypeSpec)type, names); } return(type); }
protected override Expression DoResolve(ResolveContext rc) { var src = source.Resolve(rc); if (src == null) { return(null); } if (InternalType.HasNoType(src.Type)) { rc.Report.Error(8131, source.Location, "Deconstruct assignment requires an expression with a type on the right-hand-side"); return(null); } var src_type = src.Type; if (src_type.IsTupleType) { if (src_type.Arity != targetExprs.Count) { rc.Report.Error(8132, loc, "Cannot deconstruct a tuple of `{0}' elements into `{1}' variables", src_type.Arity.ToString(), targetExprs.Count.ToString()); return(null); } var tupleLiteral = src as TupleLiteral; if (tupleLiteral == null && !ExpressionAnalyzer.IsInexpensiveLoad(src)) { var expr_variable = LocalVariable.CreateCompilerGenerated(source.Type, rc.CurrentBlock, loc); source = new CompilerAssign(expr_variable.CreateReferenceExpression(rc, loc), source, loc); instance = expr_variable.CreateReferenceExpression(rc, loc); } for (int i = 0; i < targetExprs.Count; ++i) { var tle = src_type.TypeArguments [i]; var lv = variablesToInfer? [i]; if (lv != null) { if (InternalType.HasNoType(tle)) { rc.Report.Error(8130, Location, "Cannot infer the type of implicitly-typed deconstruction variable `{0}'", lv.Name); lv.Type = InternalType.ErrorType; continue; } lv.Type = tle; lv.PrepareAssignmentAnalysis((BlockContext)rc); } var element_src = tupleLiteral == null ? new MemberAccess(instance, NamedTupleSpec.GetElementPropertyName(i)) : tupleLiteral.Elements [i].Expr; targetExprs [i] = new SimpleAssign(targetExprs [i], element_src).Resolve(rc); } eclass = ExprClass.Value; // TODO: The type is same only if there is no target element conversion // var res = (/*byte*/ b, /*short*/ s) = (2, 4); type = src.Type; return(this); } if (src_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { rc.Report.Error(8133, loc, "Cannot deconstruct dynamic objects"); return(null); } /* * var args = new Arguments (targetExprs.Count); * foreach (var t in targetExprs) { * args.Add (new Argument (t, Argument.AType.Out)); * } * * var invocation = new Invocation (new MemberAccess (src, "Deconstruct"), args); * var res = invocation.Resolve (rc); */ throw new NotImplementedException("Custom deconstruct"); }
protected override Expression DoResolve(ResolveContext rc) { var src = source.Resolve(rc); if (src == null) { return(null); } if (InternalType.HasNoType(src.Type)) { rc.Report.Error(8131, source.Location, "Deconstruct assignment requires an expression with a type on the right-hand-side"); return(null); } var src_type = src.Type; if (src_type.IsTupleType) { int target_count; if (targetExprs == null) { target_count = variables.Count; targetExprs = new List <Expression> (target_count); } else { target_count = targetExprs.Count; } if (src_type.Arity != target_count) { rc.Report.Error(8132, loc, "Cannot deconstruct a tuple of `{0}' elements into `{1}' variables", src_type.Arity.ToString(CultureInfo.InvariantCulture), target_count.ToString(CultureInfo.InvariantCulture)); return(null); } var tupleLiteral = src as TupleLiteral; if (tupleLiteral == null && !ExpressionAnalyzer.IsInexpensiveLoad(src)) { var expr_variable = LocalVariable.CreateCompilerGenerated(source.Type, rc.CurrentBlock, loc); source = new CompilerAssign(expr_variable.CreateReferenceExpression(rc, loc), source, loc); instance = expr_variable.CreateReferenceExpression(rc, loc); } var element_srcs = new List <Expression> (); var src_names = new List <string> (); for (int i = 0; i < target_count; ++i) { var element_src = tupleLiteral == null ? new MemberAccess(instance, NamedTupleSpec.GetElementPropertyName(i)) : tupleLiteral.Elements [i].Expr; element_srcs.Add(element_src); if (element_src is VariableReference) { src_names.Add((element_src as VariableReference)?.Name); } } for (int i = 0; i < target_count; ++i) { var tle = src_type.TypeArguments [i]; if (variables != null) { var variable = variables [i].Variable; if (variable.Type == InternalType.Discard) { variables [i] = null; targetExprs.Add(EmptyExpressionStatement.Instance); continue; } var variable_type = variables [i].TypeExpression; targetExprs.Add(new LocalVariableReference(variable, variable.Location)); if (variable_type is VarExpr) { if (InternalType.HasNoType(tle)) { rc.Report.Error(8130, Location, "Cannot infer the type of implicitly-typed deconstruction variable `{0}'", variable.Name); tle = InternalType.ErrorType; } variable.Type = tle; } else { variable.Type = variable_type.ResolveAsType(rc); } variable.PrepareAssignmentAnalysis((BlockContext)rc); } var element_target = (targetExprs [i] as SimpleName)?.LookupNameExpression(rc, MemberLookupRestrictions.None); if (element_target != null && src_names.Contains((element_target as VariableReference)?.Name)) { var tempType = element_target.Resolve(rc).Type; var temp = new LocalTemporary(tempType); tempExprs.Add(new SimpleAssign(temp, element_srcs [i]).Resolve(rc)); targetExprs [i] = new SimpleAssign(targetExprs [i], temp).Resolve(rc); } else { targetExprs [i] = new SimpleAssign(targetExprs [i], element_srcs [i]).Resolve(rc); } } eclass = ExprClass.Value; // TODO: The type is same only if there is no target element conversion // var res = (/*byte*/ b, /*short*/ s) = (2, 4); type = src.Type; return(this); } if (src_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { rc.Report.Error(8133, loc, "Cannot deconstruct dynamic objects"); return(null); } /* * var args = new Arguments (targetExprs.Count); * foreach (var t in targetExprs) { * args.Add (new Argument (t, Argument.AType.Out)); * } * * var invocation = new Invocation (new MemberAccess (src, "Deconstruct"), args); * var res = invocation.Resolve (rc); */ throw new NotImplementedException("Custom deconstruct"); }