Skip to content

Commit

Permalink
add JSON serialization support for more AST elements
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent committed Aug 5, 2020
1 parent c82a76a commit 2834503
Show file tree
Hide file tree
Showing 22 changed files with 958 additions and 36 deletions.
44 changes: 41 additions & 3 deletions runtime/ast/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

package ast

import (
"encoding/json"
)

type Block struct {
Statements []Statement
Range
Expand All @@ -27,18 +31,50 @@ func (b *Block) Accept(visitor Visitor) Repr {
return visitor.VisitBlock(b)
}

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

// FunctionBlock

type FunctionBlock struct {
*Block
PreConditions *Conditions
PostConditions *Conditions
Block *Block
PreConditions *Conditions `json:",omitempty"`
PostConditions *Conditions `json:",omitempty"`
}

func (b *FunctionBlock) Accept(visitor Visitor) Repr {
return visitor.VisitFunctionBlock(b)
}

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

func (b *FunctionBlock) StartPosition() Position {
return b.Block.StartPos
}

func (b *FunctionBlock) EndPosition() Position {
return b.Block.EndPos
}

// Condition

type Condition struct {
Expand All @@ -51,6 +87,8 @@ func (c *Condition) Accept(visitor Visitor) Repr {
return visitor.VisitCondition(c)
}

// Conditions

type Conditions []*Condition

func (c *Conditions) Append(conditions Conditions) {
Expand Down
238 changes: 238 additions & 0 deletions runtime/ast/block_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
/*
* Cadence - The resource-oriented smart contract programming language
*
* Copyright 2019-2020 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"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestBlock_MarshalJSON(t *testing.T) {

block := &Block{
Statements: []Statement{
&ExpressionStatement{
Expression: &BoolExpression{
Value: false,
Range: Range{
StartPos: Position{Offset: 1, Line: 2, Column: 3},
EndPos: Position{Offset: 4, Line: 5, Column: 6},
},
},
},
},
Range: Range{
StartPos: Position{Offset: 7, Line: 8, Column: 9},
EndPos: Position{Offset: 10, Line: 11, Column: 12},
},
}

actual, err := json.Marshal(block)
require.NoError(t, err)

assert.JSONEq(t,
`
{
"Type": "Block",
"Statements": [
{
"Type": "ExpressionStatement",
"Expression": {
"Type": "BoolExpression",
"Value": false,
"StartPos": {"Offset": 1, "Line": 2, "Column": 3},
"EndPos": {"Offset": 4, "Line": 5, "Column": 6}
},
"StartPos": {"Offset": 1, "Line": 2, "Column": 3},
"EndPos": {"Offset": 4, "Line": 5, "Column": 6}
}
],
"StartPos": {"Offset": 7, "Line": 8, "Column": 9},
"EndPos": {"Offset": 10, "Line": 11, "Column": 12}
}
`,
string(actual),
)
}

func TestFunctionBlock_MarshalJSON(t *testing.T) {

t.Run("with statements", func(t *testing.T) {

block := &FunctionBlock{
Block: &Block{
Statements: []Statement{
&ExpressionStatement{
Expression: &BoolExpression{
Value: false,
Range: Range{
StartPos: Position{Offset: 1, Line: 2, Column: 3},
EndPos: Position{Offset: 4, Line: 5, Column: 6},
},
},
},
},
Range: Range{
StartPos: Position{Offset: 7, Line: 8, Column: 9},
EndPos: Position{Offset: 10, Line: 11, Column: 12},
},
},
}

actual, err := json.Marshal(block)
require.NoError(t, err)

assert.JSONEq(t,
`
{
"Type": "FunctionBlock",
"Block": {
"Type": "Block",
"Statements": [
{
"Type": "ExpressionStatement",
"Expression": {
"Type": "BoolExpression",
"Value": false,
"StartPos": {"Offset": 1, "Line": 2, "Column": 3},
"EndPos": {"Offset": 4, "Line": 5, "Column": 6}
},
"StartPos": {"Offset": 1, "Line": 2, "Column": 3},
"EndPos": {"Offset": 4, "Line": 5, "Column": 6}
}
],
"StartPos": {"Offset": 7, "Line": 8, "Column": 9},
"EndPos": {"Offset": 10, "Line": 11, "Column": 12}
},
"StartPos": {"Offset": 7, "Line": 8, "Column": 9},
"EndPos": {"Offset": 10, "Line": 11, "Column": 12}
}
`,
string(actual),
)
})

t.Run("with preconditions and postconditions", func(t *testing.T) {

block := &FunctionBlock{
Block: &Block{
Statements: []Statement{},
Range: Range{
StartPos: Position{Offset: 1, Line: 2, Column: 3},
EndPos: Position{Offset: 4, Line: 5, Column: 6},
},
},
PreConditions: &Conditions{
{
Kind: ConditionKindPre,
Test: &BoolExpression{
Value: false,
Range: Range{
StartPos: Position{Offset: 7, Line: 8, Column: 9},
EndPos: Position{Offset: 10, Line: 11, Column: 12},
},
},
Message: &StringExpression{
Value: "Pre failed",
Range: Range{
StartPos: Position{Offset: 13, Line: 14, Column: 15},
EndPos: Position{Offset: 16, Line: 17, Column: 18},
},
},
},
},
PostConditions: &Conditions{
{
Kind: ConditionKindPost,
Test: &BoolExpression{
Value: true,
Range: Range{
StartPos: Position{Offset: 19, Line: 20, Column: 21},
EndPos: Position{Offset: 22, Line: 23, Column: 24},
},
},
Message: &StringExpression{
Value: "Post failed",
Range: Range{
StartPos: Position{Offset: 25, Line: 26, Column: 27},
EndPos: Position{Offset: 28, Line: 29, Column: 30},
},
},
},
},
}

actual, err := json.Marshal(block)
require.NoError(t, err)

assert.JSONEq(t,
`
{
"Type": "FunctionBlock",
"Block": {
"Type": "Block",
"Statements": [],
"StartPos": {"Offset": 1, "Line": 2, "Column": 3},
"EndPos": {"Offset": 4, "Line": 5, "Column": 6}
},
"PreConditions": [
{
"Kind": "ConditionKindPre",
"Test": {
"Type": "BoolExpression",
"Value": false,
"StartPos": {"Offset": 7, "Line": 8, "Column": 9},
"EndPos": {"Offset": 10, "Line": 11, "Column": 12}
},
"Message": {
"Type": "StringExpression",
"Value": "Pre failed",
"StartPos": {"Offset": 13, "Line": 14, "Column": 15},
"EndPos": {"Offset": 16, "Line": 17, "Column": 18}
}
}
],
"PostConditions": [
{
"Kind": "ConditionKindPost",
"Test": {
"Type": "BoolExpression",
"Value": true,
"StartPos": {"Offset": 19, "Line": 20, "Column": 21},
"EndPos": {"Offset": 22, "Line": 23, "Column": 24}
},
"Message": {
"Type": "StringExpression",
"Value": "Post failed",
"StartPos": {"Offset": 25, "Line": 26, "Column": 27},
"EndPos": {"Offset": 28, "Line": 29, "Column": 30}
}
}
],
"StartPos": {"Offset": 1, "Line": 2, "Column": 3},
"EndPos": {"Offset": 4, "Line": 5, "Column": 6}
}
`,
string(actual),
)
})
}
Loading

0 comments on commit 2834503

Please sign in to comment.