Skip to content

Commit

Permalink
LIBRARY: almost done
Browse files Browse the repository at this point in the history
Signed-off-by: imkiva <imkiva@islovely.icu>
  • Loading branch information
imkiva committed Nov 21, 2021
1 parent ab39a50 commit 0bcfcb7
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 78 deletions.
39 changes: 7 additions & 32 deletions cli/src/main/java/org/aya/cli/library/ImportResolver.java
Expand Up @@ -4,42 +4,17 @@

import kala.collection.SeqLike;
import kala.collection.immutable.ImmutableSeq;
import kala.collection.mutable.DynamicSeq;
import org.aya.concrete.resolve.ResolveInfo;
import org.aya.concrete.stmt.Command;
import org.aya.concrete.stmt.Stmt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.nio.file.Path;
import java.util.Objects;

public record ImportResolver(
@NotNull ImportResolver.ImportFileLoader loader,
@NotNull Imports imports
@NotNull ImportResolver.ImportLoader loader,
@NotNull LibrarySource librarySource
) {
record Imports(
@NotNull Path self,
@NotNull DynamicSeq<Imports> imports
) {
public @NotNull Path canonicalPath() {
return ResolveInfo.canonicalize(self);
}

@Override public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Imports imports = (Imports) o;
return canonicalPath().equals(imports.canonicalPath());
}

@Override public int hashCode() {
return Objects.hash(self);
}
}

interface ImportFileLoader {
@Nullable Imports loadFile(@NotNull ImmutableSeq<String> mod);
@FunctionalInterface
interface ImportLoader {
@NotNull LibrarySource load(@NotNull ImmutableSeq<String> mod);
}

public void resolveStmt(@NotNull SeqLike<Stmt> stmts) {
Expand All @@ -51,8 +26,8 @@ public void resolveStmt(@NotNull Stmt stmt) {
case Command.Module mod -> resolveStmt(mod.contents());
case Command.Import cmd -> {
var ids = cmd.path().ids();
var success = loader.loadFile(ids);
if (success != null) imports.imports.append(success);
var success = loader.load(ids);
librarySource.imports().append(success);
}
default -> {}
}
Expand Down
85 changes: 44 additions & 41 deletions cli/src/main/java/org/aya/cli/library/LibraryCompiler.java
Expand Up @@ -55,49 +55,33 @@ public static int compile(@NotNull Path libraryRoot, boolean unicode) throws IOE
return buildRoot.resolve("deps").resolve(depName + "_" + version);
}

record LibraryImportFileLoader(
@NotNull LibraryCompiler compiler,
@NotNull Reporter reporter,
@NotNull SourceFileLocator locator,
@NotNull SeqView<Path> thisModulePath
) implements ImportResolver.ImportFileLoader {
@Override public ImportResolver.@Nullable Imports loadFile(@NotNull ImmutableSeq<String> mod) {
try {
for (var path : thisModulePath) {
var file = FileModuleLoader.resolveFile(path, mod);
if (Files.exists(file)) return compiler.resolveImports(reporter, locator, this, file);
}
} catch (IOException ignored) {
}
return null;
}
}

private ImportResolver.Imports resolveImports(
private @NotNull LibrarySource resolveImports(
@NotNull LibraryConfig owner,
@NotNull Reporter reporter,
@NotNull SourceFileLocator locator,
@NotNull ImportResolver.ImportFileLoader loader,
@NotNull ImportResolver.ImportLoader loader,
@NotNull Path path
) throws IOException {
var program = AyaParsing.program(locator, reporter, path);
var imports = new ImportResolver.Imports(path, DynamicSeq.create());
var finder = new ImportResolver(loader, imports);
var source = new LibrarySource(owner, path);
var finder = new ImportResolver(loader, source);
finder.resolveStmt(program);
return imports;
return source;
}

private @NotNull MutableGraph<ImportResolver.Imports> resolveImports(
private @NotNull MutableGraph<LibrarySource> resolveImports(
@NotNull LibraryConfig owner,
@NotNull Reporter reporter,
@NotNull SourceFileLocator locator,
@NotNull ImportResolver.ImportFileLoader loader,
@NotNull ImportResolver.ImportLoader loader,
@NotNull LibraryConfig config
) throws IOException {
System.out.println(" [Info] Collecting source files");
var graph = MutableGraph.<ImportResolver.Imports>create();
var graph = MutableGraph.<LibrarySource>create();
var sources = collectSource(config.librarySrcRoot());
System.out.println(" [Info] Resolving source file dependency");
for (var file : sources) {
var resolve = resolveImports(reporter, locator, loader, file);
var resolve = resolveImports(owner, reporter, locator, loader, file);
collectDep(graph, resolve);
}
return graph;
Expand Down Expand Up @@ -139,10 +123,10 @@ private boolean make(@NotNull LibraryConfig config) throws IOException {
var locator = new SourceFileLocator.Module(locatorPath.view());
var timestamp = new Timestamp(locator, thisOutRoot);

var resolveLoader = new LibraryImportFileLoader(this, reporter, locator, SeqView.of(srcRoot));
var depGraph = resolveImports(reporter, locator, resolveLoader, config);
var resolveLoader = new LibraryImportLoader(config, this, reporter, locator, locatorPath.view());
var depGraph = resolveImports(config, reporter, locator, resolveLoader, config);

var moduleLoader = new CachedModuleLoader(new LibraryModuleLoader(reporter, locator, timestamp, thisModulePath.view(), thisOutRoot));
var moduleLoader = new CachedModuleLoader(new LibraryModuleLoader(reporter, locator, thisModulePath.view(), thisOutRoot));
return make(reporter, moduleLoader, depGraph, timestamp);
}

Expand All @@ -152,13 +136,13 @@ private boolean make(@NotNull LibraryConfig config) throws IOException {
private boolean make(
@NotNull Reporter reporter,
@NotNull ModuleLoader moduleLoader,
@NotNull MutableGraph<ImportResolver.Imports> depGraph,
@NotNull MutableGraph<LibrarySource> depGraph,
@NotNull Timestamp timestamp
) {
var changed = MutableSet.<ImportResolver.Imports>create();
) throws IOException {
var changed = MutableSet.<LibrarySource>create();
var usage = depGraph.transpose();
depGraph.E().keysView().forEach(s -> {
if (timestamp.sourceModified(s.self()))
if (timestamp.sourceModified(s.file()))
collectChanged(usage, s, changed);
});

Expand All @@ -167,12 +151,12 @@ private boolean make(
return true;
}

var changedDepGraph = MutableGraph.<ImportResolver.Imports>create();
var changedDepGraph = MutableGraph.<LibrarySource>create();
changed.forEach(c -> collectDep(changedDepGraph, c));

var order = changedDepGraph.topologicalOrder().view()
.flatMap(Function.identity())
.map(ImportResolver.Imports::self)
.map(LibrarySource::file)
.toImmutableSeq();
tyckLibrary(reporter, moduleLoader, timestamp.locator, timestamp, order);
return false;
Expand All @@ -185,8 +169,9 @@ private void tyckLibrary(
@NotNull SourceFileLocator locator,
@NotNull Timestamp timestamp,
@NotNull ImmutableSeq<Path> order
) {
) throws IOException {
var coreSaver = new CoreSaver(timestamp);
for (var f : order) Files.deleteIfExists(coreFile(locator, f, timestamp.outRoot));
order.forEach(file -> {
var mod = resolveModule(moduleLoader, locator, file);
if (mod.thisProgram().isEmpty()) {
Expand Down Expand Up @@ -273,17 +258,17 @@ private void saveCompiledCore(@NotNull ResolveInfo resolveInfo, @NotNull Immutab
}
}

private static void collectDep(@NotNull MutableGraph<ImportResolver.Imports> dep, @NotNull ImportResolver.Imports info) {
private static void collectDep(@NotNull MutableGraph<LibrarySource> dep, @NotNull LibrarySource info) {
dep.suc(info).appendAll(info.imports());
info.imports().forEach(i -> {
collectDep(dep, i);
});
}

private static void collectChanged(
@NotNull MutableGraph<ImportResolver.Imports> usage,
@NotNull ImportResolver.Imports changed,
@NotNull MutableSet<ImportResolver.Imports> changedList
@NotNull MutableGraph<LibrarySource> usage,
@NotNull LibrarySource changed,
@NotNull MutableSet<LibrarySource> changedList
) {
if (changedList.contains(changed)) return;
changedList.add(changed);
Expand All @@ -306,4 +291,22 @@ private static void deleteRecursively(@NotNull Path path) throws IOException {
.forEachChecked(Files::deleteIfExists);
}
}

record LibraryImportLoader(
@NotNull LibraryConfig owner,
@NotNull LibraryCompiler compiler,
@NotNull Reporter reporter,
@NotNull SourceFileLocator locator,
@NotNull SeqView<Path> thisModulePath
) implements ImportResolver.ImportLoader {
@Override public @NotNull LibrarySource load(@NotNull ImmutableSeq<String> mod) {
var file = LibraryModuleLoader.resolveFile(thisModulePath, mod);
if (file == null) throw new IllegalArgumentException("incomplete module path");
try {
return compiler.resolveImports(owner, reporter, locator, this, file);
} catch (IOException e) {
throw new RuntimeException("Cannot load imported module " + mod, e);
}
}
}
}
Expand Up @@ -41,24 +41,23 @@
public record LibraryModuleLoader(
@NotNull Reporter reporter,
@NotNull SourceFileLocator locator,
@NotNull LibraryCompiler.Timestamp timestamp,
@NotNull SeqView<Path> thisModulePath,
@NotNull Path thisOutRoot
) implements ModuleLoader {
static @NotNull Path resolveCompiledCore(@NotNull Path basePath, @NotNull Seq<@NotNull String> moduleName) {
public static @NotNull Path resolveCompiledCore(@NotNull Path basePath, @NotNull Seq<@NotNull String> moduleName) {
var withoutExt = moduleName.foldLeft(basePath, Path::resolve);
return withoutExt.resolveSibling(withoutExt.getFileName() + ".ayac");
}

static @Nullable Path resolveCompiledDepCore(@NotNull SeqView<Path> modulePath, @NotNull Seq<String> moduleName) {
public static @Nullable Path resolveCompiledDepCore(@NotNull SeqView<Path> modulePath, @NotNull Seq<String> moduleName) {
for (var p : modulePath) {
var file = resolveCompiledCore(p, moduleName);
if (Files.exists(file)) return file;
}
return null;
}

static @Nullable Path resolveFile(@NotNull SeqView<Path> modulePath, @NotNull Seq<String> moduleName) {
public static @Nullable Path resolveFile(@NotNull SeqView<Path> modulePath, @NotNull Seq<String> moduleName) {
for (var p : modulePath) {
var file = FileModuleLoader.resolveFile(p, moduleName);
if (Files.exists(file)) return file;
Expand All @@ -80,7 +79,7 @@ public record LibraryModuleLoader(
// we are loading a module belonging to this library, try finding compiled core first.
// If found, check modifications and decide whether to proceed with compiled core.
var corePath = resolveCompiledCore(thisOutRoot, mod);
if (Files.exists(corePath) && !timestamp().sourceModified(sourcePath)) {
if (Files.exists(corePath)) {
return loadCompiledCore(mod, corePath, sourcePath);
}

Expand Down
32 changes: 32 additions & 0 deletions cli/src/main/java/org/aya/cli/library/LibrarySource.java
@@ -0,0 +1,32 @@
// Copyright (c) 2020-2021 Yinsen (Tesla) Zhang.
// Use of this source code is governed by the MIT license that can be found in the LICENSE.md file.
package org.aya.cli.library;

import kala.collection.mutable.DynamicSeq;
import org.aya.cli.library.json.LibraryConfig;
import org.aya.concrete.resolve.ResolveInfo;
import org.jetbrains.annotations.NotNull;

import java.nio.file.Path;
import java.util.Objects;

public record LibrarySource(
@NotNull LibraryConfig owner,
@NotNull Path file,
@NotNull DynamicSeq<LibrarySource> imports
) {
public LibrarySource(@NotNull LibraryConfig owner, @NotNull Path file) {
this(owner, ResolveInfo.canonicalize(file), DynamicSeq.create());
}

@Override public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LibrarySource that = (LibrarySource) o;
return owner == that.owner && file.equals(that.file);
}

@Override public int hashCode() {
return Objects.hash(owner, file);
}
}

0 comments on commit 0bcfcb7

Please sign in to comment.