Tipos
HoopLang es un lenguaje con tipos estáticos y sin funciones de usuario:
verificar un archivo es evaluarlo. Cada expresión se reduce a un valor
con uno de los tipos de este capítulo, y cada uso (una operación, una
propiedad, un argumento) exige un tipo concreto. Un tipo equivocado es un
error E001 con el nombre de los tipos involucrados; un valor del tipo
correcto pero fuera de rango es E002 (ver Diagnósticos).
Lista de tipos#
Los nombres de esta tabla son los que aparecen en los mensajes del
compilador y los que se escriben en una anotación (const x: Length = …).
| Tipo | Se obtiene de | Representación |
|---|---|---|
Length | 2.5mm, 1cm | milímetros (1cm = 10 mm) |
Angle | 45deg | grados |
Ratio | 30% | fracción (30% = 0.30) |
Int | 3 | entero de 64 bits |
Bool | true, false, comparaciones | |
Color | #rrggbb | seis dígitos hex, en minúsculas |
String | "…", '…' | texto Unicode |
Thread | el nombre de un hilo declarado con thread | |
Point | (x, y) con x, y de tipo Length | mm |
Path | path { … } | puntos en mm; abierto o cerrado (close) |
Shape | rect, circle, polygon, operaciones de formas | uno o más polígonos, con huecos |
List | [a, b, …] | elementos de cualquier tipo |
Name | un valor de enumerado (Twill, center, Script…) | el nombre tal cual |
No existen tipos Font, Fabric, Underlay, Anchor ni Hoop: esos
valores son Name (por ejemplo Twill, Auto, center,
Brother_100x100) y cada propiedad que los recibe valida la lista de
nombres permitidos (ver Primitivas,
Texto, Bastidor y Catálogos).
Length, Angle, Ratio, Int#
Las magnitudes llevan siempre su unidad: el tipo lo da la unidad del
literal (ver Léxico § Números). Un número sin unidad es
Int y debe ser entero.
Lengthse guarda en milímetros;cmse convierte al leerlo.Anglese guarda en grados.Ratiose guarda como fracción:120%es 1.2. El tipo no impone un rango; cada uso lo hace (por ejemploscaleexige> 0).Intsirve para contar: índices, pasadas, columnas, rangos defor.
No hay conversión implícita entre ellos: 3 no es 3mm, y 3 < 3mm es
E001: cannot compare Int with Length.
Un entero sin unidad donde va una magnitud lo dice:
E001: r needs a unit (e.g. 15mm), E001: a Point needs units: (1mm, 2mm).
Bool#
true, false y el resultado de las comparaciones. Es el tipo de toda
condición (if) y de los operandos de and, or y not.
Color#
Un Color solo se usa como valor (por ejemplo, en una constante o un
param); las primitivas no reciben colores sino hilos. El color de un hilo
se escribe como literal en su declaración thread (ver
Declaraciones § thread).
String#
Texto Unicode. len(s) cuenta caracteres (no bytes).
Thread#
Un identificador que nombra un hilo declarado (y no una constante) se evalúa
como un valor Thread. Las primitivas nombran su hilo directamente
(fill negro { … }), no mediante una expresión.
const principal: Thread = negroPoint#
Un par (x, y) donde ambos componentes son Length. Cualquier otra
combinación es E001: a Point is (Length, Length), not (Int, Int). Los ejes
siguen la convención de la pantalla: x crece hacia la derecha e y hacia
abajo, en milímetros.
Path#
Una secuencia de al menos dos puntos construida con path { … } (ver
Expresiones § path). Puede ser abierta o
cerrada (termina en close). Las curvas se aplanan al evaluarse.
Shape#
Una región del plano: uno o más polígonos, cada uno con huecos opcionales.
Se construye con las funciones geométricas, con métodos y con las
operaciones booleanas +, -, &. Una forma vacía (por ejemplo la
intersección de dos formas disjuntas) es un valor válido, pero una
primitiva que la recibe la rechaza (E004: the shape is empty).
List#
[a, b, c]: una secuencia de valores. Los elementos pueden ser de tipos
distintos; quien usa la lista decide qué acepta (un for recorre cualquier
lista; rails de un satín exige dos Path abiertos). len(l) da su
largo.
Name#
El valor de un enumerado que el lenguaje conoce: una tela, una fuente, un
ancla, un bastidor, un underlay, left/right, auto, satin, fill o
none (Twill, center, Script…). Cualquier otro identificador que no
esté declarado es un error donde aparece: E007: unknown name x(con sugerencia si hay un nombre parecido) o, si se declara más abajo, E007: x is used before it is declared (line N) ``. En las propiedades
que toman un enumerado (font, fabric, underlay, align, style,
anchor, origin) un nombre suelto llega tal cual y la propiedad lo valida
con su propia lista (E002 con sugerencia).
const tela: Name = PiqueAnotaciones de tipo#
const y param admiten una anotación opcional:
anotación = ":" identificador ;La anotación se compara con el nombre del tipo del valor (la tabla de
arriba); si no coincide es E001: x is declared Angle but its value is Length.
Un tipo que no está en la tabla es E001: unknown type Largo (Length, Angle, …) (con sugerencia si hay uno parecido: Lenght → Length).
// error E001
const giro: Angle = 30deg
const giro2: Angle = 30mm // error E001Conversiones#
No hay conversiones numéricas implícitas. Las únicas conversiones automáticas son entre caminos cerrados y formas:
| Desde | Hacia | Dónde |
|---|---|---|
Path cerrado (≥ 3 puntos) | Shape | donde se espera una forma (shape:, canvas:, inside, shape x = …, métodos, operaciones + - &) |
Shape de una sola pieza | Path cerrado (su contorno) | en path: de run y triple |
- Un
Pathabierto donde se espera una forma esE004: a closed shape is required: the path is missing close. - Un
Pathcerrado con menos de tres puntos esE004: a closed path needs at least 3 points. - Una forma de varias piezas en
path:esE004: run along a shape needs a single piece (this shape has several). - Cualquier otro valor donde se espera una forma es
E001: expected a Shape, not Length.
Operaciones entre tipos#
Esta tabla es exhaustiva: cualquier combinación que no aparece es
E001: cannot compute A op B (con los nombres de los tipos), salvo las
excepciones indicadas.
Aritmética#
| Operación | Resultado |
|---|---|
Length + Length, Length - Length | Length |
Length * Ratio, Ratio * Length | Length |
Length * Int, Int * Length | Length |
Length / Int (divisor ≠ 0) | Length |
Length / Length (divisor ≠ 0) | Ratio |
Angle + Angle, Angle - Angle | Angle |
Angle * Int, Int * Angle | Angle |
Angle * Ratio, Ratio * Angle | Angle |
Angle / Int (divisor ≠ 0) | Angle |
Angle / Angle (divisor ≠ 0) | Ratio |
Ratio + Ratio, Ratio - Ratio, Ratio * Ratio | Ratio |
Ratio * Int, Int * Ratio | Ratio |
Int + Int, Int - Int, Int * Int | Int |
Int mod Int (divisor ≠ 0) | Int (resto euclidiano: nunca negativo) |
Point + Point, Point - Point | Point (componente a componente) |
Notas:
Int / Intno existe y tiene su propio mensaje:E001: Int / Int has no whole result: use mod for the remainder (i mod 2), or a Length (10mm / 3).- Una división o un
modpor cero esE002: division by zero. - No hay
Length * Length, niRatio / …, ni operaciones dePointcon escalares.
Formas#
Si ambos operandos son Shape o Path cerrado:
| Operación | Resultado |
|---|---|
a + b | Shape: unión |
a - b | Shape: diferencia (a sin b) |
a & b | Shape: intersección |
Cualquier otro operador entre formas (*, /, mod) es
E001: shapes only support + (union), - (difference) and & (intersection).
& entre valores que no son formas es E001: cannot compute A & B.
Negación#
-x existe para Length, Angle, Ratio e Int (-3, -50%). Para
cualquier otro tipo es E001: cannot negate a String.
Comparación#
| Operación | Tipos | Resultado |
|---|---|---|
==, != | dos valores del mismo tipo, cualquiera | Bool |
<, <=, >, >= | dos Int, dos Length, dos Angle o dos Ratio | Bool |
- Tipos distintos:
E001: cannot compare Int with Length. - Orden entre tipos sin orden:
E001: Color has no order (only ==, !=). ==compara valores exactos (las longitudes como números de punto flotante, los colores ya normalizados a minúsculas).
Lógica#
| Operación | Resultado |
|---|---|
Bool and Bool, Bool or Bool | Bool |
not Bool | Bool |
Otros tipos: E001: and/or join Bool values, not Int and Bool y
E001: not takes a Bool, not Int.
Ejemplo#
const a: Length = 1cm + 2mm
const b: Ratio = a / 4mm
const c: Length = a * 50%
const d: Angle = 90deg / 4
const e: Ratio = 90deg / 45deg
const f: Int = 7 mod 3
const g: Point = (10mm, 5mm) + (1mm, 1mm)
const h: Bool = a > 10mm and not (f == 0)// error E001
const x = 2mm * 3mm // error E001