Skip to content

Commit

Permalink
Merge pull request #239 from DJRHails/address_literal
Browse files Browse the repository at this point in the history
Support address literals
  • Loading branch information
franklinsch authored Jul 6, 2018
2 parents 9ae2e5b + 1d3cbcb commit e518d66
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 2 deletions.
1 change: 1 addition & 0 deletions Sources/AST/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ public struct Environment {
case .boolean(_): return .basicType(.bool)
case .decimal(.integer(_)): return .basicType(.int)
case .string(_): return .basicType(.string)
case .address(_): return .basicType(.address)
default: fatalError()
}
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/AST/Token.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ extension Token {
case boolean(BooleanLiteral)
case decimal(DecimalLiteral)
case string(String)
case address(String)
}

public enum BooleanLiteral: String {
Expand Down Expand Up @@ -191,7 +192,8 @@ extension Token.Kind.Literal: CustomStringConvertible {
switch self {
case .boolean(let boolean): return boolean.rawValue
case .decimal(let decimal): return decimal.description
case .string(let string): return "literal \"\(string)\""
case .string(let string): return "literal \"\(string)\""
case .address(let hex): return "literal \(hex)"
}
}
}
Expand Down
1 change: 1 addition & 0 deletions Sources/IRGen/Function/IULIAExpression.swift
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ struct IULIALiteralToken {
case .decimal(.real(let num1, let num2)): return "\(num1).\(num2)"
case .decimal(.integer(let num)): return "\(num)"
case .string(let string): return "\"\(string)\""
case .address(let hex): return hex
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/Parser/Tokenizer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ public struct Tokenizer {
} else {
tokens.append(Token(kind: .literal(.decimal(.integer(num))), sourceLocation: sourceLocation))
}
} else if component.hasPrefix("0x") {
// The token is an address literal.
tokens.append(Token(kind: .literal(.address(component)), sourceLocation: sourceLocation))
} else if let first = component.first, let last = component.last, first == "\"", first == last {
// The token is a string literal.
tokens.append(Token(kind: .literal(.string(String(component[(component.index(after: component.startIndex)..<component.index(before: component.endIndex))]))), sourceLocation: sourceLocation))
Expand Down
8 changes: 7 additions & 1 deletion Sources/SemanticAnalyzer/SemanticAnalyzer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,13 @@ public struct SemanticAnalyzer: ASTPass {
}

public func process(literalToken: Token, passContext: ASTPassContext) -> ASTPassResult<Token> {
return ASTPassResult(element: literalToken, diagnostics: [], passContext: passContext)
var diagnostics = [Diagnostic]()
if case .literal(let token) = literalToken.kind,
case .address(let address) = token,
address.count != 42 {
diagnostics.append(.invalidAddressLiteral(literalToken))
}
return ASTPassResult(element: literalToken, diagnostics: diagnostics, passContext: passContext)
}

/// Whether an expression refers to a state property.
Expand Down
4 changes: 4 additions & 0 deletions Sources/SemanticAnalyzer/SemanticError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ extension Diagnostic {
return Diagnostic(severity: .error, sourceLocation: identifier.sourceLocation, message: "Use of invalid character '\(character)' in '\(identifier.name)'")
}

static func invalidAddressLiteral(_ literalToken: Token) -> Diagnostic {
return Diagnostic(severity: .error, sourceLocation: literalToken.sourceLocation, message: "Address literal should be 42 characters long")
}

static func noMatchingFunctionForFunctionCall(_ functionCall: FunctionCall, contextCallerCapabilities: [CallerCapability], candidates: [FunctionInformation]) -> Diagnostic {

let candidateNotes = candidates.map { candidate -> Diagnostic in
Expand Down
48 changes: 48 additions & 0 deletions Tests/ParserTests/literals.flint
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// RUN: %flintc %s --dump-ast | %FileCheck %s --prefix CHECK-AST

// CHECK-AST: ContractDeclaration
// CHECK-AST: identifier "Foo"
contract Foo {}

Foo :: (any) {
// CHECK-AST: InitializerDeclaration
// CHECK-AST: public
public init() {}

func foo() -> Int {

// CHECK-AST: BinaryExpression
// CHECK-AST: VariableDeclaration
// CHECK-AST: var
// CHECK-AST: identifier "a"
// CHECK-AST: built-in type Int
// CHECK-AST: =
// CHECK-AST: literal 2
var a: Int = 2
return a
}

// CHECK-AST: BinaryExpression
// CHECK-AST: VariableDeclaration
// CHECK-AST: let
// CHECK-AST: identifier "a"
// CHECK-AST: built-in type String
// CHECK-AST: =
// CHECK-AST: literal "hello"
func bar() -> String {
let a: String = "hello"
return a
}

// CHECK-AST: BinaryExpression
// CHECK-AST: VariableDeclaration
// CHECK-AST: let
// CHECK-AST: identifier "a"
// CHECK-AST: built-in type Address
// CHECK-AST: =
// CHECK-AST: literal 0x0000000000000000000000000000000000000000
func zoo() -> Address {
let a: Address = 0x0000000000000000000000000000000000000000
return a
}
}
16 changes: 16 additions & 0 deletions Tests/SemanticTests/literals.flint
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %flintc %s --verify

contract Literals {}

Literals :: (any) {
public init() {}

func foo() -> Address {
return 0xF668Cb74A4E9901972057cf4BEAC00b8826Fa99D
}

func bar() {
// 41 characters
let a: Address = 0x668Cb74A4E9901972057cf4BEAC00b8826Fa99D // expected-error {{Address literal should be 42 characters long}}
}
}

0 comments on commit e518d66

Please sign in to comment.