Skip to content

Commit

Permalink
Improve MoveGen diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Ross Rachar committed Sep 2, 2019
1 parent 6cd516f commit c45e54e
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 52 deletions.
5 changes: 4 additions & 1 deletion Sources/Compiler/Target.swift
Expand Up @@ -96,7 +96,10 @@ public class MoveTarget: Target {
}
exit(0)
}
let generator = MoveGenerator(ast: irPreprocessOutcome.element, environment: environment)

let generator = MoveGenerator(ast: irPreprocessOutcome.element,
environment: environment,
sourceContext: sourceContext)
return generator.generateCode()
}
}
2 changes: 1 addition & 1 deletion Sources/MoveGen/AST/FunctionDeclaration.swift
Expand Up @@ -120,7 +120,7 @@ extension AST.FunctionDeclaration {
}

let args: [FunctionArgument] = signature.parameters.map { parameter in
return FunctionArgument(.identifier(parameter.identifier))
FunctionArgument(.identifier(parameter.identifier))
}

let functionCallExpr: Expression = .functionCall(
Expand Down
24 changes: 16 additions & 8 deletions Sources/MoveGen/Component/MoveSelf.swift
Expand Up @@ -10,6 +10,7 @@ import Lexer
import MoveIR
import Source
import AST
import Diagnostic

/// Generates code for a "self" expression.
struct MoveSelf {
Expand All @@ -32,14 +33,21 @@ struct MoveSelf {
fatalError("Unexpected token \(token.kind)")
}
guard !functionContext.isConstructor else {
print(#"""
\#u{001B}[1;38;5;196mMoveIR generation error:\#u{001B}[0m \#
`self' reference before all fields initialized in function `init' in \#(token.sourceLocation)
\#tCannot use `self' in a constructor before all attributes have been assigned to, \#
as some are still unitialized. This includes any method calls which could access instance fields.
\#tInstead try moving method calls to after all values have been initialized.
"""#)
exit(1)
Diagnostics.add(Diagnostic(severity: .error,
sourceLocation: token.sourceLocation,
message: "`self' reference before all fields initialized in function `init'"))
Diagnostics.add(Diagnostic(severity: .note,
sourceLocation: token.sourceLocation,
message: #"""
Cannot use `self' in a constructor before all \#
attributes have been assigned to, \#
as some are still unitialised. This includes any \#
method calls which could access instance fields. \#
Instead try moving method calls to after all values \#
have been initialized.
"""#))
Diagnostics.displayAndExit()
}

if position == .left {
Expand Down
16 changes: 7 additions & 9 deletions Sources/MoveGen/Declaration/MoveVariableDeclaration.swift
Expand Up @@ -8,6 +8,7 @@
import Foundation
import AST
import MoveIR
import Diagnostic

/// Generates code for a variable declaration.
struct MoveVariableDeclaration {
Expand All @@ -18,15 +19,12 @@ struct MoveVariableDeclaration {
from: variableDeclaration.type.rawType,
environment: functionContext.environment
)?.render(functionContext: functionContext) else {
print("""
Cannot get variable declaration type from \(variableDeclaration.type.rawType) \
at position \(variableDeclaration.sourceLocation) for variable \(variableDeclaration.identifier.name).
\(functionContext.blockStack)
flintc internal error located at \(#file):\(#line)
""")
exit(1)
Diagnostics.add(Diagnostic(
severity: .error,
sourceLocation: variableDeclaration.sourceLocation,
message: "Cannot get variable declaration type from \(variableDeclaration.type.rawType)"
))
Diagnostics.displayAndExit()
}
guard !variableDeclaration.identifier.isSelf else {
return .variableDeclaration(MoveIR.VariableDeclaration((MoveSelf.name, typeIR)))
Expand Down
21 changes: 21 additions & 0 deletions Sources/MoveGen/Diagnostics/Diagnostics.swift
@@ -0,0 +1,21 @@
import Diagnostic
import Foundation

class Diagnostics {
public static var diagnostics: [Diagnostic] = []
public static var sourceContext: SourceContext? = nil

static func add(_ diagnostics: Diagnostic...) {
self.diagnostics.append(contentsOf: diagnostics)
}

static func display() {
try! print(DiagnosticsFormatter(diagnostics: diagnostics,
sourceContext: sourceContext!).rendered())
}

static func displayAndExit(code: Int32 = 1) -> Never {
display()
return exit(code)
}
}
9 changes: 7 additions & 2 deletions Sources/MoveGen/MoveCanonicalType.swift
Expand Up @@ -8,6 +8,7 @@
import Foundation
import AST
import MoveIR
import Diagnostic

/// A MoveIR type.
indirect enum CanonicalType: CustomStringConvertible {
Expand All @@ -29,7 +30,9 @@ indirect enum CanonicalType: CustomStringConvertible {
case .bool: self = .bool
case .string: self = .bytearray
default:
print("rawType: \(rawType)")
Diagnostics.add(Diagnostic(severity: .warning,
sourceLocation: nil,
message: "Could not detect basic type for `\(rawType)'"))
return nil
}

Expand Down Expand Up @@ -60,7 +63,9 @@ indirect enum CanonicalType: CustomStringConvertible {
case .dictionaryType(let key, _):
self = CanonicalType(from: key)!
default:
print("rawType': \(rawType)")
Diagnostics.add(Diagnostic(severity: .warning,
sourceLocation: nil,
message: "Could not detect type for `\(rawType)'"))
return nil
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/MoveGen/MoveContract.swift
Expand Up @@ -39,7 +39,7 @@ struct MoveContract {
let renderedImports = MoveIR.Statement.renderStatements(statements: imports)
// Generate code for each function in the contract.
let functions = contractBehaviorDeclarations.flatMap { contractBehaviorDeclaration in
return contractBehaviorDeclaration.members.compactMap { member -> MoveFunction? in
contractBehaviorDeclaration.members.compactMap { member -> MoveFunction? in
guard case .functionDeclaration(let functionDeclaration) = member else {
return nil
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/MoveGen/MoveGenerator.swift
Expand Up @@ -4,14 +4,16 @@

import Foundation
import AST
import Diagnostic

public struct MoveGenerator {
var topLevelModule: TopLevelModule
var environment: Environment

public init(ast topLevelModule: TopLevelModule, environment: Environment) {
public init(ast topLevelModule: TopLevelModule, environment: Environment, sourceContext: SourceContext) {
self.topLevelModule = topLevelModule
self.environment = environment
Diagnostics.sourceContext = sourceContext
}

public func generateCode() -> String {
Expand Down
7 changes: 5 additions & 2 deletions Sources/MoveGen/Preprocessor/MovePreprocessor.swift
Expand Up @@ -10,6 +10,7 @@ import AST
import Foundation
import Source
import Lexer
import Diagnostic

/// A preprocessing step to update the program's AST before code generation.
public struct MovePreprocessor: ASTPass {
Expand Down Expand Up @@ -104,8 +105,10 @@ extension ASTPass {
guard let environment = passContext.environment,
var scopeContext = passContext.scopeContext,
let enclosingType = passContext.enclosingTypeIdentifier?.name else {
print("Cannot infer type for \(element.sourceLocation)")
exit(1)
Diagnostics.add(Diagnostic(severity: .error,
sourceLocation: element.sourceLocation,
message: "Insufficient information to deduce type"))
Diagnostics.displayAndExit()
}

var type: RawType = environment.type(of: element,
Expand Down
6 changes: 3 additions & 3 deletions Sources/flint-ca/Analyser.swift
Expand Up @@ -28,9 +28,9 @@ struct Analyser {
let diagnosticPool = DiagnosticPool(shouldVerify: false,
quiet: false,
sourceContext: SourceContext(
sourceFiles: inputFiles,
sourceCodeString: sourceCode,
isForServer: true))
sourceFiles: inputFiles,
sourceCodeString: sourceCode,
isForServer: true))

let config = CompilerContractAnalyserConfiguration(sourceFiles: inputFiles,
sourceCode: sourceCode,
Expand Down
3 changes: 2 additions & 1 deletion Tests/MoveTests/BehaviourTests/tests/structs.flint
Expand Up @@ -38,12 +38,13 @@ contract C {
var b: B = B()
var c: B = B()
let d: Int = 5
var e: Bool = true
var e: Bool
}

C :: (any) {
public init() {
getE()
e = true
}

public func getAx() -> Int {
Expand Down
23 changes: 0 additions & 23 deletions install_deps_and_compile_ubuntu1804.sh

This file was deleted.

0 comments on commit c45e54e

Please sign in to comment.