Esempio n. 1
0
        internal void ExpandInPlace([NotNull] Context ctx)
        {
            IEnumerable <ZilObject> RecursiveExpandWithSplice(ZilObject zo)
            {
                ZilObject result;

                ZilObject SetSourceLine(ZilResult zr)
                {
                    var newObj = (ZilObject)zr;

                    newObj.SourceLine = zo.SourceLine;
                    return(newObj);
                }

                switch (zo)
                {
                case ZilList list:
                    result = new ZilList(list.SelectMany(RecursiveExpandWithSplice));
                    break;

                case ZilVector vector:
                    result = new ZilVector(vector.SelectMany(RecursiveExpandWithSplice).ToArray());
                    break;

                case ZilForm form:
                    ZilObject expanded;
                    try
                    {
                        using (DiagnosticContext.Push(form.SourceLine))
                        {
                            expanded = (ZilObject)form.Expand(ctx);
                        }
                    }
                    catch (InterpreterError ex)
                    {
                        ctx.HandleError(ex);
                        return(new[] { ctx.FALSE });
                    }
                    if (expanded is IMayExpandAfterEvaluation expandAfter &&
                        expandAfter.ShouldExpandAfterEvaluation)
                    {
                        return(expandAfter.ExpandAfterEvaluation().AsResultSequence()
                               .Select(SetSourceLine)
                               .Select(xo => ReferenceEquals(xo, form) ? xo : new ZilMacroResult(xo)));
                    }
                    else if (!ReferenceEquals(expanded, form))
                    {
                        expanded.SourceLine = zo.SourceLine;
                        return(RecursiveExpandWithSplice(expanded)
                               .Select(xo => new ZilMacroResult(xo)));
                    }
                    else
                    {
                        result = new ZilForm(form.SelectMany(RecursiveExpandWithSplice));
                    }
                    break;
Esempio n. 2
0
        static void RearrangeVector([NotNull] ZilVector vector, int recordSize, [NotNull] int[] desiredIndexOrder)
        {
            var output = new List <ZilObject>(vector.GetLength());

            foreach (var srcIndex in desiredIndexOrder)
            {
                for (int i = 0; i < recordSize; i++)
                {
                    output.Add(vector[srcIndex * recordSize + i]);
                }
            }

            for (int i = 0; i < output.Count; i++)
            {
                vector[i] = output[i];
            }
        }
Esempio n. 3
0
        public void TestDEFSTRUCT_ExistingObject()
        {
            var ctx       = new Context();
            var pointAtom = ZilAtom.Parse("POINT", ctx);

            TestHelpers.EvalAndAssert(ctx, "<DEFSTRUCT POINT VECTOR (POINT-X FIX 0) (POINT-Y FIX 0) (POINT-Z FIX 0) (POINT-W FIX 'NONE)>",
                                      pointAtom);

            // put values into existing object, setting any omitted fields to default values (unless the default is NONE!)
            var vector = new ZilVector(new ZilFix(123), new ZilFix(456), new ZilFix(789), new ZilFix(1011));

            ctx.SetLocalVal(ZilAtom.Parse("MY-VECTOR", ctx),
                            new ZilStructuredHash(pointAtom, PrimType.VECTOR, vector));
            TestHelpers.EvalAndAssert(ctx, "<MAKE-POINT 'POINT .MY-VECTOR 'POINT-Y 999 'POINT-X 888>",
                                      new ZilStructuredHash(pointAtom, PrimType.VECTOR, vector));
            TestHelpers.AssertStructurallyEqual(new ZilFix(888), vector[0]);
            TestHelpers.AssertStructurallyEqual(new ZilFix(999), vector[1]);
            TestHelpers.AssertStructurallyEqual(new ZilFix(0), vector[2]);
            TestHelpers.AssertStructurallyEqual(new ZilFix(1011), vector[3]);
        }
Esempio n. 4
0
        public static ZilResult SORT(Context ctx,
                                     [NotNull][Decl("<OR FALSE APPLICABLE>")] ZilObject predicate,
                                     [NotNull] ZilVector vector, int recordSize        = 1, int keyOffset = 0,
                                     [CanBeNull] AdditionalSortParam[] additionalSorts = null)
        {
            if (keyOffset < 0 || keyOffset >= recordSize)
            {
                throw new InterpreterError(InterpreterMessages._0_Expected_0__Key_Offset__Record_Size, "SORT");
            }

            var vectorLength = vector.GetLength();
            int numRecords   = Math.DivRem(vectorLength, recordSize, out var remainder);

            if (remainder != 0)
            {
                throw new InterpreterError(InterpreterMessages._0_Vector_Length_Must_Be_A_Multiple_Of_Record_Size, "SORT");
            }

            if (additionalSorts != null)
            {
                foreach (var asp in additionalSorts)
                {
                    if (asp.RecordSize < 1)
                    {
                        throw new InterpreterError(InterpreterMessages._0_Expected_0__Key_Offset__Record_Size, "SORT");
                    }

                    var len  = asp.Vector.GetLength();
                    int recs = Math.DivRem(len, asp.RecordSize, out var rem);

                    if (rem != 0)
                    {
                        throw new InterpreterError(InterpreterMessages._0_Vector_Length_Must_Be_A_Multiple_Of_Record_Size, "SORT");
                    }

                    if (recs != numRecords)
                    {
                        throw new InterpreterError(InterpreterMessages._0_All_Vectors_Must_Have_The_Same_Number_Of_Records, "SORT");
                    }
                }
            }

            ZilObject KeySelector(int i) => vector[i * recordSize + keyOffset];

            Comparison <ZilObject> comparison;

            if (predicate.IsTrue)
            {
                // user-provided comparison
                var applicable = predicate.AsApplicable(ctx);
                Debug.Assert(applicable != null);

                var args = new ZilObject[2];
                comparison = (a, b) =>
                {
                    // greater?
                    args[0] = a;
                    args[1] = b;

                    var zr = applicable.ApplyNoEval(ctx, args);
                    if (zr.ShouldPass())
                    {
                        throw new SortAbortedException(zr);
                    }

                    if (((ZilObject)zr).IsTrue)
                    {
                        return(1);
                    }

                    // less?
                    args[0] = b;
                    args[1] = a;

                    zr = applicable.ApplyNoEval(ctx, args);
                    if (zr.ShouldPass())
                    {
                        throw new SortAbortedException(zr);
                    }

                    if (((ZilObject)zr).IsTrue)
                    {
                        return(-1);
                    }

                    // equal
                    return(0);
                };
            }
            else
            {
                // default comparison
                comparison = (a, b) =>
                {
                    if (a.GetTypeAtom(ctx) != b.GetTypeAtom(ctx))
                    {
                        throw new InterpreterError(InterpreterMessages._0_Keys_Must_Have_The_Same_Type_To_Use_Default_Comparison, "SORT");
                    }

                    a = a.GetPrimitive(ctx);
                    b = b.GetPrimitive(ctx);

                    switch (a.PrimType)
                    {
                    case PrimType.ATOM:
                        return(string.Compare(((ZilAtom)a).Text, ((ZilAtom)b).Text, StringComparison.Ordinal));

                    case PrimType.FIX:
                        return(((ZilFix)a).Value.CompareTo(((ZilFix)b).Value));

                    case PrimType.STRING:
                        return(string.Compare(((ZilString)a).Text, ((ZilString)b).Text, StringComparison.Ordinal));

                    default:
                        throw new InterpreterError(InterpreterMessages._0_Key_Primtypes_Must_Be_ATOM_FIX_Or_STRING_To_Use_Default_Comparison, "SORT");
                    }
                };
            }

            try
            {
                // sort
                var sortedIndexes =
                    Enumerable.Range(0, numRecords)
                    .OrderBy(KeySelector, Comparer <ZilObject> .Create(comparison))
                    .ToArray();

                // write output
                RearrangeVector(vector, recordSize, sortedIndexes);

                if (additionalSorts != null)
                {
                    foreach (var asp in additionalSorts)
                    {
                        RearrangeVector(asp.Vector, asp.RecordSize, sortedIndexes);
                    }
                }

                return(vector);
            }
            catch (SortAbortedException ex)
            {
                return(ex.ZilResult);
            }
            catch (Exception wrapper) when(wrapper.InnerException is SortAbortedException ex)
            {
                return(ex.ZilResult);
            }
        }