implements PR023

This commit is contained in:
bQUARKz 2026-03-06 11:45:47 +00:00
parent 213c6a2f76
commit 57f1a617ac
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
13 changed files with 383 additions and 15 deletions

View File

@ -0,0 +1,22 @@
package p.studio.compiler.pbs.stdlib;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.Optional;
public final class EmptyStdlibEnvironmentResolver implements StdlibEnvironmentResolver {
private static final StdlibEnvironment EMPTY = new StdlibEnvironment() {
@Override
public Optional<StdlibModuleSource> resolveModule(
final String project,
final ReadOnlyList<String> pathSegments) {
return Optional.empty();
}
};
@Override
public StdlibEnvironment resolve(final int stdlibVersion) {
return EMPTY;
}
}

View File

@ -0,0 +1,63 @@
package p.studio.compiler.pbs.stdlib;
import p.studio.compiler.pbs.ast.PbsAst;
import p.studio.compiler.pbs.lexer.PbsLexer;
import p.studio.compiler.pbs.linking.PbsModuleVisibilityValidator;
import p.studio.compiler.pbs.parser.PbsBarrelParser;
import p.studio.compiler.pbs.parser.PbsParser;
import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
public final class InterfaceModuleLoader {
private final AtomicInteger nextSyntheticFileId;
public InterfaceModuleLoader() {
this(1_000_000);
}
public InterfaceModuleLoader(final int firstSyntheticFileId) {
this.nextSyntheticFileId = new AtomicInteger(firstSyntheticFileId);
}
public PbsModuleVisibilityValidator.ModuleUnit load(
final StdlibModuleSource moduleSource,
final DiagnosticSink diagnostics) {
final var sources = new ArrayList<PbsModuleVisibilityValidator.SourceFile>(moduleSource.sourceFiles().size());
for (final var sourceFile : moduleSource.sourceFiles()) {
final var fileId = new FileId(nextSyntheticFileId.getAndIncrement());
final var sourceAst = parseSource(sourceFile.source(), fileId, diagnostics);
sources.add(new PbsModuleVisibilityValidator.SourceFile(fileId, sourceAst));
}
final var barrels = new ArrayList<PbsModuleVisibilityValidator.BarrelFile>(1);
final var barrelFileId = new FileId(nextSyntheticFileId.getAndIncrement());
final var barrelAst = parseBarrel(moduleSource.barrelSource(), barrelFileId, diagnostics);
barrels.add(new PbsModuleVisibilityValidator.BarrelFile(barrelFileId, barrelAst));
return new PbsModuleVisibilityValidator.ModuleUnit(
new PbsModuleVisibilityValidator.ModuleCoordinates(moduleSource.project(), moduleSource.pathSegments()),
ReadOnlyList.wrap(sources),
ReadOnlyList.wrap(barrels));
}
private PbsAst.File parseSource(
final String source,
final FileId fileId,
final DiagnosticSink diagnostics) {
final var tokens = PbsLexer.lex(source, fileId, diagnostics);
return PbsParser.parse(tokens, fileId, diagnostics);
}
private PbsAst.BarrelFile parseBarrel(
final String source,
final FileId fileId,
final DiagnosticSink diagnostics) {
final var tokens = PbsLexer.lex(source, fileId, diagnostics);
return PbsBarrelParser.parse(tokens, fileId, diagnostics);
}
}

View File

@ -0,0 +1,10 @@
package p.studio.compiler.pbs.stdlib;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.Optional;
public interface StdlibEnvironment {
Optional<StdlibModuleSource> resolveModule(String project, ReadOnlyList<String> pathSegments);
}

View File

@ -0,0 +1,6 @@
package p.studio.compiler.pbs.stdlib;
public interface StdlibEnvironmentResolver {
StdlibEnvironment resolve(int stdlibVersion);
}

View File

