Skip to content

Commit b6b5c1e

Browse files
MaxGraeydcodeIO
authored andcommitted
Add TypedArray#join/toString (AssemblyScript#834)
1 parent 763c3c1 commit b6b5c1e

14 files changed

+11743
-2217
lines changed

std/assembly/array.ts

+9-238
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { BLOCK_MAXSIZE } from "./rt/common";
44
import { COMPARATOR, SORT } from "./util/sort";
55
import { ArrayBuffer, ArrayBufferView } from "./arraybuffer";
6-
import { itoa, dtoa, itoa_stream, dtoa_stream, MAX_DOUBLE_LENGTH } from "./util/number";
6+
import { joinBooleanArray, joinIntegerArray, joinFloatArray, joinStringArray, joinArrays, joinObjectArray } from "./util/string";
77
import { idof, isArray as builtin_isArray } from "./builtins";
88
import { E_INDEXOUTOFRANGE, E_INVALIDLENGTH, E_EMPTYARRAY, E_HOLEYARRAY } from "./util/error";
99

@@ -477,247 +477,18 @@ export class Array<T> extends ArrayBufferView {
477477
}
478478

479479
join(separator: string = ","): string {
480-
if (isBoolean<T>()) return this.join_bool(separator);
481-
if (isInteger<T>()) return this.join_int(separator);
482-
if (isFloat<T>()) return this.join_flt(separator);
483-
if (isString<T>()) return this.join_str(separator);
484-
if (isArray<T>()) return this.join_arr(separator);
485-
if (isReference<T>()) return this.join_ref(separator);
480+
var dataStart = this.dataStart;
481+
var length = this.length_;
482+
if (isString<T>()) return joinStringArray(dataStart, length, separator);
483+
if (isBoolean<T>()) return joinBooleanArray(dataStart, length, separator);
484+
if (isInteger<T>()) return joinIntegerArray<T>(dataStart, length, separator);
485+
if (isFloat<T>()) return joinFloatArray<T>(dataStart, length, separator);
486+
if (isArray<T>()) return joinArrays<T>(dataStart, length, separator);
487+
if (isReference<T>()) return joinObjectArray<T>(dataStart, length, separator);
486488
ERROR("unspported element type");
487489
return <string>unreachable();
488490
}
489491

