Skip to content

Conversation

@MaxGraey
Copy link
Member

@MaxGraey MaxGraey commented Apr 5, 2018

No description provided.

@MaxGraey MaxGraey changed the title Add String#repeat method [WIP] Add String#repeat method Apr 5, 2018
@MaxGraey MaxGraey changed the title [WIP] Add String#repeat method Add String#repeat method Apr 5, 2018
@MaxGraey
Copy link
Member Author

MaxGraey commented Apr 5, 2018

Ready for merging


repeat(count: i32 = 0): String {
assert(this !== null);
assert(count >= 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe JS does throw new RangeError("Invalid count value") there, hmm. Still unsure what's best as this will eventually result in quite a few static strings in modules where methods that do so are used. For now I'd tend to stay consistent with JS here, as other functions do it as well.


while (count) {
if (count & 1) result = result.concat(str);
if (count > 1) str = str.concat(str);
Copy link
Member

@dcodeIO dcodeIO Apr 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there'd be a benefit in doing this on a lower level, like inlined. Could potentially reduce allocations in that a properly sized buffer can be pre-allocated. Wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

if (count === 0 || !length) return EMPTY;
if (count === 1) return this;

var result = allocate(length * count);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this missing the leading 32-bit length?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I use this allocation method which already include HEADER size during allocation if I right understand your comment =)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah, makes sense then.

var strLen = length << 1;

for (let offset = 0, len = strLen * count; offset < len; offset += strLen) {
move_memory(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess copy size could also increase. Like, repeating "a" four times would first create "aa" and then copy "aa" to "aaaa". Wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it, and move_memory may better optimize for copy large world chunks, but this increase codebase and but benefits may be not so huge. Need benchmark. For now I can add TODO comment for future if don't mind

private static __lte(left: String, right: String): bool {
if (left === right) return true;
if (left === null) return right === null;
else if (right === null) return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can remove the else

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

if (left === null || right === null) return false;
if (left === right || left === null || right === null) {
return false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In stdlib, I'm trying to avoid such blocks. Doesn't look as nice, but the parser ultimately can skip producing one BlockStatement, slightly reducing memory footprint. Not sure if that's overoptimization already, but I had the feeling it might be okish to do :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I should refactor this to 3-timed if instead one block?

Copy link
Member

@dcodeIO dcodeIO Apr 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just if (left === right || left === null || right === null) return false;, so it results in the following AST:

IfStatement - Expression - ReturnStatement 

instead of

IfStatement - Expression - BlockStatement (with just one child) - ReturnStatement 
Copy link
Member Author

@MaxGraey MaxGraey Apr 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored this. But I can't see any changes even in untouched wast except assert's column/line numbers. Is it normal? It seems this overoptimization)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it does compile to the same thing, but the parser has to allocate one less AST node. My though was that, since stdlib is always included in compilation and fully parsed (unlike other compilers that might link it in), that it would accumulate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, got it

@dcodeIO dcodeIO merged commit b7ef219 into AssemblyScript:master Apr 7, 2018
@dcodeIO
Copy link
Member

dcodeIO commented Apr 7, 2018

Thanks! :)

@MaxGraey MaxGraey deleted the add-more-string-methods branch June 12, 2018 09:59
radu-matei pushed a commit to radu-matei/assemblyscript that referenced this pull request Oct 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants