-
-
Notifications
You must be signed in to change notification settings - Fork 696
feat: properly parse and resolve tuples #3018
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 21 commits
8ff13cd
19cacf9
4527d65
c53e659
8c480bb
6c869a5
b7dfb8f
98fe27f
39eb3f9
e8563bd
4b2a399
5cc7dce
5375b24
c8429ce
1ca3ad7
7c7f000
dda5084
5874329
e5ab232
5ef3d89
d59cbbc
301a564
a97c523
9cd4cb2
f45638a
729cb2d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
|
|
||
| import { | ||
| CommonFlags, | ||
| Feature, | ||
| LIBRARY_PREFIX, | ||
| PATH_DELIMITER | ||
| } from "./common"; | ||
|
|
@@ -42,6 +43,7 @@ import { | |
| TypeName, | ||
| NamedTypeNode, | ||
| FunctionTypeNode, | ||
| TupleTypeNode, | ||
| ArrowKind, | ||
|
|
||
| Expression, | ||
|
|
@@ -90,6 +92,7 @@ import { | |
|
|
||
| mangleInternalPath | ||
| } from "./ast"; | ||
| import { Options } from "./compiler"; | ||
|
|
||
| /** Represents a dependee. */ | ||
| class Dependee { | ||
|
|
@@ -118,7 +121,8 @@ export class Parser extends DiagnosticEmitter { | |
| sources: Source[]; | ||
| /** Current overridden module name. */ | ||
| currentModuleName: string | null = null; | ||
|
|
||
| /** Compiler options. (temporary. remove after multi-value/tuple support is finished) */ | ||
| options: Options | null = null; | ||
| /** Constructs a new parser. */ | ||
| constructor( | ||
| diagnostics: DiagnosticMessage[] | null = null, | ||
|
|
@@ -509,8 +513,14 @@ export class Parser extends DiagnosticEmitter { | |
|
|
||
| let type: TypeNode; | ||
|
|
||
| // 'readonly' Type | ||
| if (token == Token.Readonly) { | ||
| let innerType = this.parseType(tn, acceptParenthesized, suppressErrors); | ||
| if (!innerType) return null; | ||
| type = Node.createReadonlyType(innerType, tn.range(startPos, tn.pos)); | ||
|
|
||
| // '(' ... | ||
| if (token == Token.OpenParen) { | ||
| } else if (token == Token.OpenParen) { | ||
|
|
||
| // '(' FunctionSignature ')' | ||
| let isInnerParenthesized = tn.skip(Token.OpenParen); | ||
|
|
@@ -563,6 +573,42 @@ export class Parser extends DiagnosticEmitter { | |
| return null; | ||
| } | ||
|
|
||
| // '[' ((Identifier ':')? Type (',' (Identifier ':')? Type)*)? ']' | ||
| } else if (token == Token.OpenBracket && this.options && this.options!.hasFeature(Feature.MultiValue)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually tuple doesn't and is impossible to rely on mutli-value. declare function f(): [i32,i32];
function b() {
let a = f();
let b = a;
b[0] = 1;
assert(a[0] == 1);
}In this cases, multiple value cannot handle this case since it treat the whole tuple as a value instead of a heap object.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @HerrCai0907, I'll add full support for tuples in the future. Tuples will need to exist in two forms:
Then, depending on usage, tuples will be lifted and lowered from multi-value to tuple
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We’ve been discussing this for a long time, and it’s clear that the only way to ensure that tuples are properly converted to multivalues is to place a |
||
| let elements: TypeNode[] = []; | ||
| let elementNames: (IdentifierExpression | null)[] = []; | ||
| let hasElementNames = false; | ||
|
MaxGraey marked this conversation as resolved.
|
||
| if (!tn.skip(Token.CloseBracket)) { | ||
| do { | ||
| let elementName: IdentifierExpression | null = null; | ||
| let state = tn.mark(); | ||
| if (tn.skip(Token.Identifier)) { | ||
| let name = tn.readIdentifier(); | ||
| let nameRange = tn.range(); | ||
| if (tn.skip(Token.Colon)) { | ||
| elementName = Node.createIdentifierExpression(name, nameRange); | ||
| hasElementNames = true; | ||
| } else { | ||
| tn.reset(state); | ||
| } | ||
| } | ||
| let element = this.parseType(tn, true, suppressErrors); | ||
| if (!element) return null; | ||
| elements.push(element); | ||
| elementNames.push(elementName); | ||
| } while (tn.skip(Token.Comma)); | ||
| if (!tn.skip(Token.CloseBracket)) { | ||
| if (!suppressErrors) { | ||
| this.error( | ||
| DiagnosticCode._0_expected, | ||
| tn.range(tn.pos), "]" | ||
| ); | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| type = Node.createTupleType(elements, hasElementNames ? elementNames : null, false, tn.range(startPos, tn.pos)); | ||
|
|
||
| // 'void' | ||
| } else if (token == Token.Void) { | ||
| type = Node.createNamedType( | ||
|
|
@@ -4581,6 +4627,13 @@ function isCircularTypeAlias(name: string, type: TypeNode): bool { | |
| } | ||
| break; | ||
| } | ||
| case NodeKind.TupleType: { | ||
| let elements = (<TupleTypeNode>type).elements; | ||
| for (let i = 0, k = elements.length; i < k; i++) { | ||
| if (isCircularTypeAlias(name, elements[i])) return true; | ||
| } | ||
| break; | ||
| } | ||
| default: assert(false); | ||
| } | ||
| return false; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "asc_flags": [ | ||
| "--enable", "multi-value" | ||
| ], | ||
| "stderr": [ | ||
| "TS2456: Type alias 'Loop' circularly references itself.", | ||
| "1 parse error(s)" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| type Loop = [Loop, i32]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "asc_flags": [ | ||
| "--disable", "multi-value" | ||
| ], | ||
| "stderr": [ | ||
| "TS1110: Type expected.", | ||
| "3 parse error(s)" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| export function tupleDisabled(x: [left: i32, right: i32]): void {} | ||
| export type tupleTypeDisabled1 = [i32, i32]; | ||
| export type tupleTypeDisabled2 = []; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "asc_flags": [ | ||
| "--enable", "multi-value" | ||
| ], | ||
| "stderr": [ | ||
| "AS100: Not implemented: Tuple types", | ||
| "20 compile error(s)" | ||
|
JairusSW marked this conversation as resolved.
Outdated
|
||
| ] | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.