HoopLang Docs
/
Playground
Referencia del lenguaje

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 = …).

TipoSe obtiene deRepresentación
Length2.5mm, 1cmmilímetros (1cm = 10 mm)
Angle45deggrados
Ratio30%fracción (30% = 0.30)
Int3entero de 64 bits
Booltrue, false, comparaciones
Color#rrggbbseis dígitos hex, en minúsculas
String"…", '…'texto Unicode
Threadel nombre de un hilo declarado con thread
Point(x, y) con x, y de tipo Lengthmm
Pathpath { … }puntos en mm; abierto o cerrado (close)
Shaperect, circle, polygon, operaciones de formasuno o más polígonos, con huecos
List[a, b, …]elementos de cualquier tipo
Nameun 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.

  • Length se guarda en milímetros; cm se convierte al leerlo.
  • Angle se guarda en grados.
  • Ratio se guarda como fracción: 120% es 1.2. El tipo no impone un rango; cada uso lo hace (por ejemplo scale exige > 0).
  • Int sirve para contar: índices, pasadas, columnas, rangos de for.

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.

HoopLang
const principal: Thread = negro

Point#

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).

HoopLang
const tela: Name = Pique

Anotaciones de tipo#

const y param admiten una anotación opcional:

ebnf
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).

HoopLang
// error E001
const giro: Angle = 30deg
const giro2: Angle = 30mm // error E001

Conversiones#

No hay conversiones numéricas implícitas. Las únicas conversiones automáticas son entre caminos cerrados y formas:

DesdeHaciaDónde
Path cerrado (≥ 3 puntos)Shapedonde se espera una forma (shape:, canvas:, inside, shape x = …, métodos, operaciones + - &)
Shape de una sola piezaPath cerrado (su contorno)en path: de run y triple
  • Un Path abierto donde se espera una forma es E004: a closed shape is required: the path is missing close.
  • Un Path cerrado con menos de tres puntos es E004: a closed path needs at least 3 points.
  • Una forma de varias piezas en path: es E004: 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ónResultado
Length + Length, Length - LengthLength
Length * Ratio, Ratio * LengthLength
Length * Int, Int * LengthLength
Length / Int (divisor ≠ 0)Length
Length / Length (divisor ≠ 0)Ratio
Angle + Angle, Angle - AngleAngle
Angle * Int, Int * AngleAngle
Angle * Ratio, Ratio * AngleAngle
Angle / Int (divisor ≠ 0)Angle
Angle / Angle (divisor ≠ 0)Ratio
Ratio + Ratio, Ratio - Ratio, Ratio * RatioRatio
Ratio * Int, Int * RatioRatio
Int + Int, Int - Int, Int * IntInt
Int mod Int (divisor ≠ 0)Int (resto euclidiano: nunca negativo)
Point + Point, Point - PointPoint (componente a componente)

Notas:

  • Int / Int no 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 mod por cero es E002: division by zero.
  • No hay Length * Length, ni Ratio / …, ni operaciones de Point con escalares.

Formas#

Si ambos operandos son Shape o Path cerrado:

OperaciónResultado
a + bShape: unión
a - bShape: diferencia (a sin b)
a & bShape: 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ónTiposResultado
==, !=dos valores del mismo tipo, cualquieraBool
<, <=, >, >=dos Int, dos Length, dos Angle o dos RatioBool
  • 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ónResultado
Bool and Bool, Bool or BoolBool
not BoolBool

Otros tipos: E001: and/or join Bool values, not Int and Bool y E001: not takes a Bool, not Int.

Ejemplo#

HoopLang
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)
HoopLang
// error E001
const x = 2mm * 3mm // error E001