Skip to content

Commit

Permalink
Merge pull request #1587 from hylo-lang/show-requirements
Browse files Browse the repository at this point in the history
Add an option to log requirement systems after completion
  • Loading branch information
kyouko-taiga authored Sep 9, 2024
2 parents b9461a6 + 9c3077d commit 5e205b8
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 16 deletions.
23 changes: 21 additions & 2 deletions Sources/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ public struct Driver: ParsableCommand {
valueName: "file:line"))
private var inferenceTracingSite: SourceLine?

@Option(
name: [.customLong("show-requirements")],
help: ArgumentHelp(
"Log the requirement system of the generic declaration at the given line.",
valueName: "file:line"))
private var showRequirementsSite: SourceLine?

@Option(
name: [.customLong("emit")],
help: ArgumentHelp(
Expand Down Expand Up @@ -258,11 +265,14 @@ public struct Driver: ParsableCommand {
dependencies = try TypedProgram(
annotating: ScopedProgram(a), inParallel: experimentalParallelTypeChecking,
reportingDiagnosticsTo: &log,
tracingInferenceIf: shouldTraceInference)
tracingInferenceIf: shouldTraceInference,
loggingRequirementSystemIf: shouldLogRequirements)
}

let (program, sourceModule) = try dependencies.loadModule(
reportingDiagnosticsTo: &log, tracingInferenceIf: shouldTraceInference
reportingDiagnosticsTo: &log,
tracingInferenceIf: shouldTraceInference,
loggingRequirementSystemIf: shouldLogRequirements
) { (ast, log, space) in
try ast.loadModule(
productName, parsing: sourceFiles(in: inputs), inNodeSpace: space,
Expand Down Expand Up @@ -355,6 +365,15 @@ public struct Driver: ParsableCommand {
}
}

/// Returns `true` if the requirement system of `n`, which is in `p`, should be logged.
private func shouldLogRequirements(_ n: AnyDeclID, _ p: TypedProgram) -> Bool {
if let s = showRequirementsSite {
return (n.kind.value is GenericDecl.Type) && s.bounds.contains(p[n].site.start)
} else {
return false
}
}

/// Returns `program` lowered to Hylo IR, accumulating diagnostics in `log` and throwing if an
/// error occurred.
///
Expand Down
32 changes: 25 additions & 7 deletions Sources/FrontEnd/TypeChecking/TypeChecker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ struct TypeChecker {
/// The representation under construction.
private var cache: Cache

/// A closure that takes a node and its containing program, and returns `true` if a trace of type
/// inference should be logged on the console for that node.
/// A closure that accepts a node with its containing program and returns `true` if a trace of
/// type inference should be logged on the console for that node.
private let shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)?

/// A closure that accepts a generic declaration with its containing program and returns `true`
/// if the requirement system of its environment should be logged on the console.
private let shouldLogRequirementSystem: ((AnyDeclID, TypedProgram) -> Bool)?

/// The local copy of the program being type checked.
var program: TypedProgram {
cache.local
Expand All @@ -34,16 +38,19 @@ struct TypeChecker {
self.identifier = 0
self.cache = Cache(local: p)
self.shouldTraceInference = nil
self.shouldLogRequirementSystem = nil
}

/// Creates an instance for constructing `instanceUnderConstruction`.
init(
constructing instanceUnderConstruction: TypedProgram,
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)?
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)?,
loggingRequirementSystemIf shouldLogRequirements: ((AnyDeclID, TypedProgram) -> Bool)?
) {
self.identifier = 0
self.cache = Cache(local: instanceUnderConstruction)
self.shouldTraceInference = shouldTraceInference
self.shouldLogRequirementSystem = shouldLogRequirements
}

/// Creates an instance with given `identifier` for constructing `instanceUnderConstruction`
Expand All @@ -53,13 +60,15 @@ struct TypeChecker {
init(
_ identifier: UInt8,
collaborativelyConstructing instanceUnderConstruction: SharedMutable<TypedProgram>,
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)?
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)?,
loggingRequirementSystemIf shouldLogRequirements: ((AnyDeclID, TypedProgram) -> Bool)?
) {
self.identifier = identifier
self.nextFreshVariableIdentifier = UInt64(identifier) << 56
self.cache = instanceUnderConstruction.read(
applying: { Cache(local: $0, shared: instanceUnderConstruction) })
self.shouldTraceInference = shouldTraceInference
self.shouldLogRequirementSystem = shouldLogRequirements
}

