forked from flintlang/flint
/
MoveSelf.swift
67 lines (59 loc) · 2.38 KB
/
MoveSelf.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//
// MoveSelf.swift
// MoveGen
//
// Created by Hails, Daniel R on 29/08/2018.
//
import Foundation
import Lexer
import MoveIR
import Source
import AST
import Diagnostic
/// Generates code for a "self" expression.
struct MoveSelf {
var token: Token
var position: Position = .normal
public static let name = "this"
public static let prefix = "__\(name)_"
public var identifier: AST.Identifier {
return AST.Identifier(identifierToken: token)
}
static func generate(sourceLocation: SourceLocation, position: Position = .normal) -> MoveSelf {
return MoveSelf(token: Token(kind: Token.Kind.`self`, sourceLocation: sourceLocation), position: position)
}
func rendered(functionContext: FunctionContext, forceMove: Bool = false) -> MoveIR.Expression {
guard case .`self` = token.kind else {
fatalError("Unexpected token \(token.kind)")
}
guard !functionContext.isConstructor else {
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 {
return .identifier(MoveSelf.name)
} else if forceMove {
return .transfer(.move(.identifier(MoveSelf.name)))
} else if !(functionContext.selfType.isInout) {
return .identifier(MoveSelf.name)
} else if position == .accessed {
return .operation(.dereference(.operation(.mutableReference(
.transfer(.copy(.identifier(MoveSelf.name)))
))))
} else {
return .transfer(.copy(.identifier(MoveSelf.name)))
}
}
}