예제 #1
0
        private async Task <ExecValue> executeNativeCharFunctionAsync(ExecutionContext ctx, FunctionDefinition func,
                                                                      ObjectData thisValue)
        {
            char this_native = thisValue.NativeChar;

            if (func == ctx.Env.CharLengthGetter)
            {
                ObjectData result = await ObjectData.CreateInstanceAsync(ctx, func.ResultTypeName.Evaluation.Components,
                                                                         (byte)Encoding.UTF8.GetByteCount($"{this_native}")).ConfigureAwait(false);

                return(ExecValue.CreateReturn(result));
            }
            else if (func == ctx.Env.CharToString)
            {
                ObjectData result = await createStringAsync(ctx, $"{this_native}").ConfigureAwait(false);

                if (!ctx.Heap.TryInc(ctx, result, RefCountIncReason.NewString, $"{this_native}"))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                return(ExecValue.CreateReturn(result));
            }
            else
            {
                throw new NotImplementedException($"Function {func} is not implemented");
            }
        }
예제 #2
0
 private int validatedIndex(int idx)
 {
     if (idx < 0 || idx >= this.data.Length)
     {
         throw new IndexOutOfRangeException($"{ExceptionCode.SourceInfo()}");
     }
     return(idx);
 }
예제 #3
0
파일: ObjectData.cs 프로젝트: macias/Skila
        private int dereferencedCount(IExpression parentExpr, IExpression childExpr)
        {
            if (childExpr != null && childExpr.DereferencedCount_LEGACY != parentExpr.DereferencingCount)
            {
                throw new Exception($"Internal error {ExceptionCode.SourceInfo()}");
            }

            return(parentExpr.DereferencingCount);
        }
예제 #4
0
        internal ObjectData GetArgument(FunctionDefinition func, string paramName)
        {
            FunctionParameter param = func.Parameters.SingleOrDefault(it => it.Name.Name == paramName);

            if (param == null)
            {
                throw new System.Exception($"Internal error {ExceptionCode.SourceInfo()}");
            }
            return(this.FunctionArguments[param.Index]);
        }
예제 #5
0
        private async Task <ExecValue> executeNativeChannelFunctionAsync(ExecutionContext ctx, FunctionDefinition func, ObjectData this_value)
        {
            if (func.IsDefaultInitConstructor())
            {
                Channels.IChannel <ObjectData> channel = Channels.Channel.Create <ObjectData>();
                ctx.Heap.TryAddDisposable(channel);
                ObjectData channel_obj = await ObjectData.CreateInstanceAsync(ctx, this_value.RunTimeTypeInstance, channel).ConfigureAwait(false);

                this_value.Assign(channel_obj);
                return(ExecValue.CreateReturn(null));
            }
            else if (func.Name.Name == NameFactory.ChannelSend)
            {
                ObjectData arg = ctx.FunctionArguments.Single();
                if (!ctx.Env.IsPointerOfType(arg.RunTimeTypeInstance))
                {
                    arg = arg.Copy();
                }

                Channels.IChannel <ObjectData> channel = this_value.PlainValue.Cast <Channels.IChannel <ObjectData> >();
                bool result = await channel.SendAsync(arg).ConfigureAwait(false);

                return(ExecValue.CreateReturn(await ObjectData.CreateInstanceAsync(ctx, this_value.RunTimeTypeInstance, result).ConfigureAwait(false)));
            }
            else if (func.Name.Name == NameFactory.ChannelReceive)
            {
                Channels.IChannel <ObjectData> channel = this_value.PlainValue.Cast <Channels.IChannel <ObjectData> >();
                EntityInstance  channel_type           = this_value.RunTimeTypeInstance;
                IEntityInstance value_type             = channel_type.TemplateArguments.Single();

                Option <ObjectData> received = await channel.ReceiveAsync().ConfigureAwait(false);

                // we have to compute Skila Option type (not C# one we use for C# channel type)
                EntityInstance option_type = ctx.Env.OptionType.GetInstance(
                    TypeMutability.None,
                    TemplateTranslation.Create(ctx.Env.OptionType.InstanceOf, value_type),
                    Lifetime.Timeless);
                ExecValue opt_exec = await createOption(ctx, option_type, received).ConfigureAwait(false);

                if (opt_exec.IsThrow)
                {
                    return(opt_exec);
                }
                ObjectData result = opt_exec.ExprValue;

                // at this point Skila option is initialized so we can return it

                return(ExecValue.CreateReturn(result));
            }
            else
            {
                throw new NotImplementedException($"{ExceptionCode.SourceInfo()}");
            }
        }