490-
private join_bool(separator: string = ","): string {
491-
var lastIndex = this.length_ - 1;
492-
if (lastIndex < 0) return "";
493-
var dataStart = this.dataStart;
494-
if (!lastIndex) return select("true", "false", load<bool>(dataStart));
495-
496-
var sepLen = separator.length;
497-
var valueLen = 5; // max possible length of element len("false")
498-
var estLen = (valueLen + sepLen) * lastIndex + valueLen;
499-
var result = changetype<string>(__alloc(estLen << 1, idof<string>())); // retains
500-
var offset = 0;
501-
var value: bool;
502-
for (let i = 0; i < lastIndex; ++i) {
503-
value = load<bool>(dataStart + i);
504-
valueLen = 4 + i32(!value);
505-
memory.copy(
506-
changetype<usize>(result) + (<usize>offset << 1),
507-
changetype<usize>(select("true", "false", value)),
508-
<usize>valueLen << 1
509-
);
510-
offset += valueLen;
511-
if (sepLen) {
512-
memory.copy(
513-
changetype<usize>(result) + (<usize>offset << 1),
514-
changetype<usize>(separator),
515-
<usize>sepLen << 1
516-
);
517-
offset += sepLen;
518-
}
519-
}
520-
value = load<bool>(dataStart + <usize>lastIndex);
521-
valueLen = 4 + i32(!value);
522-
memory.copy(
523-
changetype<usize>(result) + (<usize>offset << 1),
524-
changetype<usize>(select("true", "false", value)),
525-
valueLen << 1
526-
);
527-
offset += valueLen;
528-
529-
if (estLen > offset) return result.substring(0, offset);
530-
return result;
531-
}
532-
533-
private join_int(separator: string = ","): string {
534-
var lastIndex = this.length_ - 1;
535-
if (lastIndex < 0) return "";
536-
var dataStart = this.dataStart;
537-
// @ts-ignore: type
538-
if (!lastIndex) return changetype<string>(itoa<T>(load<T>(dataStart))); // retains
539-
540-
var sepLen = separator.length;
541-
const valueLen = (sizeof<T>() <= 4 ? 10 : 20) + i32(isSigned<T>());
542-
var estLen = (valueLen + sepLen) * lastIndex + valueLen;
543-
var result = changetype<string>(__alloc(estLen << 1, idof<string>())); // retains
544-
var offset = 0;
545-
var value: T;
546-
for (let i = 0; i < lastIndex; ++i) {
547-
value = load<T>(dataStart + (<usize>i << alignof<T>()));
548-
// @ts-ignore: type
549-
offset += itoa_stream<T>(changetype<usize>(result), offset, value);
550-
if (sepLen) {
551-
memory.copy(
552-
changetype<usize>(result) + (<usize>offset << 1),
553-
changetype<usize>(separator),
554-
<usize>sepLen << 1
555-
);
556-
offset += sepLen;
557-
}
558-
}
559-
value = load<T>(dataStart + (<usize>lastIndex << alignof<T>()));
560-
// @ts-ignore: type
561-
offset += itoa_stream<T>(changetype<usize>(result), offset, value);
562-
if (estLen > offset) return result.substring(0, offset);
563-
return result;
564-
}
565-
566-
private join_flt(separator: string = ","): string {
567-
var lastIndex = this.length_ - 1;
568-
if (lastIndex < 0) return "";
569-
var dataStart = this.dataStart;
570-
if (!lastIndex) {
571-
return changetype<string>(dtoa(
572-
// @ts-ignore: type
573-
load<T>(dataStart))
574-
); // retains
575-
}
576-
577-
const valueLen = MAX_DOUBLE_LENGTH;
578-
var sepLen = separator.length;
579-
var estLen = (valueLen + sepLen) * lastIndex + valueLen;
580-
var result = changetype<string>(__alloc(estLen << 1, idof<string>())); // retains
581-
var offset = 0;
582-
var value: T;
583-
for (let i = 0; i < lastIndex; ++i) {
584-
value = load<T>(dataStart + (<usize>i << alignof<T>()));
585-
offset += dtoa_stream(changetype<usize>(result), offset,
586-
// @ts-ignore: type
587-
value
588-
);
589-
if (sepLen) {
590-
memory.copy(
591-
changetype<usize>(result) + (<usize>offset << 1),
592-
changetype<usize>(separator),
593-
<usize>sepLen << 1
594-
);
595-
offset += sepLen;
596-
}
597-
}
598-
value = load<T>(dataStart + (<usize>lastIndex << alignof<T>()));
599-
offset += dtoa_stream(changetype<usize>(result), offset,
600-
// @ts-ignore: type
601-
value
602-
);
603-
if (estLen > offset) return result.substring(0, offset);
604-
return result;
605-
}
606-
607-
private join_str(separator: string = ","): string {
608-
var lastIndex = this.length_ - 1;
609-
if (lastIndex < 0) return "";
610-
var dataStart = this.dataStart;
611-
if (!lastIndex) return load<string>(dataStart);
612-
613-
var sepLen = separator.length;
614-
var estLen = 0;
615-
var value: string | null;
616-
for (let i = 0, len = lastIndex + 1; i < len; ++i) {
617-
value = load<string>(dataStart + (<usize>i << alignof<T>()));
618-
if (value !== null) estLen += value.length;
619-
}
620-
var offset = 0;
621-
var result = changetype<string>(__alloc((estLen + sepLen * lastIndex) << 1, idof<string>())); // retains
622-
for (let i = 0; i < lastIndex; ++i) {
623-
value = load<string>(dataStart + (<usize>i << alignof<T>()));
624-
if (value !== null) {
625-
let valueLen = changetype<string>(value).length;
626-
memory.copy(
627-
changetype<usize>(result) + (<usize>offset << 1),
628-
changetype<usize>(value),
629-
<usize>valueLen << 1
630-
);
631-
offset += valueLen;
632-
}
633-
if (sepLen) {
634-
memory.copy(
635-
changetype<usize>(result) + (<usize>offset << 1),
636-
changetype<usize>(separator),
637-
<usize>sepLen << 1
638-
);
639-
offset += sepLen;
640-
}
641-
}
642-
value = load<string>(dataStart + (<usize>lastIndex << alignof<T>()));
643-
if (value !== null) {
644-
memory.copy(
645-
changetype<usize>(result) + (<usize>offset << 1),
646-
changetype<usize>(value),
647-
<usize>changetype<string>(value).length << 1
648-
);
649-
}
650-
return result;
651-
}
652-
653-
private join_arr(separator: string = ","): string {
654-
var lastIndex = this.length_ - 1;
655-
if (lastIndex < 0) return "";
656-
657-
var result = "";
658-
var sepLen = separator.length;
659-
var base = this.dataStart;
660-
var value: T;
661-
if (!lastIndex) {
662-
value = load<T>(base);
663-
// @ts-ignore: type
664-
return value ? value.join(separator) : "";
665-
}
666-
for (let i = 0; i < lastIndex; ++i) {
667-
value = load<T>(base + (<usize>i << alignof<T>()));
668-
// @ts-ignore: type
669-
if (value) result += value.join(separator);
670-
if (sepLen) result += separator;
671-
}
672-
value = load<T>(base + (<usize>lastIndex << alignof<T>()));
673-
// @ts-ignore: type
674-
if (value) result += value.join(separator);
675-
return result; // registered by concatenation (FIXME: lots of garbage)
676-
}
677-
678-
private join_ref(separator: string = ","): string {
679-
var lastIndex = this.length_ - 1;
680-
if (lastIndex < 0) return "";
681-
var base = this.dataStart;
682-
if (!lastIndex) return "[object Object]";
683-
684-
const valueLen = 15; // max possible length of element len("[object Object]")
685-
var sepLen = separator.length;
686-
var estLen = (valueLen + sepLen) * lastIndex + valueLen;
687-
var result = changetype<string>(__alloc(estLen << 1, idof<string>()));
688-
var offset = 0;
689-
var value: T;
690-
for (let i = 0; i < lastIndex; ++i) {
691-
value = load<T>(base + (<usize>i << alignof<T>()));
692-
if (value) {
693-
memory.copy(
694-
changetype<usize>(result) + (<usize>offset << 1),
695-
changetype<usize>("[object Object]"),
696-
<usize>valueLen << 1
697-
);
698-
offset += valueLen;
699-
}
700-
if (sepLen) {
701-
memory.copy(
702-
changetype<usize>(result) + (<usize>offset << 1),
703-
changetype<usize>(separator),
704-
<usize>sepLen << 1
705-
);
706-
offset += sepLen;
707-
}
708-
}
709-
if (load<T>(base + (<usize>lastIndex << alignof<T>()))) {
710-
memory.copy(
711-
changetype<usize>(result) + (<usize>offset << 1),
712-
changetype<usize>("[object Object]"),
713-
<usize>valueLen << 1
714-
);
715-
offset += valueLen;
716-
}
717-
if (estLen > offset) return result.substring(0, offset);
718-
return result;
719-
}
720-
721492
toString(): string {
722493
return this.join();
723494
}

std/assembly/index.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,10 @@ declare abstract class TypedArray<T> implements ArrayBufferView<T> {
11891189
forEach(callbackfn: (value: T, index: i32, self: this) => void): void;
11901190
/** The reverse() method reverses a typed array in place. The first typed array element becomes the last and the last becomes the first. This method has the same algorithm as Array.prototype.reverse(). */
11911191
reverse(): this;
1192+
/** The join() method joins all elements of an array into a string. This method has the same algorithm as Array.prototype.join(). */
1193+
join(separator?: string): string;
1194+
/** The toString() method returns a string representing the specified array and its elements. This method has the same algorithm as Array.prototype.toString() */
1195+
toString(): string;
11921196
}
11931197

11941198
/** An array of twos-complement 8-bit signed integers. */

0 commit comments

Comments
 (0)