@ -0,0 +1,29 @@
package p.studio.compiler.pbs.stdlib;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.Objects;
public record StdlibModuleSource(
String project,
ReadOnlyList<String> pathSegments,
ReadOnlyList<SourceFile> sourceFiles,
String barrelSource) {
public StdlibModuleSource {
project = Objects.requireNonNull(project, "project");
pathSegments = pathSegments == null ? ReadOnlyList.empty() : pathSegments;
sourceFiles = sourceFiles == null ? ReadOnlyList.empty() : sourceFiles;
barrelSource = Objects.requireNonNull(barrelSource, "barrelSource");
}
public record SourceFile(
String logicalPath,
String source) {
public SourceFile {
logicalPath = Objects.requireNonNull(logicalPath, "logicalPath");
source = Objects.requireNonNull(source, "source");
}
}
}

View File

@ -14,6 +14,9 @@ import p.studio.compiler.pbs.linking.PbsLinkErrors;
import p.studio.compiler.pbs.linking.PbsModuleVisibilityValidator; import p.studio.compiler.pbs.linking.PbsModuleVisibilityValidator;
import p.studio.compiler.pbs.parser.PbsBarrelParser; import p.studio.compiler.pbs.parser.PbsBarrelParser;
import p.studio.compiler.pbs.parser.PbsParser; import p.studio.compiler.pbs.parser.PbsParser;
import p.studio.compiler.pbs.stdlib.EmptyStdlibEnvironmentResolver;
import p.studio.compiler.pbs.stdlib.InterfaceModuleLoader;
import p.studio.compiler.pbs.stdlib.StdlibEnvironmentResolver;
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.DiagnosticSink;
import p.studio.compiler.source.diagnostics.DiagnosticPhase; import p.studio.compiler.source.diagnostics.DiagnosticPhase;
@ -23,6 +26,7 @@ import p.studio.utilities.logs.LogAggregator;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -34,6 +38,19 @@ import java.util.Set;
public class PBSFrontendPhaseService implements FrontendPhaseService { public class PBSFrontendPhaseService implements FrontendPhaseService {
private final PbsFrontendCompiler frontendCompiler = new PbsFrontendCompiler(); private final PbsFrontendCompiler frontendCompiler = new PbsFrontendCompiler();
private final PbsModuleVisibilityValidator moduleVisibilityValidator = new PbsModuleVisibilityValidator(); private final PbsModuleVisibilityValidator moduleVisibilityValidator = new PbsModuleVisibilityValidator();
private final StdlibEnvironmentResolver stdlibEnvironmentResolver;
private final InterfaceModuleLoader interfaceModuleLoader;
public PBSFrontendPhaseService() {
this(new EmptyStdlibEnvironmentResolver(), new InterfaceModuleLoader());
}
PBSFrontendPhaseService(
final StdlibEnvironmentResolver stdlibEnvironmentResolver,
final InterfaceModuleLoader interfaceModuleLoader) {
this.stdlibEnvironmentResolver = stdlibEnvironmentResolver;
this.interfaceModuleLoader = interfaceModuleLoader;
}
@Override @Override
public IRBackend compile( public IRBackend compile(
@ -99,6 +116,8 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
} }
} }
loadReservedStdlibModules(modulesByCoordinates, diagnostics, ctx.stdlibVersion());
final var modules = new ArrayList<PbsModuleVisibilityValidator.ModuleUnit>(modulesByCoordinates.size()); final var modules = new ArrayList<PbsModuleVisibilityValidator.ModuleUnit>(modulesByCoordinates.size());
for (final var entry : modulesByCoordinates.entrySet()) { for (final var entry : modulesByCoordinates.entrySet()) {
final var coordinates = entry.getKey(); final var coordinates = entry.getKey();
@ -127,6 +146,67 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
return irBackend; return irBackend;
} }
private void loadReservedStdlibModules(
final Map<PbsModuleVisibilityValidator.ModuleCoordinates, MutableModuleUnit> modulesByCoordinates,
final DiagnosticSink diagnostics,
final int stdlibVersion) {
final var stdlibEnvironment = stdlibEnvironmentResolver.resolve(stdlibVersion);
final var pending = new ArrayDeque<PbsModuleVisibilityValidator.ModuleCoordinates>();
final var resolved = new HashSet<String>();
enqueueReservedImportsFromKnownModules(modulesByCoordinates, pending);
while (!pending.isEmpty()) {
final var target = pending.removeFirst();
final var targetKey = moduleKey(target);
if (!resolved.add(targetKey)) {
continue;
}
if (modulesByCoordinates.containsKey(target)) {
continue;
}
final var moduleSource = stdlibEnvironment.resolveModule(target.project(), target.pathSegments());
if (moduleSource.isEmpty()) {
continue;
}
final var loadedModule = interfaceModuleLoader.load(moduleSource.get(), diagnostics);
final var moduleData = new MutableModuleUnit();
moduleData.sources.addAll(loadedModule.sourceFiles().asList());
moduleData.barrels.addAll(loadedModule.barrelFiles().asList());
modulesByCoordinates.put(loadedModule.coordinates(), moduleData);
enqueueReservedImportsFromSourceFiles(loadedModule.sourceFiles().asList(), pending);
}
}
private void enqueueReservedImportsFromKnownModules(
final Map<PbsModuleVisibilityValidator.ModuleCoordinates, MutableModuleUnit> modulesByCoordinates,
final ArrayDeque<PbsModuleVisibilityValidator.ModuleCoordinates> pending) {
for (final var moduleUnit : modulesByCoordinates.values()) {
enqueueReservedImportsFromSourceFiles(moduleUnit.sources, pending);
}
}
private void enqueueReservedImportsFromSourceFiles(
final Iterable<PbsModuleVisibilityValidator.SourceFile> sourceFiles,
final ArrayDeque<PbsModuleVisibilityValidator.ModuleCoordinates> pending) {
for (final var source : sourceFiles) {
for (final var importDecl : source.ast().imports()) {
final var moduleRef = importDecl.moduleRef();
if (!isReservedProjectSpace(moduleRef.project())) {
continue;
}
pending.addLast(new PbsModuleVisibilityValidator.ModuleCoordinates(
moduleRef.project(),
moduleRef.pathSegments()));
}
}
}
private boolean isReservedProjectSpace(final String projectName) {
return "core".equals(projectName) || "sdk".equals(projectName);
}
private PbsAst.File parseSourceFile( private PbsAst.File parseSourceFile(
final FileId fileId, final FileId fileId,
final String source, final String source,

View File

@ -8,6 +8,10 @@ import p.studio.compiler.models.BuildStack;
import p.studio.compiler.models.ProjectDescriptor; import p.studio.compiler.models.ProjectDescriptor;
import p.studio.compiler.models.SourceHandle; import p.studio.compiler.models.SourceHandle;
import p.studio.compiler.models.SourceKind; import p.studio.compiler.models.SourceKind;
import p.studio.compiler.pbs.stdlib.InterfaceModuleLoader;
import p.studio.compiler.pbs.stdlib.StdlibEnvironment;
import p.studio.compiler.pbs.stdlib.StdlibEnvironmentResolver;
import p.studio.compiler.pbs.stdlib.StdlibModuleSource;
import p.studio.compiler.pbs.linking.PbsLinkErrors; import p.studio.compiler.pbs.linking.PbsLinkErrors;
import p.studio.compiler.source.diagnostics.DiagnosticSink; import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.compiler.source.identifiers.ProjectId; import p.studio.compiler.source.identifiers.ProjectId;
@ -21,7 +25,10 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -216,6 +223,111 @@ class PBSFrontendPhaseServiceTest {
assertEquals(0, irBackend.getFunctions().size()); assertEquals(0, irBackend.getFunctions().size());
} }
@Test
void shouldResolveReservedImportsThroughStdlibResolverForSelectedMajor() throws IOException {
final var projectRoot = tempDir.resolve("project-stdlib");
final var sourceRoot = projectRoot.resolve("src");
final var modulePath = sourceRoot.resolve("app");
Files.createDirectories(modulePath);
final var sourceFile = modulePath.resolve("source.pbs");
final var modBarrel = modulePath.resolve("mod.barrel");
Files.writeString(sourceFile, """
import { draw } from @sdk:gfx;
fn use() -> int { return 1; }
""");
Files.writeString(modBarrel, "pub fn use() -> int;");
final var projectTable = new ProjectTable();
final var fileTable = new FileTable(1);
final var projectId = projectTable.register(ProjectDescriptor.builder()
.rootPath(projectRoot)
.name("app")
.version("1.0.0")
.sourceRoots(ReadOnlyList.wrap(List.of(sourceRoot)))
.build());
registerFile(projectId, projectRoot, sourceFile, fileTable);
registerFile(projectId, projectRoot, modBarrel, fileTable);
final var stdlibModule = new StdlibModuleSource(
"sdk",
ReadOnlyList.wrap(List.of("gfx")),
ReadOnlyList.wrap(List.of(new StdlibModuleSource.SourceFile("gfx.pbs", "fn draw() -> int { return 1; }"))),
"pub fn draw() -> int;");
final var frontendService = new PBSFrontendPhaseService(
resolverForMajor(7, stdlibModule),
new InterfaceModuleLoader(2_000_000));
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
7);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = frontendService.compile(
ctx,
diagnostics,
LogAggregator.empty(),
BuildingIssueSink.empty());
assertTrue(diagnostics.stream().noneMatch(d ->
d.getCode().equals(PbsLinkErrors.E_LINK_IMPORT_MODULE_NOT_FOUND.name())));
assertTrue(diagnostics.stream().noneMatch(d ->
d.getCode().equals(PbsLinkErrors.E_LINK_IMPORT_SYMBOL_UNRESOLVED.name())));
assertEquals(1, irBackend.getFunctions().size());
assertEquals("use", irBackend.getFunctions().getFirst().name());
}
@Test
void shouldReportReservedImportModuleNotFoundWhenStdlibResolverMissesModule() throws IOException {
final var projectRoot = tempDir.resolve("project-stdlib-missing");
final var sourceRoot = projectRoot.resolve("src");
final var modulePath = sourceRoot.resolve("app");
Files.createDirectories(modulePath);
final var sourceFile = modulePath.resolve("source.pbs");
final var modBarrel = modulePath.resolve("mod.barrel");
Files.writeString(sourceFile, """
import { draw } from @sdk:gfx;
fn use() -> int { return 1; }
""");
Files.writeString(modBarrel, "pub fn use() -> int;");
final var projectTable = new ProjectTable();
final var fileTable = new FileTable(1);
final var projectId = projectTable.register(ProjectDescriptor.builder()
.rootPath(projectRoot)
.name("app")
.version("1.0.0")
.sourceRoots(ReadOnlyList.wrap(List.of(sourceRoot)))
.build());
registerFile(projectId, projectRoot, sourceFile, fileTable);
registerFile(projectId, projectRoot, modBarrel, fileTable);
final var frontendService = new PBSFrontendPhaseService(
resolverForMajor(7),
new InterfaceModuleLoader(2_100_000));
final var ctx = new FrontendPhaseContext(
projectTable,
fileTable,
new BuildStack(ReadOnlyList.wrap(List.of(projectId))),
7);
final var diagnostics = DiagnosticSink.empty();
final var irBackend = frontendService.compile(
ctx,
diagnostics,
LogAggregator.empty(),
BuildingIssueSink.empty());
assertTrue(diagnostics.stream().anyMatch(d ->
d.getCode().equals(PbsLinkErrors.E_LINK_IMPORT_MODULE_NOT_FOUND.name())));
assertEquals(0, irBackend.getFunctions().size());
}
private void registerFile( private void registerFile(
final ProjectId projectId, final ProjectId projectId,
final Path projectRoot, final Path projectRoot,
@ -231,4 +343,32 @@ class PBSFrontendPhaseServiceTest {
SourceProviderFactory.filesystem())); SourceProviderFactory.filesystem()));
} }
private StdlibEnvironmentResolver resolverForMajor(
final int acceptedStdlib,
final StdlibModuleSource... modules) {
final var byModuleKey = new HashMap<String, StdlibModuleSource>();
for (final var module : modules) {
byModuleKey.put(moduleKey(module.project(), module.pathSegments()), module);
}
return stdlib -> {
if (stdlib != acceptedStdlib) {
return (project, pathSegments) -> Optional.empty();
}
return new StdlibEnvironment() {
@Override
public Optional<StdlibModuleSource> resolveModule(
final String project,
final ReadOnlyList<String> pathSegments) {
return Optional.ofNullable(byModuleKey.get(moduleKey(project, pathSegments)));
}
};
};
}
private String moduleKey(
final String project,
final ReadOnlyList<String> pathSegments) {
return project + ":" + String.join("/", pathSegments.asList());
}
} }