예제 #6
0
 private static async Task <ExecValue> executeNativeUnitFunctionAsync(ExecutionContext ctx, FunctionDefinition func, ObjectData this_value)
 {
     if (func.IsDefaultInitConstructor())
     {
         this_value.Assign(await ObjectData.CreateInstanceAsync(ctx, this_value.RunTimeTypeInstance, UnitType.UnitValue).ConfigureAwait(false));
         return(ExecValue.CreateReturn(null));
     }
     else
     {
         throw new NotImplementedException($"{ExceptionCode.SourceInfo()}");
     }
 }
예제 #7
0
        private static async Task <ExecValue> executeNativeIObjectFunctionAsync(ExecutionContext ctx, FunctionDefinition func, ObjectData this_value)
        {
            if (func == ctx.Env.IObjectGetTypeFunction)
            {
                // todo: add some real TypeInfo object, for now it is empty so we can return whatever is unique
                ObjectData fake = await ctx.TypeRegistry.RegisterGetAsync(ctx, this_value.RunTimeTypeInstance).ConfigureAwait(false);

                fake = await fake.ReferenceAsync(ctx).ConfigureAwait(false);

                return(ExecValue.CreateReturn(fake));
            }
            else
            {
                throw new NotImplementedException($"{ExceptionCode.SourceInfo()}");
            }
        }
예제 #8
0
        private static async Task <ObjectData> createChunkOnHeap(ExecutionContext ctx, IEntityInstance elementType,
                                                                 IEnumerable <ObjectData> elements)
        {
            ObjectData chunk_obj = await createChunk(ctx,
                                                     ctx.Env.ChunkType.GetInstance(TypeMutability.None,
                                                                                   TemplateTranslation.Create(ctx.Env.ChunkType.InstanceOf, elementType),
                                                                                   Lifetime.Timeless),
                                                     elements.ToArray()).ConfigureAwait(false);

            ObjectData chunk_ptr = await allocateOnHeapAsync(ctx,
                                                             ctx.Env.Reference(chunk_obj.RunTimeTypeInstance, TypeMutability.None, viaPointer: true),
                                                             chunk_obj).ConfigureAwait(false);

            if (!ctx.Heap.TryInc(ctx, chunk_ptr, RefCountIncReason.IncChunkOnHeap, ""))
            {
                throw new Exception($"{ExceptionCode.SourceInfo()}");
            }

            return(chunk_ptr);
        }
예제 #9
0
 private static async Task <ExecValue> executeNativeBoolFunctionAsync(ExecutionContext ctx, FunctionDefinition func, ObjectData this_value)
 {
     if (func.IsDefaultInitConstructor())
     {
         this_value.Assign(await ObjectData.CreateInstanceAsync(ctx, this_value.RunTimeTypeInstance, false).ConfigureAwait(false));
         return(ExecValue.CreateReturn(null));
     }
     else if (func.IsCopyInitConstructor(ctx.CreateBareComputation()))
     {
         this_value.Assign(ctx.FunctionArguments.Single());
         return(ExecValue.CreateReturn(null));
     }
     else if (func.Name.Name == NameFactory.NotOperator)
     {
         return(ExecValue.CreateReturn(await ObjectData.CreateInstanceAsync(ctx, this_value.RunTimeTypeInstance,
                                                                            !this_value.PlainValue.Cast <bool>()).ConfigureAwait(false)));
     }
     else
     {
         throw new NotImplementedException($"{ExceptionCode.SourceInfo()}");
     }
 }
