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 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()}"); } }