-
Notifications
You must be signed in to change notification settings - Fork 137
/
before_extractor.go
111 lines (89 loc) Β· 3.21 KB
/
before_extractor.go
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
* Cadence - The resource-oriented smart contract programming language
*
* Copyright Flow Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sema
import (
"github.com/onflow/cadence/ast"
"github.com/onflow/cadence/common"
)
type BeforeExtractor struct {
ExpressionExtractor *ast.ExpressionExtractor
report func(error)
memoryGauge common.MemoryGauge
}
func NewBeforeExtractor(memoryGauge common.MemoryGauge, report func(error)) *BeforeExtractor {
beforeExtractor := &BeforeExtractor{
report: report,
memoryGauge: memoryGauge,
}
expressionExtractor := &ast.ExpressionExtractor{
InvocationExtractor: beforeExtractor,
FunctionExtractor: beforeExtractor,
MemoryGauge: memoryGauge,
}
beforeExtractor.ExpressionExtractor = expressionExtractor
return beforeExtractor
}
func (e *BeforeExtractor) ExtractBefore(expression ast.Expression) ast.ExpressionExtraction {
return e.ExpressionExtractor.Extract(expression)
}
func (e *BeforeExtractor) ExtractInvocation(
extractor *ast.ExpressionExtractor,
expression *ast.InvocationExpression,
) ast.ExpressionExtraction {
invokedExpression := expression.InvokedExpression
if identifierExpression, ok := invokedExpression.(*ast.IdentifierExpression); ok {
const expectedArgumentCount = 1
if identifierExpression.Identifier.Identifier == BeforeIdentifier &&
len(expression.Arguments) == expectedArgumentCount {
// rewrite the argument
argumentExpression := expression.Arguments[0].Expression
argumentResult := extractor.Extract(argumentExpression)
extractedExpressions := argumentResult.ExtractedExpressions
// create a fresh identifier which has the rewritten argument
// as its initial value
newIdentifier := ast.NewIdentifier(
e.memoryGauge,
extractor.FreshIdentifier(),
ast.EmptyPosition,
)
newExpression := ast.NewIdentifierExpression(e.memoryGauge, newIdentifier)
extractedExpressions = append(extractedExpressions,
ast.ExtractedExpression{
Identifier: newIdentifier,
Expression: argumentResult.RewrittenExpression,
},
)
return ast.ExpressionExtraction{
RewrittenExpression: newExpression,
ExtractedExpressions: extractedExpressions,
}
}
}
// not an invocation of `before`, perform default extraction
return extractor.ExtractInvocation(expression)
}
func (e *BeforeExtractor) ExtractFunction(
_ *ast.ExpressionExtractor,
expression *ast.FunctionExpression,
) ast.ExpressionExtraction {
// NOTE: function expressions are not supported by the expression extractor, so return as-is
// An error is reported when checking invocation expressions, so no need to report here
return ast.ExpressionExtraction{
RewrittenExpression: expression,
}
}