예제 #10
0
        private async Task <ExecValue> callNonVariadicFunctionDirectly(ExecutionContext ctx, FunctionDefinition targetFunc,
                                                                       IEnumerable <IEntityInstance> templateArguments,
                                                                       ObjectData thisObject, params ObjectData[] arguments)
        {
            // btw. arguments have to be given in exact order as parameters go

            if (targetFunc.Parameters.Any(it => it.IsVariadic))
            {
                throw new Exception($"{ExceptionCode.SourceInfo()}");
            }

            ObjectData this_ref = await prepareThisAsync(ctx, thisObject, $"{targetFunc}").ConfigureAwait(false);

            ObjectData[] args = await prepareArguments(ctx, targetFunc,
                                                       // that is why this function does not handle variadic, it assumes single argument per parameter
                                                       arguments.Select(it => ArgumentGroup.Single(it))).ConfigureAwait(false);

            SetupFunctionCallData(ref ctx, templateArguments, this_ref, args);
            ExecValue ret = await ExecutedAsync(targetFunc, ctx).ConfigureAwait(false);

            return(ret);
        }
예제 #11
0
        private static async Task <ExecValue> executeNativeDateFunctionAsync(ExecutionContext ctx, FunctionDefinition func, ObjectData this_value)
        {
            if (func == ctx.Env.DateDayOfWeekGetter)
            {
                // todo: change the types of the Date in Skila to Int32, Nat8, Nat8
                ObjectData year_obj  = this_value.GetField(ctx.Env.DateYearField);
                var        year      = year_obj.NativeInt16;
                ObjectData month_obj = this_value.GetField(ctx.Env.DateMonthField);
                var        month     = month_obj.NativeNat8;
                ObjectData day_obj   = this_value.GetField(ctx.Env.DateDayField);
                var        day       = day_obj.NativeNat8;

                UInt64 day_of_week = (UInt64)(new DateTime(year, month, day).DayOfWeek);

                ObjectData ret_obj = await ObjectData.CreateInstanceAsync(ctx,
                                                                          func.ResultTypeName.Evaluation.Components, day_of_week).ConfigureAwait(false);

                return(ExecValue.CreateReturn(ret_obj));
            }
            else
            {
                throw new NotImplementedException($"{ExceptionCode.SourceInfo()}");
            }
        }
예제 #12
0
파일: ObjectData.cs 프로젝트: macias/Skila
            internal ObjectData GetField(IEntity entity)
            {
                VariableDeclaration field = entity.Cast <VariableDeclaration>();

                if (this.fields.TryGetValue(field, out ObjectData data))
                {
                    return(data);
                }
                // types do not inherit static fields the way instances do, so we refer to parent's fields to get its field
                else if (this.primaryParentType != null)
                {
                    return(this.primaryParentType.GetField(entity));
                }
                else
                {
                    throw new Exception($"Internal error -- no such field {entity.Name} {ExceptionCode.SourceInfo()}");
                }
            }
