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

Simplify function types #802

Merged
merged 2 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 0 additions & 2 deletions runtime/convertTypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ func ExportType(t sema.Type, results map[sema.TypeID]cadence.Type) cadence.Type
return exportReferenceType(t, results)
case *sema.RestrictedType:
return exportRestrictedType(t, results)
case *sema.CheckedFunctionType:
return exportFunctionType(t.FunctionType, results)
case *sema.CapabilityType:
return exportCapabilityType(t, results)
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -1437,7 +1437,7 @@ func (interpreter *Interpreter) compositeInitializerFunction(
}

initializer = initializers[0]
functionType := interpreter.Program.Elaboration.SpecialFunctionTypes[initializer].FunctionType
functionType := interpreter.Program.Elaboration.ConstructorFunctionTypes[initializer].FunctionType

parameterList := initializer.FunctionDeclaration.ParameterList

Expand Down
14 changes: 7 additions & 7 deletions runtime/sema/check_composite_declaration.go
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ func (checker *Checker) declareCompositeMembersAndValue(

func (checker *Checker) declareCompositeConstructor(
declaration *ast.CompositeDeclaration,
constructorType *SpecialFunctionType,
constructorType *ConstructorFunctionType,
constructorArgumentLabels []string,
) {
// Resource and event constructors are effectively always private,
Expand Down Expand Up @@ -738,7 +738,7 @@ func (checker *Checker) declareEnumConstructor(
constructorOrigins = make(map[string]*Origin, len(enumCases))
}

constructorType := &SpecialFunctionType{
constructorType := &ConstructorFunctionType{
FunctionType: &FunctionType{
Parameters: []*Parameter{
{
Expand All @@ -751,8 +751,8 @@ func (checker *Checker) declareEnumConstructor(
Type: compositeType,
},
),
Members: constructorMembers,
},
Members: constructorMembers,
}

memberCaseTypeAnnotation := NewTypeAnnotation(compositeType)
Expand Down Expand Up @@ -1271,11 +1271,11 @@ func (checker *Checker) compositeConstructorType(
compositeDeclaration *ast.CompositeDeclaration,
compositeType *CompositeType,
) (
constructorFunctionType *SpecialFunctionType,
constructorFunctionType *ConstructorFunctionType,
argumentLabels []string,
) {

constructorFunctionType = &SpecialFunctionType{
constructorFunctionType = &ConstructorFunctionType{
FunctionType: &FunctionType{
ReturnTypeAnnotation: NewTypeAnnotation(compositeType),
},
Expand All @@ -1297,8 +1297,8 @@ func (checker *Checker) compositeConstructorType(
// NOTE: Don't use `constructorFunctionType`, as it has a return type.
// The initializer itself has a `Void` return type.

checker.Elaboration.SpecialFunctionTypes[firstInitializer] =
&SpecialFunctionType{
checker.Elaboration.ConstructorFunctionTypes[firstInitializer] =
&ConstructorFunctionType{
FunctionType: &FunctionType{
Parameters: constructorFunctionType.Parameters,
ReturnTypeAnnotation: NewTypeAnnotation(VoidType),
Expand Down
2 changes: 1 addition & 1 deletion runtime/sema/check_invocation_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func (checker *Checker) checkConstructorInvocationWithResourceResult(
returnType Type,
inCreate bool,
) {
if _, ok := invokableType.(*SpecialFunctionType); !ok {
if _, ok := invokableType.(*ConstructorFunctionType); !ok {
return
}

Expand Down
4 changes: 2 additions & 2 deletions runtime/sema/elaboration.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type Elaboration struct {
AssignmentStatementValueTypes map[*ast.AssignmentStatement]Type
AssignmentStatementTargetTypes map[*ast.AssignmentStatement]Type
CompositeDeclarationTypes map[*ast.CompositeDeclaration]*CompositeType
SpecialFunctionTypes map[*ast.SpecialFunctionDeclaration]*SpecialFunctionType
ConstructorFunctionTypes map[*ast.SpecialFunctionDeclaration]*ConstructorFunctionType
FunctionExpressionFunctionType map[*ast.FunctionExpression]*FunctionType
InvocationExpressionArgumentTypes map[*ast.InvocationExpression][]Type
InvocationExpressionParameterTypes map[*ast.InvocationExpression][]Type
Expand Down Expand Up @@ -88,7 +88,7 @@ func NewElaboration() *Elaboration {
AssignmentStatementValueTypes: map[*ast.AssignmentStatement]Type{},
AssignmentStatementTargetTypes: map[*ast.AssignmentStatement]Type{},
CompositeDeclarationTypes: map[*ast.CompositeDeclaration]*CompositeType{},
SpecialFunctionTypes: map[*ast.SpecialFunctionDeclaration]*SpecialFunctionType{},
ConstructorFunctionTypes: map[*ast.SpecialFunctionDeclaration]*ConstructorFunctionType{},
FunctionExpressionFunctionType: map[*ast.FunctionExpression]*FunctionType{},
InvocationExpressionArgumentTypes: map[*ast.InvocationExpression][]Type{},
InvocationExpressionParameterTypes: map[*ast.InvocationExpression][]Type{},
Expand Down
133 changes: 61 additions & 72 deletions runtime/sema/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -1908,10 +1908,12 @@ func formatFunctionType(
// FunctionType
//
type FunctionType struct {
TypeParameters []*TypeParameter
Parameters []*Parameter
ReturnTypeAnnotation *TypeAnnotation
RequiredArgumentCount *int
TypeParameters []*TypeParameter
Parameters []*Parameter
ReturnTypeAnnotation *TypeAnnotation
RequiredArgumentCount *int
ArgumentExpressionsCheck ArgumentExpressionsCheck
Members *StringMemberOrderedMap
}

func RequiredArgumentCount(count int) *int {
Expand All @@ -1924,8 +1926,15 @@ func (t *FunctionType) InvocationFunctionType() *FunctionType {
return t
}

func (*FunctionType) CheckArgumentExpressions(_ *Checker, _ []ast.Expression, _ ast.Range) {
// NO-OP: no checks for normal functions
func (t *FunctionType) CheckArgumentExpressions(
checker *Checker,
argumentExpressions []ast.Expression,
invocationRange ast.Range,
) {
if t.ArgumentExpressionsCheck == nil {
return
}
t.ArgumentExpressionsCheck(checker, argumentExpressions, invocationRange)
}

func (t *FunctionType) String() string {
Expand Down Expand Up @@ -2304,18 +2313,6 @@ func (t *FunctionType) Resolve(typeArguments *TypeParameterTypeOrderedMap) Type
}

func (t *FunctionType) GetMembers() map[string]MemberResolver {
return withBuiltinMembers(t, nil)
}

// SpecialFunctionType is the the type representing a special function,
// i.e., a constructor or destructor

type SpecialFunctionType struct {
*FunctionType
Members *StringMemberOrderedMap
}

func (t *SpecialFunctionType) GetMembers() map[string]MemberResolver {
// TODO: optimize
members := make(map[string]MemberResolver, t.Members.Len())
t.Members.Foreach(func(name string, loopMember *Member) {
Expand All @@ -2332,6 +2329,12 @@ func (t *SpecialFunctionType) GetMembers() map[string]MemberResolver {
return withBuiltinMembers(t, members)
}

// ConstructorFunctionType is the the type representing a constructor function

type ConstructorFunctionType struct {
*FunctionType
}
turbolent marked this conversation as resolved.
Show resolved Hide resolved

// CheckedFunctionType is the the type representing a function that checks the arguments,
// e.g., integer functions

Expand All @@ -2341,19 +2344,6 @@ type ArgumentExpressionsCheck func(
invocationRange ast.Range,
)

type CheckedFunctionType struct {
*FunctionType
ArgumentExpressionsCheck ArgumentExpressionsCheck
}

func (t *CheckedFunctionType) CheckArgumentExpressions(
checker *Checker,
argumentExpressions []ast.Expression,
invocationRange ast.Range,
) {
t.ArgumentExpressionsCheck(checker, argumentExpressions, invocationRange)
}

// BaseTypeActivation is the base activation that contains
// the types available in programs
//
Expand Down Expand Up @@ -2513,23 +2503,23 @@ func init() {
panic(errors.NewUnreachableError())
}

functionType := &FunctionType{
Parameters: []*Parameter{
{
Label: ArgumentLabelNotRequired,
Identifier: "value",
TypeAnnotation: NewTypeAnnotation(NumberType),
},
},
ReturnTypeAnnotation: NewTypeAnnotation(numberType),
ArgumentExpressionsCheck: numberFunctionArgumentExpressionsChecker(numberType),
}

BaseValueActivation.Set(
typeName,
baseFunctionVariable(
typeName,
&CheckedFunctionType{
FunctionType: &FunctionType{
Parameters: []*Parameter{
{
Label: ArgumentLabelNotRequired,
Identifier: "value",
TypeAnnotation: NewTypeAnnotation(NumberType),
},
},
ReturnTypeAnnotation: NewTypeAnnotation(numberType),
},
ArgumentExpressionsCheck: numberFunctionArgumentExpressionsChecker(numberType),
},
functionType,
),
)
}
Expand Down Expand Up @@ -2560,34 +2550,33 @@ func init() {
panic(errors.NewUnreachableError())
}

functionType := &FunctionType{
Parameters: []*Parameter{
{
Label: ArgumentLabelNotRequired,
Identifier: "value",
TypeAnnotation: NewTypeAnnotation(IntegerType),
},
},
ReturnTypeAnnotation: NewTypeAnnotation(addressType),
ArgumentExpressionsCheck: func(checker *Checker, argumentExpressions []ast.Expression, _ ast.Range) {
if len(argumentExpressions) < 1 {
return
}

intExpression, ok := argumentExpressions[0].(*ast.IntegerExpression)
if !ok {
return
}

CheckAddressLiteral(intExpression, checker.report)
},
}
BaseValueActivation.Set(
typeName,
baseFunctionVariable(
typeName,
&CheckedFunctionType{
FunctionType: &FunctionType{
Parameters: []*Parameter{
{
Label: ArgumentLabelNotRequired,
Identifier: "value",
TypeAnnotation: NewTypeAnnotation(IntegerType),
},
},
ReturnTypeAnnotation: NewTypeAnnotation(addressType),
},
ArgumentExpressionsCheck: func(checker *Checker, argumentExpressions []ast.Expression, _ ast.Range) {
if len(argumentExpressions) < 1 {
return
}

intExpression, ok := argumentExpressions[0].(*ast.IntegerExpression)
if !ok {
return
}

CheckAddressLiteral(intExpression, checker.report)
},
},
functionType,
),
)
}
Expand Down Expand Up @@ -4522,17 +4511,17 @@ func (t *TransactionType) EntryPointFunctionType() *FunctionType {
}
}

func (t *TransactionType) PrepareFunctionType() *SpecialFunctionType {
return &SpecialFunctionType{
func (t *TransactionType) PrepareFunctionType() *ConstructorFunctionType {
return &ConstructorFunctionType{
FunctionType: &FunctionType{
Parameters: t.PrepareParameters,
ReturnTypeAnnotation: NewTypeAnnotation(VoidType),
},
}
}

func (*TransactionType) ExecuteFunctionType() *SpecialFunctionType {
return &SpecialFunctionType{
func (*TransactionType) ExecuteFunctionType() *ConstructorFunctionType {
return &ConstructorFunctionType{
FunctionType: &FunctionType{
Parameters: []*Parameter{},
ReturnTypeAnnotation: NewTypeAnnotation(VoidType),
Expand Down
6 changes: 3 additions & 3 deletions runtime/stdlib/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ var HashAlgorithmValue = StandardLibraryValue{
Kind: common.DeclarationKindEnum,
}

func cryptoAlgorithmEnumType(enumType *sema.CompositeType, enumCases []sema.CryptoAlgorithm) *sema.SpecialFunctionType {
func cryptoAlgorithmEnumType(enumType *sema.CompositeType, enumCases []sema.CryptoAlgorithm) *sema.ConstructorFunctionType {
members := make([]*sema.Member, len(enumCases))
for i, algo := range enumCases {
members[i] = sema.NewPublicEnumCaseMember(
Expand All @@ -196,7 +196,7 @@ func cryptoAlgorithmEnumType(enumType *sema.CompositeType, enumCases []sema.Cryp
)
}

constructorType := &sema.SpecialFunctionType{
constructorType := &sema.ConstructorFunctionType{
FunctionType: &sema.FunctionType{
Parameters: []*sema.Parameter{
{
Expand All @@ -209,8 +209,8 @@ func cryptoAlgorithmEnumType(enumType *sema.CompositeType, enumCases []sema.Cryp
Type: enumType,
},
),
Members: sema.GetMembersAsMap(members),
},
Members: sema.GetMembersAsMap(members),
}

return constructorType
Expand Down