Requirement¶
A Requirement is a symbol node for declaring generic types
and operations associated with the types.
Declaración¶
Sintaxis¶
Requirement(symbol_table symtab, identifier name,
identifier* args, require_instantiation* requires)
Argumentos¶
Argument Name |
Denotes |
|---|---|
|
symbol table of the requirement |
|
name of the requirement |
|
symbol names inside the requirement |
|
instantiating argument types through require calls |
Valores devueltos¶
N/A
Descripción¶
Generic types and their abstract methods (whose implementation are not yet known) are needed during implementation of generic functions. Requirements fills the hole here by declaring (adhoc) generic types and their associated methods. Requirements are analoguos to typeclasses in Haskell and traits in Rust.
name denotes the name of the requirement. In the example below, the name of the requirements are semigroup and monoid.
args denotes the parameters of the requirement. A warning is generated if there is no corresponding symbol found in the requirement’s symtab for a given paramater. In the example below, the parameters (T, op) make up the args of the semigroup requirement.
symtab denotes the symbol table of the requirement. It contains generic types, represented by variables typed with TypeParameter, and abstract functions whose signatures may contain generic types. An error is generated if a symbol found in the symtab but not declared in args. In the example below, semigroup’s symtab contains the variable T with type TypeParameter T and the function op with type TypeParameter T x TypeParameter T -> TypeParameter T.
require_instantiation (Require statements) are calls to requirements that replace the types of the arguments with the corresponding parameters” types in the requirement. As an example the requirement monoid below reuses semigroup through require :: semigroup(S, combine). Although S and combine are not declared as symbols inside monoid, this statement maps the typing for both S and combine with the parameter T and op in semigroup that defines S as a type parameter. As a result, type(S) is a valid type in monoid and two methods combine and empty are associated with it.
Tipos¶
Ejemplos¶
LFortran:
module semigroup_m
requirement semigroup(T, op)
type, deferred :: T
function op(x,y) result(z)
type(T), intent(in) :: x, y
type(T) :: z
end function
end requirement
requirement monoid(S, combine, empty)
require :: semigroup(S, combine)
pure function empty()
type(S) :: empty
end function
end requirement
end module
ASR:
semigroup_m:
(Module
(SymbolTable
2
{
semigroup:
(Requirement
(SymbolTable
3
{
op:
(Function
(SymbolTable
4
{
x:
(Variable
4
x
[]
In
()
()
Default
(TypeParameter
t
)
()
Source
Public
Required
.false.
),
y:
(Variable
4
y
[]
In
()
()
Default
(TypeParameter
t
)
()
Source
Public
Required
.false.
),
z:
(Variable
4
z
[]
ReturnVar
()
()
Default
(TypeParameter
t
)
()
Source
Public
Required
.false.
)
})
op
(FunctionType
[(TypeParameter
t
)
(TypeParameter
t
)]
(TypeParameter
t
)
Source
Implementation
()
.false.
.false.
.false.
.false.
.false.
[]
.true.
)
[]
[(Var 4 x)
(Var 4 y)]
[]
(Var 4 z)
Public
.false.
.false.
()
),
t:
(Variable
3
t
[]
In
()
()
Default
(TypeParameter
t
)
()
Source
Public
Required
.false.
)
})
semigroup
[t
op]
[]
)
})
semigroup_m
[]
.false.
.false.
)