예제 #13
0
        private async Task <ExecValue> executeNativeFileFunctionAsync(ExecutionContext ctx, FunctionDefinition func)
        {
            if (func == ctx.Env.FileReadLines)
            {
                ObjectData filepath_obj = ctx.GetArgument(func, NameFactory.FileFilePathParameter);
                if (!filepath_obj.TryDereferenceAnyOnce(ctx.Env, out ObjectData filepath_val))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                string filepath = filepath_val.PlainValue.Cast <string>();

                string[] lines = null;
                try
                {
                    // todo: change it to ReadLines once we have deferred execution
                    lines = System.IO.File.ReadAllLines(filepath);
                }
#pragma warning disable 0168
                catch (Exception ex) // we would use it when debugging
#pragma warning restore 0168
                {
                }

                Option <ObjectData> opt_lines_obj;
                ObjectData          chunk_ptr;

                if (lines == null)
                {
                    chunk_ptr     = null;
                    opt_lines_obj = new Option <ObjectData>();
                }
                else
                {
                    IEntityInstance string_ptr_instance;
                    {
                        IEntityInstance ptr_iterable_instance     = func.ResultTypeName.Evaluation.Components.Cast <EntityInstance>().TemplateArguments.Single();
                        IEntityInstance iterable_str_ptr_instance = ptr_iterable_instance.Cast <EntityInstance>().TemplateArguments.Single();
                        string_ptr_instance = iterable_str_ptr_instance.Cast <EntityInstance>().TemplateArguments.Single();
                    }

                    var lines_obj = new ObjectData[lines.Length];
                    int i         = 0;
                    foreach (string s in lines)
                    {
                        ObjectData s_ptr = await createStringAsync(ctx, s).ConfigureAwait(false);

                        if (!ctx.Heap.TryInc(ctx, s_ptr, RefCountIncReason.FileLine, $"{filepath}"))
                        {
                            throw new Exception($"{ExceptionCode.SourceInfo()}");
                        }

                        lines_obj[i] = s_ptr;
                        ++i;
                    }

                    chunk_ptr = await createChunkOnHeap(ctx, string_ptr_instance, lines_obj).ConfigureAwait(false);

                    opt_lines_obj = new Option <ObjectData>(chunk_ptr);
                }


                ExecValue opt_exec = await createOption(ctx, func.ResultTypeName.Evaluation.Components, opt_lines_obj).ConfigureAwait(false);

                if (chunk_ptr != null)
                {
                    ctx.Heap.TryRelease(ctx, chunk_ptr, null, false, RefCountDecReason.DroppingLocalPointer, "");
                }

                if (opt_exec.IsThrow)
                {
                    return(opt_exec);
                }
                ObjectData result = opt_exec.ExprValue;
                return(ExecValue.CreateReturn(result));
            }
            else if (func == ctx.Env.FileExists)
            {
                ObjectData filepath_obj = ctx.GetArgument(func, NameFactory.FileFilePathParameter);
                if (!filepath_obj.TryDereferenceAnyOnce(ctx.Env, out ObjectData filepath_val))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                string filepath = filepath_val.PlainValue.Cast <string>();

                bool exists = System.IO.File.Exists(filepath);

                ExecValue result = ExecValue.CreateReturn(await ObjectData.CreateInstanceAsync(ctx, func.ResultTypeName.Evaluation.Components,
                                                                                               exists).ConfigureAwait(false));
                return(result);
            }
            else
            {
                throw new NotImplementedException($"{ExceptionCode.SourceInfo()}");
            }
        }
