Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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");
        }
Esempio n. 3
0
        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");
        }