View File

@ -23,7 +23,11 @@ public class FrontendPhasePipelineStage implements PipelineStage {
} }
final var projectTable = ctx.resolvedWorkspace.graph().projectTable(); final var projectTable = ctx.resolvedWorkspace.graph().projectTable();
final var fileTable = ctx.fileTable; final var fileTable = ctx.fileTable;
final var frontendPhaseContext = new FrontendPhaseContext(projectTable, fileTable, ctx.resolvedWorkspace.stack()); final var frontendPhaseContext = new FrontendPhaseContext(
projectTable,
fileTable,
ctx.resolvedWorkspace.stack(),
ctx.resolvedWorkspace.stdlib());
final var diagnostics = DiagnosticSink.empty(); final var diagnostics = DiagnosticSink.empty();
final var issues = BuildingIssueSink.empty(); final var issues = BuildingIssueSink.empty();
ctx.irBackend = service.get().compile(frontendPhaseContext, diagnostics, logs, issues); ctx.irBackend = service.get().compile(frontendPhaseContext, diagnostics, logs, issues);

View File

@ -47,7 +47,7 @@ public final class DependencyContext {
throw new BuildException("dependenciesByProjectId: internal error: rootProjectId ProjectId not set"); throw new BuildException("dependenciesByProjectId: internal error: rootProjectId ProjectId not set");
} }
if (rootStdlib == null) { if (rootStdlib == null) {
throw new BuildException("dependenciesByProjectId: internal error: rootStdlibMajor not set"); throw new BuildException("dependenciesByProjectId: internal error: rootStdlib not set");
} }
final var dependenciesByProject = buildDependenciesByProject(); final var dependenciesByProject = buildDependenciesByProject();
final var workspaceGraph = new WorkspaceGraph(projectTable, dependenciesByProject); final var workspaceGraph = new WorkspaceGraph(projectTable, dependenciesByProject);