/// Reports the given diagnostic.
Expand Down Expand Up @@ -1429,21 +1438,30 @@ struct TypeChecker {
/// Builds and type checks the generic environment of `d`.
private mutating func checkEnvironment<T: GenericDecl & LexicalScope>(of d: T.ID) {
// TODO: Type check default values
_ = environment(of: d)
let e = environment(of: d)
check(program[d].genericParameters)
if let f = shouldLogRequirementSystem, f(AnyDeclID(d), program) {
print(program.describe(e.requirements))
}
}

/// Builds and type checks the generic environment of `d`.
private mutating func checkEnvironment(of d: TraitDecl.ID) {
// TODO: Type check default values
_ = environment(of: d)
let e = environment(of: d)
check(program[d].genericParameters)
if let f = shouldLogRequirementSystem, f(AnyDeclID(d), program) {
print(program.describe(e.requirements))
}
}

/// Builds and type checks the generic environment of `d`.
private mutating func checkEnvironment<T: TypeExtendingDecl>(of d: T.ID) {
// TODO: Type check default values
_ = environment(of: d)
let e = environment(of: d)
if let f = shouldLogRequirementSystem, f(AnyDeclID(d), program) {
print(program.describe(e.requirements))
}
}

/// Type checks the conformances declared by `d`.
Expand Down
24 changes: 17 additions & 7 deletions Sources/FrontEnd/TypedProgram.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public struct TypedProgram {
annotating base: ScopedProgram,
inParallel typeCheckingIsParallel: Bool = false,
reportingDiagnosticsTo log: inout DiagnosticSet,
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)? = nil
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)? = nil,
loggingRequirementSystemIf shouldLogRequirements: ((AnyDeclID, TypedProgram) -> Bool)? = nil
) throws {
let instanceUnderConstruction = SharedMutable(TypedProgram(partiallyFormedFrom: base))

Expand All @@ -75,7 +76,8 @@ public struct TypedProgram {
let t = TypeCheckTask(
Array(chunk), withCheckerIdentifiedBy: UInt8(i),
collaborativelyConstructing: instanceUnderConstruction,
tracingInferenceIf: nil)
tracingInferenceIf: nil,
loggingRequirementSystemIf: nil)
tasks.append(t)
}

Expand All @@ -89,7 +91,8 @@ public struct TypedProgram {
self = try instanceUnderConstruction.read {
var checker = TypeChecker(
constructing: $0,
tracingInferenceIf: typeCheckingIsParallel ? nil : shouldTraceInference)
tracingInferenceIf: typeCheckingIsParallel ? nil : shouldTraceInference,
loggingRequirementSystemIf: typeCheckingIsParallel ? nil : shouldLogRequirements)
checker.checkAllDeclarations()

log.formUnion(checker.diagnostics)
Expand All @@ -107,13 +110,17 @@ public struct TypedProgram {
public func loadModule(
reportingDiagnosticsTo log: inout DiagnosticSet,
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)? = nil,
loggingRequirementSystemIf shouldLogRequirements: ((AnyDeclID, TypedProgram) -> Bool)? = nil,
creatingContentsWith make: AST.ModuleLoader
) throws -> (Self, ModuleDecl.ID) {
let (p, m) = try base.loadModule(reportingDiagnosticsTo: &log, creatingContentsWith: make)
var extended = self
extended.base = consume p

var checker = TypeChecker(constructing: extended, tracingInferenceIf: shouldTraceInference)
var checker = TypeChecker(
constructing: extended,
tracingInferenceIf: shouldTraceInference,
loggingRequirementSystemIf: shouldLogRequirements)
checker.checkModule(m)

log.formUnion(checker.diagnostics)
Expand All @@ -136,12 +143,15 @@ public struct TypedProgram {
_ sources: [TranslationUnit.ID],
withCheckerIdentifiedBy checkerIdentifier: UInt8,
collaborativelyConstructing instanceUnderConstruction: SharedMutable<TypedProgram>,
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)?
tracingInferenceIf shouldTraceInference: ((AnyNodeID, TypedProgram) -> Bool)?,
loggingRequirementSystemIf shouldLogRequirements: ((AnyDeclID, TypedProgram) -> Bool)?
) {
self.sources = sources
self.checker = TypeChecker(
checkerIdentifier, collaborativelyConstructing: instanceUnderConstruction,
tracingInferenceIf: shouldTraceInference)
checkerIdentifier,
collaborativelyConstructing: instanceUnderConstruction,
tracingInferenceIf: shouldTraceInference,
loggingRequirementSystemIf: shouldLogRequirements)
}

/// Executes the operation.
Expand Down

0 comments on commit 5e205b8

Please sign in to comment.