xtype (halted)

Check-in [7c1cdf6127]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Migrate documentation to Markdown.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7c1cdf61276b81bcc5d2942508217a871e499c410d7c15c4a329d88614af90f5
User & Date: imagic 2024-06-25 11:34:59.596
Context
2024-10-05
21:29
Improve license embedding. ... (check-in: 4eed6cd5ea user: imagic tags: trunk)
2024-06-25
11:34
Migrate documentation to Markdown. ... (check-in: 7c1cdf6127 user: imagic tags: trunk)
2021-11-26
18:31
Release 1.1. ... (check-in: 7ebae51af7 user: imagic tags: trunk, 1.1)
Changes
Unified Diff Ignore Whitespace Patch
Name change from README.adoc to README.md.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16

17
18

19

20

21
22
23
24
25
26
27
28
29

30
31

32
33
34
35

36
37

38
39


40
41
42
43
44
45


46
47
48
49


50
51
52
53

54
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
= xtype
ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]
:toc: left
:toclevels: 5

*xtype*, or Extended Type, is a dynamic type system library for Lua.

Sometimes, advanced type checking code is needed to implement specific abstractions; *xtype* aims to fulfill that need.


.Incentives:

Simplification:: Prevent writing redundant type checking code.
Interoperability:: Having a general low-level type system library can ease the interactions of third-party code.

Metaprogramming / Genericity:: Exploit the dynamic nature of Lua to generate definitions on-the-fly.



See link:src[], link:rockspecs[] or https://luarocks.org/modules/imagicthecat-0a6b669a3a/xtype[luarocks].

== Concepts

=== Type

A **xtype**'s type is either primitive or non-primitive.

A primitive type is a string. It can be any Lua types from `type()` or additional types like `xtype` or `multifunction`.


A non-primitive type is a table defining the type. It contains the `xtype_name`, `xtype_stack` and `xtype_set` fields and should identify as a `xtype`.


==== Value

Any Lua value has a type; we will call this the terminal type of the value as opposed to inherited types.


If the metatable of a `table` or `userdata` value has a `xtype` field, then the type is the value of that field.


If the value is a `cdata`, its type is defined by `xtype.ctype()` or the `\__xtype` field (e.g. through the metatype `__index`) which will call `xtype.ctype()` when encountered.



Otherwise, the type is the Lua type returned by `type()`.

==== Inheritance

A non-primitive type can inherit from other types, building a stack of types. This stack defines the order in which the types are evaluated, from the terminal type to the least specific inherited types.



=== Multifunction

A multifunction is a function that can have multiple definitions, each associated to a specific signature. When called, it resolves the call by selecting a matching definition from the call signature.



==== Metaprogramming

We can use Lua as its own metaprogramming language: we can generate Lua code from Lua.


A multifunction can have generators that are called when no definitions could be found, allowing to generate definitions for specific call signatures on-the-fly.


== API

=== xtype

[source, lua]
----
-- Create a type.
--
-- The created type is a table with 3 fields: xtype_name, xtype_stack and xtype_set.
-- The table can be modified as long as the xtype fields are left untouched.
-- A default metatable is set; it can be replaced at the condition that the
-- type would still be recognized as a "xtype".
--
|
<
<
<
<
<
<
<
<
<

|

|
>

|
>
|
|
>
|
>

>
|

|

|



|
>

|
>

|

|
>

|
>

|
>
>



|

|
>
>

|

|
>
>

|

|
>

|
>

|

|

|
<







1









2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
# xtype










**xtype**, or Extended Type, is a dynamic type system library for Lua.

Sometimes, advanced type checking code is needed to implement specific
abstractions; **xtype** aims to fulfill that need.

Incentives:

- Simplification: Prevent writing redundant type checking code.
- Interoperability: Having a general low-level type system library can ease the
  interactions of third-party code.
- Metaprogramming / Genericity: Exploit the dynamic nature of Lua to generate
  definitions on-the-fly.

See `src/`, `rockspecs/` or
[luarocks](https://luarocks.org/modules/imagicthecat-0a6b669a3a/xtype).

## Concepts

### Type

A **xtype**'s type is either primitive or non-primitive.

A primitive type is a string. It can be any Lua types from `type()` or
additional types like `xtype` or `multifunction`.

A non-primitive type is a table defining the type. It contains the `xtype_name`,
`xtype_stack` and `xtype_set` fields and should identify as a `xtype`.

#### Value

Any Lua value has a type; we will call this the terminal type of the value as
opposed to inherited types.

If the metatable of a `table` or `userdata` value has a `xtype` field, then the
type is the value of that field.

If the value is a `cdata`, its type is defined by `xtype.ctype()` or the
`__xtype` field (e.g. through the metatype `__index`) which will call
`xtype.ctype()` when encountered.

Otherwise, the type is the Lua type returned by `type()`.

#### Inheritance

A non-primitive type can inherit from other types, building a stack of types.
This stack defines the order in which the types are evaluated, from the terminal
type to the least specific inherited types.

### Multifunction

A multifunction is a function that can have multiple definitions, each
associated to a specific signature. When called, it resolves the call by
selecting a matching definition from the call signature.

#### Metaprogramming

We can use Lua as its own metaprogramming language: we can generate Lua code
from Lua.

A multifunction can have generators that are called when no definitions could be
found, allowing to generate definitions for specific call signatures on-the-fly.

## API

### xtype

```lua

-- Create a type.
--
-- The created type is a table with 3 fields: xtype_name, xtype_stack and xtype_set.
-- The table can be modified as long as the xtype fields are left untouched.
-- A default metatable is set; it can be replaced at the condition that the
-- type would still be recognized as a "xtype".
--
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
xtype.tpllist(tpl, i, j, separator)

-- Template substitution.
-- tpl: string with $... parameters
-- args: map of param => value
-- return processed template
xtype.tplsub(tpl, args)
----


=== Multifunction

[source, lua]
----
-- Define a multifunction signature.
-- The keyword "any" matches any type. It is the least specific match for a
-- given terminal type.
--
-- f: definition function; nil to undefine
-- ...: signature, list of types
multifunction:define(f, ...)







<
>

|

|
<







149
150
151
152
153
154
155

156
157
158
159
160

161
162
163
164
165
166
167
xtype.tpllist(tpl, i, j, separator)

-- Template substitution.
-- tpl: string with $... parameters
-- args: map of param => value
-- return processed template
xtype.tplsub(tpl, args)

```

### Multifunction

```lua

-- Define a multifunction signature.
-- The keyword "any" matches any type. It is the least specific match for a
-- given terminal type.
--
-- f: definition function; nil to undefine
-- ...: signature, list of types
multifunction:define(f, ...)
182
183
184
185
186
187
188
189


multifunction.definitions = {} -- map of sign hash => {.f, .sign}

-- Hash function signature.
-- sign: signature, list of types
-- return number
multifunction:hashSign(sign)
----








<
>
188
189
190
191
192
193
194

195

multifunction.definitions = {} -- map of sign hash => {.f, .sign}

-- Hash function signature.
-- sign: signature, list of types
-- return number
multifunction:hashSign(sign)

```