3 Commits
Author SHA1 Message Date
HEL 8197131d8d docs: add Column and Frame to manual 2026-07-03 13:31:56 +02:00
HEL cf91187b7a fix(checker): remove bool as subtype of int 2026-07-03 12:56:47 +02:00
HEL 1b2bdf0b79 docs: add alias statements to manual 2026-07-03 12:56:20 +02:00
3 changed files with 89 additions and 4 deletions
+58 -3
View File
@@ -198,10 +198,26 @@ python3 build/midas/script.py
In this chapter, you will find a complete reference for the Midas definition language. In this chapter, you will find a complete reference for the Midas definition language.
A `*.midas` file contains a number of statements, which can be: A `*.midas` file contains a number of statements, which can be:
- *`alias`* statements (see @alias-stmt): to define a new type alias
- *`type`* statements (see @type-stmt): to define a new type - *`type`* statements (see @type-stmt): to define a new type
- *`extend`* statements (see @extend-stmt): to define member of a type - *`extend`* statements (see @extend-stmt): to define member of a type
- *`predicate`* statements (see @predicate-stmt): to define named predicates that can be used in constraint types - *`predicate`* statements (see @predicate-stmt): to define named predicates that can be used in constraint types
== Alias Statement <alias-stmt>
An *`alias`* statement lets you define a new type alias. It requires a unique name and base type.
While a `type` statement (see @type-stmt) allows generic definitions, aliases are purely a for givin an alternative name to a type.
#figure(
```midas
alias MyType = float
```,
caption: [Simple `alias` statement declaring a new type "`MyType`" equivalent to `float`],
) <midas-simple-alias>
This statement defines a new type called `MyType` which is equivalent to `float`. `MyType` and `float` can be used interchangeably.
== Type Statement <type-stmt> == Type Statement <type-stmt>
A *`type`* statement lets you define a new type. It requires a unique name and base type. A *`type`* statement lets you define a new type. It requires a unique name and base type.
@@ -212,7 +228,7 @@ The simplest form of a *`type`* statement is:
type MyType = float type MyType = float
```, ```,
caption: [Simple `type` statement declaring a new type "`MyType`" as a subtype of `float`], caption: [Simple `type` statement declaring a new type "`MyType`" as a subtype of `float`],
) <midas-simple-alias> ) <midas-simple-type>
This statement defines a new type called `MyType` which is a subtype of `float`. `MyType` is a `float` but a `float` is not necessarily `MyType`. This statement defines a new type called `MyType` which is a subtype of `float`. `MyType` is a `float` but a `float` is not necessarily `MyType`.
@@ -291,8 +307,7 @@ To better refine a generic type, you can also bound type parameters using the fo
caption: [Generic container type definition with a bound], caption: [Generic container type definition with a bound],
) )
This can be read as "`Container` is a generic type which takes one type parameter `T` that must be a subtype of `float`". This can be read as "`Container` is a generic type which takes one type parameter `T` that must be a subtype of `float`".\
You can use a generic type, i.e. instantiate it, by using a similar syntax with concrete type as arguments: You can use a generic type, i.e. instantiate it, by using a similar syntax with concrete type as arguments:
#figure( #figure(
@@ -318,6 +333,46 @@ The _body_ of a generic type, i.e. the right-hand side of the definition, can co
caption: [Type parameters in a generic type's body], caption: [Type parameters in a generic type's body],
) )
=== `Column` / `Frame` types
To provide useful type-checking for data engineers, Midas offers two special types: `Column` and `Frame`.
Their goal is to help type check Pandas' `Series` and `DataFrame` respectively.
==== `Column`
The `Column` type is a generic type used to represent a `pandas.Series` object.
You can use it like any other generic type and it will provide type checking for some common methods and attributes offered by Pandas.
#figure(
```midas
type Temperature = float
alias Temperatures = Column[Temperature]
```,
caption: [Simple column type definition],
)
==== `Frame`
The `Frame` type is a super-powered generic type used to represent a `pandas.DataFrame` object.
In place of type arguments, `Frame` accepts a schema, i.e. a series of column definitions.
@simple-frame show how you can define a simple frame type with 3 columns:
- `name`: a column of `Name` values
- `age`: a column of `int` values
- `height`: a column of `float where _ >= 0` values
Notice that you don't need to specify `Column` types.
#figure(
```midas
type Name = str where len(_) != 0
alias Data = Frame[
name: Name,
age: int,
height: float where _ >= 0
]
```,
) <simple-frame>
#pagebreak() #pagebreak()
== Extend Statement <extend-stmt> == Extend Statement <extend-stmt>
+31
View File
@@ -37,6 +37,9 @@ contexts:
pop: true pop: true
keywords: keywords:
- match: \balias\b
scope: keyword.declaration.midas
push: alias-stmt
- match: \btype\b - match: \btype\b
scope: keyword.declaration.midas scope: keyword.declaration.midas
push: type-stmt push: type-stmt
@@ -47,6 +50,15 @@ contexts:
scope: keyword.declaration.midas scope: keyword.declaration.midas
push: predicate-stmt push: predicate-stmt
alias-stmt:
- match: "{{identifier}}"
scope: entity.name.type
- match: "="
scope: keyword.operator.equal.midas
push: type-expr
- match: $
pop: true
type-stmt: type-stmt:
- match: "{{identifier}}" - match: "{{identifier}}"
scope: entity.name.type scope: entity.name.type
@@ -67,6 +79,13 @@ contexts:
- match: \b(where)\b - match: \b(where)\b
scope: keyword.other.midas scope: keyword.other.midas
set: constraint set: constraint
- match: "Frame"
scope: entity.name.type
push:
- match: \[
push: frame-schema
- match: $
pop: true
- match: "{{identifier}}" - match: "{{identifier}}"
scope: entity.name.type scope: entity.name.type
- match: $ - match: $
@@ -178,3 +197,15 @@ contexts:
- match: '\)' - match: '\)'
pop: true pop: true
frame-schema:
- include: frame-column
- match: \]
# scope: punctuation.section.block.end
pop: true
frame-column:
- match: "{{identifier}}"
scope: variable.other.member
- match: ":"
push: type-expr
-1
View File
@@ -19,7 +19,6 @@ if TYPE_CHECKING:
BUILTIN_SUBTYPES: dict[str, set[str]] = { BUILTIN_SUBTYPES: dict[str, set[str]] = {
"object": {"float", "list", "dict", "str", "bytes", "tuple"}, "object": {"float", "list", "dict", "str", "bytes", "tuple"},
"float": {"int"}, "float": {"int"},
"int": {"bool"},
} }