From c53f42ee2f9d4dbf88c3fbb540adb8ddad62b6d0 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 19:43:38 +0300 Subject: [PATCH 01/26] init --- src/diagnosticMessages.json | 1 + src/glue/js/i64.d.ts | 2 + src/glue/js/i64.js | 8 ++++ src/glue/wasm/i64.ts | 12 +++++ src/tokenizer.ts | 74 +++++++++++++++++++++++++++-- tests/parser/literals.ts | 7 +++ tests/parser/literals.ts.fixture.ts | 27 +++++++---- 7 files changed, 118 insertions(+), 13 deletions(-) diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index a69e5d608f..339a3f3a45 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -46,6 +46,7 @@ "Property '{0}' is always assigned before being used.": 233, "Expression does not compile to a value at runtime.": 234, "Only variables, functions and enums become WebAssembly module exports.": 235, + "Literal '{0}' does not fit into the type 'i64'.": 236, "Importing the table disables some indirect call optimizations.": 901, "Exporting the table disables some indirect call optimizations.": 902, diff --git a/src/glue/js/i64.d.ts b/src/glue/js/i64.d.ts index 8b4780cde9..c4f1735645 100644 --- a/src/glue/js/i64.d.ts +++ b/src/glue/js/i64.d.ts @@ -49,4 +49,6 @@ declare function i64_is_f64(value: i64): boolean; declare function i64_to_f32(value: i64): f64; declare function i64_to_f64(value: i64): f64; +declare function i64_to_u64(value: i64): u64; declare function i64_to_string(value: i64, unsigned?: boolean): string; +declare function i64_clone(value: i64): i64; diff --git a/src/glue/js/i64.js b/src/glue/js/i64.js index 78a2fc06e4..28a846b061 100644 --- a/src/glue/js/i64.js +++ b/src/glue/js/i64.js @@ -187,6 +187,14 @@ globalThis.i64_to_f64 = function i64_to_f64(value) { return value.toNumber(); }; +globalThis.i64_to_u64 = function i64_to_u64(value) { + return value.toUnsigned(); +}; + globalThis.i64_to_string = function i64_to_string(value, unsigned) { return unsigned ? value.toUnsigned().toString() : value.toString(); }; + +globalThis.i64_clone = function i64_clone(value) { + return Long.fromBits(value.low, value.high, value.unsigned); +}; diff --git a/src/glue/wasm/i64.ts b/src/glue/wasm/i64.ts index 03e4d121e3..a173dc0e22 100644 --- a/src/glue/wasm/i64.ts +++ b/src/glue/wasm/i64.ts @@ -244,8 +244,20 @@ function i64_to_f64(value: i64): f64 { return value; } +// @ts-ignore: decorator +@global @inline +function i64_to_u64(value: i64): u64 { + return value; +} + // @ts-ignore: decorator @global @inline function i64_to_string(value: i64, unsigned: bool = false): string { return unsigned ? u64(value).toString() : value.toString(); } + +// @ts-ignore: decorator +@global @inline +function i64_clone(value: i64): i64 { + return value; +} diff --git a/src/tokenizer.ts b/src/tokenizer.ts index fab060fd5c..4f0056b252 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -1355,8 +1355,12 @@ export class Tokenizer extends DiagnosticEmitter { var sepEnd = start; var value = i64_new(0); var i64_4 = i64_new(4); + var prevValue: i64; + // var overflowSigned = false; + var overflowUnsigned = false; while (pos < end) { let c = text.charCodeAt(pos); + prevValue = i64_clone(value); if (c >= CharCode._0 && c <= CharCode._9) { // value = (value << 4) + c - CharCode._0; value = i64_add( @@ -1388,9 +1392,22 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } + if (i64_gt(prevValue, value)) { + // Signed overflow occurred + // overflowSigned = true; + if (i64_gt(i64_to_u64(prevValue), i64_to_u64(value))) { + // Unsigned overflow occurred + overflowUnsigned = true; + } + } ++pos; } - if (pos == start) { + if (overflowUnsigned) { + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_the_type_i64, + this.range(start, pos), "0x" + this.source.text.substring(start, pos) + ); + } else if (pos == start) { this.error( DiagnosticCode.Hexadecimal_digit_expected, this.range(start) @@ -1413,8 +1430,13 @@ export class Tokenizer extends DiagnosticEmitter { var sepEnd = start; var value = i64_new(0); var i64_10 = i64_new(10); + var prevValue: i64; + var overflowUnsigned = false; + // var overflowSigned = false; + while (pos < end) { let c = text.charCodeAt(pos); + prevValue = i64_clone(value); if (c >= CharCode._0 && c <= CharCode._9) { // value = value * 10 + c - CharCode._0; value = i64_add( @@ -1439,9 +1461,22 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } + if (i64_gt(prevValue, value)) { + // Signed overflow occurred + // overflowSigned = true; + if (i64_gt(i64_to_u64(prevValue), i64_to_u64(value))) { + // Unsigned overflow occurred + overflowUnsigned = true; + } + } ++pos; } - if (pos == start) { + if (overflowUnsigned) { + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_the_type_i64, + this.range(start, pos), this.source.text.substring(start, pos) + ); + } else if (pos == start) { this.error( DiagnosticCode.Digit_expected, this.range(start) @@ -1464,8 +1499,13 @@ export class Tokenizer extends DiagnosticEmitter { var sepEnd = start; var value = i64_new(0); var i64_3 = i64_new(3); + var prevValue: i64; + var overflowUnsigned = false; + // var overflowSigned = false; + while (pos < end) { let c = text.charCodeAt(pos); + prevValue = i64_clone(value); if (c >= CharCode._0 && c <= CharCode._7) { // value = (value << 3) + c - CharCode._0; value = i64_add( @@ -1485,9 +1525,22 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } + if (i64_gt(prevValue, value)) { + // Signed overflow occurred + // overflowSigned = true; + if (i64_gt(i64_to_u64(prevValue), i64_to_u64(value))) { + // Unsigned overflow occurred + overflowUnsigned = true; + } + } ++pos; } - if (pos == start) { + if (overflowUnsigned) { + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_the_type_i64, + this.range(start, pos), "0o" + this.source.text.substring(start, pos) + ); + } else if (pos == start) { this.error( DiagnosticCode.Octal_digit_expected, this.range(start) @@ -1510,8 +1563,12 @@ export class Tokenizer extends DiagnosticEmitter { var sepEnd = start; var value = i64_new(0); var i64_1 = i64_new(1); + var prevValue: i64; + var overflow = false; + while (pos < end) { let c = text.charCodeAt(pos); + prevValue = i64_clone(value); if (c == CharCode._0) { // value = (value << 1); value = i64_shl(value, i64_1); @@ -1534,9 +1591,18 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } + if (i64_gt(prevValue, value)) { + // Overflow occurred + overflow = true; + } ++pos; } - if (pos == start) { + if (overflow) { + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_the_type_i64, + this.range(start, pos), "0b" + this.source.text.substring(start, pos) + ); + } else if (pos == start) { this.error( DiagnosticCode.Binary_digit_expected, this.range(start) diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index 1f445aeb77..bdef778068 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -45,6 +45,7 @@ 0b0; 0b1; 0b1111111111111111111111111111111; +0xFFFFFFFFFFFFFFFF 0.0; 0.123; .0; @@ -93,6 +94,12 @@ tag`\unicode\xGG\u\x`; // see https://tc39.es/proposal-template-literal-revision 2.0b; `\unicode\xGG\u\x`; +// doesn't fit into i64 +0x10000000000000000; +0xFFF000000000000FFF; +0o2000000000000000000000; +0b10000000000000000000000000000000000000000000000000000000000000000; + // technically invalid, but not handled by AS yet, TS1005: ';' expected 3 4; 5 c; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index 8f7d004851..b576866eb9 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -45,6 +45,7 @@ 0; 1; 2147483647; +-1; 0; 0.123; 0; @@ -89,6 +90,10 @@ a; 2; b; `icodeGx`; +0; +-1152921504606842881; +0; +0; 3; 4; 5; @@ -97,13 +102,17 @@ c; d; a; b; -// ERROR 1109: "Expression expected." in literals.ts(86,4+1) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(87,2+0) +// ERROR 1109: "Expression expected." in literals.ts(87,4+1) // ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(88,2+0) -// ERROR 1109: "Expression expected." in literals.ts(89,3+1) -// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(91,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(92,3+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(93,4+0) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(94,4+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(94,12+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(94,16+1) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(89,2+0) +// ERROR 1109: "Expression expected." in literals.ts(90,3+1) +// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(92,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(93,3+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(94,4+0) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,4+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,12+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,16+1) +// ERROR 236: "Literal '0x10000000000000000' does not fit into the type 'i64'." in literals.ts(98,3+17) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into the type 'i64'." in literals.ts(99,3+18) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into the type 'i64'." in literals.ts(100,3+22) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into the type 'i64'." in literals.ts(101,3+65) From 347ae698f0287c679810b00a8a90529d40a2d1d3 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 19:45:36 +0300 Subject: [PATCH 02/26] better --- src/diagnosticMessages.json | 2 +- src/tokenizer.ts | 8 ++++---- tests/parser/literals.ts.fixture.ts | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 339a3f3a45..b25661a371 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -46,7 +46,7 @@ "Property '{0}' is always assigned before being used.": 233, "Expression does not compile to a value at runtime.": 234, "Only variables, functions and enums become WebAssembly module exports.": 235, - "Literal '{0}' does not fit into the type 'i64'.": 236, + "Literal '{0}' does not fit into 'i64' or 'u64' types.": 236, "Importing the table disables some indirect call optimizations.": 901, "Exporting the table disables some indirect call optimizations.": 902, diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 4f0056b252..07877e8e67 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -1404,7 +1404,7 @@ export class Tokenizer extends DiagnosticEmitter { } if (overflowUnsigned) { this.error( - DiagnosticCode.Literal_0_does_not_fit_into_the_type_i64, + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, this.range(start, pos), "0x" + this.source.text.substring(start, pos) ); } else if (pos == start) { @@ -1473,7 +1473,7 @@ export class Tokenizer extends DiagnosticEmitter { } if (overflowUnsigned) { this.error( - DiagnosticCode.Literal_0_does_not_fit_into_the_type_i64, + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, this.range(start, pos), this.source.text.substring(start, pos) ); } else if (pos == start) { @@ -1537,7 +1537,7 @@ export class Tokenizer extends DiagnosticEmitter { } if (overflowUnsigned) { this.error( - DiagnosticCode.Literal_0_does_not_fit_into_the_type_i64, + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, this.range(start, pos), "0o" + this.source.text.substring(start, pos) ); } else if (pos == start) { @@ -1599,7 +1599,7 @@ export class Tokenizer extends DiagnosticEmitter { } if (overflow) { this.error( - DiagnosticCode.Literal_0_does_not_fit_into_the_type_i64, + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, this.range(start, pos), "0b" + this.source.text.substring(start, pos) ); } else if (pos == start) { diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index b576866eb9..a4b56a5bb9 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -112,7 +112,7 @@ b; // ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,4+1) // ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,12+1) // ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,16+1) -// ERROR 236: "Literal '0x10000000000000000' does not fit into the type 'i64'." in literals.ts(98,3+17) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into the type 'i64'." in literals.ts(99,3+18) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into the type 'i64'." in literals.ts(100,3+22) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into the type 'i64'." in literals.ts(101,3+65) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(98,3+17) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(99,3+18) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(100,3+22) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(101,3+65) From 2a44d270c2cff53fa408dbe8aee41e720822bb3d Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 19:47:09 +0300 Subject: [PATCH 03/26] clarify comment --- tests/parser/literals.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index bdef778068..d559167d35 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -94,7 +94,7 @@ tag`\unicode\xGG\u\x`; // see https://tc39.es/proposal-template-literal-revision 2.0b; `\unicode\xGG\u\x`; -// doesn't fit into i64 +// doesn't fit into i64 / u64 0x10000000000000000; 0xFFF000000000000FFF; 0o2000000000000000000000; From ab39cf2b9e88cf32e9372d1950f8c2ca19e64035 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 20:11:05 +0300 Subject: [PATCH 04/26] fix lint --- src/glue/js/i64.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/glue/js/i64.d.ts b/src/glue/js/i64.d.ts index c4f1735645..8efdf0088e 100644 --- a/src/glue/js/i64.d.ts +++ b/src/glue/js/i64.d.ts @@ -4,6 +4,7 @@ */ declare type i64 = { __Long__: true }; // opaque +declare type u64 = { __Long__: true, unsigned: true }; // opaque declare const i64_zero: i64; declare const i64_one: i64; From 26d05aca1da0b2809577ab9746a4afc235eafec4 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 20:57:27 +0300 Subject: [PATCH 05/26] simplify --- src/glue/js/i64.d.ts | 3 +-- src/glue/js/i64.js | 8 ++++---- src/glue/wasm/i64.ts | 12 ++++++------ src/tokenizer.ts | 34 ++++++++++------------------------ 4 files changed, 21 insertions(+), 36 deletions(-) diff --git a/src/glue/js/i64.d.ts b/src/glue/js/i64.d.ts index 8efdf0088e..3e278b8132 100644 --- a/src/glue/js/i64.d.ts +++ b/src/glue/js/i64.d.ts @@ -4,7 +4,6 @@ */ declare type i64 = { __Long__: true }; // opaque -declare type u64 = { __Long__: true, unsigned: true }; // opaque declare const i64_zero: i64; declare const i64_one: i64; @@ -35,6 +34,7 @@ declare function i64_shr_u(left: i64, right: i64): i64; declare function i64_eq(left: i64, right: i64): boolean; declare function i64_ne(left: i64, right: i64): boolean; declare function i64_gt(left: i64, right: i64): boolean; +declare function i64_gt_u(left: i64, right: i64): boolean; declare function i64_align(value: i64, alignment: i32): i64; @@ -50,6 +50,5 @@ declare function i64_is_f64(value: i64): boolean; declare function i64_to_f32(value: i64): f64; declare function i64_to_f64(value: i64): f64; -declare function i64_to_u64(value: i64): u64; declare function i64_to_string(value: i64, unsigned?: boolean): string; declare function i64_clone(value: i64): i64; diff --git a/src/glue/js/i64.js b/src/glue/js/i64.js index 28a846b061..296a49081d 100644 --- a/src/glue/js/i64.js +++ b/src/glue/js/i64.js @@ -128,6 +128,10 @@ globalThis.i64_gt = function i64_gt(left, right) { return left.gt(right); }; +globalThis.i64_gt_u = function i64_gt_u(left, right) { + return left.toUnsigned().gt(right.toUnsigned()); +}; + globalThis.i64_align = function i64_align(value, alignment) { assert(alignment && (alignment & (alignment - 1)) == 0); var mask = Long.fromInt(alignment - 1); @@ -187,10 +191,6 @@ globalThis.i64_to_f64 = function i64_to_f64(value) { return value.toNumber(); }; -globalThis.i64_to_u64 = function i64_to_u64(value) { - return value.toUnsigned(); -}; - globalThis.i64_to_string = function i64_to_string(value, unsigned) { return unsigned ? value.toUnsigned().toString() : value.toString(); }; diff --git a/src/glue/wasm/i64.ts b/src/glue/wasm/i64.ts index a173dc0e22..fcdc9b5de1 100644 --- a/src/glue/wasm/i64.ts +++ b/src/glue/wasm/i64.ts @@ -170,6 +170,12 @@ function i64_gt(left: i64, right: i64): bool { return left > right; } +// @ts-ignore: decorator +@global @inline +function i64_gt_u(left: i64, right: i64): bool { + return left > right; +} + // @ts-ignore: decorator @global @inline function i64_align(value: i64, alignment: i64): i64 { @@ -244,12 +250,6 @@ function i64_to_f64(value: i64): f64 { return value; } -// @ts-ignore: decorator -@global @inline -function i64_to_u64(value: i64): u64 { - return value; -} - // @ts-ignore: decorator @global @inline function i64_to_string(value: i64, unsigned: bool = false): string { diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 07877e8e67..caffbc94bf 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -1356,8 +1356,8 @@ export class Tokenizer extends DiagnosticEmitter { var value = i64_new(0); var i64_4 = i64_new(4); var prevValue: i64; - // var overflowSigned = false; var overflowUnsigned = false; + while (pos < end) { let c = text.charCodeAt(pos); prevValue = i64_clone(value); @@ -1392,13 +1392,9 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt(prevValue, value)) { - // Signed overflow occurred - // overflowSigned = true; - if (i64_gt(i64_to_u64(prevValue), i64_to_u64(value))) { - // Unsigned overflow occurred - overflowUnsigned = true; - } + if (i64_gt_u(prevValue, value)) { + // Unsigned overflow occurred + overflowUnsigned = true; } ++pos; } @@ -1432,7 +1428,6 @@ export class Tokenizer extends DiagnosticEmitter { var i64_10 = i64_new(10); var prevValue: i64; var overflowUnsigned = false; - // var overflowSigned = false; while (pos < end) { let c = text.charCodeAt(pos); @@ -1461,13 +1456,9 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt(prevValue, value)) { - // Signed overflow occurred - // overflowSigned = true; - if (i64_gt(i64_to_u64(prevValue), i64_to_u64(value))) { - // Unsigned overflow occurred - overflowUnsigned = true; - } + if (i64_gt_u(prevValue, value)) { + // Unsigned overflow occurred + overflowUnsigned = true; } ++pos; } @@ -1501,7 +1492,6 @@ export class Tokenizer extends DiagnosticEmitter { var i64_3 = i64_new(3); var prevValue: i64; var overflowUnsigned = false; - // var overflowSigned = false; while (pos < end) { let c = text.charCodeAt(pos); @@ -1525,13 +1515,9 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt(prevValue, value)) { - // Signed overflow occurred - // overflowSigned = true; - if (i64_gt(i64_to_u64(prevValue), i64_to_u64(value))) { - // Unsigned overflow occurred - overflowUnsigned = true; - } + if (i64_gt_u(prevValue, value)) { + // Unsigned overflow occurred + overflowUnsigned = true; } ++pos; } From 6001a420c1ec5e4470a3993a4ec03cc5303c315a Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 21:08:15 +0300 Subject: [PATCH 06/26] refactor --- src/tokenizer.ts | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/tokenizer.ts b/src/tokenizer.ts index caffbc94bf..9209d26564 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -1355,27 +1355,26 @@ export class Tokenizer extends DiagnosticEmitter { var sepEnd = start; var value = i64_new(0); var i64_4 = i64_new(4); - var prevValue: i64; + var nextValue = value; var overflowUnsigned = false; while (pos < end) { let c = text.charCodeAt(pos); - prevValue = i64_clone(value); if (c >= CharCode._0 && c <= CharCode._9) { // value = (value << 4) + c - CharCode._0; - value = i64_add( + nextValue = i64_add( i64_shl(value, i64_4), i64_new(c - CharCode._0) ); } else if (c >= CharCode.A && c <= CharCode.F) { // value = (value << 4) + 10 + c - CharCode.A; - value = i64_add( + nextValue = i64_add( i64_shl(value, i64_4), i64_new(10 + c - CharCode.A) ); } else if (c >= CharCode.a && c <= CharCode.f) { // value = (value << 4) + 10 + c - CharCode.a; - value = i64_add( + nextValue = i64_add( i64_shl(value, i64_4), i64_new(10 + c - CharCode.a) ); @@ -1392,10 +1391,11 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(prevValue, value)) { + if (i64_gt_u(value, nextValue)) { // Unsigned overflow occurred overflowUnsigned = true; } + value = nextValue; ++pos; } if (overflowUnsigned) { @@ -1426,15 +1426,14 @@ export class Tokenizer extends DiagnosticEmitter { var sepEnd = start; var value = i64_new(0); var i64_10 = i64_new(10); - var prevValue: i64; + var nextValue = value; var overflowUnsigned = false; while (pos < end) { let c = text.charCodeAt(pos); - prevValue = i64_clone(value); if (c >= CharCode._0 && c <= CharCode._9) { // value = value * 10 + c - CharCode._0; - value = i64_add( + nextValue = i64_add( i64_mul(value, i64_10), i64_new(c - CharCode._0) ); @@ -1456,10 +1455,11 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(prevValue, value)) { + if (i64_gt_u(value, nextValue)) { // Unsigned overflow occurred overflowUnsigned = true; } + value = nextValue; ++pos; } if (overflowUnsigned) { @@ -1490,15 +1490,14 @@ export class Tokenizer extends DiagnosticEmitter { var sepEnd = start; var value = i64_new(0); var i64_3 = i64_new(3); - var prevValue: i64; + var nextValue = value; var overflowUnsigned = false; while (pos < end) { let c = text.charCodeAt(pos); - prevValue = i64_clone(value); if (c >= CharCode._0 && c <= CharCode._7) { // value = (value << 3) + c - CharCode._0; - value = i64_add( + nextValue = i64_add( i64_shl(value, i64_3), i64_new(c - CharCode._0) ); @@ -1515,10 +1514,11 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(prevValue, value)) { + if (i64_gt_u(value, nextValue)) { // Unsigned overflow occurred overflowUnsigned = true; } + value = nextValue; ++pos; } if (overflowUnsigned) { @@ -1549,18 +1549,17 @@ export class Tokenizer extends DiagnosticEmitter { var sepEnd = start; var value = i64_new(0); var i64_1 = i64_new(1); - var prevValue: i64; + var nextValue = value; var overflow = false; while (pos < end) { let c = text.charCodeAt(pos); - prevValue = i64_clone(value); if (c == CharCode._0) { // value = (value << 1); - value = i64_shl(value, i64_1); + nextValue = i64_shl(value, i64_1); } else if (c == CharCode._1) { // value = (value << 1) + 1; - value = i64_add( + nextValue = i64_add( i64_shl(value, i64_1), i64_1 ); @@ -1577,10 +1576,11 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt(prevValue, value)) { + if (i64_gt(value, nextValue)) { // Overflow occurred overflow = true; } + value = nextValue; ++pos; } if (overflow) { From 14b64a17c7e25c40e14eda1f6c7f71eba4406089 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 21:33:08 +0300 Subject: [PATCH 07/26] improve printing visitIntegerLiteralExpression in AST --- src/extra/ast.ts | 4 +++- tests/parser/literals.ts.fixture.ts | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/extra/ast.ts b/src/extra/ast.ts index 2ba8f449ae..fff9aaccb6 100644 --- a/src/extra/ast.ts +++ b/src/extra/ast.ts @@ -678,7 +678,9 @@ export class ASTBuilder { } visitIntegerLiteralExpression(node: IntegerLiteralExpression): void { - this.sb.push(i64_to_string(node.value)); + var range = node.range; + var hasExplicitSign = range.source.text.startsWith("-", range.start); + this.sb.push(i64_to_string(node.value, !hasExplicitSign)); } visitStringLiteral(str: string): void { diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index a4b56a5bb9..708c1b0e9c 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -45,7 +45,7 @@ 0; 1; 2147483647; --1; +18446744073709551615; 0; 0.123; 0; @@ -91,7 +91,7 @@ a; b; `icodeGx`; 0; --1152921504606842881; +17293822569102708735; 0; 0; 3; From 2b46dcf29323ad2206760c57c584b1e20105b271 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 21:39:28 +0300 Subject: [PATCH 08/26] add literal with explicit neative for literals --- tests/parser/literals.ts | 3 ++- tests/parser/literals.ts.fixture.ts | 27 ++++++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index d559167d35..2b96c565e3 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -45,7 +45,8 @@ 0b0; 0b1; 0b1111111111111111111111111111111; -0xFFFFFFFFFFFFFFFF +0xFFFFFFFFFFFFFFFF; +-123; 0.0; 0.123; .0; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index 708c1b0e9c..efb44b44cd 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -46,6 +46,7 @@ 1; 2147483647; 18446744073709551615; +-123; 0; 0.123; 0; @@ -102,17 +103,17 @@ c; d; a; b; -// ERROR 1109: "Expression expected." in literals.ts(87,4+1) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(88,2+0) +// ERROR 1109: "Expression expected." in literals.ts(88,4+1) // ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(89,2+0) -// ERROR 1109: "Expression expected." in literals.ts(90,3+1) -// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(92,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(93,3+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(94,4+0) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,4+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,12+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(95,16+1) -// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(98,3+17) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(99,3+18) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(100,3+22) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(101,3+65) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(90,2+0) +// ERROR 1109: "Expression expected." in literals.ts(91,3+1) +// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(93,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(94,3+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(95,4+0) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(96,4+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(96,12+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(96,16+1) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(99,3+17) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(100,3+18) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(101,3+22) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(102,3+65) From d0549cf657a981d34259c89c964ed2504a747fac Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 23:17:48 +0300 Subject: [PATCH 09/26] more tests --- tests/parser/literals.ts | 2 ++ tests/parser/literals.ts.fixture.ts | 29 ++++++++++++++++------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index 2b96c565e3..eddcda81bf 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -45,6 +45,7 @@ 0b0; 0b1; 0b1111111111111111111111111111111; +18446744073709551615; 0xFFFFFFFFFFFFFFFF; -123; 0.0; @@ -96,6 +97,7 @@ tag`\unicode\xGG\u\x`; // see https://tc39.es/proposal-template-literal-revision `\unicode\xGG\u\x`; // doesn't fit into i64 / u64 +18446744073709551616; 0x10000000000000000; 0xFFF000000000000FFF; 0o2000000000000000000000; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index efb44b44cd..a4ef98a0bd 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -46,6 +46,7 @@ 1; 2147483647; 18446744073709551615; +18446744073709551615; -123; 0; 0.123; @@ -92,6 +93,7 @@ a; b; `icodeGx`; 0; +0; 17293822569102708735; 0; 0; @@ -103,17 +105,18 @@ c; d; a; b; -// ERROR 1109: "Expression expected." in literals.ts(88,4+1) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(89,2+0) +// ERROR 1109: "Expression expected." in literals.ts(89,4+1) // ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(90,2+0) -// ERROR 1109: "Expression expected." in literals.ts(91,3+1) -// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(93,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(94,3+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(95,4+0) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(96,4+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(96,12+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(96,16+1) -// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(99,3+17) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(100,3+18) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(101,3+22) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(102,3+65) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(91,2+0) +// ERROR 1109: "Expression expected." in literals.ts(92,3+1) +// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(94,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(95,3+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(96,4+0) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(97,4+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(97,12+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(97,16+1) +// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(100,1+20) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(101,3+17) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(102,3+18) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(103,3+22) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(104,3+65) From 3cc5aeb084b17e8e541d00b1c16eef984f67c784 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 8 Jul 2022 23:24:30 +0300 Subject: [PATCH 10/26] better --- src/tokenizer.ts | 52 ++++++++++++++++------------- tests/parser/literals.ts.fixture.ts | 8 ++--- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 9209d26564..8e32ca05b2 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -1398,12 +1398,7 @@ export class Tokenizer extends DiagnosticEmitter { value = nextValue; ++pos; } - if (overflowUnsigned) { - this.error( - DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, - this.range(start, pos), "0x" + this.source.text.substring(start, pos) - ); - } else if (pos == start) { + if (pos == start) { this.error( DiagnosticCode.Hexadecimal_digit_expected, this.range(start) @@ -1413,6 +1408,12 @@ export class Tokenizer extends DiagnosticEmitter { DiagnosticCode.Numeric_separators_are_not_allowed_here, this.range(sepEnd - 1) ); + } else if (overflowUnsigned) { + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, + this.range(start - 2, pos), + this.source.text.substring(start - 2, pos) + ); } this.pos = pos; return value; @@ -1462,12 +1463,7 @@ export class Tokenizer extends DiagnosticEmitter { value = nextValue; ++pos; } - if (overflowUnsigned) { - this.error( - DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, - this.range(start, pos), this.source.text.substring(start, pos) - ); - } else if (pos == start) { + if (pos == start) { this.error( DiagnosticCode.Digit_expected, this.range(start) @@ -1477,6 +1473,12 @@ export class Tokenizer extends DiagnosticEmitter { DiagnosticCode.Numeric_separators_are_not_allowed_here, this.range(sepEnd - 1) ); + } else if (overflowUnsigned) { + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, + this.range(start, pos), + this.source.text.substring(start, pos) + ); } this.pos = pos; return value; @@ -1521,12 +1523,7 @@ export class Tokenizer extends DiagnosticEmitter { value = nextValue; ++pos; } - if (overflowUnsigned) { - this.error( - DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, - this.range(start, pos), "0o" + this.source.text.substring(start, pos) - ); - } else if (pos == start) { + if (pos == start) { this.error( DiagnosticCode.Octal_digit_expected, this.range(start) @@ -1536,6 +1533,12 @@ export class Tokenizer extends DiagnosticEmitter { DiagnosticCode.Numeric_separators_are_not_allowed_here, this.range(sepEnd - 1) ); + } else if (overflowUnsigned) { + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, + this.range(start - 2, pos), + this.source.text.substring(start - 2, pos) + ); } this.pos = pos; return value; @@ -1583,12 +1586,7 @@ export class Tokenizer extends DiagnosticEmitter { value = nextValue; ++pos; } - if (overflow) { - this.error( - DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, - this.range(start, pos), "0b" + this.source.text.substring(start, pos) - ); - } else if (pos == start) { + if (pos == start) { this.error( DiagnosticCode.Binary_digit_expected, this.range(start) @@ -1598,6 +1596,12 @@ export class Tokenizer extends DiagnosticEmitter { DiagnosticCode.Numeric_separators_are_not_allowed_here, this.range(sepEnd - 1) ); + } else if (overflow) { + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, + this.range(start - 2, pos), + this.source.text.substring(start - 2, pos) + ); } this.pos = pos; return value; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index a4ef98a0bd..b15e3b70e0 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -116,7 +116,7 @@ b; // ERROR 1125: "Hexadecimal digit expected." in literals.ts(97,12+1) // ERROR 1125: "Hexadecimal digit expected." in literals.ts(97,16+1) // ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(100,1+20) -// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(101,3+17) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(102,3+18) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(103,3+22) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(104,3+65) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(101,1+19) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(102,1+20) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(103,1+24) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(104,1+67) From 1b143d28c8624fe6b9736e11e57913f2776f628d Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sat, 9 Jul 2022 15:32:46 +0300 Subject: [PATCH 11/26] fix extra/tsconfig --- src/extra/tsconfig.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/extra/tsconfig.json b/src/extra/tsconfig.json index be647996f0..ddfc2bda24 100644 --- a/src/extra/tsconfig.json +++ b/src/extra/tsconfig.json @@ -1,6 +1,12 @@ { "extends": "../../std/portable.json", "include": [ - "./**/*.ts" + "../**/*.ts" + ], + "exclude": [ + "../**/node_modules/", + "../tests/**", + "../lib/**", + "./glue/wasm/**" ] } From cc62dcb89f4a639e7bcab4e935ddbd026ba57096 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 12:43:46 +0300 Subject: [PATCH 12/26] also detect lower bound for signed overflows --- src/glue/js/i64.d.ts | 6 ++++ src/glue/js/i64.js | 14 +++++++++ src/glue/wasm/i64.ts | 24 ++++++++++++++ src/tokenizer.ts | 49 ++++++++++++++++++----------- tests/parser/literals.ts | 4 +++ tests/parser/literals.ts.fixture.ts | 36 ++++++++++++--------- 6 files changed, 100 insertions(+), 33 deletions(-) diff --git a/src/glue/js/i64.d.ts b/src/glue/js/i64.d.ts index 3e278b8132..d6b855b757 100644 --- a/src/glue/js/i64.d.ts +++ b/src/glue/js/i64.d.ts @@ -7,6 +7,9 @@ declare type i64 = { __Long__: true }; // opaque declare const i64_zero: i64; declare const i64_one: i64; +declare const i64_neg_one: i64; +declare const i64_minimum: i64; +declare const i64_maximum: i64; declare function i64_is(value: unknown): value is i64; declare function i64_new(lo: i32, hi?: i32): i64; @@ -14,6 +17,7 @@ declare function i64_low(value: i64): i32; declare function i64_high(value: i64): i32; declare function i64_not(value: i64): i64; +declare function i64_neg(value: i64): i64; declare function i64_clz(value: i64): i32; declare function i64_ctz(value: i64): i32; @@ -33,10 +37,12 @@ declare function i64_shr(left: i64, right: i64): i64; declare function i64_shr_u(left: i64, right: i64): i64; declare function i64_eq(left: i64, right: i64): boolean; declare function i64_ne(left: i64, right: i64): boolean; +declare function i64_ge(left: i64, right: i64): boolean; declare function i64_gt(left: i64, right: i64): boolean; declare function i64_gt_u(left: i64, right: i64): boolean; declare function i64_align(value: i64, alignment: i32): i64; +declare function i64_signbit(value): boolean; declare function i64_is_i8(value: i64): boolean; declare function i64_is_i16(value: i64): boolean; diff --git a/src/glue/js/i64.js b/src/glue/js/i64.js index 296a49081d..8ae4858587 100644 --- a/src/glue/js/i64.js +++ b/src/glue/js/i64.js @@ -10,6 +10,8 @@ import Long from "long"; globalThis.i64_zero = Long.ZERO; globalThis.i64_one = Long.ONE; globalThis.i64_neg_one = Long.fromInt(-1); +globalThis.i64_minimum = Long.MIN_VALUE; +globalThis.i64_maximum = Long.MAX_VALUE; globalThis.i64_is = function i64_is(value) { return Long.isLong(value); @@ -31,6 +33,10 @@ globalThis.i64_not = function i64_not(value) { return value.not(); }; +globalThis.i64_neg = function i64_neg(value) { + return value.neg(); +}; + globalThis.i64_clz = function i64_clz(value) { return value.clz(); }; @@ -124,6 +130,10 @@ globalThis.i64_ne = function i64_ne(left, right) { return left.ne(right); }; +globalThis.i64_ge = function i64_ge(left, right) { + return left.ge(right); +}; + globalThis.i64_gt = function i64_gt(left, right) { return left.gt(right); }; @@ -138,6 +148,10 @@ globalThis.i64_align = function i64_align(value, alignment) { return value.add(mask).and(mask.not()); }; +globalThis.i64_signbit = function i64_signbit(value) { + return Boolean(value.high >>> 31); +}; + globalThis.i64_is_i8 = function i64_is_i8(value) { return value.high === 0 && (value.low >= 0 && value.low <= i8.MAX_VALUE) || value.high === -1 && (value.low >= i8.MIN_VALUE && value.low < 0); diff --git a/src/glue/wasm/i64.ts b/src/glue/wasm/i64.ts index fcdc9b5de1..4c70437afa 100644 --- a/src/glue/wasm/i64.ts +++ b/src/glue/wasm/i64.ts @@ -14,6 +14,12 @@ // @ts-ignore: decorator @global const i64_neg_one: i64 = -1; +// @ts-ignore: decorator +@global const i64_minimum: i64 = i64.MIN_VALUE; + +// @ts-ignore: decorator +@global const i64_maximum: i64 = i64.MAX_VALUE; + // @ts-ignore: decorator @global @inline function i64_is(value: T): bool { @@ -38,6 +44,12 @@ function i64_not(value: i64): i64 { return ~value; } +// @ts-ignore: decorator +@global @inline +function i64_neg(value: i64): i64 { + return -value; +} + // @ts-ignore: decorator @global @inline function i64_clz(value: i64): i32 { @@ -164,6 +176,12 @@ function i64_ne(left: i64, right: i64): bool { return left != right; } +// @ts-ignore: decorator +@global @inline +function i64_ge(left: i64, right: i64): bool { + return left >= right; +} + // @ts-ignore: decorator @global @inline function i64_gt(left: i64, right: i64): bool { @@ -184,6 +202,12 @@ function i64_align(value: i64, alignment: i64): i64 { return (value + mask) & ~mask; } +// @ts-ignore: decorator +@global @inline +function i64_signbit(value: i64): bool { + return (value >>> 63); +} + // @ts-ignore: decorator @global @inline function i64_is_i8(value: i64): bool { diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 8e32ca05b2..dc210ac0dd 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -1356,7 +1356,7 @@ export class Tokenizer extends DiagnosticEmitter { var value = i64_new(0); var i64_4 = i64_new(4); var nextValue = value; - var overflowUnsigned = false; + var overflowOccurred = false; while (pos < end) { let c = text.charCodeAt(pos); @@ -1391,9 +1391,13 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(value, nextValue)) { - // Unsigned overflow occurred - overflowUnsigned = true; + if (i64_gt_u(value, nextValue) || ( + i64_ne(value, i64_neg_one) && i64_ne(nextValue, i64_neg_one) && + i64_ne(value, i64_minimum) && i64_ne(nextValue, i64_minimum) && + i64_signbit(nextValue) && !i64_signbit(value) + )) { + // Signed or unsigned overflow occurred + overflowOccurred = true; } value = nextValue; ++pos; @@ -1408,7 +1412,8 @@ export class Tokenizer extends DiagnosticEmitter { DiagnosticCode.Numeric_separators_are_not_allowed_here, this.range(sepEnd - 1) ); - } else if (overflowUnsigned) { + } + if (overflowOccurred) { this.error( DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, this.range(start - 2, pos), @@ -1428,7 +1433,7 @@ export class Tokenizer extends DiagnosticEmitter { var value = i64_new(0); var i64_10 = i64_new(10); var nextValue = value; - var overflowUnsigned = false; + var overflowOccurred = false; while (pos < end) { let c = text.charCodeAt(pos); @@ -1456,9 +1461,13 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(value, nextValue)) { - // Unsigned overflow occurred - overflowUnsigned = true; + if (i64_gt_u(value, nextValue) || ( + i64_ne(value, i64_neg_one) && i64_ne(nextValue, i64_neg_one) && + i64_ne(value, i64_minimum) && i64_ne(nextValue, i64_minimum) && + i64_signbit(nextValue) && !i64_signbit(value) + )) { + // Signed or unsigned overflow occurred + overflowOccurred = true; } value = nextValue; ++pos; @@ -1473,7 +1482,7 @@ export class Tokenizer extends DiagnosticEmitter { DiagnosticCode.Numeric_separators_are_not_allowed_here, this.range(sepEnd - 1) ); - } else if (overflowUnsigned) { + } else if (overflowOccurred) { this.error( DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, this.range(start, pos), @@ -1493,7 +1502,7 @@ export class Tokenizer extends DiagnosticEmitter { var value = i64_new(0); var i64_3 = i64_new(3); var nextValue = value; - var overflowUnsigned = false; + var overflowOccurred = false; while (pos < end) { let c = text.charCodeAt(pos); @@ -1516,9 +1525,13 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(value, nextValue)) { - // Unsigned overflow occurred - overflowUnsigned = true; + if (i64_gt_u(value, nextValue) || ( + i64_ne(value, i64_neg_one) && i64_ne(nextValue, i64_neg_one) && + i64_ne(value, i64_minimum) && i64_ne(nextValue, i64_minimum) && + i64_signbit(nextValue) && !i64_signbit(value) + )) { + // Signed or unsigned overflow occurred + overflowOccurred = true; } value = nextValue; ++pos; @@ -1533,7 +1546,7 @@ export class Tokenizer extends DiagnosticEmitter { DiagnosticCode.Numeric_separators_are_not_allowed_here, this.range(sepEnd - 1) ); - } else if (overflowUnsigned) { + } else if (overflowOccurred) { this.error( DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, this.range(start - 2, pos), @@ -1553,7 +1566,7 @@ export class Tokenizer extends DiagnosticEmitter { var value = i64_new(0); var i64_1 = i64_new(1); var nextValue = value; - var overflow = false; + var overflowOccurred = false; while (pos < end) { let c = text.charCodeAt(pos); @@ -1581,7 +1594,7 @@ export class Tokenizer extends DiagnosticEmitter { } if (i64_gt(value, nextValue)) { // Overflow occurred - overflow = true; + overflowOccurred = true; } value = nextValue; ++pos; @@ -1596,7 +1609,7 @@ export class Tokenizer extends DiagnosticEmitter { DiagnosticCode.Numeric_separators_are_not_allowed_here, this.range(sepEnd - 1) ); - } else if (overflow) { + } else if (overflowOccurred) { this.error( DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, this.range(start - 2, pos), diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index eddcda81bf..07b34febb8 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -47,6 +47,8 @@ 0b1111111111111111111111111111111; 18446744073709551615; 0xFFFFFFFFFFFFFFFF; +-9223372036854775808; +-0x8000000000000000; -123; 0.0; 0.123; @@ -98,7 +100,9 @@ tag`\unicode\xGG\u\x`; // see https://tc39.es/proposal-template-literal-revision // doesn't fit into i64 / u64 18446744073709551616; +-9223372036854775809; 0x10000000000000000; +-0x8000000000000001; 0xFFF000000000000FFF; 0o2000000000000000000000; 0b10000000000000000000000000000000000000000000000000000000000000000; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index b15e3b70e0..27a53896a8 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -47,6 +47,8 @@ 2147483647; 18446744073709551615; 18446744073709551615; +-9223372036854775808; +-9223372036854775808; -123; 0; 0.123; @@ -93,7 +95,9 @@ a; b; `icodeGx`; 0; +-9223372036854775809; 0; +-9223372036854775809; 17293822569102708735; 0; 0; @@ -105,18 +109,20 @@ c; d; a; b; -// ERROR 1109: "Expression expected." in literals.ts(89,4+1) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(90,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(91,2+0) -// ERROR 1109: "Expression expected." in literals.ts(92,3+1) -// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(94,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(95,3+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(96,4+0) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(97,4+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(97,12+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(97,16+1) -// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(100,1+20) -// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(101,1+19) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(102,1+20) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(103,1+24) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(104,1+67) +// ERROR 1109: "Expression expected." in literals.ts(91,4+1) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(92,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(93,2+0) +// ERROR 1109: "Expression expected." in literals.ts(94,3+1) +// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(96,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(97,3+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(98,4+0) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(99,4+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(99,12+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(99,16+1) +// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(102,1+20) +// ERROR 236: "Literal '9223372036854775809' does not fit into 'i64' or 'u64' types." in literals.ts(103,2+19) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(104,1+19) +// ERROR 236: "Literal '0x8000000000000001' does not fit into 'i64' or 'u64' types." in literals.ts(105,2+18) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(106,1+20) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(107,1+24) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(108,1+67) From 9f09d3108676c09edaeeedbc9a1358269c3044ed Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 12:59:34 +0300 Subject: [PATCH 13/26] more tests --- tests/parser/literals.ts | 4 +++ tests/parser/literals.ts.fixture.ts | 38 ++++++++++++++++------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index 07b34febb8..e35ba6641b 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -47,8 +47,12 @@ 0b1111111111111111111111111111111; 18446744073709551615; 0xFFFFFFFFFFFFFFFF; +-9223372036854775807; -9223372036854775808; +-0x7FFFFFFFFFFFFFFF; -0x8000000000000000; +-1; +-0x1; -123; 0.0; 0.123; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index 27a53896a8..49e0306dce 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -47,8 +47,12 @@ 2147483647; 18446744073709551615; 18446744073709551615; +-9223372036854775807; -9223372036854775808; +-9223372036854775807; -9223372036854775808; +-1; +-1; -123; 0; 0.123; @@ -109,20 +113,20 @@ c; d; a; b; -// ERROR 1109: "Expression expected." in literals.ts(91,4+1) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(92,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(93,2+0) -// ERROR 1109: "Expression expected." in literals.ts(94,3+1) -// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(96,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(97,3+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(98,4+0) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(99,4+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(99,12+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(99,16+1) -// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(102,1+20) -// ERROR 236: "Literal '9223372036854775809' does not fit into 'i64' or 'u64' types." in literals.ts(103,2+19) -// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(104,1+19) -// ERROR 236: "Literal '0x8000000000000001' does not fit into 'i64' or 'u64' types." in literals.ts(105,2+18) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(106,1+20) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(107,1+24) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(108,1+67) +// ERROR 1109: "Expression expected." in literals.ts(95,4+1) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(96,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(97,2+0) +// ERROR 1109: "Expression expected." in literals.ts(98,3+1) +// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(100,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(101,3+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(102,4+0) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(103,4+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(103,12+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(103,16+1) +// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(106,1+20) +// ERROR 236: "Literal '9223372036854775809' does not fit into 'i64' or 'u64' types." in literals.ts(107,2+19) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(108,1+19) +// ERROR 236: "Literal '0x8000000000000001' does not fit into 'i64' or 'u64' types." in literals.ts(109,2+18) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(110,1+20) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(111,1+24) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(112,1+67) From aa21e4d18787fad46bbe3f6020356d55be786ff6 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 13:01:14 +0300 Subject: [PATCH 14/26] more --- tests/parser/literals.ts | 2 ++ tests/parser/literals.ts.fixture.ts | 36 +++++++++++++++-------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index e35ba6641b..0b35140fbb 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -46,6 +46,8 @@ 0b1; 0b1111111111111111111111111111111; 18446744073709551615; +0x7FFFFFFFFFFFFFFF; +0x8000000000000000; 0xFFFFFFFFFFFFFFFF; -9223372036854775807; -9223372036854775808; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index 49e0306dce..7b2a6ac2e1 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -46,6 +46,8 @@ 1; 2147483647; 18446744073709551615; +9223372036854775807; +9223372036854775808; 18446744073709551615; -9223372036854775807; -9223372036854775808; @@ -113,20 +115,20 @@ c; d; a; b; -// ERROR 1109: "Expression expected." in literals.ts(95,4+1) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(96,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(97,2+0) -// ERROR 1109: "Expression expected." in literals.ts(98,3+1) -// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(100,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(101,3+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(102,4+0) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(103,4+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(103,12+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(103,16+1) -// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(106,1+20) -// ERROR 236: "Literal '9223372036854775809' does not fit into 'i64' or 'u64' types." in literals.ts(107,2+19) -// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(108,1+19) -// ERROR 236: "Literal '0x8000000000000001' does not fit into 'i64' or 'u64' types." in literals.ts(109,2+18) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(110,1+20) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(111,1+24) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(112,1+67) +// ERROR 1109: "Expression expected." in literals.ts(97,4+1) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(98,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(99,2+0) +// ERROR 1109: "Expression expected." in literals.ts(100,3+1) +// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(102,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(103,3+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(104,4+0) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(105,4+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(105,12+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(105,16+1) +// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(108,1+20) +// ERROR 236: "Literal '9223372036854775809' does not fit into 'i64' or 'u64' types." in literals.ts(109,2+19) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(110,1+19) +// ERROR 236: "Literal '0x8000000000000001' does not fit into 'i64' or 'u64' types." in literals.ts(111,2+18) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(112,1+20) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(113,1+24) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(114,1+67) From d233d4f3748e785a9b4f6f877dfa671d1d051199 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 14:09:24 +0300 Subject: [PATCH 15/26] in tokenized we can detect only unsigned overflows --- src/tokenizer.ts | 24 ++++++--------------- tests/parser/literals.ts | 5 +++-- tests/parser/literals.ts.fixture.ts | 33 +++++++++++++---------------- 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/tokenizer.ts b/src/tokenizer.ts index dc210ac0dd..e1ae0fa9d3 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -1391,12 +1391,8 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(value, nextValue) || ( - i64_ne(value, i64_neg_one) && i64_ne(nextValue, i64_neg_one) && - i64_ne(value, i64_minimum) && i64_ne(nextValue, i64_minimum) && - i64_signbit(nextValue) && !i64_signbit(value) - )) { - // Signed or unsigned overflow occurred + if (i64_gt_u(value, nextValue)) { + // Unsigned overflow occurred overflowOccurred = true; } value = nextValue; @@ -1461,12 +1457,8 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(value, nextValue) || ( - i64_ne(value, i64_neg_one) && i64_ne(nextValue, i64_neg_one) && - i64_ne(value, i64_minimum) && i64_ne(nextValue, i64_minimum) && - i64_signbit(nextValue) && !i64_signbit(value) - )) { - // Signed or unsigned overflow occurred + if (i64_gt_u(value, nextValue)) { + // Unsigned overflow occurred overflowOccurred = true; } value = nextValue; @@ -1525,12 +1517,8 @@ export class Tokenizer extends DiagnosticEmitter { } else { break; } - if (i64_gt_u(value, nextValue) || ( - i64_ne(value, i64_neg_one) && i64_ne(nextValue, i64_neg_one) && - i64_ne(value, i64_minimum) && i64_ne(nextValue, i64_minimum) && - i64_signbit(nextValue) && !i64_signbit(value) - )) { - // Signed or unsigned overflow occurred + if (i64_gt_u(value, nextValue)) { + // Unsigned overflow occurred overflowOccurred = true; } value = nextValue; diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index 0b35140fbb..6defc6a8c9 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -48,6 +48,7 @@ 18446744073709551615; 0x7FFFFFFFFFFFFFFF; 0x8000000000000000; +0x9E19DB92B4E31BA9; 0xFFFFFFFFFFFFFFFF; -9223372036854775807; -9223372036854775808; @@ -106,9 +107,9 @@ tag`\unicode\xGG\u\x`; // see https://tc39.es/proposal-template-literal-revision // doesn't fit into i64 / u64 18446744073709551616; --9223372036854775809; +// -9223372036854775809; TODO 0x10000000000000000; --0x8000000000000001; +// -0x8000000000000001; TODO 0xFFF000000000000FFF; 0o2000000000000000000000; 0b10000000000000000000000000000000000000000000000000000000000000000; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index 7b2a6ac2e1..58c849a440 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -48,6 +48,7 @@ 18446744073709551615; 9223372036854775807; 9223372036854775808; +11392378155556871081; 18446744073709551615; -9223372036854775807; -9223372036854775808; @@ -101,9 +102,7 @@ a; b; `icodeGx`; 0; --9223372036854775809; 0; --9223372036854775809; 17293822569102708735; 0; 0; @@ -115,20 +114,18 @@ c; d; a; b; -// ERROR 1109: "Expression expected." in literals.ts(97,4+1) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(98,2+0) +// ERROR 1109: "Expression expected." in literals.ts(98,4+1) // ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(99,2+0) -// ERROR 1109: "Expression expected." in literals.ts(100,3+1) -// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(102,2+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(103,3+0) -// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(104,4+0) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(105,4+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(105,12+1) -// ERROR 1125: "Hexadecimal digit expected." in literals.ts(105,16+1) -// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(108,1+20) -// ERROR 236: "Literal '9223372036854775809' does not fit into 'i64' or 'u64' types." in literals.ts(109,2+19) -// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(110,1+19) -// ERROR 236: "Literal '0x8000000000000001' does not fit into 'i64' or 'u64' types." in literals.ts(111,2+18) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(112,1+20) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(113,1+24) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(114,1+67) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(100,2+0) +// ERROR 1109: "Expression expected." in literals.ts(101,3+1) +// ERROR 6188: "Numeric separators are not allowed here." in literals.ts(103,2+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(104,3+0) +// ERROR 1351: "An identifier or keyword cannot immediately follow a numeric literal." in literals.ts(105,4+0) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(106,4+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(106,12+1) +// ERROR 1125: "Hexadecimal digit expected." in literals.ts(106,16+1) +// ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(109,1+20) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(111,1+19) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(113,1+20) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(114,1+24) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(115,1+67) From d811e8cbc97410e2500b6489a7a6e0d9965e2499 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 16:12:20 +0300 Subject: [PATCH 16/26] refactor --- tests/parser/literals.ts | 6 ++++-- tests/parser/literals.ts.fixture.ts | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index 6defc6a8c9..f3c3f95ac2 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -107,13 +107,15 @@ tag`\unicode\xGG\u\x`; // see https://tc39.es/proposal-template-literal-revision // doesn't fit into i64 / u64 18446744073709551616; -// -9223372036854775809; TODO 0x10000000000000000; -// -0x8000000000000001; TODO 0xFFF000000000000FFF; 0o2000000000000000000000; 0b10000000000000000000000000000000000000000000000000000000000000000; +// TODO: signed underflow +// -9223372036854775809; +// -0x8000000000000001; + // technically invalid, but not handled by AS yet, TS1005: ';' expected 3 4; 5 c; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index 58c849a440..3f71d572ae 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -125,7 +125,7 @@ b; // ERROR 1125: "Hexadecimal digit expected." in literals.ts(106,12+1) // ERROR 1125: "Hexadecimal digit expected." in literals.ts(106,16+1) // ERROR 236: "Literal '18446744073709551616' does not fit into 'i64' or 'u64' types." in literals.ts(109,1+20) -// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(111,1+19) -// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(113,1+20) -// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(114,1+24) -// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(115,1+67) +// ERROR 236: "Literal '0x10000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(110,1+19) +// ERROR 236: "Literal '0xFFF000000000000FFF' does not fit into 'i64' or 'u64' types." in literals.ts(111,1+20) +// ERROR 236: "Literal '0o2000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(112,1+24) +// ERROR 236: "Literal '0b10000000000000000000000000000000000000000000000000000000000000000' does not fit into 'i64' or 'u64' types." in literals.ts(113,1+67) From 5faf57a5bbd20c5386df280d5ef30f78feba5e02 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 16:26:19 +0300 Subject: [PATCH 17/26] minor refactoring --- src/compiler.ts | 8 +------- src/resolver.ts | 13 ++++++++++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 98d9a42084..c3ba35a019 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -8091,13 +8091,7 @@ export class Compiler extends DiagnosticEmitter { } case LiteralKind.INTEGER: { let intValue = (expression).value; - if (implicitlyNegate) { - intValue = i64_sub( - i64_new(0), - intValue - ); - } - let type = this.resolver.determineIntegerLiteralType(intValue, contextualType); + let type = this.resolver.determineIntegerLiteralType(intValue, implicitlyNegate, contextualType); this.currentType = type; switch (type.kind) { case TypeKind.ISIZE: if (!this.options.isWasm64) return module.i32(i64_low(intValue)); diff --git a/src/resolver.ts b/src/resolver.ts index 2cdfe69a4f..4f71351e65 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -1513,9 +1513,15 @@ export class Resolver extends DiagnosticEmitter { determineIntegerLiteralType( /** Integer literal value. */ intValue: i64, + /** Has unary minus before literal. */ + negate: bool, /** Contextual type. */ ctxType: Type ): Type { + if (negate) { + intValue = i64_sub(i64_new(0), intValue); + // TODO: check overflow + } if (ctxType.isValue) { // compile to contextual type if matching switch (ctxType.kind) { @@ -1715,7 +1721,11 @@ export class Resolver extends DiagnosticEmitter { case Token.MINUS: { // implicitly negate if an integer literal to distinguish between i32/u32/i64 if (operand.isLiteralKind(LiteralKind.INTEGER)) { - return this.determineIntegerLiteralType(i64_sub(i64_zero, (operand).value), ctxType); + return this.determineIntegerLiteralType( + (operand).value, + true, + ctxType + ); } // fall-through } @@ -2179,6 +2189,7 @@ export class Resolver extends DiagnosticEmitter { case LiteralKind.INTEGER: { let intType = this.determineIntegerLiteralType( (node).value, + false, ctxType ); return assert(intType.getClassOrWrapper(this.program)); From c6a565d184c8b0188de845f66591fc55f0529799 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 16:35:01 +0300 Subject: [PATCH 18/26] compleate i64 relational ops --- src/glue/js/i64.d.ts | 6 ++++++ src/glue/js/i64.js | 20 ++++++++++++++++++++ src/glue/wasm/i64.ts | 30 ++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/src/glue/js/i64.d.ts b/src/glue/js/i64.d.ts index d6b855b757..4b0d28bdb9 100644 --- a/src/glue/js/i64.d.ts +++ b/src/glue/js/i64.d.ts @@ -35,11 +35,17 @@ declare function i64_xor(left: i64, right: i64): i64; declare function i64_shl(left: i64, right: i64): i64; declare function i64_shr(left: i64, right: i64): i64; declare function i64_shr_u(left: i64, right: i64): i64; + declare function i64_eq(left: i64, right: i64): boolean; declare function i64_ne(left: i64, right: i64): boolean; declare function i64_ge(left: i64, right: i64): boolean; +declare function i64_ge_u(left: i64, right: i64): boolean; declare function i64_gt(left: i64, right: i64): boolean; declare function i64_gt_u(left: i64, right: i64): boolean; +declare function i64_le(left: i64, right: i64): boolean; +declare function i64_le_u(left: i64, right: i64): boolean; +declare function i64_lt(left: i64, right: i64): boolean; +declare function i64_lt_u(left: i64, right: i64): boolean; declare function i64_align(value: i64, alignment: i32): i64; declare function i64_signbit(value): boolean; diff --git a/src/glue/js/i64.js b/src/glue/js/i64.js index 8ae4858587..d58d34c1c9 100644 --- a/src/glue/js/i64.js +++ b/src/glue/js/i64.js @@ -134,6 +134,10 @@ globalThis.i64_ge = function i64_ge(left, right) { return left.ge(right); }; +globalThis.i64_ge_u = function i64_ge_u(left, right) { + return left.toUnsigned().ge(right.toUnsigned()); +}; + globalThis.i64_gt = function i64_gt(left, right) { return left.gt(right); }; @@ -142,6 +146,22 @@ globalThis.i64_gt_u = function i64_gt_u(left, right) { return left.toUnsigned().gt(right.toUnsigned()); }; +globalThis.i64_le = function i64_le(left, right) { + return left.le(right); +}; + +globalThis.i64_le_u = function i64_le_u(left, right) { + return left.toUnsigned().le(right.toUnsigned()); +}; + +globalThis.i64_lt = function i64_lt(left, right) { + return left.lt(right); +}; + +globalThis.i64_lt_u = function i64_lt_u(left, right) { + return left.toUnsigned().lt(right.toUnsigned()); +}; + globalThis.i64_align = function i64_align(value, alignment) { assert(alignment && (alignment & (alignment - 1)) == 0); var mask = Long.fromInt(alignment - 1); diff --git a/src/glue/wasm/i64.ts b/src/glue/wasm/i64.ts index 4c70437afa..496d77bccc 100644 --- a/src/glue/wasm/i64.ts +++ b/src/glue/wasm/i64.ts @@ -182,6 +182,12 @@ function i64_ge(left: i64, right: i64): bool { return left >= right; } +// @ts-ignore: decorator +@global @inline +function i64_ge_u(left: i64, right: i64): bool { + return left >= right; +} + // @ts-ignore: decorator @global @inline function i64_gt(left: i64, right: i64): bool { @@ -194,6 +200,30 @@ function i64_gt_u(left: i64, right: i64): bool { return left > right; } +// @ts-ignore: decorator +@global @inline +function i64_le(left: i64, right: i64): bool { + return left <= right; +} + +// @ts-ignore: decorator +@global @inline +function i64_le_u(left: i64, right: i64): bool { + return left <= right; +} + +// @ts-ignore: decorator +@global @inline +function i64_lt(left: i64, right: i64): bool { + return left < right; +} + +// @ts-ignore: decorator +@global @inline +function i64_lt_u(left: i64, right: i64): bool { + return left < right; +} + // @ts-ignore: decorator @global @inline function i64_align(value: i64, alignment: i64): i64 { From e5486a5822ba0979b4f82f026348b14e14b5c417 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 16:43:21 +0300 Subject: [PATCH 19/26] fix --- src/compiler.ts | 1 + src/resolver.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler.ts b/src/compiler.ts index c3ba35a019..38f37e643c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -8092,6 +8092,7 @@ export class Compiler extends DiagnosticEmitter { case LiteralKind.INTEGER: { let intValue = (expression).value; let type = this.resolver.determineIntegerLiteralType(intValue, implicitlyNegate, contextualType); + if (implicitlyNegate) intValue = i64_neg(intValue); this.currentType = type; switch (type.kind) { case TypeKind.ISIZE: if (!this.options.isWasm64) return module.i32(i64_low(intValue)); diff --git a/src/resolver.ts b/src/resolver.ts index 4f71351e65..c30b0b580e 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -1519,7 +1519,7 @@ export class Resolver extends DiagnosticEmitter { ctxType: Type ): Type { if (negate) { - intValue = i64_sub(i64_new(0), intValue); + intValue = i64_neg(intValue); // TODO: check overflow } if (ctxType.isValue) { From 2252b84dcb72016ddd8dbab383ece5f7bff04118 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 19:47:03 +0300 Subject: [PATCH 20/26] wip --- src/compiler.ts | 10 +++++++--- src/resolver.ts | 31 +++++++++++++++++++++++++---- tests/compiler/literals.debug.wat | 4 ++++ tests/compiler/literals.json | 4 ++++ tests/compiler/literals.ts | 6 ++++++ tests/parser/literals.ts | 4 ---- tests/parser/literals.ts.fixture.ts | 2 ++ 7 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 38f37e643c..947a673362 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -8090,9 +8090,13 @@ export class Compiler extends DiagnosticEmitter { return module.f64(floatValue); } case LiteralKind.INTEGER: { - let intValue = (expression).value; - let type = this.resolver.determineIntegerLiteralType(intValue, implicitlyNegate, contextualType); - if (implicitlyNegate) intValue = i64_neg(intValue); + let expr = expression; + let type = this.resolver.determineIntegerLiteralType(expr, implicitlyNegate, contextualType); + + let intValue = implicitlyNegate + ? i64_neg(expr.value) + : expr.value; + this.currentType = type; switch (type.kind) { case TypeKind.ISIZE: if (!this.options.isWasm64) return module.i32(i64_low(intValue)); diff --git a/src/resolver.ts b/src/resolver.ts index c30b0b580e..f53efbddab 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -1512,15 +1512,38 @@ export class Resolver extends DiagnosticEmitter { /** Determines the final type of an integer literal given the specified contextual type. */ determineIntegerLiteralType( /** Integer literal value. */ - intValue: i64, + expr: IntegerLiteralExpression, /** Has unary minus before literal. */ negate: bool, /** Contextual type. */ ctxType: Type ): Type { + let intValue = expr.value; if (negate) { + console.log("+intValue: ", i64_to_string(intValue), + expr.range.source.text.substring(expr.range.start - 1, expr.range.end) + ); + console.log("-intValue: ", i64_to_string(i64_neg(intValue))); + // Check signed overflow + if ( + // x > 0 && x + i64.min > 0 -> underflow + (i64_gt(intValue, i64_zero) && + i64_gt(i64_add(intValue, i64_minimum), i64_zero)) || + // x < 0 && x + i64.max < 0 -> overflow + (i64_lt(intValue, i64_zero) && + i64_lt(i64_add(intValue, i64_maximum), i64_zero)) + ) { + // console.log(">>> overflow!", expr.range.source.text.substring(expr.range.start - 1)); + this.error( + DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, + expr.range, + expr.range.source.text.substring( + expr.range.start - 1, + expr.range.end + ) + ); + } intValue = i64_neg(intValue); - // TODO: check overflow } if (ctxType.isValue) { // compile to contextual type if matching @@ -1722,7 +1745,7 @@ export class Resolver extends DiagnosticEmitter { // implicitly negate if an integer literal to distinguish between i32/u32/i64 if (operand.isLiteralKind(LiteralKind.INTEGER)) { return this.determineIntegerLiteralType( - (operand).value, + operand, true, ctxType ); @@ -2188,7 +2211,7 @@ export class Resolver extends DiagnosticEmitter { switch (node.literalKind) { case LiteralKind.INTEGER: { let intType = this.determineIntegerLiteralType( - (node).value, + node, false, ctxType ); diff --git a/tests/compiler/literals.debug.wat b/tests/compiler/literals.debug.wat index f29febd140..deb7ab7156 100644 --- a/tests/compiler/literals.debug.wat +++ b/tests/compiler/literals.debug.wat @@ -97,6 +97,10 @@ drop i32.const 0 drop + i64.const 9223372036854775807 + drop + i64.const 9223372036854775807 + drop ) (func $~start call $start:literals diff --git a/tests/compiler/literals.json b/tests/compiler/literals.json index 1bdd02b1be..3d8e58d1df 100644 --- a/tests/compiler/literals.json +++ b/tests/compiler/literals.json @@ -1,4 +1,8 @@ { "asc_flags": [ + ], + "stderr": [ + "ERROR 236: \"Literal '-9223372036854775809' does not fit into 'i64' or 'u64' types.\" in literals.ts(47,1+21)", + "EOF" ] } diff --git a/tests/compiler/literals.ts b/tests/compiler/literals.ts index 0b3652c816..f55efa0137 100644 --- a/tests/compiler/literals.ts +++ b/tests/compiler/literals.ts @@ -42,3 +42,9 @@ 0b1; true; false; + +// Signed underflow +-9223372036854775809; +// -0x8000000000000001; + +ERROR("EOF"); diff --git a/tests/parser/literals.ts b/tests/parser/literals.ts index f3c3f95ac2..086346090b 100644 --- a/tests/parser/literals.ts +++ b/tests/parser/literals.ts @@ -112,10 +112,6 @@ tag`\unicode\xGG\u\x`; // see https://tc39.es/proposal-template-literal-revision 0o2000000000000000000000; 0b10000000000000000000000000000000000000000000000000000000000000000; -// TODO: signed underflow -// -9223372036854775809; -// -0x8000000000000001; - // technically invalid, but not handled by AS yet, TS1005: ';' expected 3 4; 5 c; diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index 3f71d572ae..73e22a4e26 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -106,6 +106,8 @@ b; 17293822569102708735; 0; 0; +-9223372036854775809; +-9223372036854775809; 3; 4; 5; From e969bf211d8e6ab976c69f26f22e6cf3bb4e1d3f Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 20:23:51 +0300 Subject: [PATCH 21/26] add tests & cleanup --- src/resolver.ts | 16 ++-------------- tests/compiler/literals.json | 3 ++- tests/compiler/literals.ts | 2 +- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/resolver.ts b/src/resolver.ts index f53efbddab..151ee503f7 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -1520,20 +1520,8 @@ export class Resolver extends DiagnosticEmitter { ): Type { let intValue = expr.value; if (negate) { - console.log("+intValue: ", i64_to_string(intValue), - expr.range.source.text.substring(expr.range.start - 1, expr.range.end) - ); - console.log("-intValue: ", i64_to_string(i64_neg(intValue))); - // Check signed overflow - if ( - // x > 0 && x + i64.min > 0 -> underflow - (i64_gt(intValue, i64_zero) && - i64_gt(i64_add(intValue, i64_minimum), i64_zero)) || - // x < 0 && x + i64.max < 0 -> overflow - (i64_lt(intValue, i64_zero) && - i64_lt(i64_add(intValue, i64_maximum), i64_zero)) - ) { - // console.log(">>> overflow!", expr.range.source.text.substring(expr.range.start - 1)); + // x + i64.min > 0 -> underflow + if (i64_gt(i64_add(intValue, i64_minimum), i64_zero)) { this.error( DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, expr.range, diff --git a/tests/compiler/literals.json b/tests/compiler/literals.json index 3d8e58d1df..b77e56240c 100644 --- a/tests/compiler/literals.json +++ b/tests/compiler/literals.json @@ -2,7 +2,8 @@ "asc_flags": [ ], "stderr": [ - "ERROR 236: \"Literal '-9223372036854775809' does not fit into 'i64' or 'u64' types.\" in literals.ts(47,1+21)", + "AS236: Literal '-9223372036854775809' does not fit into 'i64' or 'u64' types.", + "AS236: Literal '-0x8000000000000001' does not fit into 'i64' or 'u64' types.", "EOF" ] } diff --git a/tests/compiler/literals.ts b/tests/compiler/literals.ts index f55efa0137..bcb9c5e8ef 100644 --- a/tests/compiler/literals.ts +++ b/tests/compiler/literals.ts @@ -45,6 +45,6 @@ false; // Signed underflow -9223372036854775809; -// -0x8000000000000001; +-0x8000000000000001; ERROR("EOF"); From 01bb598524180fac2721e9ad823a521cfb812833 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 11 Jul 2022 20:26:38 +0300 Subject: [PATCH 22/26] upd fixture --- tests/parser/literals.ts.fixture.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/parser/literals.ts.fixture.ts b/tests/parser/literals.ts.fixture.ts index 73e22a4e26..3f71d572ae 100644 --- a/tests/parser/literals.ts.fixture.ts +++ b/tests/parser/literals.ts.fixture.ts @@ -106,8 +106,6 @@ b; 17293822569102708735; 0; 0; --9223372036854775809; --9223372036854775809; 3; 4; 5; From e854892f58d000131db9a8c2bfb095b91d57e4e3 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 12 Jul 2022 07:06:02 +0300 Subject: [PATCH 23/26] refactor --- src/resolver.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/resolver.ts b/src/resolver.ts index 151ee503f7..9f8afa0b1e 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -1522,13 +1522,10 @@ export class Resolver extends DiagnosticEmitter { if (negate) { // x + i64.min > 0 -> underflow if (i64_gt(i64_add(intValue, i64_minimum), i64_zero)) { + let range = expr.range; this.error( DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types, - expr.range, - expr.range.source.text.substring( - expr.range.start - 1, - expr.range.end - ) + range, range.source.text.substring(range.start - 1, range.end) ); } intValue = i64_neg(intValue); From 277b41d8db114ec8d9e29642453bae5837419435 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 12 Jul 2022 07:17:51 +0300 Subject: [PATCH 24/26] more tests --- tests/compiler/literals.json | 1 + tests/compiler/literals.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/tests/compiler/literals.json b/tests/compiler/literals.json index b77e56240c..5a0469c44c 100644 --- a/tests/compiler/literals.json +++ b/tests/compiler/literals.json @@ -4,6 +4,7 @@ "stderr": [ "AS236: Literal '-9223372036854775809' does not fit into 'i64' or 'u64' types.", "AS236: Literal '-0x8000000000000001' does not fit into 'i64' or 'u64' types.", + "AS236: Literal '-0o1000000000000000000001' does not fit into 'i64' or 'u64' types.", "EOF" ] } diff --git a/tests/compiler/literals.ts b/tests/compiler/literals.ts index bcb9c5e8ef..2c7d6df5de 100644 --- a/tests/compiler/literals.ts +++ b/tests/compiler/literals.ts @@ -43,8 +43,14 @@ true; false; +0x8000000000000000; +-0x8000000000000000; +0o1000000000000000000000; +-0o1000000000000000000000; + // Signed underflow -9223372036854775809; -0x8000000000000001; +-0o1000000000000000000001; ERROR("EOF"); From c7889cfbdc8fd660ba0966e69d7cae3ff4f542cb Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 12 Jul 2022 13:08:50 +0300 Subject: [PATCH 25/26] simplify some i64 checks --- src/glue/wasm/i64.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/glue/wasm/i64.ts b/src/glue/wasm/i64.ts index 496d77bccc..e0c10fc685 100644 --- a/src/glue/wasm/i64.ts +++ b/src/glue/wasm/i64.ts @@ -241,19 +241,19 @@ function i64_signbit(value: i64): bool { // @ts-ignore: decorator @global @inline function i64_is_i8(value: i64): bool { - return value >= i8.MIN_VALUE && value <= i8.MAX_VALUE; + return value >= i8.MIN_VALUE && value <= i8.MAX_VALUE; } // @ts-ignore: decorator @global @inline function i64_is_i16(value: i64): bool { - return value >= i16.MIN_VALUE && value <= i16.MAX_VALUE; + return value >= i16.MIN_VALUE && value <= i16.MAX_VALUE; } // @ts-ignore: decorator @global @inline function i64_is_i32(value: i64): bool { - return value >= i32.MIN_VALUE && value <= i32.MAX_VALUE; + return value >= i32.MIN_VALUE && value <= i32.MAX_VALUE; } // @ts-ignore: decorator From 3559e4e531a4de1be6132724a99ef64be0aa3884 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 19 Jul 2022 19:41:18 +0300 Subject: [PATCH 26/26] move literal's fail cases to separate fixture --- tests/compiler/literals-errors.json | 10 ++++++++++ tests/compiler/literals-errors.ts | 6 ++++++ tests/compiler/literals.debug.wat | 8 ++++++-- tests/compiler/literals.json | 6 ------ tests/compiler/literals.ts | 7 ------- 5 files changed, 22 insertions(+), 15 deletions(-) create mode 100644 tests/compiler/literals-errors.json create mode 100644 tests/compiler/literals-errors.ts diff --git a/tests/compiler/literals-errors.json b/tests/compiler/literals-errors.json new file mode 100644 index 0000000000..5a0469c44c --- /dev/null +++ b/tests/compiler/literals-errors.json @@ -0,0 +1,10 @@ +{ + "asc_flags": [ + ], + "stderr": [ + "AS236: Literal '-9223372036854775809' does not fit into 'i64' or 'u64' types.", + "AS236: Literal '-0x8000000000000001' does not fit into 'i64' or 'u64' types.", + "AS236: Literal '-0o1000000000000000000001' does not fit into 'i64' or 'u64' types.", + "EOF" + ] +} diff --git a/tests/compiler/literals-errors.ts b/tests/compiler/literals-errors.ts new file mode 100644 index 0000000000..1317db1aa4 --- /dev/null +++ b/tests/compiler/literals-errors.ts @@ -0,0 +1,6 @@ +// Signed underflow +-9223372036854775809; +-0x8000000000000001; +-0o1000000000000000000001; + +ERROR("EOF"); diff --git a/tests/compiler/literals.debug.wat b/tests/compiler/literals.debug.wat index deb7ab7156..238ac11537 100644 --- a/tests/compiler/literals.debug.wat +++ b/tests/compiler/literals.debug.wat @@ -97,9 +97,13 @@ drop i32.const 0 drop - i64.const 9223372036854775807 + i64.const -9223372036854775808 drop - i64.const 9223372036854775807 + i64.const -9223372036854775808 + drop + i64.const -9223372036854775808 + drop + i64.const -9223372036854775808 drop ) (func $~start diff --git a/tests/compiler/literals.json b/tests/compiler/literals.json index 5a0469c44c..1bdd02b1be 100644 --- a/tests/compiler/literals.json +++ b/tests/compiler/literals.json @@ -1,10 +1,4 @@ { "asc_flags": [ - ], - "stderr": [ - "AS236: Literal '-9223372036854775809' does not fit into 'i64' or 'u64' types.", - "AS236: Literal '-0x8000000000000001' does not fit into 'i64' or 'u64' types.", - "AS236: Literal '-0o1000000000000000000001' does not fit into 'i64' or 'u64' types.", - "EOF" ] } diff --git a/tests/compiler/literals.ts b/tests/compiler/literals.ts index 2c7d6df5de..417e1a3773 100644 --- a/tests/compiler/literals.ts +++ b/tests/compiler/literals.ts @@ -47,10 +47,3 @@ false; -0x8000000000000000; 0o1000000000000000000000; -0o1000000000000000000000; - -// Signed underflow --9223372036854775809; --0x8000000000000001; --0o1000000000000000000001; - -ERROR("EOF");