예제 #14
0
        private async Task <ExecValue> executeNativeUtf8StringFunctionAsync(ExecutionContext ctx, FunctionDefinition func,
                                                                            ObjectData thisValue)
        {
            string this_native = thisValue.NativeString;

            if (func == ctx.Env.Utf8StringCopyConstructor)
            {
                ObjectData arg_str_obj = ctx.FunctionArguments[0];
                if (!arg_str_obj.TryDereferenceAnyOnce(ctx.Env, out ObjectData arg_str_val))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                string native_str_arg = arg_str_val.NativeString;

                return(await assignedNativeString(ctx, thisValue, native_str_arg).ConfigureAwait(false));
            }
            else if (func == ctx.Env.Utf8StringRemove)
            {
                ObjectData arg_start_obj    = ctx.FunctionArguments[0];
                int        native_start_arg = (int)arg_start_obj.NativeNat;
                ObjectData arg_end_obj      = ctx.FunctionArguments[1];
                int        native_end_arg   = (int)arg_end_obj.NativeNat;
                int        native_len_arg   = native_end_arg - native_start_arg;

                byte[] this_utf8 = Encoding.UTF8.GetBytes(this_native);
                string rest      = Encoding.UTF8.GetString(this_utf8, 0, native_start_arg)
                                   + Encoding.UTF8.GetString(this_utf8, native_start_arg + native_len_arg, this_utf8.Length - (native_start_arg + native_len_arg));

                return(await assignedNativeString(ctx, thisValue, rest).ConfigureAwait(false));
            }
            else if (func == ctx.Env.Utf8StringCountGetter)
            {
                int[]      code_points = toCodePoints(this_native);
                ObjectData result      = await ObjectData.CreateInstanceAsync(ctx, func.ResultTypeName.Evaluation.Components,
                                                                              (UInt64)code_points.Length).ConfigureAwait(false);

                return(ExecValue.CreateReturn(result));
            }
            else if (func == ctx.Env.Utf8StringLengthGetter)
            {
                int        length = Encoding.UTF8.GetByteCount(this_native);
                ObjectData result = await ObjectData.CreateInstanceAsync(ctx, func.ResultTypeName.Evaluation.Components,
                                                                         (UInt64)length).ConfigureAwait(false);

                return(ExecValue.CreateReturn(result));
            }
            else if (func == ctx.Env.Utf8StringTrimStart)
            {
                string trimmed = this_native.TrimStart();
                return(await assignedNativeString(ctx, thisValue, trimmed).ConfigureAwait(false));
            }
            else if (func == ctx.Env.Utf8StringReverse)
            {
                // https://en.wikipedia.org/wiki/Combining_character
                string reversed = reverseGraphemeClusters(this_native);
                return(await assignedNativeString(ctx, thisValue, reversed).ConfigureAwait(false));
            }
            else if (func == ctx.Env.Utf8StringTrimEnd)
            {
                string trimmed = this_native.TrimEnd();
                return(await assignedNativeString(ctx, thisValue, trimmed).ConfigureAwait(false));
            }
            else if (func == ctx.Env.Utf8StringAtGetter)
            {
                ObjectData arg_idx_obj    = ctx.FunctionArguments[0];
                int        native_idx_arg = (int)arg_idx_obj.NativeNat;

                byte[] this_utf8 = Encoding.UTF8.GetBytes(this_native);
                string sub       = Encoding.UTF8.GetString(this_utf8, native_idx_arg, this_utf8.Length - native_idx_arg);

                ObjectData obj_ch = await createCharAsync(ctx, sub[0]).ConfigureAwait(false);

                // indexer returns reference to an element value
                ObjectData obj_ref = await obj_ch.ReferenceAsync(ctx).ConfigureAwait(false);

                return(ExecValue.CreateReturn(obj_ref));
            }
            else if (func == ctx.Env.Utf8StringSlice)
            {
                ObjectData arg_start_obj    = ctx.FunctionArguments[0];
                int        native_start_arg = (int)arg_start_obj.NativeNat;
                ObjectData arg_end_obj      = ctx.FunctionArguments[1];
                int        native_end_arg   = (int)arg_end_obj.NativeNat;
                int        native_len_arg   = native_end_arg - native_start_arg;

                byte[] this_utf8 = Encoding.UTF8.GetBytes(this_native);
                string sub       = Encoding.UTF8.GetString(this_utf8, native_start_arg, native_len_arg);

                ObjectData result = await createStringAsync(ctx, sub).ConfigureAwait(false);

                if (!ctx.Heap.TryInc(ctx, result, RefCountIncReason.NewString, sub))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                return(ExecValue.CreateReturn(result));
            }
            else if (func == ctx.Env.Utf8StringConcat)
            {
                ObjectData arg_str_obj = ctx.FunctionArguments[0];
                if (!arg_str_obj.TryDereferenceAnyOnce(ctx.Env, out ObjectData arg_str_val))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                string native_str_arg = arg_str_val.NativeString;

                string concatenated = this_native + native_str_arg;
                return(await assignedNativeString(ctx, thisValue, concatenated).ConfigureAwait(false));
            }
            else if (func == ctx.Env.Utf8StringIndexOfString)
            {
                ObjectData arg_str_obj = ctx.FunctionArguments[0];
                if (!arg_str_obj.TryDereferenceAnyOnce(ctx.Env, out ObjectData arg_str_val))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                string     native_str_arg = arg_str_val.NativeString;
                ObjectData arg_idx_obj    = ctx.FunctionArguments[1];
                int        native_idx_arg = (int)arg_idx_obj.NativeNat;

                byte[] this_utf8 = Encoding.UTF8.GetBytes(this_native);
                string sub       = Encoding.UTF8.GetString(this_utf8, native_idx_arg, this_utf8.Length - native_idx_arg);

                int idx = sub.IndexOf(native_str_arg);

                Option <ObjectData> index_obj;
                if (idx != -1)
                {
                    idx       = native_idx_arg + Encoding.UTF8.GetByteCount(sub.Substring(0, idx));
                    index_obj = new Option <ObjectData>(await ObjectData.CreateInstanceAsync(ctx, ctx.Env.SizeType.InstanceOf, (UInt64)idx)
                                                        .ConfigureAwait(false));
                }
                else
                {
                    index_obj = new Option <ObjectData>();
                }

                ExecValue opt_exec = await createOption(ctx, func.ResultTypeName.Evaluation.Components, index_obj).ConfigureAwait(false);

                if (opt_exec.IsThrow)
                {
                    return(opt_exec);
                }

                return(ExecValue.CreateReturn(opt_exec.ExprValue));
            }
            else if (func == ctx.Env.Utf8StringLastIndexOfChar)
            {
                ObjectData arg_char_obj    = ctx.FunctionArguments[0];
                char       native_char_arg = arg_char_obj.NativeChar;
                ObjectData arg_idx_obj     = ctx.FunctionArguments[1];
                int        native_idx_arg  = (int)arg_idx_obj.NativeNat;

                byte[] this_utf8 = Encoding.UTF8.GetBytes(this_native);
                string sub       = Encoding.UTF8.GetString(this_utf8, 0, native_idx_arg);

                int idx = sub.LastIndexOf(native_char_arg);

                Option <ObjectData> index_obj;
                if (idx != -1)
                {
                    idx       = Encoding.UTF8.GetByteCount(this_native.Substring(0, idx));
                    index_obj = new Option <ObjectData>(await ObjectData.CreateInstanceAsync(ctx, ctx.Env.SizeType.InstanceOf, (UInt64)idx)
                                                        .ConfigureAwait(false));
                }
                else
                {
                    index_obj = new Option <ObjectData>();
                }

                ExecValue opt_exec = await createOption(ctx, func.ResultTypeName.Evaluation.Components, index_obj).ConfigureAwait(false);

                if (opt_exec.IsThrow)
                {
                    return(opt_exec);
                }

                return(ExecValue.CreateReturn(opt_exec.ExprValue));
            }
            else
            {
                ExecValue?result = await equalityTestAsync <string>(ctx, func, thisValue, heapArguments : true).ConfigureAwait(false);

                if (result.HasValue)
                {
                    return(result.Value);
                }
                else
                {
                    throw new NotImplementedException($"Function {func} is not implemented");
                }
            }
        }