View File

@ -5,7 +5,7 @@ import p.studio.compiler.source.identifiers.ProjectId;
public record ResolvedWorkspace( public record ResolvedWorkspace(
ProjectId mainProjectId, ProjectId mainProjectId,
FrontendSpec frontendSpec, FrontendSpec frontendSpec,
int stdlibMajor, int stdlib,
WorkspaceGraph graph, WorkspaceGraph graph,
BuildStack stack) { BuildStack stack) {
public ProjectDescriptor mainProject() { public ProjectDescriptor mainProject() {

View File

@ -45,7 +45,7 @@ public final class PrometeuManifestUtils {
.error(true) .error(true)
.message("[DEPS]: manifest missing 'version': " + manifestPathCanon)); .message("[DEPS]: manifest missing 'version': " + manifestPathCanon));
} }
final var stdlibMajorMaybe = parseStdlibMajor(dto.stdlib(), manifestPathCanon, issuesLocal); final var stdlibMaybe = parseStdlib(dto.stdlib(), manifestPathCanon, issuesLocal);
final var language = StringUtils.isBlank(dto.language()) final var language = StringUtils.isBlank(dto.language())
? FrontendRegistryService.getDefaultFrontendSpec().getLanguageId() ? FrontendRegistryService.getDefaultFrontendSpec().getLanguageId()
: dto.language(); : dto.language();
@ -54,34 +54,34 @@ public final class PrometeuManifestUtils {
issues.merge(issuesLocal); issues.merge(issuesLocal);
return Optional.empty(); return Optional.empty();
} }
return Optional.of(new PrometeuManifest(dto.name(), dto.version(), language, stdlibMajorMaybe.getAsInt(), ReadOnlyList.wrap(dependencies))); return Optional.of(new PrometeuManifest(dto.name(), dto.version(), language, stdlibMaybe.getAsInt(), ReadOnlyList.wrap(dependencies)));
} }
private static OptionalInt parseStdlibMajor( private static OptionalInt parseStdlib(
final String stdlib, final String stdlibStr,
final Path manifestPathCanon, final Path manifestPathCanon,
final BuildingIssueSink issues) { final BuildingIssueSink issues) {
if (StringUtils.isBlank(stdlib)) { if (StringUtils.isBlank(stdlibStr)) {
issues.report(builder -> builder issues.report(builder -> builder
.error(true) .error(true)
.message("[DEPS]: manifest missing 'stdlib': " + manifestPathCanon)); .message("[DEPS]: manifest missing 'stdlib': " + manifestPathCanon));
return OptionalInt.empty(); return OptionalInt.empty();
} }
final int stdlibMajor; final int stdlib;
try { try {
stdlibMajor = Integer.parseInt(stdlib); stdlib = Integer.parseInt(stdlibStr);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
issues.report(builder -> builder issues.report(builder -> builder
.error(true) .error(true)
.message("[DEPS]: invalid 'stdlib' major version \"" + stdlib + "\": " + manifestPathCanon)); .message("[DEPS]: invalid 'stdlib' major version \"" + stdlibStr + "\": " + manifestPathCanon));
return OptionalInt.empty(); return OptionalInt.empty();
} }
if (stdlibMajor <= 0 || !stdlib.equals(Integer.toString(stdlibMajor))) { if (stdlib <= 0 || !stdlibStr.equals(Integer.toString(stdlib))) {
issues.report(builder -> builder issues.report(builder -> builder
.error(true) .error(true)
.message("[DEPS]: invalid 'stdlib' major version \"" + stdlib + "\": " + manifestPathCanon)); .message("[DEPS]: invalid 'stdlib' major version \"" + stdlibStr + "\": " + manifestPathCanon));
return OptionalInt.empty(); return OptionalInt.empty();
} }
return OptionalInt.of(stdlibMajor); return OptionalInt.of(stdlib);
} }
} }

