예제 #1
0
        public virtual void Emit(CompilationContext context)
        {
            var sourceType     = SourceType;
            var targetType     = TargetMember.MemberType;
            var targetCanWrite = TargetMember.CanWrite(HasOption(MemberMapOptions.NonPublic));

            if (targetCanWrite && _converter != null)
            {
                EmitSource(context);
                _converter.Emit(sourceType, targetType, context);
                EmitSetTarget(context);
                return;
            }
            if (!targetCanWrite && _mapper != null)
            {
                EmitSource(context);
                EmitSetTarget(context);
                _mapper.Emit(sourceType, targetType, context);
                return;
            }
            if (!HasOption(MemberMapOptions.Hierarchy) ||
                !targetType.GetTypeInfo().IsClass ||
                targetType.IsNullable())
            {
                var converter = GetConvertEmitter(sourceType, targetType);
                if (converter != null)
                {
                    EmitSource(context);
                    converter(context);
                    EmitSetTarget(context);
                }
            }
            else
            {
                var mapperType = _genericMapperTypes[Triplet.Create(_container, sourceType, targetType)];
                if (targetCanWrite)
                {
                    EmitSource(context);
                    context.CurrentType = sourceType;
                    context.EmitCall(mapperType.GetMethod("Convert"));
                    EmitSetTarget(context);
                }
                else
                {
                    var sourceValue = context.DeclareLocal(sourceType);
                    EmitSource(context);
                    context.Emit(OpCodes.Stloc, sourceValue);

                    var targetValue = context.DeclareLocal(targetType);
                    ((IMemberBuilder)TargetMember).EmitGetter(context);
                    context.Emit(OpCodes.Stloc, targetValue);

                    context.Emit(OpCodes.Ldloc, sourceValue);
                    context.Emit(OpCodes.Ldloc, targetValue);
                    context.EmitCall(mapperType.GetMethod("Map"));
                }
            }
        }
예제 #2
0
        public void SaveRangeIsCalled()
        {
            var ranges  = new List <Triplet <ILNode, IndexRange, int> >();
            var options = new LNodePrinterOptions {
                SaveRange = (n, r, d) => ranges.Add(Triplet.Create(n, r, d))
            };

            LNode node = F.Call(_("var"), F.Call(S.Assign, x, F.Call(S.Sub, two)));

            Stmt("var(x = -2);", node);
            string output = Les2LanguageService.Value.Print(node, null, ParsingMode.Statements, options);

            ExpectSavedRange(ranges, output, node, "var(x = -2);");
            // "(" is part of the target because if there is %trailing trivia on the target, it appears after "("
            ExpectSavedRange(ranges, output, node.Target, "var(");
            ExpectSavedRange(ranges, output, node[0], "x = -2");
            ExpectSavedRange(ranges, output, node[0][0], "x");
            ExpectSavedRange(ranges, output, node[0][1], "-2");
            ExpectSavedRange(ranges, output, node[0][1].Target, "-");
            ExpectSavedRange(ranges, output, node[0][1][0], "2");
            // The space is included because suffix trivia on an operator Target is printed after the space
            ExpectSavedRange(ranges, output, node[0].Target, "= ");

            ranges.Clear();
            LNode body, signature;

            node = F.Call(S.Lambda, signature = F.Call("MyMethod", F.Call(S.Colon, x, F.Call(S.Array, _("int")))),
                          F.Braces(body = F.Call(Foo, F.Call("'.+", x, F.Literal(123)), F.Tuple(a, b))));
            // There's extra indent inside the braces because the braces are a subexpression of `=>`
            Exact("MyMethod(x : [int]) => {\n    Foo(x .+ 123, (a; b));\n  };", node);
            output = Les2LanguageService.Value.Print(node, null, ParsingMode.Statements, options);
            ExpectSavedRange(ranges, output, node.Target, "=> ");
            ExpectSavedRange(ranges, output, signature, "MyMethod(x : [int])");
            ExpectSavedRange(ranges, output, signature.Target, "MyMethod(");
            ExpectSavedRange(ranges, output, body, "Foo(x .+ 123, (a; b));");
            ExpectSavedRange(ranges, output, body.Target, "Foo(");
            ExpectSavedRange(ranges, output, signature[0], "x : [int]");
            ExpectSavedRange(ranges, output, signature[0].Target, ": ");
            ExpectSavedRange(ranges, output, signature[0][1], "[int]");
            ExpectSavedRange(ranges, output, signature[0][1][0], "int");
            // It could be argued that the comma shouldn't be included, but it allows suffix trivia to appear after the comma
            ExpectSavedRange(ranges, output, body[0], "x .+ 123, ");
            ExpectSavedRange(ranges, output, body[0][0], "x");
            ExpectSavedRange(ranges, output, body[0][1], "123");
            ExpectSavedRange(ranges, output, body[0].Target, ".+ ");
            ExpectSavedRange(ranges, output, body[1], "(a; b)");
            ExpectSavedRange(ranges, output, body[1][0], "a; ");
            ExpectSavedRange(ranges, output, body[1][1], "b");
        }