예제 #15
0
        private async Task <ExecValue> executeNativeChunkFunctionAsync(ExecutionContext ctx, FunctionDefinition func, ObjectData this_value)
        {
            if (func == ctx.Env.ChunkSizeConstructor)
            {
                IEntityInstance elem_type = this_value.RunTimeTypeInstance.TemplateArguments.Single();
                ObjectData      size_obj  = ctx.FunctionArguments.Single();
                var             size      = size_obj.NativeNat64;
                ObjectData[]    chunk     = (await Task.WhenAll(Enumerable.Range(0, (int)size).Select(_ => ObjectData.CreateEmptyAsync(ctx, elem_type))).ConfigureAwait(false)).ToArray();
                this_value.Assign(await createChunk(ctx, this_value.RunTimeTypeInstance, chunk).ConfigureAwait(false));
                return(ExecValue.CreateReturn(null));
            }
            else if (func == ctx.Env.ChunkResizeConstructor)
            {
                IEntityInstance elem_type  = this_value.RunTimeTypeInstance.TemplateArguments.Single();
                ObjectData      size_obj   = ctx.FunctionArguments[0];
                var             size       = size_obj.NativeNat64;
                ObjectData      source_obj = ctx.FunctionArguments[1];
                if (!source_obj.TryDereferenceAnyOnce(ctx.Env, out ObjectData val_obj))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                Chunk source = val_obj.PlainValue.Cast <Chunk>();

                ObjectData[] chunk     = new ObjectData[size];
                var          copy_size = Math.Min(size, source.Count);
                for (UInt64 i = 0; i != copy_size; ++i)
                {
                    chunk[i] = source[i];
                    ctx.Heap.TryInc(ctx, source[i], RefCountIncReason.CopyingChunkElem, "");
                }
                for (var i = copy_size; i < size; ++i)
                {
                    chunk[i] = await ObjectData.CreateEmptyAsync(ctx, elem_type).ConfigureAwait(false);
                }
                this_value.Assign(await createChunk(ctx, this_value.RunTimeTypeInstance, chunk).ConfigureAwait(false));
                return(ExecValue.CreateReturn(null));
            }
            else if (func == ctx.Env.ChunkAtSet)
            {
                ObjectData idx_obj = ctx.GetArgument(func, NameFactory.IndexIndexerParameter);
                var        idx     = idx_obj.NativeNat64;
                Chunk      chunk   = this_value.PlainValue.Cast <Chunk>();
                ctx.Heap.TryRelease(ctx, chunk[idx], passingOutObject: null, isPassingOut: false, reason: RefCountDecReason.ReplacingChunkElem, comment: "");
                ObjectData arg_ref_object = ctx.GetArgument(func, NameFactory.PropertySetterValueParameter);
                // indexer takes reference to element
                if (!arg_ref_object.TryDereferenceAnyOnce(ctx.Env, out ObjectData arg_val))
                {
                    throw new Exception($"{ExceptionCode.SourceInfo()}");
                }
                if (!ctx.Heap.TryIncPointer(ctx, arg_val, RefCountIncReason.SettingChunkElem, ""))
                {
                    arg_val = arg_val.Copy();
                }
                chunk[idx] = arg_val;
                return(ExecValue.CreateReturn(null));
            }
            else if (func == ctx.Env.ChunkAtGet)
            {
                ObjectData idx_obj   = ctx.GetArgument(func, NameFactory.IndexIndexerParameter);
                var        idx       = idx_obj.NativeNat64;
                Chunk      chunk     = this_value.PlainValue.Cast <Chunk>();
                ObjectData obj_value = chunk[idx];
                // indexer returns reference to an element value
                ObjectData obj_ref = await obj_value.ReferenceAsync(ctx).ConfigureAwait(false);

                return(ExecValue.CreateReturn(obj_ref));
            }
            else if (func == ctx.Env.ChunkCount)
            {
                Chunk      chunk  = this_value.PlainValue.Cast <Chunk>();
                ObjectData result = await ObjectData.CreateInstanceAsync(ctx, func.ResultTypeName.Evaluation.Components,
                                                                         chunk.Count).ConfigureAwait(false);

                return(ExecValue.CreateReturn(result));
            }
            else
            {
                throw new NotImplementedException($"{ExceptionCode.SourceInfo()}");
            }
        }
