semantifold 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/build/src/backends/effects.js +3 -1
- package/build/src/backends/php.d.ts.map +1 -1
- package/build/src/backends/php.js +56 -3
- package/build/src/backends/python.js +11 -7
- package/build/src/backends/scalars.js +2 -2
- package/build/src/backends/shared.d.ts +2 -1
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +210 -8
- package/build/src/backends/writer.d.ts +18 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +40 -4
- package/build/src/frontends/java.d.ts +1 -1
- package/build/src/frontends/java.d.ts.map +1 -1
- package/build/src/frontends/java.js +14 -11
- package/build/src/frontends/javascript-typescript.d.ts +1 -1
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
- package/build/src/frontends/javascript-typescript.js +17 -17
- package/build/src/frontends/php.d.ts +5 -1
- package/build/src/frontends/php.d.ts.map +1 -1
- package/build/src/frontends/php.js +159 -31
- package/build/src/frontends/python.d.ts.map +1 -1
- package/build/src/frontends/python.js +37 -7
- package/build/src/frontends/ruby.d.ts +1 -1
- package/build/src/frontends/ruby.d.ts.map +1 -1
- package/build/src/frontends/ruby.js +12 -9
- package/build/src/frontends/types.d.ts +9 -2
- package/build/src/frontends/types.d.ts.map +1 -1
- package/build/src/frontends/types.js +26 -9
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +30 -6
- package/build/src/mapping.d.ts.map +1 -1
- package/build/src/mapping.js +4 -2
- package/build/src/semantic/effects.d.ts.map +1 -1
- package/build/src/semantic/effects.js +3 -1
- package/build/src/semantic/provenance.d.ts.map +1 -1
- package/build/src/semantic/provenance.js +37 -4
- package/build/src/semantic/types.d.ts +140 -9
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +37 -6
- package/build/src/semantic/validate.d.ts +31 -2
- package/build/src/semantic/validate.d.ts.map +1 -1
- package/build/src/semantic/validate.js +347 -28
- package/docs/adr-bounded-subtyping.md +180 -0
- package/docs/goals.md +1 -1
- package/docs/language-support.md +5 -4
- package/docs/testing.md +2 -2
- package/package.json +1 -1
- package/src/backends/effects.js +1 -0
- package/src/backends/php.js +56 -2
- package/src/backends/python.js +10 -4
- package/src/backends/scalars.js +1 -1
- package/src/backends/shared.js +211 -7
- package/src/backends/writer.js +41 -3
- package/src/frontends/java.js +13 -10
- package/src/frontends/javascript-typescript.js +16 -16
- package/src/frontends/php.js +175 -31
- package/src/frontends/python.js +39 -5
- package/src/frontends/ruby.js +11 -8
- package/src/frontends/types.js +26 -8
- package/src/language-registry.js +29 -5
- package/src/mapping.js +3 -1
- package/src/semantic/effects.js +1 -0
- package/src/semantic/provenance.js +34 -3
- package/src/semantic/types.js +39 -5
- package/src/semantic/validate.js +378 -27
package/src/frontends/python.js
CHANGED
|
@@ -5,8 +5,8 @@ import PythonLanguage from "tree-sitter-python"
|
|
|
5
5
|
import {missingType, parseFailure, SemantifoldDiagnostic, unsupportedSyntax} from "../diagnostic.js"
|
|
6
6
|
import {locationFromOffsets, moduleLocation, utf8ByteOffsetToUtf16Offset} from "../semantic/location.js"
|
|
7
7
|
import {withAdaptedOperation} from "../semantic/operators.js"
|
|
8
|
-
import {withParserRanges} from "../semantic/provenance.js"
|
|
9
|
-
import {hasOnlyUnicodeScalars} from "../semantic/scalars.js"
|
|
8
|
+
import {setParserRanges, withParserRanges} from "../semantic/provenance.js"
|
|
9
|
+
import {hasOnlyUnicodeScalars, voidType} from "../semantic/scalars.js"
|
|
10
10
|
import {requireSourceScalarType} from "./scalars.js"
|
|
11
11
|
|
|
12
12
|
const parser = new Parser()
|
|
@@ -171,6 +171,31 @@ function convertType(node, subject, ownerLocation, filename, source) {
|
|
|
171
171
|
return requireSourceScalarType("python", children[0].text, subject, ownerLocation, typeLocation)
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Converts one exact scalar or Task 005 `None` function-return annotation.
|
|
176
|
+
* @param {import("tree-sitter").SyntaxNode | null} node - Return type node, if present.
|
|
177
|
+
* @param {string} subject - Typed function return.
|
|
178
|
+
* @param {import("../semantic/types.js").SourceLocation} ownerLocation - Owning function.
|
|
179
|
+
* @param {string} filename - Source filename.
|
|
180
|
+
* @param {string} source - Complete source.
|
|
181
|
+
* @returns {import("../semantic/types.js").SemanticFunctionReturnType} Semantic return type.
|
|
182
|
+
*/
|
|
183
|
+
function convertReturnType(node, subject, ownerLocation, filename, source) {
|
|
184
|
+
if (!node) return missingType("python", subject, ownerLocation)
|
|
185
|
+
const typeLocation = nodeLocation(node, filename, source)
|
|
186
|
+
const children = node.namedChildren.filter((child) => child.type != "comment")
|
|
187
|
+
|
|
188
|
+
if (node.type == "type" && children.length == 1 && children[0].type == "none" && node.text == "None") {
|
|
189
|
+
const type = voidType()
|
|
190
|
+
|
|
191
|
+
setParserRanges(type, {type: typeLocation})
|
|
192
|
+
|
|
193
|
+
return type
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return convertType(node, subject, ownerLocation, filename, source)
|
|
197
|
+
}
|
|
198
|
+
|
|
174
199
|
/**
|
|
175
200
|
* Finds exactly one anonymous operator token directly owned by a parser node.
|
|
176
201
|
* @param {import("tree-sitter").SyntaxNode} node - Operation node.
|
|
@@ -434,7 +459,8 @@ function convertStatement(node, context, visible, filename, source) {
|
|
|
434
459
|
if (node.type == "return_statement") {
|
|
435
460
|
const expressions = node.namedChildren.filter((child) => child.type != "comment")
|
|
436
461
|
|
|
437
|
-
if (expressions.length
|
|
462
|
+
if (expressions.length > 1) return unsupportedSyntax("python", "return with more than one expression", location)
|
|
463
|
+
if (expressions.length == 0) return {kind: "ReturnStatement", location}
|
|
438
464
|
|
|
439
465
|
return {expression: convertExpression(expressions[0], filename, source), kind: "ReturnStatement", location}
|
|
440
466
|
}
|
|
@@ -444,8 +470,16 @@ function convertStatement(node, context, visible, filename, source) {
|
|
|
444
470
|
|
|
445
471
|
if (expressions.length != 1) return unsupportedSyntax("python", node.type, location)
|
|
446
472
|
if (expressions[0].type == "assignment") return convertAssignment(expressions[0], context, visible, filename, source)
|
|
473
|
+
if (expressions[0].type == "call") {
|
|
474
|
+
const calleeNode = requiredField(expressions[0], "function", filename, source)
|
|
475
|
+
|
|
476
|
+
if (calleeNode.type == "identifier" && calleeNode.text == "print") return convertPrint(expressions[0], filename, source, location)
|
|
477
|
+
const call = /** @type {import("../semantic/types.js").CallExpression} */ (convertExpression(expressions[0], filename, source))
|
|
478
|
+
|
|
479
|
+
return {expression: call, kind: /** @type {const} */ ("ExpressionStatement"), location}
|
|
480
|
+
}
|
|
447
481
|
|
|
448
|
-
return
|
|
482
|
+
return unsupportedSyntax("python", "expression statement other than assignment, print, or direct call", location)
|
|
449
483
|
}
|
|
450
484
|
|
|
451
485
|
return unsupportedSyntax("python", node.type, location)
|
|
@@ -611,7 +645,7 @@ function convertFunction(node, context, filename, source) {
|
|
|
611
645
|
location,
|
|
612
646
|
name,
|
|
613
647
|
parameters,
|
|
614
|
-
returnType:
|
|
648
|
+
returnType: convertReturnType(returnNode, `Function '${name}' return`, location, filename, source)
|
|
615
649
|
}, {name: nodeLocation(nameNode, filename, source)})
|
|
616
650
|
}
|
|
617
651
|
|
package/src/frontends/ruby.js
CHANGED
|
@@ -61,7 +61,7 @@ const referenceMethodHooks = new Set([
|
|
|
61
61
|
"respond_to_missing?", "send", "singleton_class", "size"
|
|
62
62
|
])
|
|
63
63
|
/** @typedef {{name: string, nameLocation: import("../semantic/types.js").SourceLocation, parameters: import("../semantic/types.js").Parameter[], returnType: import("../semantic/types.js").SemanticFunctionReturnType, typeParameters?: import("../semantic/types.js").TypeParameter[], location: import("../semantic/types.js").SourceLocation}} RubyFunctionSignature */
|
|
64
|
-
/** @typedef {{bindings: Map<string, import("../semantic/types.js").SemanticBindingType>, catchBindingNames?: Set<string>, classes: Map<string, import("../semantic/types.js").ClassDeclaration>, catchBindingNodes?: Map<string, import("../semantic/types.js").CatchBinding>, currentCatchBindingNode?: import("../semantic/types.js").CatchBinding, currentClass?: import("../semantic/types.js").ClassDeclaration, errorNames: Map<string, import("../semantic/types.js").ErrorDeclaration>, errors: Map<string, import("../semantic/types.js").ErrorDeclaration>, functions: Map<string, RubyFunctionSignature>, orderedMapDeclarations?: Set<object>, records: Map<string, import("../semantic/types.js").RecordDeclaration>, recordNames: Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>, loopDepth?: number, returnType?: import("../semantic/types.js").SemanticFunctionReturnType, typeParameters?: Map<string, import("../semantic/types.js").TypeParameter>}} RubyConversionContext */
|
|
64
|
+
/** @typedef {{bindings: Map<string, import("../semantic/types.js").SemanticBindingType>, catchBindingNames?: Set<string>, classes: Map<string, import("../semantic/types.js").ClassDeclaration>, catchBindingNodes?: Map<string, import("../semantic/types.js").CatchBinding>, currentCatchBindingNode?: import("../semantic/types.js").CatchBinding, currentClass?: import("../semantic/types.js").ClassDeclaration, errorNames: Map<string, import("../semantic/types.js").ErrorDeclaration>, errors: Map<string, import("../semantic/types.js").ErrorDeclaration>, functions: Map<string, RubyFunctionSignature>, orderedMapDeclarations?: Set<object>, records: Map<string, import("../semantic/types.js").RecordDeclaration>, recordNames: Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>, loopDepth?: number, returnType?: import("../semantic/types.js").SemanticFunctionReturnType, typeParameters?: Map<string, import("../semantic/types.js").TypeParameter>}} RubyConversionContext */
|
|
65
65
|
const rubyBinaryOperations = new Map([
|
|
66
66
|
["+", "Add"],
|
|
67
67
|
["-", "Subtract"],
|
|
@@ -357,6 +357,9 @@ function convertExpression(node, filename, source, context, expectedType, preser
|
|
|
357
357
|
reference: referenceType(/** @type {string} */ (declaration.id), nodeLocation(node.receiver, filename, source))},
|
|
358
358
|
{class: nodeLocation(node.receiver, filename, source)})
|
|
359
359
|
}
|
|
360
|
+
if (declaration.kind == "InterfaceDeclaration") {
|
|
361
|
+
return unsupportedSyntax("ruby", "construction of an interface", nodeLocation(node.receiver, filename, source))
|
|
362
|
+
}
|
|
360
363
|
if (declaration.kind == "EffectResourceDeclaration") {
|
|
361
364
|
return unsupportedSyntax("ruby", "owned resource construction", nodeLocation(node.receiver, filename, source))
|
|
362
365
|
}
|
|
@@ -817,7 +820,7 @@ function associatedComments(comments, node, source) {
|
|
|
817
820
|
* @param {LocalVariableWriteNode} node - Local write.
|
|
818
821
|
* @param {string} filename - Source filename.
|
|
819
822
|
* @param {string} source - Complete source.
|
|
820
|
-
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} recordNames - Nominal declarations by source name.
|
|
823
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} recordNames - Nominal declarations by source name.
|
|
821
824
|
* @param {Map<string, import("../semantic/types.js").TypeParameter>} [typeParameters] - Declaration-scoped parameters.
|
|
822
825
|
* @returns {{immutable: boolean, type: import("../semantic/types.js").SemanticValueType} | undefined} Metadata when present.
|
|
823
826
|
*/
|
|
@@ -1301,7 +1304,7 @@ function isImmediateCommentGap(gap) {
|
|
|
1301
1304
|
* @param {import("../semantic/types.js").SourceLocation} location - Source location.
|
|
1302
1305
|
* @param {string} source - Complete parser input.
|
|
1303
1306
|
* @param {import("../semantic/types.js").SourceLocation} [typeLocation] - Exact type comment token location.
|
|
1304
|
-
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} [recordNames] - Nominal declarations by source name.
|
|
1307
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} [recordNames] - Nominal declarations by source name.
|
|
1305
1308
|
* @param {Map<string, import("../semantic/types.js").TypeParameter>} [typeParameters] - Declaration-scoped parameters.
|
|
1306
1309
|
* @returns {import("../semantic/types.js").SemanticValueType} Semantic type.
|
|
1307
1310
|
*/
|
|
@@ -1315,7 +1318,7 @@ function convertType(sourceType, subject, location, source, typeLocation = locat
|
|
|
1315
1318
|
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
1316
1319
|
* @param {string} filename - Source filename.
|
|
1317
1320
|
* @param {string} source - Complete source.
|
|
1318
|
-
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} recordNames - Nominal declarations by source name.
|
|
1321
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} recordNames - Nominal declarations by source name.
|
|
1319
1322
|
* @param {string} ownerId - Stable function identity.
|
|
1320
1323
|
* @param {boolean} [allowBuiltinOutput] - Whether compiler authority admits the exact output facade function.
|
|
1321
1324
|
* @returns {RubyFunctionSignature} Semantic signature.
|
|
@@ -1380,7 +1383,7 @@ function convertFunctionSignature(node, comments, filename, source, recordNames,
|
|
|
1380
1383
|
* @param {DefNode} node - Prism definition.
|
|
1381
1384
|
* @param {RubyFunctionSignature} signature - Converted signature.
|
|
1382
1385
|
* @param {Map<string, RubyFunctionSignature>} functions - Module signatures.
|
|
1383
|
-
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} recordNames - Nominal declarations by source name.
|
|
1386
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} recordNames - Nominal declarations by source name.
|
|
1384
1387
|
* @param {Map<string, import("../semantic/types.js").RecordDeclaration>} records - Record declarations by identity.
|
|
1385
1388
|
* @param {Map<string, import("../semantic/types.js").ClassDeclaration>} classes - Reference classes by identity.
|
|
1386
1389
|
* @param {Map<string, import("../semantic/types.js").ErrorDeclaration>} errorNames - Error declarations by source name.
|
|
@@ -1491,7 +1494,7 @@ function convertRubyError(node, declaration, filename, source) {
|
|
|
1491
1494
|
* Converts the bounded Ruby reference-class profile.
|
|
1492
1495
|
* @param {ClassNode} node - Prism class declaration.
|
|
1493
1496
|
* @param {import("../semantic/types.js").ClassDeclaration} declaration - Predeclared class identity.
|
|
1494
|
-
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} nominalNames - Visible nominal declarations.
|
|
1497
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} nominalNames - Visible nominal declarations.
|
|
1495
1498
|
* @param {Map<string, import("../semantic/types.js").RecordDeclaration>} records - Records by identity.
|
|
1496
1499
|
* @param {Map<string, import("../semantic/types.js").ClassDeclaration>} classes - Classes by identity.
|
|
1497
1500
|
* @param {Map<string, RubyFunctionSignature>} functions - Top-level signatures.
|
|
@@ -1607,7 +1610,7 @@ function convertRubyReferenceClass(node, declaration, nominalNames, records, cla
|
|
|
1607
1610
|
* Converts one exact typed-reader/initializer/freeze Ruby record profile.
|
|
1608
1611
|
* @param {ClassNode} node - Prism class declaration.
|
|
1609
1612
|
* @param {import("../semantic/types.js").RecordDeclaration} declaration - Predeclared nominal identity.
|
|
1610
|
-
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} recordNames - Nominal declarations by name.
|
|
1613
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} recordNames - Nominal declarations by name.
|
|
1611
1614
|
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Parser-owned comments.
|
|
1612
1615
|
* @param {string} filename - Source filename.
|
|
1613
1616
|
* @param {string} source - Complete source.
|
|
@@ -1894,7 +1897,7 @@ export function parseRuby({capabilities = [], filename, source, program}) {
|
|
|
1894
1897
|
classDeclarations.findIndex((candidate) => candidate.name == declaration.name) != index)
|
|
1895
1898
|
|
|
1896
1899
|
if (reopened) return unsupportedSyntax("ruby", `reference class reopening '${reopened.name}'`, reopened.location)
|
|
1897
|
-
const recordNames = /** @type {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} */ (
|
|
1900
|
+
const recordNames = /** @type {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} */ (
|
|
1898
1901
|
new Map(program?.records ?? []))
|
|
1899
1902
|
for (const [name, declaration] of program?.classes ?? []) recordNames.set(name, declaration)
|
|
1900
1903
|
for (const resource of capabilities.flatMap(({resources}) => resources)) recordNames.set(resource.name, resource)
|
package/src/frontends/types.js
CHANGED
|
@@ -55,6 +55,7 @@ export function iterationBindingType(type, location) {
|
|
|
55
55
|
if (type.kind == "RecordType") return recordType(type.declarationId, location,
|
|
56
56
|
type.arguments?.map((argument) => iterationBindingType(argument, location)))
|
|
57
57
|
if (type.kind == "ReferenceType") return referenceType(type.declarationId, location)
|
|
58
|
+
if (type.kind == "InterfaceType") return interfaceType(type.declarationId, location)
|
|
58
59
|
if (type.kind == "OwnedResourceType") return ownedResourceType(type.resourceId, location)
|
|
59
60
|
if (type.kind == "OwnedReferenceType") return ownedReferenceType(type.declarationId, location)
|
|
60
61
|
|
|
@@ -166,6 +167,19 @@ export function referenceType(declarationId, location) {
|
|
|
166
167
|
return type
|
|
167
168
|
}
|
|
168
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Builds one nominal interface type with a parser-owned type range.
|
|
172
|
+
* @param {string} declarationId - Stable interface declaration identity.
|
|
173
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Complete type-expression range.
|
|
174
|
+
* @returns {import("../semantic/types.js").InterfaceType} Interface type.
|
|
175
|
+
*/
|
|
176
|
+
export function interfaceType(declarationId, location) {
|
|
177
|
+
const type = {declarationId, kind: /** @type {const} */ ("InterfaceType")}
|
|
178
|
+
|
|
179
|
+
setParserRanges(type, {type: location})
|
|
180
|
+
return type
|
|
181
|
+
}
|
|
182
|
+
|
|
169
183
|
/**
|
|
170
184
|
* Builds one compiler-owned resource type with a parser-owned name range.
|
|
171
185
|
* @param {string} resourceId - Stable capability resource identity.
|
|
@@ -392,7 +406,7 @@ function collectKnownSubstitutions(formal, actual, substitutions) {
|
|
|
392
406
|
* @param {"javascript" | "php" | "ruby"} input.language - Comment profile.
|
|
393
407
|
* @param {import("../semantic/types.js").SourceLocation} input.location - Exact type token range.
|
|
394
408
|
* @param {import("../semantic/types.js").SourceLocation} input.ownerLocation - Owning declaration range.
|
|
395
|
-
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} [input.records] - Available nominal declarations by source name.
|
|
409
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} [input.records] - Available nominal declarations by source name.
|
|
396
410
|
* @param {Map<string, import("../semantic/types.js").TypeParameter>} [input.typeParameters] - Declaration-scoped parameters by name.
|
|
397
411
|
* @param {string} input.source - Complete parser input for exact subranges.
|
|
398
412
|
* @param {string | undefined} input.sourceType - Exact comment-parser/Prism-owned type token.
|
|
@@ -451,9 +465,11 @@ export function documentedValueType({language, location, ownerLocation, records
|
|
|
451
465
|
|
|
452
466
|
if (directRecord?.id) return directRecord.kind == "ClassDeclaration"
|
|
453
467
|
? referenceType(directRecord.id, location)
|
|
454
|
-
: directRecord.kind == "
|
|
455
|
-
?
|
|
456
|
-
:
|
|
468
|
+
: directRecord.kind == "InterfaceDeclaration"
|
|
469
|
+
? interfaceType(directRecord.id, location)
|
|
470
|
+
: directRecord.kind == "EffectResourceDeclaration"
|
|
471
|
+
? ownedResourceType(directRecord.id, location)
|
|
472
|
+
: recordType(directRecord.id, location)
|
|
457
473
|
const directTypeParameter = typeParameters.get(unwrappedName)
|
|
458
474
|
|
|
459
475
|
if (directTypeParameter?.id) return typeVariable(directTypeParameter.id, location)
|
|
@@ -484,7 +500,7 @@ class DocumentedTypeParser {
|
|
|
484
500
|
* @param {string} text - Parser-owned type text.
|
|
485
501
|
* @param {import("../semantic/types.js").SourceLocation} location - Whole token location.
|
|
486
502
|
* @param {string} source - Complete source.
|
|
487
|
-
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} records - Available nominal declarations.
|
|
503
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration | import("../semantic/types.js").InterfaceDeclaration>} records - Available nominal declarations.
|
|
488
504
|
* @param {Map<string, import("../semantic/types.js").TypeParameter>} typeParameters - Declaration-scoped parameters.
|
|
489
505
|
*/
|
|
490
506
|
constructor(language, text, location, source, records, typeParameters) {
|
|
@@ -580,9 +596,11 @@ class DocumentedTypeParser {
|
|
|
580
596
|
if (record?.id && this.text[this.offset] != "<" && this.text[this.offset] != "[") {
|
|
581
597
|
const type = record.kind == "ClassDeclaration"
|
|
582
598
|
? referenceType(record.id, this.range(start, nameEnd))
|
|
583
|
-
: record.kind == "
|
|
584
|
-
?
|
|
585
|
-
:
|
|
599
|
+
: record.kind == "InterfaceDeclaration"
|
|
600
|
+
? interfaceType(record.id, this.range(start, nameEnd))
|
|
601
|
+
: record.kind == "EffectResourceDeclaration"
|
|
602
|
+
? ownedResourceType(record.id, this.range(start, nameEnd))
|
|
603
|
+
: recordType(record.id, this.range(start, nameEnd))
|
|
586
604
|
|
|
587
605
|
if (this.language == "ruby" && this.consume("?")) {
|
|
588
606
|
return optionalType(type, this.range(start, this.offset), this.typeRange(type, start, nameEnd))
|
package/src/language-registry.js
CHANGED
|
@@ -169,6 +169,7 @@ export function createLanguageRegistry(candidateRecords) {
|
|
|
169
169
|
}
|
|
170
170
|
if (typeof candidate.roundTrip != "boolean") invalidRegistry(`Registry record '${id}' requires a Boolean round-trip declaration.`, id)
|
|
171
171
|
const featuresCandidate = candidate.features ?? {
|
|
172
|
+
boundedSubtyping: false,
|
|
172
173
|
closedRecords: false,
|
|
173
174
|
conditionControlledLoops: false,
|
|
174
175
|
conditionalExpressions: false,
|
|
@@ -185,7 +186,8 @@ export function createLanguageRegistry(candidateRecords) {
|
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
if (!isPlainObject(featuresCandidate) ||
|
|
188
|
-
Object.keys(featuresCandidate).sort().join(",") != "closedRecords,conditionControlledLoops,conditionalExpressions,effectfulCapabilitiesAndResources,generalFunctionsAndCalls,immutableCollections,optionalValues,orderedListIteration,orderedMapIteration,referenceClasses,stringInterpolation,typeParametersAndGenerics,typedErrors" ||
|
|
189
|
+
Object.keys(featuresCandidate).sort().join(",") != "boundedSubtyping,closedRecords,conditionControlledLoops,conditionalExpressions,effectfulCapabilitiesAndResources,generalFunctionsAndCalls,immutableCollections,optionalValues,orderedListIteration,orderedMapIteration,referenceClasses,stringInterpolation,typeParametersAndGenerics,typedErrors" ||
|
|
190
|
+
typeof featuresCandidate.boundedSubtyping != "boolean" ||
|
|
189
191
|
typeof featuresCandidate.closedRecords != "boolean" ||
|
|
190
192
|
typeof featuresCandidate.conditionControlledLoops != "boolean" ||
|
|
191
193
|
typeof featuresCandidate.conditionalExpressions != "boolean" ||
|
|
@@ -196,12 +198,14 @@ export function createLanguageRegistry(candidateRecords) {
|
|
|
196
198
|
typeof featuresCandidate.orderedListIteration != "boolean" ||
|
|
197
199
|
typeof featuresCandidate.orderedMapIteration != "boolean" ||
|
|
198
200
|
typeof featuresCandidate.referenceClasses != "boolean" ||
|
|
201
|
+
(featuresCandidate.boundedSubtyping && !featuresCandidate.referenceClasses) ||
|
|
199
202
|
typeof featuresCandidate.stringInterpolation != "boolean" ||
|
|
200
203
|
typeof featuresCandidate.typedErrors != "boolean" ||
|
|
201
204
|
typeof featuresCandidate.typeParametersAndGenerics != "boolean") {
|
|
202
205
|
invalidRegistry(`Registry record '${id}' has an invalid feature declaration.`, id)
|
|
203
206
|
}
|
|
204
207
|
const features = deepFreeze(/** @type {import("./semantic/types.js").LanguageFeatureCapabilities} */ ({
|
|
208
|
+
boundedSubtyping: featuresCandidate.boundedSubtyping,
|
|
205
209
|
closedRecords: featuresCandidate.closedRecords,
|
|
206
210
|
conditionControlledLoops: featuresCandidate.conditionControlledLoops,
|
|
207
211
|
conditionalExpressions: featuresCandidate.conditionalExpressions,
|
|
@@ -541,6 +545,22 @@ const records = [
|
|
|
541
545
|
acceptance: {stages: ["parse", "generate", "compile", "execute"], toolchains: ["python"]},
|
|
542
546
|
check: {factory: createPythonCheckPlan, stages: ["compile"], toolchains: ["python"]},
|
|
543
547
|
defaultFilename: "program.py",
|
|
548
|
+
features: {
|
|
549
|
+
boundedSubtyping: false,
|
|
550
|
+
closedRecords: false,
|
|
551
|
+
conditionControlledLoops: false,
|
|
552
|
+
conditionalExpressions: false,
|
|
553
|
+
effectfulCapabilitiesAndResources: false,
|
|
554
|
+
generalFunctionsAndCalls: true,
|
|
555
|
+
immutableCollections: false,
|
|
556
|
+
optionalValues: false,
|
|
557
|
+
orderedListIteration: false,
|
|
558
|
+
orderedMapIteration: false,
|
|
559
|
+
referenceClasses: false,
|
|
560
|
+
stringInterpolation: false,
|
|
561
|
+
typedErrors: false,
|
|
562
|
+
typeParametersAndGenerics: false
|
|
563
|
+
},
|
|
544
564
|
frontend: pythonFrontend,
|
|
545
565
|
id: "python",
|
|
546
566
|
mediaType: "text/x-python",
|
|
@@ -582,6 +602,7 @@ const records = [
|
|
|
582
602
|
optionalValues: false,
|
|
583
603
|
orderedListIteration: false,
|
|
584
604
|
orderedMapIteration: false,
|
|
605
|
+
boundedSubtyping: false,
|
|
585
606
|
referenceClasses: false,
|
|
586
607
|
typedErrors: false,
|
|
587
608
|
typeParametersAndGenerics: false
|
|
@@ -621,6 +642,7 @@ const records = [
|
|
|
621
642
|
optionalValues: false,
|
|
622
643
|
orderedListIteration: false,
|
|
623
644
|
orderedMapIteration: false,
|
|
645
|
+
boundedSubtyping: false,
|
|
624
646
|
referenceClasses: false,
|
|
625
647
|
typedErrors: false,
|
|
626
648
|
typeParametersAndGenerics: false
|
|
@@ -646,6 +668,7 @@ const records = [
|
|
|
646
668
|
optionalValues: false,
|
|
647
669
|
orderedListIteration: false,
|
|
648
670
|
orderedMapIteration: false,
|
|
671
|
+
boundedSubtyping: false,
|
|
649
672
|
referenceClasses: false,
|
|
650
673
|
typedErrors: false,
|
|
651
674
|
typeParametersAndGenerics: false
|
|
@@ -661,7 +684,7 @@ const records = [
|
|
|
661
684
|
artifactMultiplicity: "multiple",
|
|
662
685
|
binaryBackend: generateBrowserWasm,
|
|
663
686
|
defaultFilename: "program.wasm",
|
|
664
|
-
features: {closedRecords: false, conditionControlledLoops: false, conditionalExpressions: false, stringInterpolation: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
687
|
+
features: {boundedSubtyping: false, closedRecords: false, conditionControlledLoops: false, conditionalExpressions: false, stringInterpolation: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
665
688
|
id: "wasm",
|
|
666
689
|
mapping: {binaryRanges: true, richText: true, sourceMapV3: true},
|
|
667
690
|
mediaType: "application/wasm",
|
|
@@ -671,7 +694,7 @@ const records = [
|
|
|
671
694
|
acceptance: {stages: ["generate", "compile", "validate", "instantiate", "execute"], toolchains: ["android"]},
|
|
672
695
|
applicationBackend: generateAndroidApplication,
|
|
673
696
|
artifactMultiplicity: "multiple",
|
|
674
|
-
features: {closedRecords: false, conditionControlledLoops: false, conditionalExpressions: false, stringInterpolation: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
697
|
+
features: {boundedSubtyping: false, closedRecords: false, conditionControlledLoops: false, conditionalExpressions: false, stringInterpolation: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
675
698
|
id: "android",
|
|
676
699
|
mapping: {binaryRanges: true, richText: true, sourceMapV3: true},
|
|
677
700
|
roundTrip: false
|
|
@@ -680,7 +703,7 @@ const records = [
|
|
|
680
703
|
acceptance: {stages: ["generate"], toolchains: []},
|
|
681
704
|
applicationBackend: generateIosApplication,
|
|
682
705
|
artifactMultiplicity: "multiple",
|
|
683
|
-
features: {closedRecords: false, conditionControlledLoops: false, conditionalExpressions: false, stringInterpolation: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
706
|
+
features: {boundedSubtyping: false, closedRecords: false, conditionControlledLoops: false, conditionalExpressions: false, stringInterpolation: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
684
707
|
id: "ios",
|
|
685
708
|
mapping: {binaryRanges: true, richText: true, sourceMapV3: true},
|
|
686
709
|
roundTrip: false
|
|
@@ -689,7 +712,7 @@ const records = [
|
|
|
689
712
|
acceptance: {stages: ["generate", "restore", "compile", "validate", "instantiate", "execute"], toolchains: ["flutter", "android"]},
|
|
690
713
|
applicationBackend: generateFlutterApplication,
|
|
691
714
|
artifactMultiplicity: "multiple",
|
|
692
|
-
features: {closedRecords: false, conditionControlledLoops: false, conditionalExpressions: false, stringInterpolation: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
715
|
+
features: {boundedSubtyping: false, closedRecords: false, conditionControlledLoops: false, conditionalExpressions: false, stringInterpolation: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
693
716
|
id: "flutter",
|
|
694
717
|
mapping: {binaryRanges: true, richText: true, sourceMapV3: true},
|
|
695
718
|
roundTrip: false
|
|
@@ -712,6 +735,7 @@ function language(values) {
|
|
|
712
735
|
return {
|
|
713
736
|
artifactMultiplicity: "single",
|
|
714
737
|
features: {
|
|
738
|
+
boundedSubtyping: String(values.id) == "php",
|
|
715
739
|
closedRecords: ["php", "ruby", "javascript", "typescript", "java"].includes(String(values.id)),
|
|
716
740
|
conditionControlledLoops: ["php", "ruby", "javascript", "typescript", "java"].includes(String(values.id)),
|
|
717
741
|
conditionalExpressions: ["php", "ruby", "javascript", "typescript", "java"].includes(String(values.id)),
|
package/src/mapping.js
CHANGED
|
@@ -764,7 +764,7 @@ export function validateMapping(value) {
|
|
|
764
764
|
for (const symbol of mapping.symbols) {
|
|
765
765
|
if (!symbol || typeof symbol != "object" || typeof symbol.id != "string" || symbol.id.length == 0 || symbolIds.has(symbol.id) ||
|
|
766
766
|
typeof symbol.name != "string" || symbol.name.length == 0 ||
|
|
767
|
-
!["capability", "resource", "failure", "operation", "record", "class", "error", "field", "constructor", "method", "function", "typeParameter", "parameter", "local", "iteration", "catch"].includes(symbol.kind) ||
|
|
767
|
+
!["capability", "resource", "failure", "operation", "record", "interface", "interfaceMethod", "class", "error", "field", "constructor", "method", "function", "typeParameter", "parameter", "local", "iteration", "catch"].includes(symbol.kind) ||
|
|
768
768
|
!nodeIds.has(symbol.declarationNodeId) || !Array.isArray(symbol.references) ||
|
|
769
769
|
symbol.semanticDeclarationId !== undefined && (typeof symbol.semanticDeclarationId != "string" || !(
|
|
770
770
|
symbol.kind == "function" && /^(?:[a-z][a-z0-9._-]*#)?function:[0-9]+$/u.test(symbol.semanticDeclarationId) ||
|
|
@@ -774,6 +774,8 @@ export function validateMapping(value) {
|
|
|
774
774
|
symbol.kind == "field" && /^(?:[a-z][a-z0-9._-]*#)?(?:record|class):[0-9]+:field:[0-9]+$/u.test(symbol.semanticDeclarationId) ||
|
|
775
775
|
symbol.kind == "constructor" && /^(?:[a-z][a-z0-9._-]*#)?class:[0-9]+:constructor$/u.test(symbol.semanticDeclarationId) ||
|
|
776
776
|
symbol.kind == "method" && /^(?:[a-z][a-z0-9._-]*#)?class:[0-9]+:method:[0-9]+$/u.test(symbol.semanticDeclarationId) ||
|
|
777
|
+
symbol.kind == "interface" && /^(?:[a-z][a-z0-9._-]*#)?interface:[0-9]+$/u.test(symbol.semanticDeclarationId) ||
|
|
778
|
+
symbol.kind == "interfaceMethod" && /^(?:[a-z][a-z0-9._-]*#)?interface:[0-9]+:method:[0-9]+$/u.test(symbol.semanticDeclarationId) ||
|
|
777
779
|
symbol.kind == "typeParameter" && /^(?:[a-z][a-z0-9._-]*#)?(?:function|record):[0-9]+:type:[0-9]+$/u.test(symbol.semanticDeclarationId) ||
|
|
778
780
|
symbol.kind == "capability" && /^(?:module:[0-9]+\/)?capability:[0-9]+$/u.test(symbol.semanticDeclarationId) ||
|
|
779
781
|
symbol.kind == "resource" && /^(?:module:[0-9]+\/)?capability:[0-9]+\/resource:[0-9]+$/u.test(symbol.semanticDeclarationId) ||
|
package/src/semantic/effects.js
CHANGED
|
@@ -326,6 +326,7 @@ function typeIdentity(type) {
|
|
|
326
326
|
if (type.kind == "RecordType") return {arguments: type.arguments?.map((argument) =>
|
|
327
327
|
/** @type {import("./types.js").SemanticTypeIdentity} */ (typeIdentity(argument))), declarationId: type.declarationId, kind: type.kind}
|
|
328
328
|
if (type.kind == "ReferenceType") return {declarationId: type.declarationId, kind: type.kind}
|
|
329
|
+
if (type.kind == "InterfaceType") return {declarationId: type.declarationId, kind: type.kind}
|
|
329
330
|
return {kind: type.kind, parameterId: type.parameterId}
|
|
330
331
|
}
|
|
331
332
|
|
|
@@ -492,6 +492,7 @@ export function semanticEntries(module) {
|
|
|
492
492
|
node.imports.forEach((child, index) => visit(child, `/imports/${index}`, location))
|
|
493
493
|
}
|
|
494
494
|
;(node.records ?? []).forEach((child, index) => visit(child, `/records/${index}`, location))
|
|
495
|
+
;(node.interfaces ?? []).forEach((child, index) => visit(child, `/interfaces/${index}`, location))
|
|
495
496
|
if (!("sourceFilename" in node) || Reflect.get(node, "stdlibFacade") !== undefined) {
|
|
496
497
|
;(node.classes ?? []).forEach((child, index) => visit(child, `/classes/${index}`, location))
|
|
497
498
|
}
|
|
@@ -512,7 +513,14 @@ export function semanticEntries(module) {
|
|
|
512
513
|
} else if (node.kind == "EffectOperationDeclaration") {
|
|
513
514
|
node.parameters.forEach((child, index) => visit(child.type, `${path}/parameters/${index}/type`, location))
|
|
514
515
|
visit(node.returnType, `${path}/returnType`, location)
|
|
516
|
+
} else if (node.kind == "InterfaceDeclaration") {
|
|
517
|
+
(node.extends ?? []).forEach((child, index) => visit(child, `${path}/extends/${index}`, location))
|
|
518
|
+
node.methods.forEach((child, index) => visit(child, `${path}/methods/${index}`, location))
|
|
519
|
+
} else if (node.kind == "InterfaceMethodDeclaration") {
|
|
520
|
+
node.parameters.forEach((child, index) => visit(child.type, `${path}/parameters/${index}/type`, location))
|
|
521
|
+
visit(node.returnType, `${path}/returnType`, location)
|
|
515
522
|
} else if (node.kind == "ClassDeclaration") {
|
|
523
|
+
(node.implements ?? []).forEach((child, index) => visit(child, `${path}/implements/${index}`, location))
|
|
516
524
|
node.fields.forEach((child, index) => visit(child, `${path}/fields/${index}`, location))
|
|
517
525
|
visit(node.constructor, `${path}/constructor`, location)
|
|
518
526
|
node.methods.forEach((child, index) => visit(child, `${path}/methods/${index}`, location))
|
|
@@ -665,6 +673,10 @@ function resolveSymbols(module, records) {
|
|
|
665
673
|
/** @type {Map<string, string>} */
|
|
666
674
|
const fieldSymbols = new Map()
|
|
667
675
|
/** @type {Map<string, string>} */
|
|
676
|
+
const interfaceSymbols = new Map()
|
|
677
|
+
/** @type {Map<string, string>} */
|
|
678
|
+
const interfaceMethodSymbols = new Map()
|
|
679
|
+
/** @type {Map<string, string>} */
|
|
668
680
|
const classSymbols = new Map()
|
|
669
681
|
/** @type {Map<string, string>} */
|
|
670
682
|
const constructorSymbols = new Map()
|
|
@@ -724,11 +736,29 @@ function resolveSymbols(module, records) {
|
|
|
724
736
|
if (declaration.id) errorSymbols.set(declaration.id, symbol)
|
|
725
737
|
}
|
|
726
738
|
|
|
739
|
+
for (const [index, declaration] of (module.interfaces ?? []).entries()) {
|
|
740
|
+
const declarationPath = `/interfaces/${index}`
|
|
741
|
+
const interfaceSymbol = declare(declaration, declaration.name, "interface", declarationPath)
|
|
742
|
+
|
|
743
|
+
if (declaration.id) interfaceSymbols.set(declaration.id, interfaceSymbol)
|
|
744
|
+
for (const [extendsIndex, parent] of (declaration.extends ?? []).entries()) {
|
|
745
|
+
visitType(parent, `${declarationPath}/extends/${extendsIndex}`)
|
|
746
|
+
}
|
|
747
|
+
for (const [methodIndex, method] of declaration.methods.entries()) {
|
|
748
|
+
const symbol = declare(method, method.name, "interfaceMethod", `${declarationPath}/methods/${methodIndex}`)
|
|
749
|
+
|
|
750
|
+
if (method.id) interfaceMethodSymbols.set(method.id, symbol)
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
727
754
|
for (const [index, declaration] of (module.classes ?? []).entries()) {
|
|
728
755
|
const declarationPath = `/classes/${index}`
|
|
729
756
|
const classSymbol = declare(declaration, declaration.name, "class", declarationPath)
|
|
730
757
|
|
|
731
758
|
if (declaration.id) classSymbols.set(declaration.id, classSymbol)
|
|
759
|
+
for (const [implementsIndex, implemented] of (declaration.implements ?? []).entries()) {
|
|
760
|
+
visitType(implemented, `${declarationPath}/implements/${implementsIndex}`)
|
|
761
|
+
}
|
|
732
762
|
for (const [fieldIndex, field] of declaration.fields.entries()) {
|
|
733
763
|
const symbol = declare(field, field.name, "field", `${declarationPath}/fields/${fieldIndex}`)
|
|
734
764
|
|
|
@@ -806,7 +836,7 @@ function resolveSymbols(module, records) {
|
|
|
806
836
|
|
|
807
837
|
/**
|
|
808
838
|
* Declares one canonical symbol.
|
|
809
|
-
* @param {import("./types.js").EffectCapabilityDeclaration | import("./types.js").EffectResourceDeclaration | import("./types.js").EffectFailureDeclaration | import("./types.js").EffectOperationDeclaration | import("./types.js").RecordDeclaration | import("./types.js").ClassDeclaration | import("./types.js").ErrorDeclaration | import("./types.js").RecordField | import("./types.js").PrivateField | import("./types.js").ConstructorDeclaration | import("./types.js").MethodDeclaration | import("./types.js").FunctionDeclaration | import("./types.js").TypeParameter | import("./types.js").Parameter | import("./types.js").LocalDeclaration | import("./types.js").ValueBinding | import("./types.js").CatchBinding} node - Declaration.
|
|
839
|
+
* @param {import("./types.js").EffectCapabilityDeclaration | import("./types.js").EffectResourceDeclaration | import("./types.js").EffectFailureDeclaration | import("./types.js").EffectOperationDeclaration | import("./types.js").RecordDeclaration | import("./types.js").ClassDeclaration | import("./types.js").InterfaceDeclaration | import("./types.js").InterfaceMethodDeclaration | import("./types.js").ErrorDeclaration | import("./types.js").RecordField | import("./types.js").PrivateField | import("./types.js").ConstructorDeclaration | import("./types.js").MethodDeclaration | import("./types.js").FunctionDeclaration | import("./types.js").TypeParameter | import("./types.js").Parameter | import("./types.js").LocalDeclaration | import("./types.js").ValueBinding | import("./types.js").CatchBinding} node - Declaration.
|
|
810
840
|
* @param {string} name - Symbol name.
|
|
811
841
|
* @param {import("./types.js").SemanticSymbolKind} kind - Symbol kind.
|
|
812
842
|
* @param {string} path - Declaration occurrence path.
|
|
@@ -828,7 +858,7 @@ function resolveSymbols(module, records) {
|
|
|
828
858
|
location,
|
|
829
859
|
name,
|
|
830
860
|
references: [],
|
|
831
|
-
...(["capability", "resource", "failure", "operation", "record", "class", "error", "field", "constructor", "method", "function", "typeParameter"].includes(kind)
|
|
861
|
+
...(["capability", "resource", "failure", "operation", "record", "interface", "interfaceMethod", "class", "error", "field", "constructor", "method", "function", "typeParameter"].includes(kind)
|
|
832
862
|
? {semanticDeclarationId: /** @type {{id?: string}} */ (node).id}
|
|
833
863
|
: {})
|
|
834
864
|
})
|
|
@@ -1009,6 +1039,7 @@ function resolveSymbols(module, records) {
|
|
|
1009
1039
|
for (const [index, argument] of (type.arguments ?? []).entries()) visitType(argument, `${path}/arguments/${index}`)
|
|
1010
1040
|
}
|
|
1011
1041
|
else if (type.kind == "ErrorType") reference(type, errorSymbols.get(type.declarationId), "type", path)
|
|
1042
|
+
else if (type.kind == "InterfaceType") reference(type, interfaceSymbols.get(type.declarationId), "type", path)
|
|
1012
1043
|
else if (type.kind == "ReferenceType" || type.kind == "OwnedReferenceType") reference(type, classSymbols.get(type.declarationId), "type", path)
|
|
1013
1044
|
else if (type.kind == "OwnedResourceType") reference(type, resourceSymbols.get(type.resourceId), "type", path)
|
|
1014
1045
|
else if (type.kind == "ListType") visitType(type.elementType, `${path}/elementType`)
|
|
@@ -1020,7 +1051,7 @@ function resolveSymbols(module, records) {
|
|
|
1020
1051
|
|
|
1021
1052
|
/**
|
|
1022
1053
|
* Attaches one resolved symbol reference.
|
|
1023
|
-
* @param {import("./types.js").IdentifierExpression | import("./types.js").ReceiverExpression | import("./types.js").CallExpression | import("./types.js").EffectCallExpression | import("./types.js").MethodCallExpression | import("./types.js").TypeVariableReference | import("./types.js").RecordType | import("./types.js").ReferenceType | import("./types.js").OwnedReferenceType | import("./types.js").OwnedResourceType | import("./types.js").RecordConstruction | import("./types.js").ReferenceConstruction | import("./types.js").MemberRead | import("./types.js").PrivateFieldRead | import("./types.js").PrivateFieldWriteStatement | import("./types.js").RethrowStatement | import("./types.js").ErrorType | import("./types.js").ErrorConstruction} node - Reference node.
|
|
1054
|
+
* @param {import("./types.js").IdentifierExpression | import("./types.js").ReceiverExpression | import("./types.js").CallExpression | import("./types.js").EffectCallExpression | import("./types.js").MethodCallExpression | import("./types.js").TypeVariableReference | import("./types.js").RecordType | import("./types.js").ReferenceType | import("./types.js").InterfaceType | import("./types.js").OwnedReferenceType | import("./types.js").OwnedResourceType | import("./types.js").RecordConstruction | import("./types.js").ReferenceConstruction | import("./types.js").MemberRead | import("./types.js").PrivateFieldRead | import("./types.js").PrivateFieldWriteStatement | import("./types.js").RethrowStatement | import("./types.js").ErrorType | import("./types.js").ErrorConstruction} node - Reference node.
|
|
1024
1055
|
* @param {string | undefined} symbolId - Resolved symbol.
|
|
1025
1056
|
* @param {"type" | "construct" | "member" | "read" | "write" | "call"} role - Reference role.
|
|
1026
1057
|
* @param {string} path - Reference occurrence path.
|
package/src/semantic/types.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
/** @typedef {SemanticTypeName | "void"} FunctionReturnTypeName */
|
|
9
9
|
/** @typedef {"IntegerNegate" | "BooleanNot"} SemanticUnaryOperation */
|
|
10
10
|
/** @typedef {"IntegerAdd" | "IntegerSubtract" | "IntegerMultiply" | "BooleanAnd" | "BooleanOr" | "IntegerEqual" | "IntegerNotEqual" | "BooleanEqual" | "BooleanNotEqual" | "StringEqual" | "StringNotEqual" | "IntegerLessThan" | "IntegerLessThanOrEqual" | "IntegerGreaterThan" | "IntegerGreaterThanOrEqual" | "StringConcat"} SemanticBinaryOperation */
|
|
11
|
-
/** @typedef {"capability" | "resource" | "failure" | "operation" | "record" | "class" | "error" | "field" | "constructor" | "method" | "function" | "typeParameter" | "parameter" | "local" | "iteration" | "catch"} SemanticSymbolKind */
|
|
12
|
-
/** @typedef {"record" | "class" | "error" | "function"} SemanticDeclarationKind */
|
|
11
|
+
/** @typedef {"capability" | "resource" | "failure" | "operation" | "record" | "interface" | "interfaceMethod" | "class" | "error" | "field" | "constructor" | "method" | "function" | "typeParameter" | "parameter" | "local" | "iteration" | "catch"} SemanticSymbolKind */
|
|
12
|
+
/** @typedef {"record" | "interface" | "class" | "error" | "function"} SemanticDeclarationKind */
|
|
13
13
|
/** @typedef {"declaration" | "type" | "construct" | "member" | "read" | "write" | "call"} SemanticSymbolRole */
|
|
14
14
|
/** @typedef {"parse" | "generate" | "restore" | "compile" | "link" | "validate" | "instantiate" | "execute"} AcceptanceStage */
|
|
15
15
|
/** @typedef {"entry" | "source" | "manifest" | "support" | "mapping" | "resource" | "loader"} GeneratedArtifactRole */
|
|
@@ -186,6 +186,7 @@
|
|
|
186
186
|
* @property {boolean} typedErrors - Task 011 nominal unchecked errors, raises, and exact typed catches.
|
|
187
187
|
* @property {boolean} typeParametersAndGenerics - Task 012 invariant unbounded type parameters and closed generic applications.
|
|
188
188
|
* @property {boolean} referenceClasses - Task 033 nominal reference classes, private instance state, exact constructors, and receiver methods.
|
|
189
|
+
* @property {boolean} boundedSubtyping - Task 048 nominal interfaces with exact implementation contracts and implicit upcast (requires referenceClasses).
|
|
189
190
|
* @property {boolean} effectfulCapabilitiesAndResources - Task 034 authorized host effects, typed failures, and owned resources.
|
|
190
191
|
*/
|
|
191
192
|
|
|
@@ -700,7 +701,14 @@
|
|
|
700
701
|
* @property {SemanticNodeSourceProvenance} [sourceProvenance] - Parser-owned type-name range.
|
|
701
702
|
*/
|
|
702
703
|
|
|
703
|
-
/**
|
|
704
|
+
/**
|
|
705
|
+
* @typedef InterfaceType
|
|
706
|
+
* @property {"InterfaceType"} kind - Nominal bounded-subtyping interface type discriminator.
|
|
707
|
+
* @property {string} declarationId - Stable module-local interface declaration identity.
|
|
708
|
+
* @property {SemanticNodeSourceProvenance} [sourceProvenance] - Parser-owned type-name range.
|
|
709
|
+
*/
|
|
710
|
+
|
|
711
|
+
/** @typedef {TypeReference | TypeVariableReference | ListType | MapType | OrderedMapType | OptionalType | RecordType | ReferenceType | OwnedResourceType | OwnedReferenceType | InterfaceType} SemanticValueType */
|
|
704
712
|
/** @typedef {SemanticValueType | ErrorType} SemanticBindingType */
|
|
705
713
|
|
|
706
714
|
/**
|
|
@@ -712,7 +720,7 @@
|
|
|
712
720
|
|
|
713
721
|
/** @typedef {SemanticValueType | FunctionReturnTypeReference} SemanticFunctionReturnType */
|
|
714
722
|
|
|
715
|
-
/** @typedef {SemanticTypeName | {kind: "TypeVariableReference", parameterId: string} | {kind: "ListType", elementType: SemanticTypeIdentity} | {kind: "MapType", keyType: SemanticTypeIdentity, valueType: SemanticTypeIdentity} | {kind: "OrderedMapType", keyType: SemanticTypeIdentity, valueType: SemanticTypeIdentity, order: "insertion"} | {kind: "OptionalType", valueType: SemanticTypeIdentity} | {kind: "RecordType", declarationId: string, arguments?: SemanticTypeIdentity[]} | {kind: "ReferenceType", declarationId: string} | {kind: "OwnedResourceType", resourceId: string} | {kind: "OwnedReferenceType", declarationId: string}} SemanticTypeIdentity */
|
|
723
|
+
/** @typedef {SemanticTypeName | {kind: "TypeVariableReference", parameterId: string} | {kind: "ListType", elementType: SemanticTypeIdentity} | {kind: "MapType", keyType: SemanticTypeIdentity, valueType: SemanticTypeIdentity} | {kind: "OrderedMapType", keyType: SemanticTypeIdentity, valueType: SemanticTypeIdentity, order: "insertion"} | {kind: "OptionalType", valueType: SemanticTypeIdentity} | {kind: "RecordType", declarationId: string, arguments?: SemanticTypeIdentity[]} | {kind: "ReferenceType", declarationId: string} | {kind: "OwnedResourceType", resourceId: string} | {kind: "OwnedReferenceType", declarationId: string} | {kind: "InterfaceType", declarationId: string}} SemanticTypeIdentity */
|
|
716
724
|
/** @typedef {SemanticTypeIdentity | "void"} FunctionReturnTypeIdentity */
|
|
717
725
|
|
|
718
726
|
/**
|
|
@@ -1345,10 +1353,33 @@
|
|
|
1345
1353
|
* @property {Block} body - Method body.
|
|
1346
1354
|
* @property {readonly ["host"]} [effects] - Inferred checked host-effect fact.
|
|
1347
1355
|
* @property {string[]} [failureIds] - Ordered capability failures reachable through the method.
|
|
1356
|
+
* @property {{interfaceId: string, methodId: string}} [implements] - Exact satisfied interface member, required after validation when the method satisfies an interface contract.
|
|
1348
1357
|
* @property {SourceLocation} location - Complete method location.
|
|
1349
1358
|
* @property {SemanticNodeSourceProvenance} [sourceProvenance] - Parser-owned method-name range.
|
|
1350
1359
|
*/
|
|
1351
1360
|
|
|
1361
|
+
/**
|
|
1362
|
+
* @typedef InterfaceMethodDeclaration
|
|
1363
|
+
* @property {"InterfaceMethodDeclaration"} kind - Signature-only interface contract member.
|
|
1364
|
+
* @property {string} [id] - Stable interface-scoped method identity, required after validation.
|
|
1365
|
+
* @property {string} name - Source-visible method name.
|
|
1366
|
+
* @property {Parameter[]} parameters - Exact positional required parameters with explicit types.
|
|
1367
|
+
* @property {SemanticFunctionReturnType} returnType - Exact value or void return.
|
|
1368
|
+
* @property {SourceLocation} location - Complete interface method location.
|
|
1369
|
+
* @property {SemanticNodeSourceProvenance} [sourceProvenance] - Parser-owned method-name range.
|
|
1370
|
+
*/
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* @typedef InterfaceDeclaration
|
|
1374
|
+
* @property {"InterfaceDeclaration"} kind - Closed signature-only nominal interface with exact implementation contracts.
|
|
1375
|
+
* @property {string} [id] - Stable module-local interface identity, required after validation.
|
|
1376
|
+
* @property {string} name - Source-visible interface name.
|
|
1377
|
+
* @property {InterfaceType[]} [extends] - Direct interface parents in source order; omitted when empty.
|
|
1378
|
+
* @property {InterfaceMethodDeclaration[]} methods - Ordered closed signature set.
|
|
1379
|
+
* @property {SourceLocation} location - Complete interface location.
|
|
1380
|
+
* @property {SemanticNodeSourceProvenance} [sourceProvenance] - Parser-owned interface-name range.
|
|
1381
|
+
*/
|
|
1382
|
+
|
|
1352
1383
|
/**
|
|
1353
1384
|
* @typedef ClassDeclaration
|
|
1354
1385
|
* @property {"ClassDeclaration"} kind - Nominal reference class with private mutable state.
|
|
@@ -1357,6 +1388,7 @@
|
|
|
1357
1388
|
* @property {PrivateField[]} fields - Ordered private instance state.
|
|
1358
1389
|
* @property {ConstructorDeclaration} constructor - Sole exact constructor.
|
|
1359
1390
|
* @property {MethodDeclaration[]} methods - Ordered receiver methods.
|
|
1391
|
+
* @property {InterfaceType[]} [implements] - Direct interface contracts in source order; omitted when empty.
|
|
1360
1392
|
* @property {{kind: "ordinary"} | {kind: "ownedResource", fieldId: string, resourceId: string}} [ownership] - Explicit class ownership profile.
|
|
1361
1393
|
* @property {SourceLocation} location - Complete class location.
|
|
1362
1394
|
* @property {SemanticNodeSourceProvenance} [sourceProvenance] - Parser-owned class-name range.
|
|
@@ -1391,6 +1423,7 @@
|
|
|
1391
1423
|
* @typedef SemanticModule
|
|
1392
1424
|
* @property {"Module"} kind - Node discriminator.
|
|
1393
1425
|
* @property {RecordDeclaration[]} [records] - Top-level nominal record declarations in source order; omitted when empty.
|
|
1426
|
+
* @property {InterfaceDeclaration[]} [interfaces] - Top-level nominal interface declarations in source order; omitted when empty.
|
|
1394
1427
|
* @property {ClassDeclaration[]} [classes] - Top-level nominal reference classes in source order; omitted when empty.
|
|
1395
1428
|
* @property {ErrorDeclaration[]} [errors] - Top-level nominal unchecked error declarations in source order; omitted when empty.
|
|
1396
1429
|
* @property {EffectCapabilityDeclaration[]} [capabilities] - Compiler-authorized Task 034 declarations; omission is the legacy empty set.
|
|
@@ -1441,6 +1474,7 @@
|
|
|
1441
1474
|
* @property {string} id - Stable caller-supplied logical module identity.
|
|
1442
1475
|
* @property {string} sourceFilename - Explicit source filename; never an implicit read request.
|
|
1443
1476
|
* @property {RecordDeclaration[]} [records] - Top-level nominal record declarations.
|
|
1477
|
+
* @property {InterfaceDeclaration[]} [interfaces] - Top-level nominal interface declarations.
|
|
1444
1478
|
* @property {ClassDeclaration[]} [classes] - Compiler-owned facade reference classes.
|
|
1445
1479
|
* @property {ErrorDeclaration[]} [errors] - Top-level nominal unchecked error declarations.
|
|
1446
1480
|
* @property {FunctionDeclaration[]} functions - Top-level functions.
|
|
@@ -1486,7 +1520,7 @@
|
|
|
1486
1520
|
* @property {StdlibFacadeProgramDescriptor} [stdlibFacades] - Complete selected source-language facade closure.
|
|
1487
1521
|
*/
|
|
1488
1522
|
|
|
1489
|
-
/** @typedef {SemanticModule | SemanticProgramModule | SemanticImport | SemanticExport | RecordDeclaration | ClassDeclaration | ErrorDeclaration | EffectCapabilityDeclaration | EffectResourceDeclaration | EffectFailureDeclaration | EffectOperationDeclaration | RecordField | PrivateField | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | TypeParameter | Parameter | ValueBinding | CatchBinding | CatchHandler | Block | Statement | EntryPoint | Expression | ErrorConstruction | ErrorType | MapEntry | SemanticValueType | FunctionReturnTypeReference} SemanticNode */
|
|
1523
|
+
/** @typedef {SemanticModule | SemanticProgramModule | SemanticImport | SemanticExport | RecordDeclaration | InterfaceDeclaration | InterfaceMethodDeclaration | ClassDeclaration | ErrorDeclaration | EffectCapabilityDeclaration | EffectResourceDeclaration | EffectFailureDeclaration | EffectOperationDeclaration | RecordField | PrivateField | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | TypeParameter | Parameter | ValueBinding | CatchBinding | CatchHandler | Block | Statement | EntryPoint | Expression | ErrorConstruction | ErrorType | MapEntry | SemanticValueType | FunctionReturnTypeReference} SemanticNode */
|
|
1490
1524
|
/** @typedef {SemanticNode} SemanticNodeWithoutLocations */
|
|
1491
1525
|
|
|
1492
1526
|
export {}
|