예제 #3
0
        public void Solve()
        {
            var  n   = sc.Integer();
            var  u   = sc.Long();
            var  v   = sc.Long();
            var  a   = sc.Long(n);
            long ans = 0;
            var  E   = new List <Triplet <long, int, int> >();

            for (int i = 1; i < n; i++)
            {
                E.Add(Triplet.Create(u * (a[i] - a[i - 1]), i - 1, i));
            }
            E.Sort();
            var set = new DisjointSet(n);

            foreach (var x in E)
            {
                if (x.I > v)
                {
                    continue;
                }
                if (set.IsUnited(x.J, x.K))
                {
                    continue;
                }
                else
                {
                    set.Unite(x.J, x.K);
                    ans += x.I;
                }
            }
            var cnt = 0;

            for (int i = 0; i < n; i++)
            {
                if (set[i] == i)
                {
                    cnt++;
                }
            }
            IO.Printer.Out.WriteLine(ans + (cnt - 1) * v);
        }
        public SimpleCssStyleDefinition(IList <SimpleCssSelectorElement> selectorElements, IEnumerable <Pair <string, string> > propertyDefinitions, int index)
        {
            elements            = selectorElements;
            PropertyDefinitions = propertyDefinitions;
            Index = index;

            //http://www.w3.org/TR/REC-CSS2/cascade.html#specificity
            specificity = Triplet.Create(0, 0, 0);
            foreach (var elem in selectorElements)
            {
                if (!elem.Id.IsEmpty())
                {
                    specificity.First = specificity.First + 1;
                }
                specificity.Second += elem.Classes.Length;
                if (!elem.Tag.IsEmpty())
                {
                    specificity.Third = specificity.Third + 1;
                }
            }
        }
