Skip to content

Commit

Permalink
Also support fixed sized array types
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdrag00nv2 committed Jul 29, 2023
1 parent 19dbd0e commit ae5936a
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 146 deletions.
51 changes: 25 additions & 26 deletions runtime/sema/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,31 @@ func getArrayMembers(arrayType ArrayType) map[string]MemberResolver {
)
},
},
ArrayTypeFilterFunctionName: {
Kind: common.DeclarationKindFunction,
Resolve: func(memoryGauge common.MemoryGauge, identifier string, targetRange ast.Range, report func(error)) *Member {

elementType := arrayType.ElementType(false)

if elementType.IsResourceType() {
report(
&InvalidResourceArrayMemberError{
Name: identifier,
DeclarationKind: common.DeclarationKindFunction,
Range: targetRange,
},
)
}

return NewPublicFunctionMember(
memoryGauge,
arrayType,
identifier,
ArrayFilterFunctionType(elementType),
arrayTypeFilterFunctionDocString,
)
},
},
}

// TODO: maybe still return members but report a helpful error?
Expand Down Expand Up @@ -2090,32 +2115,6 @@ func getArrayMembers(arrayType ArrayType) map[string]MemberResolver {
)
},
}

members[ArrayTypeFilterFunctionName] = MemberResolver{
Kind: common.DeclarationKindFunction,
Resolve: func(memoryGauge common.MemoryGauge, identifier string, targetRange ast.Range, report func(error)) *Member {

elementType := arrayType.ElementType(false)

if elementType.IsResourceType() {
report(
&InvalidResourceArrayMemberError{
Name: identifier,
DeclarationKind: common.DeclarationKindFunction,
Range: targetRange,
},
)
}

return NewPublicFunctionMember(
memoryGauge,
arrayType,
identifier,
ArrayFilterFunctionType(elementType),
arrayTypeFilterFunctionDocString,
)
},
}
}

return withBuiltinMembers(arrayType, members)
Expand Down
26 changes: 10 additions & 16 deletions runtime/tests/checker/arrays_dictionaries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,16 @@ func TestCheckArrayFilter(t *testing.T) {
let y = x.filter(onlyEven)
}
fun testFixedSize() {
let x : [Int; 5] = [1, 2, 3, 21, 30]
let onlyEvenInt =
fun (_ x: Int): Bool {
return x % 2 == 0
}
let y = x.filter(onlyEvenInt)
}
`)

require.NoError(t, err)
Expand Down Expand Up @@ -1187,22 +1197,6 @@ func TestCheckArrayFilterInvalidArgs(t *testing.T) {
&sema.TypeMismatchError{},
},
)

testInvalidArgs(`
fun test() {
let x : [Int; 5] = [1, 2, 3, 21, 30]
let onlyEvenInt =
fun (_ x: Int): Bool {
return x % 2 == 0
}
let y = x.filter(onlyEvenInt)
}
`,
[]sema.SemanticError{
&sema.NotDeclaredMemberError{},
},
)
}

func TestCheckResourceArrayFilterInvalid(t *testing.T) {
Expand Down
259 changes: 155 additions & 104 deletions runtime/tests/interpreter/interpreter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10745,68 +10745,99 @@ func TestInterpretArrayFilter(t *testing.T) {
t.Parallel()

inter := parseCheckAndInterpret(t, `
let xs = [1, 2, 3, 100, 200]
let emptyVals: [Int] = []
let xs = [1, 2, 3, 100, 200]
let xs_fixed: [Int; 5] = [1, 2, 3, 100, 200]
let emptyVals: [Int] = []
let emptyVals_fixed: [Int; 0] = []
fun filterxs(): [Int] {
let onlyEven =
fun (_ x: Int): Bool {
return x % 2 == 0
}
return xs.filter(onlyEven)
}
fun originalxs(): [Int] {
return xs
}
fun filterxs(): [Int] {
return xs.filter(onlyEven)
}
fun originalxs(): [Int] {
return xs
}
fun filterempty(): [Int] {
let onlyEven =
fun (_ x: Int): Bool {
return x % 2 == 0
}
fun filterxs_fixed(): [Int] {
return xs_fixed.filter(onlyEven)
}
fun originalxs_fixed(): [Int; 5] {
return xs_fixed
}
fun filterempty(): [Int] {
return emptyVals.filter(onlyEven)
}
fun originalempty(): [Int] {
return emptyVals
}
return emptyVals.filter(onlyEven)
}
fun originalempty(): [Int] {
return emptyVals
}
pub struct TestStruct {
pub var test: Int
init(_ t: Int) {
self.test = t
fun filterempty_fixed(): [Int] {
return emptyVals_fixed.filter(onlyEven)
}
}
let sa = [TestStruct(1), TestStruct(2), TestStruct(3)]
fun filtersa(): [Int] {
let onlyOdd =
fun originalempty_fixed(): [Int; 0] {
return emptyVals_fixed
}
pub struct TestStruct {
pub var test: Int
init(_ t: Int) {
self.test = t
}
}
let onlyOddStruct =
fun (_ x: TestStruct): Bool {
return x.test % 2 == 1
}
let sa_filtered = sa.filter(onlyOdd)
let sa = [TestStruct(1), TestStruct(2), TestStruct(3)]
let sa_fixed: [TestStruct; 3] = [TestStruct(1), TestStruct(2), TestStruct(3)]
let res: [Int] = [];
for s in sa_filtered {
res.append(s.test)
fun filtersa(): [Int] {
let sa_filtered = sa.filter(onlyOddStruct)
let res: [Int] = [];
for s in sa_filtered {
res.append(s.test)
}
return res
}
fun originalsa(): [Int] {
let res: [Int] = [];
for s in sa {
res.append(s.test)
}
return res
}
return res
}
fun originalsa(): [Int] {
let res: [Int] = [];
for s in sa {
res.append(s.test)
fun filtersa_fixed(): [Int] {
let sa_rev = sa_fixed.filter(onlyOddStruct)
let res: [Int] = [];
for s in sa_rev {
res.append(s.test)
}
return res
}
return res
}
`)
fun originalsa_fixed(): [Int] {
let res: [Int] = [];
for s in sa_fixed {
res.append(s.test)
}
return res
}
`)

runValidCase := func(t *testing.T, filterFuncName, originalFuncName string, filteredArray, originalArray *interpreter.ArrayValue) {
runValidCase := func(
t *testing.T,
filterFuncName,
originalFuncName string,
filteredArray, originalArray *interpreter.ArrayValue,
) {
val, err := inter.Invoke(filterFuncName)
require.NoError(t, err)

Expand All @@ -10829,69 +10860,89 @@ func TestInterpretArrayFilter(t *testing.T) {
)
}

runValidCase(t, "filterempty", "originalempty",
interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
interpreter.VariableSizedStaticType{
Type: interpreter.PrimitiveStaticTypeInt,
},
common.ZeroAddress,
), interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
interpreter.VariableSizedStaticType{
Type: interpreter.PrimitiveStaticTypeInt,
},
common.ZeroAddress,
))
for _, suffix := range []string{"_fixed", ""} {
fixed := suffix == "_fixed"

runValidCase(t, "filterxs", "originalxs",
interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
interpreter.VariableSizedStaticType{
var originalArrayType interpreter.ArrayStaticType
if fixed {
originalArrayType = &interpreter.ConstantSizedStaticType{
Type: interpreter.PrimitiveStaticTypeInt,
},
common.ZeroAddress,
interpreter.NewUnmeteredIntValueFromInt64(2),
interpreter.NewUnmeteredIntValueFromInt64(100),
interpreter.NewUnmeteredIntValueFromInt64(200),
), interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
interpreter.VariableSizedStaticType{
}
} else {
originalArrayType = &interpreter.VariableSizedStaticType{
Type: interpreter.PrimitiveStaticTypeInt,
},
common.ZeroAddress,
interpreter.NewUnmeteredIntValueFromInt64(1),
interpreter.NewUnmeteredIntValueFromInt64(2),
interpreter.NewUnmeteredIntValueFromInt64(3),
interpreter.NewUnmeteredIntValueFromInt64(100),
interpreter.NewUnmeteredIntValueFromInt64(200),
))
}
}
// Return type is always variable sized array.
var returnArrayType = &interpreter.VariableSizedStaticType{
Type: interpreter.PrimitiveStaticTypeInt,
}

