semantifold 0.6.0 → 0.7.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 +6 -3
- package/build/index.d.ts +8 -8
- package/build/index.d.ts.map +1 -1
- package/build/index.js +6 -6
- package/build/src/backends/android.js +2 -2
- package/build/src/backends/dart.d.ts +19 -0
- package/build/src/backends/dart.d.ts.map +1 -1
- package/build/src/backends/dart.js +28 -16
- package/build/src/backends/flutter.d.ts +51 -0
- package/build/src/backends/flutter.d.ts.map +1 -0
- package/build/src/backends/flutter.js +1362 -0
- package/build/src/backends/identifiers.js +5 -5
- package/build/src/backends/program.d.ts +4 -4
- package/build/src/backends/program.d.ts.map +1 -1
- package/build/src/backends/program.js +4 -4
- package/build/src/backends/shared.d.ts +7 -0
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +11 -6
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +11 -1
- package/build/src/semantic/types.d.ts +152 -2
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +38 -2
- package/docs/android.md +6 -2
- package/docs/architecture.md +2 -0
- package/docs/flutter.md +47 -0
- package/docs/goals.md +1 -1
- package/docs/language-support.md +9 -2
- package/docs/source-maps.md +2 -0
- package/docs/testing.md +22 -1
- package/index.js +5 -5
- package/package.json +1 -1
- package/src/backends/android.js +1 -1
- package/src/backends/dart.js +28 -15
- package/src/backends/flutter.js +1465 -0
- package/src/backends/identifiers.js +4 -4
- package/src/backends/program.js +3 -3
- package/src/backends/shared.js +12 -8
- package/src/language-registry.js +10 -0
- package/src/semantic/types.js +40 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {unsupportedCapability} from "../diagnostic.js"
|
|
4
4
|
|
|
5
|
-
/** @type {Record<Exclude<import("../semantic/types.js").BackendLanguage, "ios">, RegExp>} */
|
|
5
|
+
/** @type {Record<Exclude<import("../semantic/types.js").BackendLanguage, "ios" | "flutter">, RegExp>} */
|
|
6
6
|
const identifierPatterns = {
|
|
7
7
|
android: /^(?:_|\p{L})(?:_|\p{L}|\p{Nd})*$/u,
|
|
8
8
|
dart: /^(?:_|\p{L})(?:_|\p{L}|\p{Nd})*$/u,
|
|
@@ -23,7 +23,7 @@ const identifierPatterns = {
|
|
|
23
23
|
wasm: /^(?:[$_]|\p{XID_Start})(?:[$_]|\p{XID_Continue})*$/u
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/** @type {Record<Exclude<import("../semantic/types.js").BackendLanguage, "ios">, Set<string>>} */
|
|
26
|
+
/** @type {Record<Exclude<import("../semantic/types.js").BackendLanguage, "ios" | "flutter">, Set<string>>} */
|
|
27
27
|
const reservedWords = {
|
|
28
28
|
android: new Set([
|
|
29
29
|
"as", "break", "class", "continue", "do", "else", "false", "for", "fun", "if", "in", "interface", "is", "null",
|
|
@@ -236,7 +236,7 @@ export function validateTargetIdentifier(language, name, role, location) {
|
|
|
236
236
|
if (typeof name != "string") unsupportedCapability(language, `${role} identifier`, location)
|
|
237
237
|
|
|
238
238
|
const reservedName = language == "php" ? name.toLowerCase() : name
|
|
239
|
-
const syntaxLanguage = language == "ios" ? "swift" : language
|
|
239
|
+
const syntaxLanguage = language == "ios" ? "swift" : language == "flutter" ? "dart" : language
|
|
240
240
|
|
|
241
241
|
if (!identifierPatterns[syntaxLanguage].test(name) || reservedWords[syntaxLanguage].has(reservedName) ||
|
|
242
242
|
language == "python" && name.normalize("NFKC") != name ||
|
|
@@ -296,7 +296,7 @@ export function validateTargetTypeIdentifier(language, name, location) {
|
|
|
296
296
|
unsupportedCapability(language, `record type identifier '${String(name)}'`, location)
|
|
297
297
|
}
|
|
298
298
|
const reservedName = language == "php" ? name.toLowerCase() : name
|
|
299
|
-
const syntaxLanguage = language == "ios" ? "swift" : language
|
|
299
|
+
const syntaxLanguage = language == "ios" ? "swift" : language == "flutter" ? "dart" : language
|
|
300
300
|
|
|
301
301
|
if (reservedWords[syntaxLanguage].has(reservedName) || reservedTypeNames[language]?.has(reservedName)) {
|
|
302
302
|
unsupportedCapability(language, `record type identifier '${name}'`, location)
|
package/src/backends/program.js
CHANGED
|
@@ -23,7 +23,7 @@ import {programImportName, SourceWriter} from "./writer.js"
|
|
|
23
23
|
/** @type {Readonly<Set<import("../semantic/types.js").SemanticLanguage>>} */
|
|
24
24
|
const programTargets = new Set(["php", "ruby", "javascript", "typescript", "java"])
|
|
25
25
|
/** @type {Readonly<Set<import("../semantic/types.js").BackendLanguage>>} */
|
|
26
|
-
const programApplicationTargets = new Set(["android", "ios"])
|
|
26
|
+
const programApplicationTargets = new Set(["android", "ios", "flutter"])
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Validates and prepares a complete semantic program for a non-text backend without allocating a writer.
|
|
@@ -68,8 +68,8 @@ export function preflightSemanticProgram({backendLanguage, diagnosticLanguage, p
|
|
|
68
68
|
* @param {import("../semantic/types.js").BackendLanguage} input.language - Registered program target.
|
|
69
69
|
* @param {import("../semantic/types.js").SemanticProgram} input.program - Complete semantic program.
|
|
70
70
|
* @param {"text" | "application"} [input.role] - Explicit artifact role; omitted preserves text generation.
|
|
71
|
-
* @param {import("../semantic/types.js").IosApplicationConfigurationInput | import("../semantic/types.js").AndroidApplicationConfigurationInput} [input.configuration] - Application configuration.
|
|
72
|
-
* @param {import("../semantic/types.js").IosApplicationAssetInput[] | import("../semantic/types.js").AndroidApplicationInputFile[]} [input.assets] - Exact caller assets.
|
|
71
|
+
* @param {import("../semantic/types.js").IosApplicationConfigurationInput | import("../semantic/types.js").AndroidApplicationConfigurationInput | import("../semantic/types.js").FlutterApplicationConfigurationInput} [input.configuration] - Application configuration.
|
|
72
|
+
* @param {import("../semantic/types.js").IosApplicationAssetInput[] | import("../semantic/types.js").AndroidApplicationInputFile[] | import("../semantic/types.js").FlutterApplicationAssetInput[]} [input.assets] - Exact caller assets.
|
|
73
73
|
* @param {import("../semantic/types.js").AndroidApplicationInputFile[]} [input.resources] - Exact Android caller resources.
|
|
74
74
|
* @returns {import("../semantic/types.js").GeneratedArtifactSet} Transactionally validated artifact set.
|
|
75
75
|
*/
|
package/src/backends/shared.js
CHANGED
|
@@ -2241,7 +2241,8 @@ export function emitExpression(writer, expression, path, language, emitIdentifie
|
|
|
2241
2241
|
return
|
|
2242
2242
|
}
|
|
2243
2243
|
if (expression.kind == "CallExpression") {
|
|
2244
|
-
const
|
|
2244
|
+
const callArgumentSuffix = writer.callArgumentSuffixFor(expression)
|
|
2245
|
+
const dartMultiline = language == "dart" && (expression.arguments.length > 0 || Boolean(callArgumentSuffix)) &&
|
|
2245
2246
|
dartExpressionExceedsPageWidth(writer, expression)
|
|
2246
2247
|
const dartIndent = dartMultiline ? currentLineIndent(writer) : ""
|
|
2247
2248
|
|
|
@@ -2255,11 +2256,10 @@ export function emitExpression(writer, expression, path, language, emitIdentifie
|
|
|
2255
2256
|
emitExpression(writer, argument, `${path}/arguments/${index}`, language, emitIdentifier)
|
|
2256
2257
|
if (dartMultiline) writer.synthetic(",\n", "Dart formatter argument separator", [expression], [path])
|
|
2257
2258
|
})
|
|
2258
|
-
const callArgumentSuffix = writer.callArgumentSuffixFor(expression)
|
|
2259
|
-
|
|
2260
2259
|
if (callArgumentSuffix) {
|
|
2261
|
-
writer.synthetic(`${expression.arguments.length ? "
|
|
2262
|
-
|
|
2260
|
+
writer.synthetic(dartMultiline ? `${expression.arguments.length ? "" : "\n"}${dartIndent} ${callArgumentSuffix},\n` :
|
|
2261
|
+
`${expression.arguments.length ? ", " : ""}${callArgumentSuffix}`,
|
|
2262
|
+
"target-container semantic call argument", [expression], [path])
|
|
2263
2263
|
}
|
|
2264
2264
|
if (dartMultiline) writer.synthetic(dartIndent, "Dart call closing indentation", [expression], [path])
|
|
2265
2265
|
writer.mapped(")", {mappingKind: "anchor", node: expression, path})
|
|
@@ -2558,14 +2558,18 @@ function currentLineIndent(writer) {
|
|
|
2558
2558
|
* @param {import("../semantic/types.js").Expression} expression Semantic expression.
|
|
2559
2559
|
* @returns {string} Flat canonical spelling.
|
|
2560
2560
|
*/
|
|
2561
|
-
function flatDartExpression(writer, expression) {
|
|
2561
|
+
export function flatDartExpression(writer, expression) {
|
|
2562
2562
|
if (expression.kind == "IdentifierExpression") return expression.name
|
|
2563
2563
|
if (expression.kind == "IntegerLiteral") return String(expression.value)
|
|
2564
2564
|
if (expression.kind == "BooleanLiteral") return `_semantifoldBoolean(${expression.value ? "true" : "false"})`
|
|
2565
2565
|
if (expression.kind == "StringLiteral") return emitStringLiteral("dart", expression.value)
|
|
2566
2566
|
if (expression.kind == "CallExpression") {
|
|
2567
|
-
|
|
2568
|
-
|
|
2567
|
+
const arguments_ = expression.arguments.map((argument) => flatDartExpression(writer, argument))
|
|
2568
|
+
const callArgumentSuffix = writer.callArgumentSuffixFor(expression)
|
|
2569
|
+
|
|
2570
|
+
if (callArgumentSuffix) arguments_.push(callArgumentSuffix)
|
|
2571
|
+
|
|
2572
|
+
return `${writer.callNameFor(expression)}(${arguments_.join(", ")})`
|
|
2569
2573
|
}
|
|
2570
2574
|
if (expression.kind == "UnaryExpression") {
|
|
2571
2575
|
const operand = flatDartExpression(writer, expression.operand)
|
package/src/language-registry.js
CHANGED
|
@@ -18,6 +18,7 @@ import {generateTypeScript} from "./backends/typescript.js"
|
|
|
18
18
|
import {generateBrowserWasm} from "./backends/wasm.js"
|
|
19
19
|
import {generateIosApplication} from "./backends/ios.js"
|
|
20
20
|
import {generateAndroidApplication} from "./backends/android.js"
|
|
21
|
+
import {generateFlutterApplication} from "./backends/flutter.js"
|
|
21
22
|
import {parseJava} from "./frontends/java.js"
|
|
22
23
|
import {parseKotlin} from "./frontends/kotlin.js"
|
|
23
24
|
import {parseCSharp} from "./frontends/csharp.js"
|
|
@@ -549,6 +550,15 @@ const records = [
|
|
|
549
550
|
id: "ios",
|
|
550
551
|
mapping: {binaryRanges: true, richText: true, sourceMapV3: true},
|
|
551
552
|
roundTrip: false
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
acceptance: {stages: ["generate", "restore", "compile", "validate", "instantiate", "execute"], toolchains: ["flutter", "android"]},
|
|
556
|
+
applicationBackend: generateFlutterApplication,
|
|
557
|
+
artifactMultiplicity: "multiple",
|
|
558
|
+
features: {closedRecords: false, conditionControlledLoops: false, effectfulCapabilitiesAndResources: false, generalFunctionsAndCalls: false, immutableCollections: false, optionalValues: false, orderedListIteration: false, orderedMapIteration: false, referenceClasses: false, typedErrors: false, typeParametersAndGenerics: false},
|
|
559
|
+
id: "flutter",
|
|
560
|
+
mapping: {binaryRanges: true, richText: true, sourceMapV3: true},
|
|
561
|
+
roundTrip: false
|
|
552
562
|
}
|
|
553
563
|
]
|
|
554
564
|
|
package/src/semantic/types.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/** @typedef {"php" | "ruby" | "javascript" | "typescript" | "java" | "kotlin" | "python" | "csharp" | "go" | "c" | "cpp" | "rust" | "swift" | "dart" | "zig"} SemanticLanguage */
|
|
4
4
|
/** @typedef {SemanticLanguage} TextBackendLanguage */
|
|
5
|
-
/** @typedef {TextBackendLanguage | "wasm" | "ios" | "android"} BackendLanguage */
|
|
5
|
+
/** @typedef {TextBackendLanguage | "wasm" | "ios" | "android" | "flutter"} BackendLanguage */
|
|
6
6
|
/** @typedef {SemanticLanguage | "html"} GeneratedTextLanguage */
|
|
7
7
|
/** @typedef {"integer" | "boolean" | "string"} SemanticTypeName */
|
|
8
8
|
/** @typedef {SemanticTypeName | "void"} FunctionReturnTypeName */
|
|
@@ -103,6 +103,45 @@
|
|
|
103
103
|
* @property {string} sha256 - Lowercase SHA-256 of exact UTF-8 text or bytes.
|
|
104
104
|
*/
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* @typedef FlutterApplicationConfigurationInput
|
|
108
|
+
* @property {string} [packageName] - Lowercase Dart package identity.
|
|
109
|
+
* @property {string} [organization] - Lowercase reverse-DNS owning organization.
|
|
110
|
+
* @property {string} [applicationId] - Lowercase reverse-DNS Android application identity extending the organization.
|
|
111
|
+
* @property {string} [activityClassName] - Generated Java launcher Activity class name.
|
|
112
|
+
* @property {string} [displayName] - User-visible application label.
|
|
113
|
+
* @property {23} [minimumSdk] - Qualified minimum Android API.
|
|
114
|
+
* @property {35} [targetSdk] - Qualified target Android API.
|
|
115
|
+
* @property {35} [compileSdk] - Qualified compile Android API.
|
|
116
|
+
* @property {"35.0.0"} [buildToolsVersion] - Qualified Android Build Tools version.
|
|
117
|
+
* @property {number} [versionCode] - Positive Android/Flutter build number.
|
|
118
|
+
* @property {string} [versionName] - Canonical application version name.
|
|
119
|
+
* @property {unknown[]} [permissions] - Validated as the closed empty permission set.
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @typedef FlutterApplicationConfiguration
|
|
124
|
+
* @property {string} packageName - Validated Dart package identity.
|
|
125
|
+
* @property {string} organization - Validated owning organization.
|
|
126
|
+
* @property {string} applicationId - Validated Android application identity.
|
|
127
|
+
* @property {string} activityClassName - Generated Java launcher Activity class name.
|
|
128
|
+
* @property {string} displayName - User-visible application label.
|
|
129
|
+
* @property {23} minimumSdk - Qualified minimum Android API.
|
|
130
|
+
* @property {35} targetSdk - Qualified target Android API.
|
|
131
|
+
* @property {35} compileSdk - Qualified compile Android API.
|
|
132
|
+
* @property {"35.0.0"} buildToolsVersion - Qualified Android Build Tools version.
|
|
133
|
+
* @property {number} versionCode - Positive Android/Flutter build number.
|
|
134
|
+
* @property {string} versionName - Canonical application version name.
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @typedef FlutterApplicationAssetInput
|
|
139
|
+
* @property {string} path - Safe path below the generated Flutter assets root.
|
|
140
|
+
* @property {string | Uint8Array} content - Exact caller-provided text or bytes.
|
|
141
|
+
* @property {string} mediaType - Explicit artifact media type.
|
|
142
|
+
* @property {string} sha256 - Lowercase SHA-256 of exact UTF-8 text or bytes.
|
|
143
|
+
*/
|
|
144
|
+
|
|
106
145
|
/**
|
|
107
146
|
* @typedef LanguageRoleCapabilities
|
|
108
147
|
* @property {boolean} frontend - Parser adapter availability.
|