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"); } }
private int validatedIndex(int idx) { if (idx < 0 || idx >= this.data.Length) { throw new IndexOutOfRangeException($"{ExceptionCode.SourceInfo()}"); } return(idx); }
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); }
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]); }
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()}"); } }
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()}"); } }
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()}"); } }
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); }
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()}"); } }
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); }
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()}"); } }
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()}"); } }
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()}"); } }
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"); } } }
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()}"); } }
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()}"); } }