implements PR-05.0.5
This commit is contained in:
parent
19f293d8ea
commit
9aac65a2e9
@ -5,36 +5,50 @@ 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.tables.FileTable;
|
||||
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||
import p.studio.compiler.source.identifiers.FileId;
|
||||
import p.studio.compiler.source.identifiers.ProjectId;
|
||||
import p.studio.compiler.models.SourceHandle;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
|
||||
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 InterfaceModuleLoader(final int ignoredSyntheticSeed) {
|
||||
this();
|
||||
}
|
||||
|
||||
public PbsModuleVisibilityValidator.ModuleUnit load(
|
||||
final StdlibModuleSource moduleSource,
|
||||
final ProjectId syntheticOwnerProjectId,
|
||||
final FileTable fileTable,
|
||||
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());
|
||||
for (int i = 0; i < moduleSource.sourceFiles().size(); i++) {
|
||||
final var sourceFile = moduleSource.sourceFiles().get(i);
|
||||
final var fileId = registerSyntheticFile(
|
||||
syntheticOwnerProjectId,
|
||||
moduleSource,
|
||||
sourceFile.logicalPath(),
|
||||
sourceFile.source(),
|
||||
fileTable);
|
||||
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 barrelFileId = registerSyntheticFile(
|
||||
syntheticOwnerProjectId,
|
||||
moduleSource,
|
||||
"mod.barrel",
|
||||
moduleSource.barrelSource(),
|
||||
fileTable);
|
||||
final var barrelAst = parseBarrel(moduleSource.barrelSource(), barrelFileId, diagnostics);
|
||||
barrels.add(new PbsModuleVisibilityValidator.BarrelFile(barrelFileId, barrelAst));
|
||||
|
||||
@ -44,6 +58,34 @@ public final class InterfaceModuleLoader {
|
||||
ReadOnlyList.wrap(barrels));
|
||||
}
|
||||
|
||||
private FileId registerSyntheticFile(
|
||||
final ProjectId syntheticOwnerProjectId,
|
||||
final StdlibModuleSource moduleSource,
|
||||
final String logicalPath,
|
||||
final String source,
|
||||
final FileTable fileTable) {
|
||||
final var normalizedLogicalPath = (logicalPath == null || logicalPath.isBlank())
|
||||
? "source.pbs"
|
||||
: logicalPath;
|
||||
final var relativePath = Path.of("@stdlib")
|
||||
.resolve(moduleSource.project())
|
||||
.resolve(String.join("/", moduleSource.pathSegments().asList()))
|
||||
.resolve(normalizedLogicalPath);
|
||||
final var canonPath = Path.of("/virtual/stdlib")
|
||||
.resolve(moduleSource.project())
|
||||
.resolve(String.join("/", moduleSource.pathSegments().asList()))
|
||||
.resolve(normalizedLogicalPath);
|
||||
final var utf8 = source == null ? new byte[0] : source.getBytes(StandardCharsets.UTF_8);
|
||||
final var sourceHandle = new SourceHandle(
|
||||
syntheticOwnerProjectId,
|
||||
relativePath,
|
||||
canonPath,
|
||||
utf8.length,
|
||||
0,
|
||||
ignored -> () -> utf8);
|
||||
return fileTable.register(sourceHandle);
|
||||
}
|
||||
|
||||
private PbsAst.File parseSource(
|
||||
final String source,
|
||||
final FileId fileId,
|
||||
|
||||
@ -22,6 +22,8 @@ import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||
import p.studio.compiler.source.diagnostics.DiagnosticPhase;
|
||||
import p.studio.compiler.source.identifiers.FileId;
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
import p.studio.compiler.source.identifiers.ProjectId;
|
||||
import p.studio.compiler.source.tables.FileTable;
|
||||
import p.studio.compiler.source.tables.ModuleReference;
|
||||
import p.studio.compiler.source.tables.ModuleTable;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
@ -62,17 +64,25 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
final LogAggregator logs,
|
||||
final BuildingIssueSink issues) {
|
||||
final var nameTable = ctx.nameTable();
|
||||
if (!(ctx.fileTable instanceof FileTable writableFileTable)) {
|
||||
throw new IllegalStateException("PBS frontend requires writable FileTable for synthetic stdlib sources");
|
||||
}
|
||||
final var irBackendAggregator = IRBackend.aggregator();
|
||||
final var parsedSourceFiles = new ArrayList<ParsedSourceFile>();
|
||||
final Map<PbsModuleVisibilityValidator.ModuleCoordinates, MutableModuleUnit> modulesByCoordinates = new LinkedHashMap<>();
|
||||
final var moduleTable = new ModuleTable();
|
||||
final var moduleIdByFile = new HashMap<FileId, ModuleId>();
|
||||
final var failedModuleIds = new HashSet<ModuleId>();
|
||||
final var projectIdByName = new HashMap<String, ProjectId>();
|
||||
final var defaultSyntheticOwnerProjectId = ctx.stack.reverseTopologicalOrder.isEmpty()
|
||||
? null
|
||||
: ctx.stack.reverseTopologicalOrder.getFirst();
|
||||
|
||||
for (final var pId : ctx.stack.reverseTopologicalOrder) {
|
||||
final var projectDescriptor = ctx.projectTable.get(pId);
|
||||
final var projectSourceKind = ctx.sourceKind(pId);
|
||||
final var fileIds = ctx.fileTable.getFiles(pId);
|
||||
projectIdByName.putIfAbsent(projectDescriptor.getName(), pId);
|
||||
|
||||
for (final var fId : fileIds) {
|
||||
final var sourceHandle = ctx.fileTable.get(fId);
|
||||
@ -126,6 +136,9 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
parsedSourceFiles,
|
||||
moduleIdByFile,
|
||||
moduleTable,
|
||||
writableFileTable,
|
||||
projectIdByName,
|
||||
defaultSyntheticOwnerProjectId,
|
||||
diagnostics,
|
||||
ctx.stdlibVersion());
|
||||
|
||||
@ -181,6 +194,9 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
final ArrayList<ParsedSourceFile> parsedSourceFiles,
|
||||
final Map<FileId, ModuleId> moduleIdByFile,
|
||||
final ModuleTable moduleTable,
|
||||
final FileTable fileTable,
|
||||
final Map<String, ProjectId> projectIdByName,
|
||||
final ProjectId defaultSyntheticOwnerProjectId,
|
||||
final DiagnosticSink diagnostics,
|
||||
final int stdlibVersion) {
|
||||
final var stdlibEnvironment = stdlibEnvironmentResolver.resolve(stdlibVersion);
|
||||
@ -203,7 +219,15 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
continue;
|
||||
}
|
||||
|
||||
final var loadedModule = interfaceModuleLoader.load(moduleSource.get(), diagnostics);
|
||||
final var syntheticOwnerProjectId = projectIdByName.getOrDefault(target.project(), defaultSyntheticOwnerProjectId);
|
||||
if (syntheticOwnerProjectId == null) {
|
||||
continue;
|
||||
}
|
||||
final var loadedModule = interfaceModuleLoader.load(
|
||||
moduleSource.get(),
|
||||
syntheticOwnerProjectId,
|
||||
fileTable,
|
||||
diagnostics);
|
||||
final var moduleData = new MutableModuleUnit();
|
||||
moduleData.sources.addAll(loadedModule.sourceFiles().asList());
|
||||
moduleData.barrels.addAll(loadedModule.barrelFiles().asList());
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package p.studio.compiler.pbs.stdlib;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import p.studio.compiler.models.ProjectDescriptor;
|
||||
import p.studio.compiler.source.diagnostics.DiagnosticSink;
|
||||
import p.studio.compiler.source.tables.FileTable;
|
||||
import p.studio.compiler.source.tables.ProjectTable;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class InterfaceModuleLoaderTest {
|
||||
|
||||
@Test
|
||||
void shouldRegisterSyntheticStdlibFilesInFileTable() {
|
||||
final var projectTable = new ProjectTable();
|
||||
final var projectId = projectTable.register(ProjectDescriptor.builder()
|
||||
.name("app")
|
||||
.version("1.0.0")
|
||||
.rootPath(Path.of("/tmp/app"))
|
||||
.sourceRoots(ReadOnlyList.wrap(java.util.List.of(Path.of("/tmp/app/src"))))
|
||||
.build());
|
||||
final var fileTable = new FileTable(1);
|
||||
final var diagnostics = DiagnosticSink.empty();
|
||||
final var moduleSource = new StdlibModuleSource(
|
||||
"sdk",
|
||||
ReadOnlyList.wrap(java.util.List.of("gfx")),
|
||||
ReadOnlyList.wrap(java.util.List.of(new StdlibModuleSource.SourceFile(
|
||||
"source.pbs",
|
||||
"declare host Gfx { fn draw() -> void; }"))),
|
||||
"pub host Gfx;");
|
||||
|
||||
final var module = new InterfaceModuleLoader().load(moduleSource, projectId, fileTable, diagnostics);
|
||||
|
||||
assertTrue(diagnostics.isEmpty());
|
||||
assertEquals(1, module.sourceFiles().size());
|
||||
assertEquals(1, module.barrelFiles().size());
|
||||
assertFalse(module.sourceFiles().getFirst().fileId().isNone());
|
||||
assertFalse(module.barrelFiles().getFirst().fileId().isNone());
|
||||
assertTrue(fileTable.get(module.sourceFiles().getFirst().fileId()).readUtf8().isPresent());
|
||||
assertTrue(fileTable.get(module.barrelFiles().getFirst().fileId()).readUtf8().isPresent());
|
||||
assertEquals(
|
||||
"declare host Gfx { fn draw() -> void; }",
|
||||
fileTable.get(module.sourceFiles().getFirst().fileId()).readUtf8().orElseThrow());
|
||||
assertEquals(
|
||||
"pub host Gfx;",
|
||||
fileTable.get(module.barrelFiles().getFirst().fileId()).readUtf8().orElseThrow());
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user