예제 #5
0
        public void SaveRangeIsCalled()
        {
            var ranges  = new List <Triplet <ILNode, IndexRange, int> >();
            var options = new LNodePrinterOptions {
                SaveRange = (n, r, d) => ranges.Add(Triplet.Create(n, r, d))
            };

            LNode node = F.Var(F.Int32, F.Call(S.Assign, x, two));

            Stmt("int x = 2;", node);
            string output = EcsLanguageService.Value.Print(node, null, ParsingMode.Statements, options);

            ExpectSavedRange(ranges, output, node, "int x = 2;");
            ExpectSavedRange(ranges, output, node[0], "int");
            ExpectSavedRange(ranges, output, node[1], "x = 2");
            ExpectSavedRange(ranges, output, node[1][0], "x");
            ExpectSavedRange(ranges, output, node[1][1], "2");
            ExpectSavedRange(ranges, output, node[1].Target, "=");

            ranges.Clear();
            LNode body;

            node = F.Fn(F.Void, _("MyMethod"), F.AltList(), body = F.Call(Foo, F.Call(S.Add, x, one)));
            Stmt("void MyMethod() => Foo(x + 1);", node);
            output = EcsLanguageService.Value.Print(node, null, ParsingMode.Statements, options);
            ExpectSavedRange(ranges, output, node, "void MyMethod() => Foo(x + 1);");
            ExpectSavedRange(ranges, output, node[0], "void");
            ExpectSavedRange(ranges, output, node[1], "MyMethod");
            ExpectSavedRange(ranges, output, node[2], "()");
            ExpectSavedRange(ranges, output, body, "Foo(x + 1)");
            ExpectSavedRange(ranges, output, body.Target, "Foo");
            ExpectSavedRange(ranges, output, body[0], "x + 1");
            ExpectSavedRange(ranges, output, body[0][0], "x");
            ExpectSavedRange(ranges, output, body[0][1], "1");
            ExpectSavedRange(ranges, output, body[0].Target, "+");
        }
예제 #6
0
 static Triplet <Symbol, string, object> T(string typeMarker, string text, object value) =>
 Triplet.Create((Symbol)typeMarker, text, value);
예제 #7
0
        public static LNode unroll(LNode var, LNodeList cases, LNode body, IMessageSink sink)
        {
            // Maps identifiers => replacements. The integer counts how many times replacement occurred.
            var replacements = InternalList <Triplet <Symbol, LNode, int> > .Empty;

            if (var.IsId && !var.HasPAttrs())
            {
                replacements.Add(Triplet.Create(var.Name, (LNode)LNode.Missing, 0));
            }
            else
            {
                var vars = var.Args;
                if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs()))
                {
                    replacements = new Triplet <Symbol, LNode, int> [vars.Count].AsInternalList();
                    for (int i = 0; i < vars.Count; i++)
                    {
                        replacements.InternalArray[i].A = vars[i].Name;

                        // Check for duplicate names
                        for (int j = 0; j < i; j++)
                        {
                            if (replacements[i].A == replacements[j].A && replacements[i].A.Name != "_")
                            {
                                sink.Error(vars[i], "Duplicate name in the left-hand tuple");                                 // non-fatal
                            }
                        }
                    }
                }
                else
                {
                    return(Reject(sink, var, "The left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers."));
                }
            }

            UnrollCtx ctx = new UnrollCtx {
                Replacements = replacements
            };
            WList <LNode> output = new WList <LNode>();
            int iteration        = 0;
            foreach (LNode replacement in cases)
            {
                iteration++;
                bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces);
                int  count = tuple ? replacement.ArgCount : 1;
                if (replacements.Count != count)
                {
                    sink.Error(replacement, "iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Count, count);
                    if (count < replacements.Count)
                    {
                        continue;                         // too few
                    }
                }
                for (int i = 0; i < replacements.Count; i++)
                {
                    replacements.InternalArray[i].B = tuple ? replacement.Args[i] : replacement;
                }

                if (body.Calls(S.Braces))
                {
                    foreach (LNode stmt in body.Args)
                    {
                        output.Add(ctx.Replace(stmt).Value);
                    }
                }
                else
                {
                    output.Add(ctx.Replace(body).Value);
                }
            }

            foreach (var r in replacements)
            {
                if (r.C == 0 && !r.A.Name.StartsWith("_"))
                {
                    sink.Write(Severity.Warning, var, "Replacement variable '{0}' was never used", r.A);
                }
            }

            return(body.With(S.Splice, output.ToLNodeList()));
        }
예제 #8
0
 private void EnsureMapperType(Type sourceType, Type targetType, ModuleBuilder builder)
 {
     _genericMapperTypes.GetOrAdd(Triplet.Create(_container, sourceType, targetType), key => CreateMapper(builder, key.Second, key.Third));
 }