View File

@ -16,7 +16,7 @@ class PrometeuManifestUtilsTest {
Path tempDir; Path tempDir;
@Test @Test
void buildManifestParsesStdlibMajor() throws IOException { void buildManifestParsesStdlib() throws IOException {
final var manifestPath = writeManifest(""" final var manifestPath = writeManifest("""
{ {
"name": "main", "name": "main",

View File

@ -10,17 +10,31 @@ public class FrontendPhaseContext {
public final ProjectTableReader projectTable; public final ProjectTableReader projectTable;
public final FileTableReader fileTable; public final FileTableReader fileTable;
public final BuildStack stack; public final BuildStack stack;
private final int stdlibVersion;
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);
}
public FrontendPhaseContext(
final ProjectTableReader projectTable,
final FileTableReader fileTable,
final BuildStack stack,
final int stdlibVersion) {
this.projectTable = projectTable; this.projectTable = projectTable;
this.fileTable = fileTable; this.fileTable = fileTable;
this.stack = stack; this.stack = stack;
this.stdlibVersion = stdlibVersion;
} }
public SourceKind sourceKind(final ProjectId projectId) { public SourceKind sourceKind(final ProjectId projectId) {
return projectTable.sourceKind(projectId); return projectTable.sourceKind(projectId);
} }
public int stdlibVersion() {
return stdlibVersion;
}
} }