implements PLN-0006
This commit is contained in:
parent
e0c57814e1
commit
4a6cc35989
@ -4,6 +4,6 @@
|
|||||||
{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||||
{"type":"discussion","id":"DSC-0004","status":"open","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
{"type":"discussion","id":"DSC-0004","status":"open","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0006","status":"open","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[{"id":"AGD-0006","file":"AGD-0006-pbs-game-facing-asset-refs-and-call-result-discard.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[{"id":"DEC-0005","file":"DEC-0005-pbs-asset-address-surface-and-be-lowering.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27","ref_agenda":"AGD-0006"},{"id":"DEC-0006","file":"DEC-0006-pbs-ignored-values-lowering-and-warning.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27","ref_agenda":"AGD-0006"}],"plans":[{"id":"PLN-0005","file":"PLN-0005-pbs-asset-address-surface-spec-propagation.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27","ref_decisions":["DEC-0005"]},{"id":"PLN-0006","file":"PLN-0006-pbs-asset-address-surface-implementation.md","status":"review","created_at":"2026-03-27","updated_at":"2026-03-27","ref_decisions":["DEC-0005"]},{"id":"PLN-0007","file":"PLN-0007-pbs-ignored-values-warning-implementation.md","status":"review","created_at":"2026-03-27","updated_at":"2026-03-27","ref_decisions":["DEC-0006"]}],"lessons":[]}
|
{"type":"discussion","id":"DSC-0006","status":"open","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[{"id":"AGD-0006","file":"AGD-0006-pbs-game-facing-asset-refs-and-call-result-discard.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[{"id":"DEC-0005","file":"DEC-0005-pbs-asset-address-surface-and-be-lowering.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27","ref_agenda":"AGD-0006"},{"id":"DEC-0006","file":"DEC-0006-pbs-ignored-values-lowering-and-warning.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27","ref_agenda":"AGD-0006"}],"plans":[{"id":"PLN-0005","file":"PLN-0005-pbs-asset-address-surface-spec-propagation.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27","ref_decisions":["DEC-0005"]},{"id":"PLN-0006","file":"PLN-0006-pbs-asset-address-surface-implementation.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27","ref_decisions":["DEC-0005"]},{"id":"PLN-0007","file":"PLN-0007-pbs-ignored-values-warning-implementation.md","status":"review","created_at":"2026-03-27","updated_at":"2026-03-27","ref_decisions":["DEC-0006"]}],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||||
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
id: PLN-0006
|
id: PLN-0006
|
||||||
ticket: pbs-game-facing-asset-refs-and-call-result-discard
|
ticket: pbs-game-facing-asset-refs-and-call-result-discard
|
||||||
title: Implement DEC-0005 Addressable Surface, FESurfaceContext, and Backend Asset Lowering
|
title: Implement DEC-0005 Addressable Surface, FESurfaceContext, and Backend Asset Lowering
|
||||||
status: review
|
status: done
|
||||||
created: 2026-03-27
|
created: 2026-03-27
|
||||||
completed:
|
completed: 2026-03-27
|
||||||
tags: [compiler, pbs, implementation, addressable, lowering, be-fe-contract, asset-identity]
|
tags: [compiler, pbs, implementation, addressable, lowering, be-fe-contract, asset-identity]
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package p.studio.compiler.pbs;
|
package p.studio.compiler.pbs;
|
||||||
|
|
||||||
import p.studio.compiler.messages.HostAdmissionContext;
|
import p.studio.compiler.messages.HostAdmissionContext;
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.models.IRBackendExecutableFunction;
|
import p.studio.compiler.models.IRBackendExecutableFunction;
|
||||||
import p.studio.compiler.models.IRBackendFile;
|
import p.studio.compiler.models.IRBackendFile;
|
||||||
import p.studio.compiler.models.IRFunction;
|
import p.studio.compiler.models.IRFunction;
|
||||||
@ -61,6 +62,16 @@ public final class PbsFrontendCompiler {
|
|||||||
final DiagnosticSink diagnostics,
|
final DiagnosticSink diagnostics,
|
||||||
final SourceKind sourceKind,
|
final SourceKind sourceKind,
|
||||||
final HostAdmissionContext hostAdmissionContext) {
|
final HostAdmissionContext hostAdmissionContext) {
|
||||||
|
return compileFile(fileId, source, diagnostics, sourceKind, hostAdmissionContext, FESurfaceContext.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IRBackendFile compileFile(
|
||||||
|
final FileId fileId,
|
||||||
|
final String source,
|
||||||
|
final DiagnosticSink diagnostics,
|
||||||
|
final SourceKind sourceKind,
|
||||||
|
final HostAdmissionContext hostAdmissionContext,
|
||||||
|
final FESurfaceContext feSurfaceContext) {
|
||||||
final var nameTable = new NameTable();
|
final var nameTable = new NameTable();
|
||||||
final var admissionBaseline = diagnostics.errorCount();
|
final var admissionBaseline = diagnostics.errorCount();
|
||||||
final var tokens = PbsLexer.lex(source, fileId, diagnostics);
|
final var tokens = PbsLexer.lex(source, fileId, diagnostics);
|
||||||
@ -76,6 +87,7 @@ public final class PbsFrontendCompiler {
|
|||||||
ModuleId.none(),
|
ModuleId.none(),
|
||||||
ReadOnlyList.empty(),
|
ReadOnlyList.empty(),
|
||||||
hostAdmissionContext,
|
hostAdmissionContext,
|
||||||
|
feSurfaceContext,
|
||||||
nameTable);
|
nameTable);
|
||||||
if (diagnostics.errorCount() > admissionBaseline) {
|
if (diagnostics.errorCount() > admissionBaseline) {
|
||||||
return IRBackendFile.empty(fileId);
|
return IRBackendFile.empty(fileId);
|
||||||
@ -91,6 +103,7 @@ public final class PbsFrontendCompiler {
|
|||||||
final ModuleId moduleId,
|
final ModuleId moduleId,
|
||||||
final ReadOnlyList<ModuleReference> modulePool,
|
final ReadOnlyList<ModuleReference> modulePool,
|
||||||
final HostAdmissionContext hostAdmissionContext,
|
final HostAdmissionContext hostAdmissionContext,
|
||||||
|
final FESurfaceContext feSurfaceContext,
|
||||||
final NameTable nameTable) {
|
final NameTable nameTable) {
|
||||||
return compileParsedFile(
|
return compileParsedFile(
|
||||||
fileId,
|
fileId,
|
||||||
@ -100,6 +113,7 @@ public final class PbsFrontendCompiler {
|
|||||||
moduleId,
|
moduleId,
|
||||||
modulePool,
|
modulePool,
|
||||||
hostAdmissionContext,
|
hostAdmissionContext,
|
||||||
|
feSurfaceContext,
|
||||||
nameTable,
|
nameTable,
|
||||||
ReadOnlyList.empty(),
|
ReadOnlyList.empty(),
|
||||||
ReadOnlyList.empty(),
|
ReadOnlyList.empty(),
|
||||||
@ -116,6 +130,7 @@ public final class PbsFrontendCompiler {
|
|||||||
final ModuleId moduleId,
|
final ModuleId moduleId,
|
||||||
final ReadOnlyList<ModuleReference> modulePool,
|
final ReadOnlyList<ModuleReference> modulePool,
|
||||||
final HostAdmissionContext hostAdmissionContext,
|
final HostAdmissionContext hostAdmissionContext,
|
||||||
|
final FESurfaceContext feSurfaceContext,
|
||||||
final NameTable nameTable,
|
final NameTable nameTable,
|
||||||
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
||||||
final ReadOnlyList<ImportedCallableSurface> importedCallables,
|
final ReadOnlyList<ImportedCallableSurface> importedCallables,
|
||||||
@ -134,6 +149,9 @@ public final class PbsFrontendCompiler {
|
|||||||
final var effectiveImportedGlobals = importedGlobals == null
|
final var effectiveImportedGlobals = importedGlobals == null
|
||||||
? ReadOnlyList.<ImportedGlobalSurface>empty()
|
? ReadOnlyList.<ImportedGlobalSurface>empty()
|
||||||
: importedGlobals;
|
: importedGlobals;
|
||||||
|
final var effectiveFESurfaceContext = feSurfaceContext == null
|
||||||
|
? FESurfaceContext.empty()
|
||||||
|
: feSurfaceContext;
|
||||||
final var effectiveImportedReservedMetadata = importedReservedMetadata == null
|
final var effectiveImportedReservedMetadata = importedReservedMetadata == null
|
||||||
? IRReservedMetadata.empty()
|
? IRReservedMetadata.empty()
|
||||||
: importedReservedMetadata;
|
: importedReservedMetadata;
|
||||||
@ -147,7 +165,7 @@ public final class PbsFrontendCompiler {
|
|||||||
effectiveModuleId,
|
effectiveModuleId,
|
||||||
effectiveImportedGlobals,
|
effectiveImportedGlobals,
|
||||||
diagnostics);
|
diagnostics);
|
||||||
flowSemanticsValidator.validate(ast, effectiveSupplementalTopDecls, diagnostics);
|
flowSemanticsValidator.validate(ast, effectiveSupplementalTopDecls, effectiveFESurfaceContext, diagnostics);
|
||||||
lifecycleSemanticsValidator.validate(ast, effectiveSupplementalTopDecls, diagnostics);
|
lifecycleSemanticsValidator.validate(ast, effectiveSupplementalTopDecls, diagnostics);
|
||||||
if (diagnostics.errorCount() > semanticsErrorBaseline) {
|
if (diagnostics.errorCount() > semanticsErrorBaseline) {
|
||||||
return IRBackendFile.empty(fileId);
|
return IRBackendFile.empty(fileId);
|
||||||
@ -179,6 +197,7 @@ public final class PbsFrontendCompiler {
|
|||||||
effectiveModuleId,
|
effectiveModuleId,
|
||||||
mergeReservedMetadata(reservedMetadata, effectiveImportedReservedMetadata),
|
mergeReservedMetadata(reservedMetadata, effectiveImportedReservedMetadata),
|
||||||
effectiveNameTable,
|
effectiveNameTable,
|
||||||
|
effectiveFESurfaceContext,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
effectiveImportedCallables);
|
effectiveImportedCallables);
|
||||||
if (diagnostics.errorCount() > loweringErrorBaseline) {
|
if (diagnostics.errorCount() > loweringErrorBaseline) {
|
||||||
|
|||||||
@ -378,7 +378,7 @@ final class PbsExecutableBodyLowerer {
|
|||||||
handleExpr.span(),
|
handleExpr.span(),
|
||||||
context);
|
context);
|
||||||
case PbsAst.AsExpr asExpr -> lowerExpression(asExpr.expression(), context);
|
case PbsAst.AsExpr asExpr -> lowerExpression(asExpr.expression(), context);
|
||||||
case PbsAst.MemberExpr memberExpr -> lowerExpression(memberExpr.receiver(), context);
|
case PbsAst.MemberExpr memberExpr -> lowerMemberExpression(memberExpr, context);
|
||||||
case PbsAst.PropagateExpr propagateExpr -> lowerExpression(propagateExpr.expression(), context);
|
case PbsAst.PropagateExpr propagateExpr -> lowerExpression(propagateExpr.expression(), context);
|
||||||
case PbsAst.GroupExpr groupExpr -> lowerExpression(groupExpr.expression(), context);
|
case PbsAst.GroupExpr groupExpr -> lowerExpression(groupExpr.expression(), context);
|
||||||
case PbsAst.NewExpr newExpr -> lowerExpressionList(newExpr.arguments(), context);
|
case PbsAst.NewExpr newExpr -> lowerExpressionList(newExpr.arguments(), context);
|
||||||
@ -426,6 +426,25 @@ final class PbsExecutableBodyLowerer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void lowerMemberExpression(
|
||||||
|
final PbsAst.MemberExpr memberExpr,
|
||||||
|
final PbsExecutableLoweringContext context) {
|
||||||
|
final var assetReference = flattenAssetReference(memberExpr);
|
||||||
|
if (assetReference != null) {
|
||||||
|
final var assetId = context.resolveAssetId(assetReference);
|
||||||
|
if (assetId == null) {
|
||||||
|
reportUnsupportedLowering(
|
||||||
|
"asset reference does not resolve in backend-owned surface: " + assetReference,
|
||||||
|
memberExpr.span(),
|
||||||
|
context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emitPushI32(assetId, memberExpr.span(), context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lowerExpression(memberExpr.receiver(), context);
|
||||||
|
}
|
||||||
|
|
||||||
private void lowerIfExpression(
|
private void lowerIfExpression(
|
||||||
final PbsAst.IfExpr ifExpr,
|
final PbsAst.IfExpr ifExpr,
|
||||||
final PbsExecutableLoweringContext context) {
|
final PbsExecutableLoweringContext context) {
|
||||||
@ -456,6 +475,9 @@ final class PbsExecutableBodyLowerer {
|
|||||||
private void lowerIdentifierExpression(
|
private void lowerIdentifierExpression(
|
||||||
final PbsAst.IdentifierExpr identifierExpr,
|
final PbsAst.IdentifierExpr identifierExpr,
|
||||||
final PbsExecutableLoweringContext context) {
|
final PbsExecutableLoweringContext context) {
|
||||||
|
if ("assets".equals(identifierExpr.name())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final var slot = context.localSlotByNameId().get(context.nameTable().register(identifierExpr.name()));
|
final var slot = context.localSlotByNameId().get(context.nameTable().register(identifierExpr.name()));
|
||||||
if (slot != null) {
|
if (slot != null) {
|
||||||
emitGetLocal(slot, identifierExpr.span(), context);
|
emitGetLocal(slot, identifierExpr.span(), context);
|
||||||
@ -472,6 +494,20 @@ final class PbsExecutableBodyLowerer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String flattenAssetReference(final PbsAst.Expression expression) {
|
||||||
|
if (expression instanceof PbsAst.IdentifierExpr identifierExpr) {
|
||||||
|
return "assets".equals(identifierExpr.name()) ? "assets" : null;
|
||||||
|
}
|
||||||
|
if (!(expression instanceof PbsAst.MemberExpr memberExpr)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final var receiverPath = flattenAssetReference(memberExpr.receiver());
|
||||||
|
if (receiverPath == null || receiverPath.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return receiverPath + "." + memberExpr.memberName();
|
||||||
|
}
|
||||||
|
|
||||||
private void lowerConstExpression(
|
private void lowerConstExpression(
|
||||||
final PbsAst.Expression expression,
|
final PbsAst.Expression expression,
|
||||||
final PbsExecutableLoweringContext context) {
|
final PbsExecutableLoweringContext context) {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package p.studio.compiler.pbs.lowering;
|
package p.studio.compiler.pbs.lowering;
|
||||||
|
|
||||||
import p.studio.compiler.models.IRBackendExecutableFunction;
|
import p.studio.compiler.models.IRBackendExecutableFunction;
|
||||||
|
import p.studio.compiler.messages.Addressable;
|
||||||
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||||
import p.studio.compiler.source.identifiers.NameId;
|
import p.studio.compiler.source.identifiers.NameId;
|
||||||
import p.studio.compiler.source.tables.IntrinsicTable;
|
import p.studio.compiler.source.tables.IntrinsicTable;
|
||||||
@ -66,6 +67,10 @@ final class PbsExecutableLoweringContext {
|
|||||||
return metadataIndex.constDeclByNameId();
|
return metadataIndex.constDeclByNameId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, Addressable> addressableByAddress() {
|
||||||
|
return metadataIndex.addressableByAddress();
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, String> builtinCanonicalBySourceType() {
|
Map<String, String> builtinCanonicalBySourceType() {
|
||||||
return metadataIndex.builtinCanonicalBySourceType();
|
return metadataIndex.builtinCanonicalBySourceType();
|
||||||
}
|
}
|
||||||
@ -140,6 +145,14 @@ final class PbsExecutableLoweringContext {
|
|||||||
return constDeclByNameId().get(nameTable.register(constName));
|
return constDeclByNameId().get(nameTable.register(constName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Integer resolveAssetId(final String address) {
|
||||||
|
if (address == null || address.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final var addressable = addressableByAddress().get(address);
|
||||||
|
return addressable == null ? null : addressable.assetId();
|
||||||
|
}
|
||||||
|
|
||||||
int declareLocalSlot(final String localName) {
|
int declareLocalSlot(final String localName) {
|
||||||
final var nameId = nameTable.register(localName);
|
final var nameId = nameTable.register(localName);
|
||||||
final var existing = localSlotByNameId.get(nameId);
|
final var existing = localSlotByNameId.get(nameId);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package p.studio.compiler.pbs.lowering;
|
|||||||
|
|
||||||
import p.studio.compiler.models.IRBackendExecutableFunction;
|
import p.studio.compiler.models.IRBackendExecutableFunction;
|
||||||
import p.studio.compiler.models.IRReservedMetadata;
|
import p.studio.compiler.models.IRReservedMetadata;
|
||||||
|
import p.studio.compiler.messages.Addressable;
|
||||||
import p.studio.compiler.pbs.ast.PbsAst;
|
import p.studio.compiler.pbs.ast.PbsAst;
|
||||||
import p.studio.compiler.source.identifiers.CallableId;
|
import p.studio.compiler.source.identifiers.CallableId;
|
||||||
import p.studio.compiler.source.identifiers.NameId;
|
import p.studio.compiler.source.identifiers.NameId;
|
||||||
@ -46,6 +47,7 @@ public class PbsExecutableLoweringModels {
|
|||||||
Map<NameId, String> builtinConstOwnerByNameId,
|
Map<NameId, String> builtinConstOwnerByNameId,
|
||||||
Map<NameId, Integer> globalSlotByNameId,
|
Map<NameId, Integer> globalSlotByNameId,
|
||||||
Map<NameId, PbsAst.ConstDecl> constDeclByNameId,
|
Map<NameId, PbsAst.ConstDecl> constDeclByNameId,
|
||||||
|
Map<String, Addressable> addressableByAddress,
|
||||||
Map<PbsIntrinsicOwnerMethodKey, List<IRReservedMetadata.IntrinsicSurface>> intrinsicByOwnerAndMethod,
|
Map<PbsIntrinsicOwnerMethodKey, List<IRReservedMetadata.IntrinsicSurface>> intrinsicByOwnerAndMethod,
|
||||||
Map<PbsIntrinsicCanonicalKey, String> intrinsicReturnOwnerByCanonical) {
|
Map<PbsIntrinsicCanonicalKey, String> intrinsicReturnOwnerByCanonical) {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package p.studio.compiler.pbs.lowering;
|
|||||||
|
|
||||||
import p.studio.compiler.models.IRBackendExecutableFunction;
|
import p.studio.compiler.models.IRBackendExecutableFunction;
|
||||||
import p.studio.compiler.models.IRReservedMetadata;
|
import p.studio.compiler.models.IRReservedMetadata;
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.pbs.PbsFrontendCompiler;
|
import p.studio.compiler.pbs.PbsFrontendCompiler;
|
||||||
import p.studio.compiler.pbs.ast.PbsAst;
|
import p.studio.compiler.pbs.ast.PbsAst;
|
||||||
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||||
@ -29,6 +30,7 @@ public final class PbsExecutableLoweringService {
|
|||||||
final ModuleId moduleId,
|
final ModuleId moduleId,
|
||||||
final IRReservedMetadata reservedMetadata,
|
final IRReservedMetadata reservedMetadata,
|
||||||
final NameTable nameTable,
|
final NameTable nameTable,
|
||||||
|
final FESurfaceContext feSurfaceContext,
|
||||||
final DiagnosticSink diagnostics,
|
final DiagnosticSink diagnostics,
|
||||||
final ReadOnlyList<PbsFrontendCompiler.ImportedCallableSurface> importedCallables) {
|
final ReadOnlyList<PbsFrontendCompiler.ImportedCallableSurface> importedCallables) {
|
||||||
final var normalizedModuleId = moduleId == null ? ModuleId.none() : moduleId;
|
final var normalizedModuleId = moduleId == null ? ModuleId.none() : moduleId;
|
||||||
@ -37,6 +39,7 @@ public final class PbsExecutableLoweringService {
|
|||||||
supplementalTopDecls,
|
supplementalTopDecls,
|
||||||
reservedMetadata,
|
reservedMetadata,
|
||||||
nameTable,
|
nameTable,
|
||||||
|
feSurfaceContext,
|
||||||
diagnostics);
|
diagnostics);
|
||||||
final var callableRegistry = callableRegistryFactory.create(
|
final var callableRegistry = callableRegistryFactory.create(
|
||||||
ast,
|
ast,
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package p.studio.compiler.pbs.lowering;
|
package p.studio.compiler.pbs.lowering;
|
||||||
|
|
||||||
import p.studio.compiler.models.IRReservedMetadata;
|
import p.studio.compiler.models.IRReservedMetadata;
|
||||||
|
import p.studio.compiler.messages.Addressable;
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.pbs.ast.PbsAst;
|
import p.studio.compiler.pbs.ast.PbsAst;
|
||||||
import p.studio.compiler.pbs.semantics.PbsSemanticsErrors;
|
import p.studio.compiler.pbs.semantics.PbsSemanticsErrors;
|
||||||
import p.studio.compiler.source.diagnostics.DiagnosticPhase;
|
import p.studio.compiler.source.diagnostics.DiagnosticPhase;
|
||||||
@ -23,12 +25,14 @@ final class PbsExecutableMetadataIndexFactory {
|
|||||||
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
||||||
final IRReservedMetadata reservedMetadata,
|
final IRReservedMetadata reservedMetadata,
|
||||||
final NameTable nameTable,
|
final NameTable nameTable,
|
||||||
|
final FESurfaceContext feSurfaceContext,
|
||||||
final DiagnosticSink diagnostics) {
|
final DiagnosticSink diagnostics) {
|
||||||
final var hostByMethodName = indexHostBindingsByMethodName(reservedMetadata, nameTable);
|
final var hostByMethodName = indexHostBindingsByMethodName(reservedMetadata, nameTable);
|
||||||
final var builtinCanonicalBySourceType = indexBuiltinCanonicalBySourceType(reservedMetadata);
|
final var builtinCanonicalBySourceType = indexBuiltinCanonicalBySourceType(reservedMetadata);
|
||||||
final var builtinConstOwnerByNameId = indexBuiltinConstOwners(reservedMetadata, nameTable);
|
final var builtinConstOwnerByNameId = indexBuiltinConstOwners(reservedMetadata, nameTable);
|
||||||
final var globalSlotByNameId = indexGlobalSlots(ast, nameTable);
|
final var globalSlotByNameId = indexGlobalSlots(ast, nameTable);
|
||||||
final var constDeclByNameId = indexConstDecls(ast, nameTable);
|
final var constDeclByNameId = indexConstDecls(ast, nameTable);
|
||||||
|
final var addressableByAddress = indexAddressables(feSurfaceContext);
|
||||||
final var builtinSignatureByOwnerAndMethod = indexBuiltinSignatures(
|
final var builtinSignatureByOwnerAndMethod = indexBuiltinSignatures(
|
||||||
ast,
|
ast,
|
||||||
supplementalTopDecls,
|
supplementalTopDecls,
|
||||||
@ -48,6 +52,7 @@ final class PbsExecutableMetadataIndexFactory {
|
|||||||
builtinConstOwnerByNameId,
|
builtinConstOwnerByNameId,
|
||||||
globalSlotByNameId,
|
globalSlotByNameId,
|
||||||
constDeclByNameId,
|
constDeclByNameId,
|
||||||
|
addressableByAddress,
|
||||||
intrinsicByOwnerAndMethod,
|
intrinsicByOwnerAndMethod,
|
||||||
intrinsicReturnOwnerByCanonical);
|
intrinsicReturnOwnerByCanonical);
|
||||||
}
|
}
|
||||||
@ -112,6 +117,18 @@ final class PbsExecutableMetadataIndexFactory {
|
|||||||
return constDeclByNameId;
|
return constDeclByNameId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, Addressable> indexAddressables(final FESurfaceContext feSurfaceContext) {
|
||||||
|
final var addressableByAddress = new HashMap<String, Addressable>();
|
||||||
|
final var effectiveSurfaceContext = feSurfaceContext == null ? FESurfaceContext.empty() : feSurfaceContext;
|
||||||
|
for (final var addressable : effectiveSurfaceContext.assets()) {
|
||||||
|
if (addressable == null || addressable.address().isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
addressableByAddress.putIfAbsent(addressable.address(), addressable);
|
||||||
|
}
|
||||||
|
return addressableByAddress;
|
||||||
|
}
|
||||||
|
|
||||||
private Map<PbsIntrinsicOwnerMethodKey, PbsAst.FunctionSignature> indexBuiltinSignatures(
|
private Map<PbsIntrinsicOwnerMethodKey, PbsAst.FunctionSignature> indexBuiltinSignatures(
|
||||||
final PbsAst.File ast,
|
final PbsAst.File ast,
|
||||||
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package p.studio.compiler.pbs.semantics;
|
package p.studio.compiler.pbs.semantics;
|
||||||
|
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.pbs.ast.PbsAst;
|
import p.studio.compiler.pbs.ast.PbsAst;
|
||||||
import p.studio.compiler.pbs.semantics.PbsFlowSemanticSupport.Model;
|
import p.studio.compiler.pbs.semantics.PbsFlowSemanticSupport.Model;
|
||||||
import p.studio.compiler.pbs.semantics.PbsFlowSemanticSupport.Scope;
|
import p.studio.compiler.pbs.semantics.PbsFlowSemanticSupport.Scope;
|
||||||
@ -27,8 +28,9 @@ final class PbsFlowBodyAnalyzer {
|
|||||||
public void validate(
|
public void validate(
|
||||||
final PbsAst.File ast,
|
final PbsAst.File ast,
|
||||||
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
||||||
|
final FESurfaceContext feSurfaceContext,
|
||||||
final DiagnosticSink diagnostics) {
|
final DiagnosticSink diagnostics) {
|
||||||
final var model = Model.from(ast, supplementalTopDecls);
|
final var model = Model.from(ast, supplementalTopDecls, feSurfaceContext, diagnostics);
|
||||||
|
|
||||||
for (final var topDecl : ast.topDecls()) {
|
for (final var topDecl : ast.topDecls()) {
|
||||||
validateTopDecl(topDecl, model, diagnostics);
|
validateTopDecl(topDecl, model, diagnostics);
|
||||||
|
|||||||
@ -70,6 +70,11 @@ final class PbsFlowCallableResolutionAnalyzer {
|
|||||||
ExprResult analyzeMemberExpression(
|
ExprResult analyzeMemberExpression(
|
||||||
final PbsAst.MemberExpr memberExpr,
|
final PbsAst.MemberExpr memberExpr,
|
||||||
final PbsFlowExpressionContext context) {
|
final PbsFlowExpressionContext context) {
|
||||||
|
final var assetReference = flattenAssetReference(memberExpr);
|
||||||
|
if (assetReference != null) {
|
||||||
|
return resolveAssetReference(assetReference, memberExpr, context);
|
||||||
|
}
|
||||||
|
|
||||||
final var receiver = analyzeValueExpression(memberExpr.receiver(), context, null).type();
|
final var receiver = analyzeValueExpression(memberExpr.receiver(), context, null).type();
|
||||||
final var model = context.model();
|
final var model = context.model();
|
||||||
final var diagnostics = context.diagnostics();
|
final var diagnostics = context.diagnostics();
|
||||||
@ -320,6 +325,47 @@ final class PbsFlowCallableResolutionAnalyzer {
|
|||||||
&& receiver.name().equals(currentReceiverType.name());
|
&& receiver.name().equals(currentReceiverType.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ExprResult resolveAssetReference(
|
||||||
|
final String assetReference,
|
||||||
|
final PbsAst.MemberExpr memberExpr,
|
||||||
|
final PbsFlowExpressionContext context) {
|
||||||
|
final var diagnostics = context.diagnostics();
|
||||||
|
final var model = context.model();
|
||||||
|
final var resolvedAssetId = model.resolveAssetId(assetReference);
|
||||||
|
if (resolvedAssetId != null) {
|
||||||
|
return ExprResult.type(TypeView.addressable(assetReference));
|
||||||
|
}
|
||||||
|
if (model.isAssetNamespace(assetReference)) {
|
||||||
|
if (context.use() == ExprUse.VALUE) {
|
||||||
|
Diagnostics.error(diagnostics,
|
||||||
|
PbsSemanticsErrors.E_SEM_INVALID_MEMBER_ACCESS.name(),
|
||||||
|
"Asset namespace '%s' is not a terminal Addressable value".formatted(assetReference),
|
||||||
|
memberExpr.span());
|
||||||
|
return ExprResult.type(TypeView.unknown());
|
||||||
|
}
|
||||||
|
return ExprResult.type(TypeView.assetNamespace(assetReference));
|
||||||
|
}
|
||||||
|
Diagnostics.error(diagnostics,
|
||||||
|
PbsSemanticsErrors.E_SEM_INVALID_MEMBER_ACCESS.name(),
|
||||||
|
"Asset reference '%s' does not resolve in the backend-provided surface".formatted(assetReference),
|
||||||
|
memberExpr.span());
|
||||||
|
return ExprResult.type(TypeView.unknown());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String flattenAssetReference(final PbsAst.Expression expression) {
|
||||||
|
if (expression instanceof PbsAst.IdentifierExpr identifierExpr) {
|
||||||
|
return "assets".equals(identifierExpr.name()) ? "assets" : null;
|
||||||
|
}
|
||||||
|
if (!(expression instanceof PbsAst.MemberExpr memberExpr)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final var receiverPath = flattenAssetReference(memberExpr.receiver());
|
||||||
|
if (receiverPath == null || receiverPath.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return receiverPath + "." + memberExpr.memberName();
|
||||||
|
}
|
||||||
|
|
||||||
private ExprResult analyzeValueExpression(
|
private ExprResult analyzeValueExpression(
|
||||||
final PbsAst.Expression expression,
|
final PbsAst.Expression expression,
|
||||||
final PbsFlowExpressionContext context,
|
final PbsFlowExpressionContext context,
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
package p.studio.compiler.pbs.semantics;
|
package p.studio.compiler.pbs.semantics;
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.pbs.ast.PbsAst;
|
import p.studio.compiler.pbs.ast.PbsAst;
|
||||||
import p.studio.compiler.source.Span;
|
import p.studio.compiler.source.Span;
|
||||||
|
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||||
|
import p.studio.compiler.source.diagnostics.Diagnostics;
|
||||||
import p.studio.utilities.structures.ReadOnlyList;
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -44,7 +47,9 @@ final class PbsFlowSemanticSupport {
|
|||||||
OPTIONAL,
|
OPTIONAL,
|
||||||
RESULT,
|
RESULT,
|
||||||
TUPLE,
|
TUPLE,
|
||||||
TYPE_REF
|
TYPE_REF,
|
||||||
|
ADDRESSABLE,
|
||||||
|
ASSET_NAMESPACE
|
||||||
}
|
}
|
||||||
|
|
||||||
record TupleField(
|
record TupleField(
|
||||||
@ -126,6 +131,14 @@ final class PbsFlowSemanticSupport {
|
|||||||
static TypeView typeRef(final String name) {
|
static TypeView typeRef(final String name) {
|
||||||
return new TypeView(Kind.TYPE_REF, name, List.of(), null, null, List.of(), null);
|
return new TypeView(Kind.TYPE_REF, name, List.of(), null, null, List.of(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TypeView addressable(final String address) {
|
||||||
|
return new TypeView(Kind.ADDRESSABLE, address, List.of(), null, null, List.of(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TypeView assetNamespace(final String path) {
|
||||||
|
return new TypeView(Kind.ASSET_NAMESPACE, path, List.of(), null, null, List.of(), null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record CallableSymbol(
|
record CallableSymbol(
|
||||||
@ -176,14 +189,18 @@ final class PbsFlowSemanticSupport {
|
|||||||
final Set<String> knownEnumNames = new HashSet<>();
|
final Set<String> knownEnumNames = new HashSet<>();
|
||||||
final Set<String> knownErrorNames = new HashSet<>();
|
final Set<String> knownErrorNames = new HashSet<>();
|
||||||
final Set<String> knownCallbackNames = new HashSet<>();
|
final Set<String> knownCallbackNames = new HashSet<>();
|
||||||
|
final Map<String, Integer> assetIdByAddress = new HashMap<>();
|
||||||
|
final Set<String> assetNamespacePrefixes = new HashSet<>();
|
||||||
|
|
||||||
static Model from(final PbsAst.File ast) {
|
static Model from(final PbsAst.File ast) {
|
||||||
return from(ast, ReadOnlyList.empty());
|
return from(ast, ReadOnlyList.empty(), FESurfaceContext.empty(), DiagnosticSink.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Model from(
|
static Model from(
|
||||||
final PbsAst.File ast,
|
final PbsAst.File ast,
|
||||||
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls) {
|
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
||||||
|
final FESurfaceContext feSurfaceContext,
|
||||||
|
final DiagnosticSink diagnostics) {
|
||||||
final var model = new Model();
|
final var model = new Model();
|
||||||
for (final var topDecl : ast.topDecls()) {
|
for (final var topDecl : ast.topDecls()) {
|
||||||
model.registerKnownTopDecl(topDecl);
|
model.registerKnownTopDecl(topDecl);
|
||||||
@ -197,6 +214,7 @@ final class PbsFlowSemanticSupport {
|
|||||||
for (final var topDecl : supplementalTopDecls) {
|
for (final var topDecl : supplementalTopDecls) {
|
||||||
model.ingestTopDecl(topDecl);
|
model.ingestTopDecl(topDecl);
|
||||||
}
|
}
|
||||||
|
model.ingestAssetSurface(feSurfaceContext, diagnostics);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,6 +395,72 @@ final class PbsFlowSemanticSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ingestAssetSurface(
|
||||||
|
final FESurfaceContext feSurfaceContext,
|
||||||
|
final DiagnosticSink diagnostics) {
|
||||||
|
final var effectiveSurfaceContext = feSurfaceContext == null ? FESurfaceContext.empty() : feSurfaceContext;
|
||||||
|
for (final var addressable : effectiveSurfaceContext.assets()) {
|
||||||
|
if (addressable == null || addressable.address().isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assetIdByAddress.put(addressable.address(), addressable.assetId());
|
||||||
|
registerAssetNamespaces(addressable.address());
|
||||||
|
}
|
||||||
|
for (final var address : assetIdByAddress.keySet()) {
|
||||||
|
for (final var prefix : namespacePrefixesOf(address)) {
|
||||||
|
if (assetIdByAddress.containsKey(prefix)) {
|
||||||
|
Diagnostics.error(
|
||||||
|
diagnostics,
|
||||||
|
PbsSemanticsErrors.E_SEM_INVALID_MEMBER_ACCESS.name(),
|
||||||
|
"Asset surface collision: '%s' cannot be both terminal and namespace prefix".formatted(prefix),
|
||||||
|
astSyntheticSpan());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasAssetNamespaceRoot() {
|
||||||
|
return assetNamespacePrefixes.contains("assets") || assetIdByAddress.containsKey("assets");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isAssetNamespace(final String path) {
|
||||||
|
return assetNamespacePrefixes.contains(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer resolveAssetId(final String address) {
|
||||||
|
return assetIdByAddress.get(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerAssetNamespaces(final String address) {
|
||||||
|
for (final var prefix : namespacePrefixesOf(address)) {
|
||||||
|
assetNamespacePrefixes.add(prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> namespacePrefixesOf(final String address) {
|
||||||
|
final var segments = address.split("\\.");
|
||||||
|
final var prefixes = new ArrayList<String>();
|
||||||
|
if (segments.length <= 1) {
|
||||||
|
return prefixes;
|
||||||
|
}
|
||||||
|
final var builder = new StringBuilder();
|
||||||
|
for (int i = 0; i < segments.length - 1; i++) {
|
||||||
|
if (segments[i] == null || segments[i].isBlank()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (builder.length() > 0) {
|
||||||
|
builder.append('.');
|
||||||
|
}
|
||||||
|
builder.append(segments[i]);
|
||||||
|
prefixes.add(builder.toString());
|
||||||
|
}
|
||||||
|
return prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Span astSyntheticSpan() {
|
||||||
|
return Span.none();
|
||||||
|
}
|
||||||
|
|
||||||
private CallableSymbol callableFrom(
|
private CallableSymbol callableFrom(
|
||||||
final String name,
|
final String name,
|
||||||
final ReadOnlyList<PbsAst.Parameter> parameters,
|
final ReadOnlyList<PbsAst.Parameter> parameters,
|
||||||
@ -429,6 +513,9 @@ final class PbsFlowSemanticSupport {
|
|||||||
if ("str".equals(typeRef.name())) {
|
if ("str".equals(typeRef.name())) {
|
||||||
yield TypeView.str();
|
yield TypeView.str();
|
||||||
}
|
}
|
||||||
|
if ("Addressable".equals(typeRef.name())) {
|
||||||
|
yield TypeView.addressable(typeRef.name());
|
||||||
|
}
|
||||||
if (structs.containsKey(typeRef.name()) || knownStructNames.contains(typeRef.name())) {
|
if (structs.containsKey(typeRef.name()) || knownStructNames.contains(typeRef.name())) {
|
||||||
yield TypeView.struct(typeRef.name());
|
yield TypeView.struct(typeRef.name());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package p.studio.compiler.pbs.semantics;
|
package p.studio.compiler.pbs.semantics;
|
||||||
|
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.pbs.ast.PbsAst;
|
import p.studio.compiler.pbs.ast.PbsAst;
|
||||||
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||||
import p.studio.utilities.structures.ReadOnlyList;
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
@ -8,13 +9,14 @@ public final class PbsFlowSemanticsValidator {
|
|||||||
private final PbsFlowBodyAnalyzer flowBodyAnalyzer = new PbsFlowBodyAnalyzer();
|
private final PbsFlowBodyAnalyzer flowBodyAnalyzer = new PbsFlowBodyAnalyzer();
|
||||||
|
|
||||||
public void validate(final PbsAst.File ast, final DiagnosticSink diagnostics) {
|
public void validate(final PbsAst.File ast, final DiagnosticSink diagnostics) {
|
||||||
flowBodyAnalyzer.validate(ast, ReadOnlyList.empty(), diagnostics);
|
flowBodyAnalyzer.validate(ast, ReadOnlyList.empty(), FESurfaceContext.empty(), diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validate(
|
public void validate(
|
||||||
final PbsAst.File ast,
|
final PbsAst.File ast,
|
||||||
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
||||||
|
final FESurfaceContext feSurfaceContext,
|
||||||
final DiagnosticSink diagnostics) {
|
final DiagnosticSink diagnostics) {
|
||||||
flowBodyAnalyzer.validate(ast, supplementalTopDecls, diagnostics);
|
flowBodyAnalyzer.validate(ast, supplementalTopDecls, feSurfaceContext, diagnostics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,10 @@ final class PbsFlowStructuralExpressionAnalyzer {
|
|||||||
return ExprResult.type(receiverType);
|
return ExprResult.type(receiverType);
|
||||||
}
|
}
|
||||||
if (expression instanceof PbsAst.IdentifierExpr identifierExpr) {
|
if (expression instanceof PbsAst.IdentifierExpr identifierExpr) {
|
||||||
|
if ("assets".equals(identifierExpr.name()) && model.hasAssetNamespaceRoot()) {
|
||||||
|
return ExprResult.type(TypeView.assetNamespace("assets"));
|
||||||
|
}
|
||||||
|
|
||||||
final var localType = context.scope().resolve(identifierExpr.name());
|
final var localType = context.scope().resolve(identifierExpr.name());
|
||||||
if (localType != null) {
|
if (localType != null) {
|
||||||
return ExprResult.type(localType);
|
return ExprResult.type(localType);
|
||||||
|
|||||||
@ -47,7 +47,8 @@ final class PbsFlowTypeOps {
|
|||||||
}
|
}
|
||||||
return switch (actual.kind()) {
|
return switch (actual.kind()) {
|
||||||
case UNIT, INT, FLOAT, BOOL, STR -> true;
|
case UNIT, INT, FLOAT, BOOL, STR -> true;
|
||||||
case STRUCT, SERVICE, CONTRACT, CALLBACK, ENUM, ERROR, TYPE_REF -> actual.name().equals(expected.name());
|
case STRUCT, SERVICE, CONTRACT, CALLBACK, ENUM, ERROR, TYPE_REF, ASSET_NAMESPACE -> actual.name().equals(expected.name());
|
||||||
|
case ADDRESSABLE -> true;
|
||||||
case OPTIONAL -> compatible(actual.inner(), expected.inner());
|
case OPTIONAL -> compatible(actual.inner(), expected.inner());
|
||||||
case RESULT -> compatible(actual.errorType(), expected.errorType()) && compatible(actual.inner(), expected.inner());
|
case RESULT -> compatible(actual.errorType(), expected.errorType()) && compatible(actual.inner(), expected.inner());
|
||||||
case TUPLE -> tupleCompatible(actual, expected);
|
case TUPLE -> tupleCompatible(actual, expected);
|
||||||
@ -173,6 +174,9 @@ final class PbsFlowTypeOps {
|
|||||||
if ("str".equals(name)) {
|
if ("str".equals(name)) {
|
||||||
return TypeView.str();
|
return TypeView.str();
|
||||||
}
|
}
|
||||||
|
if ("Addressable".equals(name)) {
|
||||||
|
return TypeView.addressable(name);
|
||||||
|
}
|
||||||
if (model.structs.containsKey(name)) {
|
if (model.structs.containsKey(name)) {
|
||||||
return TypeView.struct(name);
|
return TypeView.struct(name);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package p.studio.compiler.services;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import p.studio.compiler.messages.BuildingIssueSink;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.messages.FrontendPhaseContext;
|
import p.studio.compiler.messages.FrontendPhaseContext;
|
||||||
import p.studio.compiler.models.IRBackend;
|
import p.studio.compiler.models.IRBackend;
|
||||||
import p.studio.compiler.models.IRBackendExecutableFunction;
|
import p.studio.compiler.models.IRBackendExecutableFunction;
|
||||||
@ -59,6 +60,7 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
|||||||
final LogAggregator logs,
|
final LogAggregator logs,
|
||||||
final BuildingIssueSink issues) {
|
final BuildingIssueSink issues) {
|
||||||
final var nameTable = ctx.nameTable();
|
final var nameTable = ctx.nameTable();
|
||||||
|
final var feSurfaceContext = ctx.feSurfaceContext();
|
||||||
final var assembly = moduleAssemblyService.assemble(ctx, nameTable, diagnostics, issues);
|
final var assembly = moduleAssemblyService.assemble(ctx, nameTable, diagnostics, issues);
|
||||||
final var parsedSourceFiles = assembly.parsedSourceFiles();
|
final var parsedSourceFiles = assembly.parsedSourceFiles();
|
||||||
final var importedSemanticContexts = importedSemanticContextService.build(parsedSourceFiles, assembly.moduleTable());
|
final var importedSemanticContexts = importedSemanticContextService.build(parsedSourceFiles, assembly.moduleTable());
|
||||||
@ -85,6 +87,7 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
|||||||
parsedSource.moduleId(),
|
parsedSource.moduleId(),
|
||||||
canonicalModulePool,
|
canonicalModulePool,
|
||||||
ctx.hostAdmissionContext(),
|
ctx.hostAdmissionContext(),
|
||||||
|
feSurfaceContext,
|
||||||
nameTable,
|
nameTable,
|
||||||
importedSemanticContext.supplementalTopDecls(),
|
importedSemanticContext.supplementalTopDecls(),
|
||||||
importedSemanticContext.importedCallables(),
|
importedSemanticContext.importedCallables(),
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package p.studio.compiler.pbs;
|
package p.studio.compiler.pbs;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import p.studio.compiler.messages.Addressable;
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.messages.HostAdmissionContext;
|
import p.studio.compiler.messages.HostAdmissionContext;
|
||||||
import p.studio.compiler.models.IRHiddenGlobalKind;
|
import p.studio.compiler.models.IRHiddenGlobalKind;
|
||||||
import p.studio.compiler.models.IRGlobalVisibility;
|
import p.studio.compiler.models.IRGlobalVisibility;
|
||||||
@ -458,6 +460,58 @@ class PbsFrontendCompilerTest {
|
|||||||
&& h.abiVersion() == 1));
|
&& h.abiVersion() == 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldLowerBackendOwnedAssetReferenceToAssetId() {
|
||||||
|
final var source = """
|
||||||
|
fn boot() -> Addressable {
|
||||||
|
return assets.ui.panel;
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
final var compiler = new PbsFrontendCompiler();
|
||||||
|
final var fileBackend = compiler.compileFile(
|
||||||
|
new FileId(12),
|
||||||
|
source,
|
||||||
|
diagnostics,
|
||||||
|
SourceKind.PROJECT,
|
||||||
|
HostAdmissionContext.permissiveDefault(),
|
||||||
|
new FESurfaceContext(ReadOnlyList.from(new Addressable("assets.ui.panel", 37))));
|
||||||
|
|
||||||
|
assertTrue(diagnostics.isEmpty(), diagnostics.stream().map(d -> d.getCode() + ":" + d.getMessage()).toList().toString());
|
||||||
|
final var executableBoot = fileBackend.executableFunctions().stream()
|
||||||
|
.filter(fn -> fn.callableName().equals("boot"))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow();
|
||||||
|
assertTrue(executableBoot.instructions().stream().anyMatch(i ->
|
||||||
|
i.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.PUSH_I32
|
||||||
|
&& "37".equals(i.label())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldRejectUnresolvedBackendOwnedAssetReference() {
|
||||||
|
final var source = """
|
||||||
|
fn boot() -> Addressable {
|
||||||
|
return assets.ui.missing;
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
final var compiler = new PbsFrontendCompiler();
|
||||||
|
final var fileBackend = compiler.compileFile(
|
||||||
|
new FileId(13),
|
||||||
|
source,
|
||||||
|
diagnostics,
|
||||||
|
SourceKind.PROJECT,
|
||||||
|
HostAdmissionContext.permissiveDefault(),
|
||||||
|
new FESurfaceContext(ReadOnlyList.from(new Addressable("assets.ui.panel", 37))));
|
||||||
|
|
||||||
|
assertTrue(diagnostics.stream().anyMatch(d ->
|
||||||
|
d.getCode().equals(PbsSemanticsErrors.E_SEM_INVALID_MEMBER_ACCESS.name())
|
||||||
|
&& d.getMessage().contains("assets.ui.missing")));
|
||||||
|
assertEquals(0, fileBackend.executableFunctions().size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRejectHostBindingWithoutCapabilityAtHostAdmission() {
|
void shouldRejectHostBindingWithoutCapabilityAtHostAdmission() {
|
||||||
final var source = """
|
final var source = """
|
||||||
|
|||||||
@ -2,7 +2,9 @@ package p.studio.compiler.services;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
import p.studio.compiler.messages.Addressable;
|
||||||
import p.studio.compiler.messages.BuildingIssueSink;
|
import p.studio.compiler.messages.BuildingIssueSink;
|
||||||
|
import p.studio.compiler.messages.FESurfaceContext;
|
||||||
import p.studio.compiler.messages.FrontendPhaseContext;
|
import p.studio.compiler.messages.FrontendPhaseContext;
|
||||||
import p.studio.compiler.models.IRGlobalVisibility;
|
import p.studio.compiler.models.IRGlobalVisibility;
|
||||||
import p.studio.compiler.models.BuildStack;
|
import p.studio.compiler.models.BuildStack;
|
||||||
@ -40,6 +42,61 @@ class PBSFrontendPhaseServiceTest {
|
|||||||
@TempDir
|
@TempDir
|
||||||
Path tempDir;
|
Path tempDir;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldPropagateBackendOwnedAssetSurfaceIntoPbsFrontendCompilation() throws IOException {
|
||||||
|
final var projectRoot = tempDir.resolve("project-assets");
|
||||||
|
final var sourceRoot = projectRoot.resolve("src");
|
||||||
|
final var modulePath = sourceRoot.resolve("main");
|
||||||
|
Files.createDirectories(modulePath);
|
||||||
|
|
||||||
|
final var sourceFile = modulePath.resolve("source.pbs");
|
||||||
|
final var modBarrel = modulePath.resolve("mod.barrel");
|
||||||
|
Files.writeString(sourceFile, """
|
||||||
|
[Frame]
|
||||||
|
fn frame() -> void {
|
||||||
|
let asset: Addressable = assets.ui.panel;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
Files.writeString(modBarrel, "pub fn frame() -> void;");
|
||||||
|
|
||||||
|
final var projectTable = new ProjectTable();
|
||||||
|
final var fileTable = new FileTable(1);
|
||||||
|
final var projectId = projectTable.register(ProjectDescriptor.builder()
|
||||||
|
.rootPath(projectRoot)
|
||||||
|
.name("core")
|
||||||
|
.version("1.0.0")
|
||||||
|
.sourceRoots(ReadOnlyList.wrap(List.of(sourceRoot)))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
registerFile(projectId, projectRoot, sourceFile, fileTable);
|
||||||
|
registerFile(projectId, projectRoot, modBarrel, fileTable);
|
||||||
|
|
||||||
|
final var ctx = new FrontendPhaseContext(
|
||||||
|
projectTable,
|
||||||
|
fileTable,
|
||||||
|
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
|
||||||
|
1,
|
||||||
|
p.studio.compiler.messages.HostAdmissionContext.permissiveDefault(),
|
||||||
|
new FESurfaceContext(ReadOnlyList.from(new Addressable("assets.ui.panel", 91))));
|
||||||
|
final var diagnostics = DiagnosticSink.empty();
|
||||||
|
|
||||||
|
final var irBackend = new PBSFrontendPhaseService().compile(
|
||||||
|
ctx,
|
||||||
|
diagnostics,
|
||||||
|
LogAggregator.empty(),
|
||||||
|
BuildingIssueSink.empty());
|
||||||
|
|
||||||
|
assertTrue(diagnostics.isEmpty(), diagnostics.stream().map(d -> d.getCode() + ":" + d.getMessage()).toList().toString());
|
||||||
|
final var frameFn = irBackend.getExecutableFunctions().stream()
|
||||||
|
.filter(function -> "frame".equals(function.callableName()))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow();
|
||||||
|
assertTrue(frameFn.instructions().stream().anyMatch(instruction ->
|
||||||
|
instruction.kind() == p.studio.compiler.models.IRBackendExecutableFunction.InstructionKind.PUSH_I32
|
||||||
|
&& "91".equals(instruction.label())));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldReportInvalidBarrelFilename() throws IOException {
|
void shouldReportInvalidBarrelFilename() throws IOException {
|
||||||
final var projectRoot = tempDir.resolve("project");
|
final var projectRoot = tempDir.resolve("project");
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
package p.studio.compiler.messages;
|
||||||
|
|
||||||
|
public record Addressable(
|
||||||
|
String address,
|
||||||
|
int assetId) {
|
||||||
|
|
||||||
|
public Addressable {
|
||||||
|
address = normalize(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalize(final String address) {
|
||||||
|
if (address == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return address.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package p.studio.compiler.messages;
|
||||||
|
|
||||||
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
public record FESurfaceContext(
|
||||||
|
ReadOnlyList<Addressable> assets) {
|
||||||
|
|
||||||
|
public FESurfaceContext {
|
||||||
|
assets = normalizeAssets(assets);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FESurfaceContext empty() {
|
||||||
|
return new FESurfaceContext(ReadOnlyList.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ReadOnlyList<Addressable> normalizeAssets(final ReadOnlyList<Addressable> assets) {
|
||||||
|
if (assets == null || assets.isEmpty()) {
|
||||||
|
return ReadOnlyList.empty();
|
||||||
|
}
|
||||||
|
final var dedup = new LinkedHashMap<String, Addressable>();
|
||||||
|
for (final var asset : assets) {
|
||||||
|
if (asset == null || asset.address().isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dedup.put(asset.address(), asset);
|
||||||
|
}
|
||||||
|
return ReadOnlyList.wrap(new ArrayList<>(dedup.values()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,12 +14,13 @@ public class FrontendPhaseContext {
|
|||||||
private final NameTable nameTable;
|
private final NameTable nameTable;
|
||||||
private final int stdlibVersion;
|
private final int stdlibVersion;
|
||||||
private final HostAdmissionContext hostAdmissionContext;
|
private final HostAdmissionContext hostAdmissionContext;
|
||||||
|
private final FESurfaceContext feSurfaceContext;
|
||||||
|
|
||||||
public FrontendPhaseContext(
|
public FrontendPhaseContext(
|
||||||
final ProjectTableReader projectTable,
|
final ProjectTableReader projectTable,
|
||||||
final FileTableReader fileTable,
|
final FileTableReader fileTable,
|
||||||
final BuildStack stack) {
|
final BuildStack stack) {
|
||||||
this(projectTable, fileTable, stack, 1, HostAdmissionContext.permissiveDefault());
|
this(projectTable, fileTable, stack, 1, HostAdmissionContext.permissiveDefault(), FESurfaceContext.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public FrontendPhaseContext(
|
public FrontendPhaseContext(
|
||||||
@ -27,7 +28,7 @@ public class FrontendPhaseContext {
|
|||||||
final FileTableReader fileTable,
|
final FileTableReader fileTable,
|
||||||
final BuildStack stack,
|
final BuildStack stack,
|
||||||
final int stdlibVersion) {
|
final int stdlibVersion) {
|
||||||
this(projectTable, fileTable, stack, stdlibVersion, HostAdmissionContext.permissiveDefault());
|
this(projectTable, fileTable, stack, stdlibVersion, HostAdmissionContext.permissiveDefault(), FESurfaceContext.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
public FrontendPhaseContext(
|
public FrontendPhaseContext(
|
||||||
@ -36,6 +37,16 @@ public class FrontendPhaseContext {
|
|||||||
final BuildStack stack,
|
final BuildStack stack,
|
||||||
final int stdlibVersion,
|
final int stdlibVersion,
|
||||||
final HostAdmissionContext hostAdmissionContext) {
|
final HostAdmissionContext hostAdmissionContext) {
|
||||||
|
this(projectTable, fileTable, stack, stdlibVersion, hostAdmissionContext, FESurfaceContext.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrontendPhaseContext(
|
||||||
|
final ProjectTableReader projectTable,
|
||||||
|
final FileTableReader fileTable,
|
||||||
|
final BuildStack stack,
|
||||||
|
final int stdlibVersion,
|
||||||
|
final HostAdmissionContext hostAdmissionContext,
|
||||||
|
final FESurfaceContext feSurfaceContext) {
|
||||||
this.projectTable = projectTable;
|
this.projectTable = projectTable;
|
||||||
this.fileTable = fileTable;
|
this.fileTable = fileTable;
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
@ -44,6 +55,9 @@ public class FrontendPhaseContext {
|
|||||||
this.hostAdmissionContext = hostAdmissionContext == null
|
this.hostAdmissionContext = hostAdmissionContext == null
|
||||||
? HostAdmissionContext.permissiveDefault()
|
? HostAdmissionContext.permissiveDefault()
|
||||||
: hostAdmissionContext;
|
: hostAdmissionContext;
|
||||||
|
this.feSurfaceContext = feSurfaceContext == null
|
||||||
|
? FESurfaceContext.empty()
|
||||||
|
: feSurfaceContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceKind sourceKind(final ProjectId projectId) {
|
public SourceKind sourceKind(final ProjectId projectId) {
|
||||||
@ -61,4 +75,8 @@ public class FrontendPhaseContext {
|
|||||||
public NameTable nameTable() {
|
public NameTable nameTable() {
|
||||||
return nameTable;
|
return nameTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FESurfaceContext feSurfaceContext() {
|
||||||
|
return feSurfaceContext;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user