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

Merge string-templates branch to master #3660

Merged
merged 48 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d078326
Modify lexer to support modes for string templates.
RZhang05 Sep 18, 2024
7ebe45b
Add parsing support for string templates.
RZhang05 Sep 18, 2024
0795b4c
Checking and interpreting for string templates.
RZhang05 Sep 18, 2024
32f1c1d
Interpret string templates with basic tests
RZhang05 Sep 19, 2024
6a36212
Add placeholder for compiler linting.
RZhang05 Sep 19, 2024
d90bbf6
Fix parsing of invalid strings.
RZhang05 Sep 19, 2024
81c3004
Run stringer to update elementtype file.
RZhang05 Sep 19, 2024
99f4ae4
Improve error messages and tests
RZhang05 Sep 20, 2024
cfa540e
Allow escaping of string template $ and add tests.
RZhang05 Sep 23, 2024
0cc3a36
Reset lexer state.
RZhang05 Sep 23, 2024
942eb03
Change string template token to \( for backwards compatibility.
RZhang05 Sep 24, 2024
e3d152d
Restrict supported types in template.
RZhang05 Sep 24, 2024
1ec5b7e
Limit string templates to identifiers only.
RZhang05 Sep 25, 2024
1ae7fe9
Clean up changes.
RZhang05 Sep 25, 2024
8799cac
Fix checker test.
RZhang05 Sep 25, 2024
67d950b
Initial test of stringer interface.
RZhang05 Sep 26, 2024
6d60b9d
Add test for custom toString.
RZhang05 Sep 26, 2024
6298e1f
Add test for conformance error.
RZhang05 Sep 26, 2024
aa51455
Fix tests for native interface types.
RZhang05 Sep 27, 2024
bda6b28
Refactor code from review.
RZhang05 Oct 2, 2024
5f16333
Refactor stringer, improve generator, update simple types.
RZhang05 Oct 2, 2024
ab157ad
Update tests.
RZhang05 Oct 2, 2024
72ff98c
Fix generator conditional conformances check.
RZhang05 Oct 2, 2024
060945d
Code cleanup.
RZhang05 Oct 2, 2024
ad94aeb
Add ConformingType interface.
RZhang05 Oct 3, 2024
26428cb
Clean up unnecessary code.
RZhang05 Oct 3, 2024
447f055
Remove unused code.
RZhang05 Oct 3, 2024
c81e69c
Add simple tests, fix formatting.
RZhang05 Oct 10, 2024
57805ee
Update code after review.
RZhang05 Oct 16, 2024
cd83793
Fix linting.
RZhang05 Oct 16, 2024
fab5f6c
Abstract common functionality, clean up.
RZhang05 Oct 16, 2024
6983288
Code cleanup.
RZhang05 Oct 16, 2024
3208a5d
Merge pull request #3585 from RZhang05/identifier-string-template
SupunS Oct 18, 2024
1772f43
Merge branch 'master' of https://github.com/onflow/cadence into featu…
SupunS Oct 18, 2024
a185a42
Merge pull request #3626 from onflow/supun/string-templates
SupunS Oct 18, 2024
3d4f6a4
Merge remote-tracking branch 'upstream/feature/string-templates' into…
RZhang05 Oct 21, 2024
b9243e3
Fix imports.
RZhang05 Oct 21, 2024
f30b70c
Update tests/checker/stringer_test.go
turbolent Oct 25, 2024
bd4c77d
Invert flag for readability.
RZhang05 Oct 28, 2024
46d882c
Merge branch 'introduce-stringer' of https://github.com/RZhang05/cade…
RZhang05 Oct 28, 2024
58d7d66
Small fix.
RZhang05 Oct 28, 2024
f3b4828
Merge branch 'master' of https://github.com/onflow/cadence into featu…
SupunS Oct 30, 2024
f642b8e
Fix tests
SupunS Oct 30, 2024
262de48
Merge pull request #3594 from RZhang05/introduce-stringer
turbolent Oct 30, 2024
4f9e343
Merge pull request #3657 from onflow/supun/update-string-templates
SupunS Oct 30, 2024
7baf551
Merge branch 'master' of https://github.com/onflow/cadence into featu…
SupunS Oct 30, 2024
247a13d
Refactor and fix struct string tests
SupunS Oct 30, 2024
1210573
Merge pull request #3661 from onflow/supun/refactor-tests
SupunS Oct 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ast/elementtype.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,5 @@ const (
ElementTypeForceExpression
ElementTypePathExpression
ElementTypeAttachExpression
ElementTypeStringTemplateExpression
)
5 changes: 3 additions & 2 deletions ast/elementtype_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 75 additions & 0 deletions ast/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,81 @@ func (*StringExpression) precedence() precedence {
return precedenceLiteral
}

// StringTemplateExpression

type StringTemplateExpression struct {
// Values and Expressions are assumed to be interleaved, V[0] + E[0] + V[1] + ... + E[n-1] + V[n]
// this is enforced in the parser e.g. "a\(b)c" will be parsed as follows
// Values: []string{"a","c"}
// Expressions: []Expression{b}
Values []string
Expressions []Expression
Range
}

var _ Expression = &StringTemplateExpression{}

func NewStringTemplateExpression(
gauge common.MemoryGauge,
values []string,
exprs []Expression,
exprRange Range,
) *StringTemplateExpression {
common.UseMemory(gauge, common.NewStringTemplateExpressionMemoryUsage(len(values)+len(exprs)))
if len(values) != len(exprs)+1 {
// assert string template alternating structure
panic(errors.NewUnreachableError())
}
return &StringTemplateExpression{
Values: values,
Expressions: exprs,
Range: exprRange,
}
}

var _ Element = &StringExpression{}
var _ Expression = &StringExpression{}

func (*StringTemplateExpression) ElementType() ElementType {
return ElementTypeStringTemplateExpression
}

func (*StringTemplateExpression) isExpression() {}

func (*StringTemplateExpression) isIfStatementTest() {}

func (e *StringTemplateExpression) Walk(walkChild func(Element)) {
walkExpressions(walkChild, e.Expressions)
}

func (e *StringTemplateExpression) String() string {
return Prettier(e)
}

func (e *StringTemplateExpression) Doc() prettier.Doc {
if len(e.Expressions) == 0 {
return prettier.Text(QuoteString(e.Values[0]))
}

// TODO: must reproduce expressions as literals
panic("not implemented")
}

func (e *StringTemplateExpression) MarshalJSON() ([]byte, error) {
type Alias StringTemplateExpression
return json.Marshal(&struct {
*Alias
Type string
}{
Type: "StringTemplateExpression",
Alias: (*Alias)(e),
})
}

func (*StringTemplateExpression) precedence() precedence {
return precedenceLiteral
}

// IntegerExpression

type IntegerExpression struct {
Expand Down
84 changes: 59 additions & 25 deletions ast/expression_extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ type StringExtractor interface {
ExtractString(extractor *ExpressionExtractor, expression *StringExpression) ExpressionExtraction
}

type StringTemplateExtractor interface {
ExtractStringTemplate(extractor *ExpressionExtractor, expression *StringTemplateExpression) ExpressionExtraction
}

type ArrayExtractor interface {
ExtractArray(extractor *ExpressionExtractor, expression *ArrayExpression) ExpressionExtraction
}
Expand Down Expand Up @@ -117,31 +121,32 @@ type AttachExtractor interface {
}

type ExpressionExtractor struct {
IndexExtractor IndexExtractor
ForceExtractor ForceExtractor
BoolExtractor BoolExtractor
NilExtractor NilExtractor
IntExtractor IntExtractor
FixedPointExtractor FixedPointExtractor
StringExtractor StringExtractor
ArrayExtractor ArrayExtractor
DictionaryExtractor DictionaryExtractor
IdentifierExtractor IdentifierExtractor
AttachExtractor AttachExtractor
MemoryGauge common.MemoryGauge
VoidExtractor VoidExtractor
UnaryExtractor UnaryExtractor
ConditionalExtractor ConditionalExtractor
InvocationExtractor InvocationExtractor
BinaryExtractor BinaryExtractor
FunctionExtractor FunctionExtractor
CastingExtractor CastingExtractor
CreateExtractor CreateExtractor
DestroyExtractor DestroyExtractor
ReferenceExtractor ReferenceExtractor
MemberExtractor MemberExtractor
PathExtractor PathExtractor
nextIdentifier int
IndexExtractor IndexExtractor
ForceExtractor ForceExtractor
BoolExtractor BoolExtractor
NilExtractor NilExtractor
IntExtractor IntExtractor
FixedPointExtractor FixedPointExtractor
StringExtractor StringExtractor
StringTemplateExtractor StringTemplateExtractor
ArrayExtractor ArrayExtractor
DictionaryExtractor DictionaryExtractor
IdentifierExtractor IdentifierExtractor
AttachExtractor AttachExtractor
MemoryGauge common.MemoryGauge
VoidExtractor VoidExtractor
UnaryExtractor UnaryExtractor
ConditionalExtractor ConditionalExtractor
InvocationExtractor InvocationExtractor
BinaryExtractor BinaryExtractor
FunctionExtractor FunctionExtractor
CastingExtractor CastingExtractor
CreateExtractor CreateExtractor
DestroyExtractor DestroyExtractor
ReferenceExtractor ReferenceExtractor
MemberExtractor MemberExtractor
PathExtractor PathExtractor
nextIdentifier int
}

var _ ExpressionVisitor[ExpressionExtraction] = &ExpressionExtractor{}
Expand Down Expand Up @@ -271,6 +276,35 @@ func (extractor *ExpressionExtractor) ExtractString(expression *StringExpression
return rewriteExpressionAsIs(expression)
}

func (extractor *ExpressionExtractor) VisitStringTemplateExpression(expression *StringTemplateExpression) ExpressionExtraction {

// delegate to child extractor, if any,
// or call default implementation

if extractor.StringTemplateExtractor != nil {
return extractor.StringTemplateExtractor.ExtractStringTemplate(extractor, expression)
}
return extractor.ExtractStringTemplate(expression)
}

func (extractor *ExpressionExtractor) ExtractStringTemplate(expression *StringTemplateExpression) ExpressionExtraction {

// copy the expression
newExpression := *expression

// rewrite all value expressions

rewrittenExpressions, extractedExpressions :=
extractor.VisitExpressions(expression.Expressions)

newExpression.Expressions = rewrittenExpressions

return ExpressionExtraction{
RewrittenExpression: &newExpression,
ExtractedExpressions: extractedExpressions,
}
}

func (extractor *ExpressionExtractor) VisitArrayExpression(expression *ArrayExpression) ExpressionExtraction {

// delegate to child extractor, if any,
Expand Down
1 change: 1 addition & 0 deletions ast/precedence.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const (
// - BoolExpression
// - NilExpression
// - StringExpression
// - StringTemplateExpression
// - IntegerExpression
// - FixedPointExpression
// - ArrayExpression
Expand Down
48 changes: 48 additions & 0 deletions ast/string_template_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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 ast

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/turbolent/prettier"
)

func TestStringTemplate_Doc(t *testing.T) {

t.Parallel()

stmt := &StringTemplateExpression{
Values: []string{
"abc",
},
Expressions: []Expression{},
Range: Range{
StartPos: Position{Offset: 4, Line: 2, Column: 3},
EndPos: Position{Offset: 11, Line: 2, Column: 10},
},
}

assert.Equal(t,
prettier.Text("\"abc\""),
stmt.Doc(),
)
}
4 changes: 4 additions & 0 deletions ast/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ type ExpressionVisitor[T any] interface {
VisitNilExpression(*NilExpression) T
VisitBoolExpression(*BoolExpression) T
VisitStringExpression(*StringExpression) T
VisitStringTemplateExpression(*StringTemplateExpression) T
VisitIntegerExpression(*IntegerExpression) T
VisitFixedPointExpression(*FixedPointExpression) T
VisitDictionaryExpression(*DictionaryExpression) T
Expand Down Expand Up @@ -219,6 +220,9 @@ func AcceptExpression[T any](expression Expression, visitor ExpressionVisitor[T]
case ElementTypeStringExpression:
return visitor.VisitStringExpression(expression.(*StringExpression))

case ElementTypeStringTemplateExpression:
return visitor.VisitStringTemplateExpression(expression.(*StringTemplateExpression))

case ElementTypeIntegerExpression:
return visitor.VisitIntegerExpression(expression.(*IntegerExpression))

Expand Down
1 change: 1 addition & 0 deletions common/memorykind.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ const (
MemoryKindIntegerExpression
MemoryKindFixedPointExpression
MemoryKindArrayExpression
MemoryKindStringTemplateExpression
MemoryKindDictionaryExpression
MemoryKindIdentifierExpression
MemoryKindInvocationExpression
Expand Down
Loading
Loading