internal static Value Fill(Script vm) { int val = vm.Argument(1).AsInt; var array = new ArrayInfo(vm, vm.Argument(0).AsInt); for (int i = array.address; i < array.address + array.length; i++) { vm.WriteWord(val, i); } return(Value.Void); }
internal static Value Pop(Script vm) { var array = new ArrayInfo(vm, vm.Argument(0).AsInt); int element = vm.Argument(1).AsInt; if (array.length <= 0) { vm.cpu.status = Cpu.Status.BAD_MEMORY_ACCESS; return(new Value(-1)); } vm.WriteWord(array.length - 1, array.address - 1); return(new Value(vm.ReadWord(array.address + array.length - 1))); }
internal static Value Clear(Script vm) { var array = new ArrayInfo(vm, vm.Argument(0).AsInt); Array.Clear(vm.memory, array.address, array.length); return(Value.Void); }
/// /// Push element to the end of an array, reallocate the array /// if it's full. If new memory is allocated the old array is /// freed. /// /// arg(0) : Address of the array /// arg(1) : Element /// /// Note that the address is passed by value, so Push returns /// a pointer to the allocated array. In the future, It might /// be better to pass a pointer to the array instead, so that /// the reference can be updated. /// internal static Value Push(Script vm) { var array = new ArrayInfo(vm, vm.Argument(0).AsInt); int element = vm.Argument(1).AsInt; if (array.length >= array.capacity) { // Double array capacity int new_array = Heap.Alloc(vm, array.capacity * 2); vm.MemCopy(array.address, new_array, array.capacity); if (array.address >= vm.cpu.heap) { // Only free array if it's in dynamic memory Heap.Free(vm, array.address); } array.address = new_array; } vm.WriteWord(element, array.address + array.length); vm.WriteWord(array.length + 1, array.address - 1); return(new Value(array.address)); }
/// /// Print formatted string from the current stack pointer. /// Format must be called with arguments pushed in reverse /// order to the stack and ESP pointing to a format string /// in memory. /// internal static string Format(Script vm) { // Arguments for printf should be pushed in reverse order. // The first argument is pointer to a str which contains the format // The following arguments must be in the sequence specified by // the format string. string fmt = vm.Argument(0).AsString; // @Performance var buffer = new StringBuilder(); bool is_fmt_char = false; // Basic state-machine printf implementation int arg = 0; foreach (char c in fmt) { if (c == '%') { is_fmt_char = true; continue; } if (is_fmt_char) { switch (c) { case 'd': { int d = vm.Argument(++arg).AsInt; buffer.Append(d); break; } case 'f': { float f = vm.Argument(++arg).AsFloat; buffer.Append(f); break; } case 's': { string s = vm.Argument(++arg).AsString; buffer.Append(s); break; } case 'n': { buffer.AppendLine(); break; } case 'c': { int i = vm.Argument(++arg).AsInt; buffer.Append(char.ConvertFromUtf32(i)); break; } case '%': { // %% means instert a % character buffer.Append(c); break; } default: break; // @Todo: error } is_fmt_char = false; continue; } buffer.Append(c); } return(buffer.ToString()); }