Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External trait attributes #477

Merged
merged 9 commits into from Sep 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
114 changes: 0 additions & 114 deletions INSTALL.md

This file was deleted.

6 changes: 3 additions & 3 deletions Sources/AST/Declaration/TraitDeclaration.swift
Expand Up @@ -14,20 +14,20 @@ public struct TraitDeclaration: ASTNode {
public var identifier: Identifier
// TODO: public var states: [TypeState]
public var members: [TraitMember]
public var moduleAddress: String? // Move-specific
public var decorators: [FunctionCall] // Move-specific

public init(
traitKind: Token,
traitToken: Token,
identifier: Identifier,
members: [TraitMember],
moduleAddress: String? = nil
decorators: [FunctionCall] = []
) {
self.traitKind = traitKind
self.traitToken = traitToken
self.identifier = identifier
self.members = members
self.moduleAddress = moduleAddress
self.decorators = decorators
}

// MARK: - ASTNode
Expand Down
3 changes: 3 additions & 0 deletions Sources/AST/Environment/Environment+Additions.swift
Expand Up @@ -263,6 +263,9 @@ extension Environment {
let special = externalTraitInitializer(trait)
addInitializerSignature(special, enclosingType: trait.identifier.name, callerProtections: [],
generated: true)
if !trait.decorators.isEmpty {
types[trait.identifier.name]?.decorators = trait.decorators
}
} else {
isExternal = false
}
Expand Down
Expand Up @@ -10,7 +10,7 @@ public enum CallableInformation {
case functionInformation(FunctionInformation)
case specialInformation(SpecialInformation)

var parameterTypes: [RawType] {
public var parameterTypes: [RawType] {
switch self {
case .functionInformation(let functionInformation):
return functionInformation.parameterTypes
Expand Down
1 change: 1 addition & 0 deletions Sources/AST/Environment/Information/TypeInformation.swift
Expand Up @@ -16,6 +16,7 @@ public struct TypeInformation {
public var publicInitializer: SpecialDeclaration?
var publicFallback: SpecialDeclaration?
var conformances: [TypeInformation] = []
public var decorators: [FunctionCall]?

public var allFunctions: [String: [FunctionInformation]] {
return conformances.map({ $0.functions }).reduce(functions, +)
Expand Down
20 changes: 18 additions & 2 deletions Sources/Compiler/Compiler.swift
Expand Up @@ -765,6 +765,16 @@ public enum CompilerTarget {
case .move: return "mvir"
}
}

public func configureSemanticAnalyser(semanticAnalyser: SemanticAnalyzer) -> SemanticAnalyzer {
switch self {
case .evm: return semanticAnalyser
case .move:
var semanticAnalyser = semanticAnalyser
semanticAnalyser.allowExternalStructs = true
return semanticAnalyser
}
}
}

public struct CompilerConfiguration {
Expand Down Expand Up @@ -813,8 +823,14 @@ public struct CompilerConfiguration {
self.maxTransactionDepth = maxTransactionDepth
self.skipVerifier = skipVerifier
self.skipCodeGen = skipCodeGen
self.diagnostics = diagnostics
self.astPasses = astPasses ?? (Compiler.defaultASTPasses + (skipVerifier ? [] : Compiler.verifierASTPasses))
self.diagnostics = diagnostics //Compiler.defaultASTPasses
self.astPasses = (astPasses ?? (Compiler.defaultASTPasses + (skipVerifier ? [] : Compiler.verifierASTPasses)))
.map { (pass: ASTPass) in
if let pass = pass as? SemanticAnalyzer {
return target.configureSemanticAnalyser(semanticAnalyser: pass)
}
return pass
}
self.stdLib = stdLib
self.target = target
}
Expand Down
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
37 changes: 37 additions & 0 deletions Sources/MoveGen/AST/TraitDeclaration.swift
@@ -0,0 +1,37 @@
//
// Created by matthewross on 31/08/19.
//

import Foundation
import AST

extension TraitDeclaration {
var moduleAddress: String? {
guard let argument: FunctionArgument = decorators.first(where: { $0.identifier.name == "module" })?.arguments[0],
let name = argument.identifier?.name,
name == "address",
case .literal(let token) = argument.expression,
case .literal(.address(let address)) = token.kind else {
return nil
}
return address
}

var isModule: Bool {
return decorators.contains(where: { $0.identifier.name == "module" })
}

var associatedModule: String? {
guard let argument = decorators.first(where: { $0.identifier.name == "associated" })?.arguments[0],
let name = argument.identifier?.name,
name == "",
case .identifier(let identifier) = argument.expression else {
return nil
}
return identifier.name
}

var isStruct: Bool {
return decorators.contains(where: { $0.identifier.name == "data" })
}
}
6 changes: 4 additions & 2 deletions Sources/MoveGen/AST/Type.swift
Expand Up @@ -8,15 +8,17 @@
import AST

extension RawType {
public func isExternalTraitType(environment: Environment) -> Bool {
public func isExternalContract(environment: Environment) -> Bool {
var internalRawType: RawType = self
while case .inoutType(let inoutType) = internalRawType {
internalRawType = inoutType
}
if case .userDefinedType(let typeIdentifier) = internalRawType {
return environment.isExternalTraitDeclared(typeIdentifier)
&& !(environment.types[typeIdentifier].flatMap { (information: TypeInformation) in
information.decorators?.contains(where: { $0.identifier.name == "data" })
} ?? false)
}

return false
}
}
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?

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)
}
}