Skip to content

Commit

Permalink
Merge pull request #139 from franklinsch/address-of
Browse files Browse the repository at this point in the history
Require & keyword for arguments passed as inout
  • Loading branch information
franklinsch authored Feb 16, 2018
2 parents 3971b51 + 3e02d8b commit f92afd3
Show file tree
Hide file tree
Showing 19 changed files with 218 additions and 61 deletions.
44 changes: 37 additions & 7 deletions Sources/AST/AST.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,18 @@ public struct Parameter: SourceEntity {
public var identifier: Identifier
public var type: Type

public var inoutToken: Token?
public var implicitToken: Token?

public var isImplicit: Bool {
return implicitToken != nil
}

public var isInout: Bool {
return inoutToken != nil
if case .inoutType = type.rawType {
return true
}

return false
}

public var isPayableValueParameter: Bool {
Expand All @@ -214,27 +217,24 @@ public struct Parameter: SourceEntity {
return .spanning(identifier, to: type)
}

public init(identifier: Identifier, type: Type, implicitToken: Token?, inoutToken: Token?) {
public init(identifier: Identifier, type: Type, implicitToken: Token?) {
self.identifier = identifier
self.type = type
self.implicitToken = implicitToken
self.inoutToken = inoutToken
}
}

public struct TypeAnnotation: SourceEntity {
public var colonToken: Token

public var inoutToken: Token?
public var type: Type

public var sourceLocation: SourceLocation {
return .spanning(colonToken, to: type)
}

public init(colonToken: Token, type: Type, inoutToken: Token?) {
public init(colonToken: Token, type: Type) {
self.colonToken = colonToken
self.inoutToken = inoutToken
self.type = type
}
}
Expand Down Expand Up @@ -268,6 +268,7 @@ public struct Type: SourceEntity {
case fixedSizeArrayType(RawType, size: Int)
case dictionaryType(key: RawType, value: RawType)
case userDefinedType(RawTypeIdentifier)
case inoutType(RawType)
case errorType

public static func ==(lhs: RawType, rhs: RawType) -> Bool {
Expand All @@ -284,6 +285,8 @@ public struct Type: SourceEntity {
return lhsKeyType == rhsKeyType && lhsValueType == rhsValueType
case (.errorType, .errorType):
return true
case (.inoutType(let lhs), .inoutType(let rhs)):
return lhs == rhs
default:
return false
}
Expand All @@ -296,6 +299,7 @@ public struct Type: SourceEntity {
case .builtInType(let builtInType): return "\(builtInType.rawValue)"
case .dictionaryType(let keyType, let valueType): return "[\(keyType.name): \(valueType.name)]"
case .userDefinedType(let identifier): return identifier
case .inoutType(let rawType): return "&\(rawType)"
case .errorType: return "Flint$ErrorType"
}
}
Expand Down Expand Up @@ -352,6 +356,16 @@ public struct Type: SourceEntity {
self.genericArguments = genericArguments
self.sourceLocation = identifier.sourceLocation
}

public init(ampersandToken: Token, inoutType: Type) {
rawType = .inoutType(inoutType.rawType)
sourceLocation = ampersandToken.sourceLocation
}

public init(inoutToken: Token, inoutType: Type) {
rawType = .inoutType(inoutType.rawType)
sourceLocation = inoutToken.sourceLocation
}

public init(openSquareBracketToken: Token, arrayWithElementType type: Type, closeSquareBracketToken: Token) {
rawType = .arrayType(type.rawType)
Expand Down Expand Up @@ -400,6 +414,7 @@ public struct CallerCapability: SourceEntity {

public indirect enum Expression: SourceEntity {
case identifier(Identifier)
case inoutExpression(InoutExpression)
case binaryExpression(BinaryExpression)
case functionCall(FunctionCall)
case literal(Token)
Expand All @@ -411,6 +426,7 @@ public indirect enum Expression: SourceEntity {
public var sourceLocation: SourceLocation {
switch self {
case .identifier(let identifier): return identifier.sourceLocation
case .inoutExpression(let inoutExpression): return inoutExpression.sourceLocation
case .binaryExpression(let binaryExpression): return binaryExpression.sourceLocation
case .functionCall(let functionCall): return functionCall.sourceLocation
case .literal(let literal): return literal.sourceLocation
Expand Down Expand Up @@ -465,6 +481,20 @@ public indirect enum Statement: SourceEntity {
}
}

public struct InoutExpression: SourceEntity {
public var ampersandToken: Token
public var expression: Expression

public var sourceLocation: SourceLocation {
return ampersandToken.sourceLocation
}

public init(ampersandToken: Token, expression: Expression) {
self.ampersandToken = ampersandToken
self.expression = expression
}
}

public struct BinaryExpression: SourceEntity {
public var lhs: Expression

Expand Down
14 changes: 14 additions & 0 deletions Sources/AST/ASTDumper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ public class ASTDumper {
self.writeLine("implicit")
}
self.dump(parameter.identifier)
if parameter.isInout {
self.writeLine("inout")
}
self.dump(parameter.type)
}
}
Expand Down Expand Up @@ -207,6 +210,10 @@ public class ASTDumper {
}
case .userDefinedType(let userDefinedType):
writeLine("user-defined type \(userDefinedType)")
case .inoutType(let rawType):
writeNode("inout type") {
self.dump(rawType)
}
case .errorType:
writeLine("Flint error type \(rawType.name)")
}
Expand All @@ -225,6 +232,7 @@ public class ASTDumper {
func dump(_ expression: Expression) {
writeNode("Expression") {
switch expression {
case .inoutExpression(let inoutExpression): self.dump(inoutExpression)
case .binaryExpression(let binaryExpression): self.dump(binaryExpression)
case .bracketedExpression(let expression): self.dump(expression)
case .functionCall(let functionCall): self.dump(functionCall)
Expand All @@ -246,6 +254,12 @@ public class ASTDumper {
}
}
}

func dump(_ inoutExpression: InoutExpression) {
writeNode("InoutExpression") {
self.dump(inoutExpression.expression)
}
}

func dump(_ binaryExpression: BinaryExpression) {
writeNode("BinaryExpression") {
Expand Down
10 changes: 10 additions & 0 deletions Sources/AST/ASTPass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public protocol ASTPass {
func process(callerCapability: CallerCapability, passContext: ASTPassContext) -> ASTPassResult<CallerCapability>
func process(expression: Expression, passContext: ASTPassContext) -> ASTPassResult<Expression>
func process(statement: Statement, passContext: ASTPassContext) -> ASTPassResult<Statement>
func process(inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression>
func process(binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression>
func process(functionCall: FunctionCall, passContext: ASTPassContext) -> ASTPassResult<FunctionCall>
func process(subscriptExpression: SubscriptExpression, passContext: ASTPassContext) -> ASTPassResult<SubscriptExpression>
Expand All @@ -44,6 +45,7 @@ public protocol ASTPass {
func postProcess(callerCapability: CallerCapability, passContext: ASTPassContext) -> ASTPassResult<CallerCapability>
func postProcess(expression: Expression, passContext: ASTPassContext) -> ASTPassResult<Expression>
func postProcess(statement: Statement, passContext: ASTPassContext) -> ASTPassResult<Statement>
func postProcess(inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression>
func postProcess(binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression>
func postProcess(functionCall: FunctionCall, passContext: ASTPassContext) -> ASTPassResult<FunctionCall>
func postProcess(subscriptExpression: SubscriptExpression, passContext: ASTPassContext) -> ASTPassResult<SubscriptExpression>
Expand Down Expand Up @@ -121,6 +123,10 @@ public struct AnyASTPass: ASTPass {
public func process(statement: Statement, passContext: ASTPassContext) -> ASTPassResult<Statement> {
return base.process(statement: statement, passContext: passContext)
}

public func process(inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression> {
return base.process(inoutExpression: inoutExpression, passContext: passContext)
}

public func process(binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression> {
return base.process(binaryExpression: binaryExpression, passContext: passContext)
Expand Down Expand Up @@ -206,6 +212,10 @@ public struct AnyASTPass: ASTPass {
public func postProcess(statement: Statement, passContext: ASTPassContext) -> ASTPassResult<Statement> {
return base.postProcess(statement: statement, passContext: passContext)
}

public func postProcess(inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression> {
return base.postProcess(inoutExpression: inoutExpression, passContext: passContext)
}

public func postProcess(binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression> {
return base.postProcess(binaryExpression: binaryExpression, passContext: passContext)
Expand Down
14 changes: 13 additions & 1 deletion Sources/AST/ASTVisitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ public struct ASTVisitor<Pass: ASTPass> {
var processResult = pass.process(expression: expression, passContext: passContext)

switch processResult.element {
case .inoutExpression(let inoutExpression):
processResult.element = .inoutExpression(processResult.combining(visit(inoutExpression, passContext: processResult.passContext)))
case .binaryExpression(let binaryExpression):
processResult.element = .binaryExpression(processResult.combining(visit(binaryExpression, passContext: processResult.passContext)))
case .bracketedExpression(let expression):
Expand Down Expand Up @@ -261,6 +263,14 @@ public struct ASTVisitor<Pass: ASTPass> {
let postProcessResult = pass.postProcess(statement: processResult.element, passContext: processResult.passContext)
return ASTPassResult(element: postProcessResult.element, diagnostics: processResult.diagnostics + postProcessResult.diagnostics, passContext: postProcessResult.passContext)
}

func visit(_ inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression> {
var processResult = pass.process(inoutExpression: inoutExpression, passContext: passContext)
processResult.element.expression = processResult.combining(visit(processResult.element.expression, passContext: processResult.passContext))

let postProcessResult = pass.postProcess(inoutExpression: processResult.element, passContext: processResult.passContext)
return ASTPassResult(element: postProcessResult.element, diagnostics: postProcessResult.diagnostics, passContext: postProcessResult.passContext)
}

func visit(_ binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression> {
var processResult = pass.process(binaryExpression: binaryExpression, passContext: passContext)
Expand Down Expand Up @@ -289,7 +299,9 @@ public struct ASTVisitor<Pass: ASTPass> {
processResult.passContext.isFunctionCall = false

processResult.element.arguments = processResult.element.arguments.map { argument in
return processResult.combining(visit(argument, passContext: processResult.passContext))

let x = visit(argument, passContext: processResult.passContext)
return processResult.combining(x)
}

let postProcessResult = pass.postProcess(functionCall: processResult.element, passContext: processResult.passContext)
Expand Down
6 changes: 6 additions & 0 deletions Sources/AST/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public struct Environment {
case .fixedSizeArrayType(let rawType, let elementCount): return size(of: rawType) * elementCount
case .arrayType(_): return 1
case .dictionaryType(_, _): return 1
case .inoutType(_): fatalError()
case .errorType: return 0

case .userDefinedType(let identifier):
Expand Down Expand Up @@ -134,6 +135,8 @@ public struct Environment {

public func type(of expression: Expression, functionDeclarationContext: FunctionDeclarationContext? = nil, enclosingType: RawTypeIdentifier, callerCapabilities: [CallerCapability] = [], scopeContext: ScopeContext) -> Type.RawType {
switch expression {
case .inoutExpression(let inoutExpression):
return .inoutType(type(of: inoutExpression.expression, functionDeclarationContext: functionDeclarationContext, enclosingType: enclosingType, callerCapabilities: callerCapabilities, scopeContext: scopeContext))
case .binaryExpression(let binaryExpression):
return type(of: binaryExpression.rhs, functionDeclarationContext: functionDeclarationContext, enclosingType: enclosingType, callerCapabilities: callerCapabilities, scopeContext: scopeContext)

Expand All @@ -146,6 +149,9 @@ public struct Environment {
case .identifier(let identifier):
if identifier.enclosingType == nil,
let type = scopeContext.type(for: identifier.name) {
if case .inoutType(let type) = type {
return type
}
return type
}
return type(of: identifier.name, enclosingType: identifier.enclosingType ?? enclosingType, scopeContext: scopeContext)!
Expand Down
12 changes: 7 additions & 5 deletions Sources/AST/Token.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ extension Token {
case openAngledBracket = "<"
case closeAngledBracket = ">"

case plus = "+"
case minus = "-"
case times = "*"
case divide = "/"
case dot = "."
case plus = "+"
case minus = "-"
case times = "*"
case divide = "/"
case dot = "."
case ampersand = "&"

// Assignments

Expand Down Expand Up @@ -72,6 +73,7 @@ extension Token {
case .minus: return 20
case .times: return 30
case .divide: return 30
case .ampersand: return 35
case .dot: return 40
default: return 0
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/IRGen/IULIAContract.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct IULIAContract {
let type = environment.type(of: property, enclosingType: identifier)!
return storageCanonicalTypes(for: type)
}
case .inoutType(_): fatalError()
}
}
}
Expand All @@ -133,6 +134,7 @@ fileprivate extension Type.RawType {
case .arrayType(_): return .uint256 // The number of elements is stored.
case .fixedSizeArrayType(let elementType, _): return CanonicalType(from: elementType)
case .userDefinedType(_): fatalError()
case .inoutType(_): fatalError()
}
}
}
1 change: 1 addition & 0 deletions Sources/IRGen/IULIAFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ extension IULIAFunction {

func render(_ expression: Expression, asLValue: Bool = false) -> String {
switch expression {
case .inoutExpression(let inoutExpression): return render(inoutExpression.expression, asLValue: true)
case .binaryExpression(let binaryExpression): return render(binaryExpression, asLValue: asLValue)
case .bracketedExpression(let expression): return render(expression)
case .functionCall(let functionCall): return render(functionCall)
Expand Down
10 changes: 9 additions & 1 deletion Sources/IRGen/IULIAPreprocessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public struct IULIAPreprocessor: ASTPass {

if let structDeclarationContext = passContext.structDeclarationContext {
let selfIdentifier = Identifier(identifierToken: Token(kind: .identifier("flintSelf"), sourceLocation: SourceLocation(line: 0, column: 0, length: 0)))
functionDeclaration.parameters.insert(Parameter(identifier: selfIdentifier, type: Type(inferredType: .userDefinedType(structDeclarationContext.structIdentifier.name), identifier: selfIdentifier), implicitToken: nil, inoutToken: nil), at: 0)
functionDeclaration.parameters.insert(Parameter(identifier: selfIdentifier, type: Type(inferredType: .userDefinedType(structDeclarationContext.structIdentifier.name), identifier: selfIdentifier), implicitToken: nil), at: 0)

let enclosingType = enclosingTypeIdentifier(in: passContext).name
let mangledName = Mangler.mangledName(functionDeclaration.identifier.name, enclosingType: enclosingType)
Expand Down Expand Up @@ -87,6 +87,10 @@ public struct IULIAPreprocessor: ASTPass {
public func process(statement: Statement, passContext: ASTPassContext) -> ASTPassResult<Statement> {
return ASTPassResult(element: statement, diagnostics: [], passContext: passContext)
}

public func process(inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression> {
return ASTPassResult(element: inoutExpression, diagnostics: [], passContext: passContext)
}

public func process(binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression> {
var passContext = passContext
Expand Down Expand Up @@ -215,6 +219,10 @@ public struct IULIAPreprocessor: ASTPass {
let passContext = passContext.withUpdates { $0.functionCallReceiverTrail = [] }
return ASTPassResult(element: statement, diagnostics: [], passContext: passContext)
}

public func postProcess(inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression> {
return ASTPassResult(element: inoutExpression, diagnostics: [], passContext: passContext)
}

public func postProcess(binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression> {
return ASTPassResult(element: binaryExpression, diagnostics: [], passContext: passContext)
Expand Down
8 changes: 8 additions & 0 deletions Sources/Optimizer/Optimizer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public struct Optimizer: ASTPass {
public func process(statement: Statement, passContext: ASTPassContext) -> ASTPassResult<Statement> {
return ASTPassResult(element: statement, diagnostics: [], passContext: passContext)
}

public func process(inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression> {
return ASTPassResult(element: inoutExpression, diagnostics: [], passContext: passContext)
}

public func process(binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression> {
return ASTPassResult(element: binaryExpression, diagnostics: [], passContext: passContext)
Expand Down Expand Up @@ -158,6 +162,10 @@ public struct Optimizer: ASTPass {
return ASTPassResult(element: statement, diagnostics: [], passContext: passContext)
}

public func postProcess(inoutExpression: InoutExpression, passContext: ASTPassContext) -> ASTPassResult<InoutExpression> {
return ASTPassResult(element: inoutExpression, diagnostics: [], passContext: passContext)
}

public func postProcess(binaryExpression: BinaryExpression, passContext: ASTPassContext) -> ASTPassResult<BinaryExpression> {
return ASTPassResult(element: binaryExpression, diagnostics: [], passContext: passContext)
}
Expand Down
Loading

0 comments on commit f92afd3

Please sign in to comment.