Skip to content

Commit

Permalink
Merge pull request #1931 from onflow/sainati/extension-parsing
Browse files Browse the repository at this point in the history
Parsing for attachments and related operations
  • Loading branch information
dsainati1 authored Nov 18, 2022
2 parents f839871 + 53c4d10 commit 269df27
Show file tree
Hide file tree
Showing 17 changed files with 1,678 additions and 130 deletions.
356 changes: 356 additions & 0 deletions runtime/ast/attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,356 @@
/*
* Cadence - The resource-oriented smart contract programming language
*
* Copyright 2019-2022 Dapper Labs, Inc.
*
* 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 (
"encoding/json"

"github.com/turbolent/prettier"

"github.com/onflow/cadence/runtime/common"
)

// AttachmentDeclaration

type AttachmentDeclaration struct {
Access Access
Identifier Identifier
BaseType *NominalType
Conformances []*NominalType
Members *Members
DocString string
Range
}

var _ Element = &AttachmentDeclaration{}
var _ Declaration = &AttachmentDeclaration{}
var _ Statement = &AttachmentDeclaration{}

func NewAttachmentDeclaration(
memoryGauge common.MemoryGauge,
access Access,
identifier Identifier,
baseType *NominalType,
conformances []*NominalType,
members *Members,
docString string,
declarationRange Range,
) *AttachmentDeclaration {
common.UseMemory(memoryGauge, common.AttachmentDeclarationMemoryUsage)

return &AttachmentDeclaration{
Access: access,
Identifier: identifier,
BaseType: baseType,
Conformances: conformances,
Members: members,
DocString: docString,
Range: declarationRange,
}
}

func (*AttachmentDeclaration) ElementType() ElementType {
return ElementTypeAttachmentDeclaration
}

func (d *AttachmentDeclaration) Walk(walkChild func(Element)) {
walkDeclarations(walkChild, d.Members.declarations)
}

func (*AttachmentDeclaration) isDeclaration() {}

// NOTE: statement, so it can be represented in the AST,
// but will be rejected in semantic analysis
func (*AttachmentDeclaration) isStatement() {}

func (d *AttachmentDeclaration) DeclarationIdentifier() *Identifier {
return &d.Identifier
}

func (d *AttachmentDeclaration) DeclarationKind() common.DeclarationKind {
return common.DeclarationKindAttachment
}

func (d *AttachmentDeclaration) DeclarationAccess() Access {
return d.Access
}

func (d *AttachmentDeclaration) DeclarationMembers() *Members {
return d.Members
}

func (d *AttachmentDeclaration) DeclarationDocString() string {
return d.DocString
}

const attachmentStatementDoc = prettier.Text("attachment")
const attachmentStatementForDoc = prettier.Text("for")
const attachmentConformancesSeparatorDoc = prettier.Text(":")

var attachmentConformanceSeparatorDoc prettier.Doc = prettier.Concat{
prettier.Text(","),
prettier.Line{},
}

func (e *AttachmentDeclaration) Doc() prettier.Doc {
var doc prettier.Concat

if e.Access != AccessNotSpecified {
doc = append(
doc,
prettier.Text(e.Access.Keyword()),
prettier.Space,
)
}

doc = append(
doc,
attachmentStatementDoc,
prettier.Space,
prettier.Text(e.Identifier.Identifier),
prettier.Space,
attachmentStatementForDoc,
prettier.Space,
e.BaseType.Doc(),
)
if len(e.Conformances) > 0 {

conformancesDoc := prettier.Concat{
prettier.Line{},
}

for i, conformance := range e.Conformances {
if i > 0 {
conformancesDoc = append(
conformancesDoc,
attachmentConformanceSeparatorDoc,
)
}

conformancesDoc = append(
conformancesDoc,
conformance.Doc(),
)
}

conformancesDoc = append(
conformancesDoc,
prettier.Dedent{
Doc: prettier.Concat{
prettier.Line{},
e.Members.Doc(),
},
},
)

doc = append(
doc,
attachmentConformancesSeparatorDoc,
prettier.Group{
Doc: prettier.Indent{
Doc: conformancesDoc,
},
},
)

} else {
doc = append(
doc,
prettier.Space,
e.Members.Doc(),
)
}

return doc
}

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

func (d *AttachmentDeclaration) String() string {
return Prettier(d)
}

// AttachExpression
type AttachExpression struct {
Base Expression
Attachment Expression
StartPos Position `json:"-"`
}

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

func (*AttachExpression) ElementType() ElementType {
return ElementTypeAttachExpression
}

func (*AttachExpression) isExpression() {}

func (*AttachExpression) isIfStatementTest() {}

func (e *AttachExpression) Walk(walkChild func(Element)) {
walkChild(e.Base)
walkChild(e.Attachment)
}

func NewAttachExpression(
gauge common.MemoryGauge,
base Expression,
attachment Expression,
startPos Position,
) *AttachExpression {
common.UseMemory(gauge, common.AttachExpressionMemoryUsage)

return &AttachExpression{
Base: base,
Attachment: attachment,
StartPos: startPos,
}
}

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

const attachExpressionDoc = prettier.Text("attach")
const attachExpressionToDoc = prettier.Text("to")

func (e *AttachExpression) Doc() prettier.Doc {
var doc prettier.Concat

return append(
doc,
attachExpressionDoc,
prettier.Space,
e.Attachment.Doc(),
prettier.Space,
attachExpressionToDoc,
prettier.Space,
e.Base.Doc(),
)
}

func (e *AttachExpression) StartPosition() Position {
return e.StartPos
}

func (e *AttachExpression) EndPosition(memoryGauge common.MemoryGauge) Position {
return e.Base.EndPosition(memoryGauge)
}

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

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

// RemoveStatement
type RemoveStatement struct {
Attachment *NominalType
Value Expression
StartPos Position `json:"-"`
}

var _ Element = &RemoveStatement{}
var _ Statement = &RemoveStatement{}

func NewRemoveStatement(
gauge common.MemoryGauge,
attachment *NominalType,
value Expression,
startPos Position,
) *RemoveStatement {
common.UseMemory(gauge, common.RemoveStatementMemoryUsage)

return &RemoveStatement{
Attachment: attachment,
Value: value,
StartPos: startPos,
}
}

func (*RemoveStatement) ElementType() ElementType {
return ElementTypeRemoveStatement
}

func (*RemoveStatement) isStatement() {}

func (s *RemoveStatement) Walk(walkChild func(Element)) {
walkChild(s.Value)
}

func (s *RemoveStatement) StartPosition() Position {
return s.StartPos
}

func (s *RemoveStatement) EndPosition(memoryGauge common.MemoryGauge) Position {
return s.Value.EndPosition(memoryGauge)
}

const removeStatementRemoveKeywordDoc = prettier.Text("remove")
const removeStatementFromKeywordDoc = prettier.Text("from")

func (s *RemoveStatement) Doc() prettier.Doc {
return prettier.Concat{
removeStatementRemoveKeywordDoc,
prettier.Space,
s.Attachment.Doc(),
prettier.Space,
removeStatementFromKeywordDoc,
prettier.Space,
s.Value.Doc(),
}
}

func (s *RemoveStatement) String() string {
return Prettier(s)
}

func (s *RemoveStatement) MarshalJSON() ([]byte, error) {
type Alias RemoveStatement
return json.Marshal(&struct {
Type string
Range
*Alias
}{
Type: "RemoveStatement",
Range: NewUnmeteredRangeFromPositioned(s),
Alias: (*Alias)(s),
})
}
Loading

0 comments on commit 269df27

Please sign in to comment.