예제 #16
0
        private async Task <ExecValue> executeNativeRegexFunctionAsync(ExecutionContext ctx, FunctionDefinition func,
                                                                       ObjectData thisValue)
        {
            if (func == ctx.Env.RegexContainsFunction)
            {
                ObjectData arg     = ctx.FunctionArguments.Single();
                ObjectData arg_val = arg.DereferencedOnce();
                string     arg_str = arg_val.NativeString;

                ObjectData pattern_obj = thisValue.GetField(ctx.Env.RegexPatternField);
                ObjectData pattern_val = pattern_obj.DereferencedOnce();
                string     pattern     = pattern_val.NativeString;

                bool val = new System.Text.RegularExpressions.Regex(pattern).IsMatch(arg_str);

                ExecValue result = ExecValue.CreateReturn(await ObjectData.CreateInstanceAsync(ctx,
                                                                                               func.ResultTypeName.Evaluation.Components, val).ConfigureAwait(false));
                return(result);
            }
            else if (func == ctx.Env.RegexMatchFunction)
            {
                ObjectData arg     = ctx.FunctionArguments.Single();
                ObjectData arg_val = arg.DereferencedOnce();
                string     arg_str = arg_val.NativeString;

                ObjectData pattern_obj = thisValue.GetField(ctx.Env.RegexPatternField);
                ObjectData pattern_val = pattern_obj.DereferencedOnce();
                string     pattern     = pattern_val.NativeString;

                System.Text.RegularExpressions.Regex           regex   = new System.Text.RegularExpressions.Regex(pattern);
                System.Text.RegularExpressions.MatchCollection matches = regex.Matches(arg_str);

                var elements = new List <ObjectData>();
                for (int match_idx = 0; match_idx < matches.Count; ++match_idx)
                {
                    System.Text.RegularExpressions.Match match = matches[match_idx];
                    ObjectData match_start_val = await createNat64Async(ctx, (UInt64)match.Index).ConfigureAwait(false);

                    ObjectData match_end_val = await createNat64Async(ctx, (UInt64)(match.Index + match.Length)).ConfigureAwait(false);

                    ObjectData array_captures_ptr;

                    {
                        if (!ctx.Env.DereferencedOnce(ctx.Env.MatchCapturesProperty.TypeName.Evaluation.Components,
                                                      out IEntityInstance array_captures_type, out bool dummy))
                        {
                            throw new Exception($"Internal error {ExceptionCode.SourceInfo()}");
                        }

                        ExecValue ret = await createObject(ctx, true, array_captures_type, ctx.Env.ArrayDefaultConstructor, null)
                                        .ConfigureAwait(false);

                        if (ret.IsThrow)
                        {
                            return(ret);
                        }

                        array_captures_ptr = ret.ExprValue;
                        ctx.Heap.TryInc(ctx, array_captures_ptr, RefCountIncReason.StoringLocalPointer, "");

                        // skipping implicit "everything" group
                        for (int grp_idx = 1; grp_idx < match.Groups.Count; ++grp_idx)
                        {
                            System.Text.RegularExpressions.Group group = match.Groups[grp_idx];
                            string group_name = regex.GroupNameFromNumber(grp_idx);
                            if (group_name == $"{grp_idx}") // hack for anonymous captures
                            {
                                group_name = null;
                            }

                            for (int cap_idx = 0; cap_idx < group.Captures.Count; ++cap_idx)
                            {
                                System.Text.RegularExpressions.Capture cap = group.Captures[cap_idx];

                                ObjectData cap_start_val = await createNat64Async(ctx, (UInt64)cap.Index).ConfigureAwait(false);

                                ObjectData cap_end_val = await createNat64Async(ctx, (UInt64)(cap.Index + cap.Length)).ConfigureAwait(false);

                                ObjectData cap_opt_name_val;
                                {
                                    Option <ObjectData> opt_group_name_obj;
                                    if (group_name != null)
                                    {
                                        ObjectData str_ptr = await createStringAsync(ctx, group_name).ConfigureAwait(false);

                                        opt_group_name_obj = new Option <ObjectData>(str_ptr);
                                    }
                                    else
                                    {
                                        opt_group_name_obj = new Option <ObjectData>();
                                    }

                                    IEntityInstance opt_cap_type = ctx.Env.CaptureConstructor.Parameters.Last().TypeName.Evaluation.Components;
                                    ExecValue       opt_exec     = await createOption(ctx, opt_cap_type, opt_group_name_obj).ConfigureAwait(false);

                                    if (opt_exec.IsThrow)
                                    {
                                        return(opt_exec);
                                    }
                                    cap_opt_name_val = opt_exec.ExprValue;
                                }
                                ExecValue capture_obj_exec = await createObject(ctx, false, ctx.Env.CaptureType.InstanceOf,
                                                                                ctx.Env.CaptureConstructor, null, cap_start_val, cap_end_val, cap_opt_name_val).ConfigureAwait(false);

                                if (capture_obj_exec.IsThrow)
                                {
                                    return(capture_obj_exec);
                                }
                                ObjectData capture_ref = await capture_obj_exec.ExprValue.ReferenceAsync(ctx).ConfigureAwait(false);

                                ExecValue append_exec = await callNonVariadicFunctionDirectly(ctx, ctx.Env.ArrayAppendFunction, null,
                                                                                              array_captures_ptr, capture_ref).ConfigureAwait(false);

                                if (append_exec.IsThrow)
                                {
                                    return(append_exec);
                                }
                            }
                        }
                    }
                    ObjectData match_val;
                    {
                        ExecValue ret = await createObject(ctx, false, ctx.Env.MatchType.InstanceOf,
                                                           ctx.Env.MatchConstructor, null, match_start_val, match_end_val, array_captures_ptr).ConfigureAwait(false);

                        ctx.Heap.TryRelease(ctx, array_captures_ptr, null, false, RefCountDecReason.DroppingLocalPointer, "");

                        if (ret.IsThrow)
                        {
                            return(ret);
                        }

                        match_val = ret.ExprValue;
                    }

                    elements.Add(match_val);
                }

                ObjectData heap_chunk = await createChunkOnHeap(ctx, ctx.Env.MatchType.InstanceOf, elements).ConfigureAwait(false);

                ExecValue result = ExecValue.CreateReturn(heap_chunk);
                return(result);
            }
            else
            {
                throw new NotImplementedException($"{ExceptionCode.SourceInfo()}");
            }
        }