runValidCase(t, "filtersa", "originalsa",
interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
interpreter.VariableSizedStaticType{
Type: interpreter.PrimitiveStaticTypeInt,
},
common.ZeroAddress,
interpreter.NewUnmeteredIntValueFromInt64(1),
interpreter.NewUnmeteredIntValueFromInt64(3),
), interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
interpreter.VariableSizedStaticType{
Type: interpreter.PrimitiveStaticTypeInt,
},
common.ZeroAddress,
interpreter.NewUnmeteredIntValueFromInt64(1),
interpreter.NewUnmeteredIntValueFromInt64(2),
interpreter.NewUnmeteredIntValueFromInt64(3),
))
setFixedSize := func(size int64) {
if fixed {
constSized, ok := originalArrayType.(*interpreter.ConstantSizedStaticType)
assert.True(t, ok)

constSized.Size = size
}
}

setFixedSize(0)
runValidCase(t, "filterempty"+suffix, "originalempty"+suffix,
interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
returnArrayType,
common.ZeroAddress,
), interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
originalArrayType,
common.ZeroAddress,
))

setFixedSize(5)
runValidCase(t, "filterxs"+suffix, "originalxs"+suffix,
interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
returnArrayType,
common.ZeroAddress,
interpreter.NewUnmeteredIntValueFromInt64(2),
interpreter.NewUnmeteredIntValueFromInt64(100),
interpreter.NewUnmeteredIntValueFromInt64(200),
), interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
originalArrayType,
common.ZeroAddress,
interpreter.NewUnmeteredIntValueFromInt64(1),
interpreter.NewUnmeteredIntValueFromInt64(2),
interpreter.NewUnmeteredIntValueFromInt64(3),
interpreter.NewUnmeteredIntValueFromInt64(100),
interpreter.NewUnmeteredIntValueFromInt64(200),
))

runValidCase(t, "filtersa"+suffix, "originalsa"+suffix,
interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
returnArrayType,
common.ZeroAddress,
interpreter.NewUnmeteredIntValueFromInt64(1),
interpreter.NewUnmeteredIntValueFromInt64(3),
), interpreter.NewArrayValue(
inter,
interpreter.EmptyLocationRange,
&interpreter.VariableSizedStaticType{
Type: interpreter.PrimitiveStaticTypeInt,
},
common.ZeroAddress,
interpreter.NewUnmeteredIntValueFromInt64(1),
interpreter.NewUnmeteredIntValueFromInt64(2),
interpreter.NewUnmeteredIntValueFromInt64(3),
))
}
}

func TestInterpretOptionalReference(t *testing.T) {
Expand Down

0 comments on commit ae5936a

Please sign in to comment.