Guía de HyperEZ
HyperEZ es un lenguaje pensado para aprender a programar y para crear juegos. Los mensajes de error están en español y explican cómo arreglar el problema. Esta guía recorre el lenguaje de principio a fin; la lista completa de funciones está en la referencia de la API (hyper docs API.md).
Lo más fácil es HyperEZ Editor (se instala con HyperEZ en Windows): escribe y pulsa F5. También puedes guardar el programa como programa.hez y escribir hyper programa.hez, hacer doble clic en el archivo o pulsar F5 en VS Code. Con hyper watch programa.hz (o Ctrl+Alt+F5 en VS Code) se vuelve a ejecutar cada vez que guardas.
Para probar ideas sin crear un archivo, escribe hyper en una terminal: es la consola interactiva. Cada línea se ejecuta al pulsar Intro, el valor de una expresión se muestra solo y lo que defines se conserva:
hz> var precio = 12
hz> precio * 3
36
hz> "oferta".upper()
"OFERTA"
.ayuda muestra los comandos de la consola: .vars (lo que has definido), .guardar archivo.hz (convierte la sesión en un programa), .cargar archivo.hz, .reiniciar y .salir.
1. Primer programa
print("¡Hola, mundo!")
var nombre = "Ana"
print("Hola, ${nombre}. Tu nombre tiene ${len(nombre)} letras.")▶ Probar en el editor
print muestra valores separados por espacios. Dentro de un texto, ${...} inserta el resultado de cualquier expresión.
2. Variables y tipos
var vidas = 3 // se puede cambiar
const MAX_VIDAS = 5 // no se puede cambiar
let semilla = 1234 // se asigna una sola vez
var puntos: number = 0 // con tipo: el compilador avisa si no encaja
var nombre: text = "Ana"
var jefe: text? = null // el ? permite null▶ Probar en el editor
Los tipos son opcionales: si los escribes, HyperEZ comprueba los errores antes de ejecutar (hyper check). Tipos básicos: number, int, text, bool, list, map, set, function, any y los nombres de tus clases.
3. Números, textos y operadores
var a = 7
print(a + 2, a - 2, a * 2, a / 2, a % 2, a ** 2) // 9 5 14 3.5 1 49
print(0xFF, 0b1010, 1_000_000)
print(round(3.14159, 2), floor(2.7), clamp(15, 0, 10), random(1, 6))
var t = " Hola Mundo "
print(t.trim().upper(), t.contains("Mundo"), t.trim().split(" "))
print("ab" * 3, "ñandú".length, "{} tiene {} puntos".format("Ana", 10))
var largo = """Un texto
de varias líneas"""
print(largo.lines().length)▶ Probar en el editor
Comparaciones: ==, !=, <, <=, >, >=. Lógica: and, or, not. Valores por defecto: x ?? "si es null"; acceso seguro: jugador?.arma?.nombre.
4. Listas, mapas, conjuntos y rangos
var numeros = [5, 3, 8, 1]
numeros.add(10)
print(numeros[0], numeros[-1], numeros[1..3])
print(numeros.map(x => x * 2), numeros.filter(x => x > 4), numeros.sum())
print(numeros.copy().sort(), numeros.maxBy(x => x), [1, 2] + [3])
var jugador = { nombre: "Ana", vida: 3 }
jugador.oro = 10
jugador["nivel"] = 2
print(jugador.nombre, jugador.keys(), jugador.get("mana", 0))
var vistos = set(1, 2, 2, 3)
print(vistos.length, 2 in vistos)
print(range(5).toList(), (1..=3).toList())▶ Probar en el editor
Comprensiones, tubería y trozos
var cuadrados = [n * n for n in 1..=5 if n % 2 == 1] // [1, 9, 25]
var precios = {fruta: precio * 2 for fruta, precio in {pera: 1, uva: 3}}
var base = {color: "azul", talla: "M"}
var camiseta = {...base, talla: "L"} // copia cambiando una clave
print(cuadrados, precios, camiseta)
print([3, 1, 2] |> len, "Programar"[..3], [1, 2, 3, 4][2..])▶ Probar en el editor
5. Decisiones y bucles
var vida = 2
if vida <= 0 {
print("Fin de la partida")
} else if vida == 1 {
print("¡Cuidado!")
} else {
print("Todo bien")
}
for i in 0..3 { print("i =", i) } // 0, 1, 2
for i in 10..0 step -5 { print(i) } // 10, 5
foreach fruta in ["pera", "uva"] { print(fruta) }
for i, fruta in ["pera", "uva"] { print(i, fruta) }
repeat 2 { print("¡hola!") }
var n = 0
while true {
n += 1
if n == 2 { continue }
if n > 3 { break }
print("n =", n)
}▶ Probar en el editor
match
match elige un resultado según un valor. Admite varios valores, rangos, guardas con if y bloques; en un bloque, la última expresión es el resultado.
function describir(x: number): text {
return match x {
0 => "cero"
1, 2, 3 => "pequeño"
4..10 => "medio"
else if x < 0 => "negativo"
else => "grande"
}
}
print(describir(2), describir(7), describir(-1), describir(50))
var tecla = "space"
var accion = match tecla {
"space" => { print("¡salto!"); "saltar" }
"escape" => "salir"
else => "nada"
}
print(accion)▶ Probar en el editor
6. Funciones
/// Calcula el daño de un ataque. (Los comentarios /// aparecen al pasar el ratón en VS Code.)
function danio(base: number, multiplicador: number = 2, ...extras: number): number {
return base * multiplicador + extras.sum()
}
print(danio(10), danio(10, 3), danio(base: 5, multiplicador: 4), danio(1, 1, 2, 3))
var doble = x => x * 2
var sumar = (a, b) => a + b
print(doble(4), sumar(2, 3))
function contador() {
var c = 0
return () => {
c += 1
return c
}
}
var siguiente = contador()
siguiente()
print(siguiente()) // 2▶ Probar en el editor
7. Clases, structs, enums e interfaces
interface Danable { function recibir(n: number): void }
class Personaje implements Danable {
var nombre: text
var vida: number = 10
static var creados = 0
constructor(nombre: text) {
this.nombre = nombre
creados += 1
}
get vivo(): bool { return vida > 0 }
function recibir(n: number): void { vida = max(0, vida - n) }
function toString(): text { return "${nombre} (${vida})" }
}
class Jefe extends Personaje {
var escudo = 2
constructor(nombre: text) {
super(nombre)
vida = 50
}
function recibir(n: number): void { super.recibir(n / escudo) }
}
var heroe = Personaje("Ana")
var jefe = Jefe("Rey")
jefe.recibir(20)
print(heroe, jefe, jefe is Personaje, Personaje.creados)
struct Punto { var x: number = 0; var y: number = 0 }
print(Punto(1, 2) == Punto(1, 2)) // los structs se comparan por valor
enum Estado { Menu, Jugando, Pausa }
var estado = Estado.Jugando
print(estado, estado.name, Estado.count)▶ Probar en el editor
8. Errores
class SinMana extends Error {}
function lanzarHechizo(mana: number) {
if mana < 5 { throw SinMana("no tienes suficiente maná") }
print("¡Bola de fuego!")
}
try {
lanzarHechizo(2)
} catch e {
print("Error:", e.message, e is SinMana)
} finally {
print("esto se ejecuta siempre")
}▶ Probar en el editor
Si un error no se captura, HyperEZ muestra el mensaje, la línea exacta y la pila de llamadas.
9. Eventos
Los eventos separan "lo que pasa" de "quién reacciona". Ideal para juegos.
event Golpe(objetivo: text, danio: number)
on Golpe as e { print("${e.objetivo} pierde ${e.danio} de vida") }
once Golpe priority 10 as e { print("¡Primer golpe de la partida!") }
emit Golpe("Ana", 5)
emit Golpe(objetivo: "Rey", danio: 7)▶ Probar en el editor
Cada on devuelve una suscripción que se cancela con off(suscripcion); off(Golpe) las cancela todas. Dentro de un manejador, e.stopPropagation() evita que se ejecuten los siguientes.
10. Tareas asíncronas
async y await permiten esperar sin bloquear el programa: temporizadores, oleadas de enemigos, animaciones de texto...
async function cuentaAtras(desde: number) {
for i in desde..0 step -1 {
print(i)
await wait(0.2)
}
print("¡Ya!")
}
async function cargar(nombre: text): text {
await wait(0.1)
return "nivel ${nombre} listo"
}
await cuentaAtras(3)
print(await awaitAll([cargar("1"), cargar("2")]))
var reloj = spawn(async () => {
while true {
await wait(1)
print("tic")
}
})
reloj.cancel()▶ Probar en el editor
11. Módulos
Cada archivo es un módulo. Todo lo que no es private se puede importar desde otro archivo:
// enemigos.hz
class Orco { var vida = 30 }
private var contador = 0
// main.hz
from "./enemigos.hz" import Orco
import "./enemigos.hz" as enemigos
var o = Orco()
var o2 = enemigos.Orco()
12. Juegos de consola
El módulo Console permite leer teclas sin pulsar Intro, escribir en color y mover el cursor. Console.interactive indica si hay un teclado (en las pruebas es false, y los ejemplos aprovechan para jugar solos).
var x = 5
var jugando = Console.interactive
while jugando {
Console.clear()
Console.print(" ".repeat(x) + "@", "cyan")
Console.print("← → para moverte, Esc para salir", "gray")
match Console.readKey() {
"left" => x = max(0, x - 1)
"right" => x = min(Console.width - 2, x + 1)
"escape" => jugando = false
else => null
}
}▶ Probar en el editor
Para juegos en tiempo real usa Console.pollKey() (no espera) junto con System.sleep(segundos). Mira la serpiente, el tres en raya y la mazmorra.
13. Archivos y partidas guardadas
var partida = { jugador: "Ana", nivel: 3, objetos: ["espada", "llave"] }
File.write("partida.json", JSON.stringify(partida, 2))
var cargada = JSON.parse(File.read("partida.json"))
print(cargada.nivel, cargada.objetos)
File.delete("partida.json")▶ Probar en el editor
Las rutas relativas parten de la carpeta del programa.
14. Pruebas
function sumar(a: number, b: number): number { return a + b }
test("sumar números", () => {
assertEqual(sumar(2, 2), 4)
assertEqual(sumar(-1, 1), 0)
})
test("lanza un error", () => {
assertThrows(() => { throw Error("boom") })
})▶ Probar en el editor
hyper test ejecuta cada archivo .hz de la carpeta tests/. Si junto a una prueba hay un archivo .out con la salida esperada, se compara línea a línea (hyper test --update lo genera).
15. Una base para todo
Además de lo anterior, HyperEZ trae de serie bibliotecas para casi cualquier proyecto. Un vistazo rápido (cada área tiene su guía en la documentación de la biblioteca):
// Sistema: otros programas, rutas, fechas
print(Process.run(System.exe, ["version"]).output.lines()[0], Path.ext("foto.png"), Time.date().year > 2000)
// Texto: expresiones regulares (r"..." no procesa las barras)
print(Regex(r"\d+").findAll("3 gatos y 12 perros").map(m => toNumber(m.text)))
// Binario: bytes, hash y compresión
print(Bytes("hola").toHex(" "), Hash.sha256("hola").substring(0, 12), Bytes("a" * 100).compress().length)
// Desestructuración y sobrecarga de operadores
var [primero, ...resto] = [1, 2, 3]
print(primero, resto, Vec2(1, 2) + Vec2(3, 4))
// Matemáticas en C++ para IA y ciencia
var m = Matrix([[1, 2], [3, 4]])
print(m.dot(Matrix.identity(2)) == m, (m * 2).toList())▶ Probar en el editor
import ai
import stats
import db
import html
print(stats.median([5, 1, 3]), ai.LinearRegression().fit([1, 2, 3], [2, 4, 6]).slope)
var base = db.Database()
base.collection("notas").insert({ alumno: "Ana", nota: 9 })
print(base.collection("notas").count(), html.escape("<b>"))▶ Probar en el editor
| Para | Usa |
|---|---|
| Juegos de consola | Console, Vec2, Color, random |
| Inteligencia artificial | Matrix, import ai |
| Datos | JSON, import csv, import stats, import db |
| Webs y APIs | import web, import site, hyper serve, Http.serve, import html, Http.get |
| Gráficos y sonido | Image, import audio |
| Scripts y herramientas | Process, File, Path, Time, import cli |
| Bajo nivel | Bytes, Hash, operadores de bits, import x86 |
| Estructuras de datos y algoritmos | import collections (pilas, colas, grafos), import algo (A*, combinatoria) |
| Documentos | import template, import markdown, import ini, import log, import zip, import svg |
import collections
import algo
import template
var g = collections.Graph()
g.addEdge("A", "B", 2)
g.addEdge("B", "C", 3)
print(g.shortestPath("A", "C").distance, algo.gridPath(["S.#", "..G"], [0, 0], [2, 1]).length)
print(template.render("{{#each n}}{{this}}{{/each}}", { n: [1, 2, 3] }), (1234.5).format(1), "Canción".removeAccents())▶ Probar en el editor
16. Herramientas
| Comando | Qué hace | |||
|---|---|---|---|---|
hyper programa.hz | Ejecuta | |||
hyper watch programa.hz | Ejecuta y repite cada vez que guardas | |||
hyper | Consola interactiva | |||
hyper check programa.hz | Busca errores sin ejecutar | |||
hyper test | Ejecuta las pruebas | |||
| `hyper new nombre --tipo juego\ | app\ | ia\ | script` | Crea un proyecto |
hyper fmt | Ordena la sangría y los espacios del código | |||
hyper serve [carpeta] | Sirve una web y recarga el navegador al guardar | |||
hyper bytecode programa.hz | Muestra las instrucciones que genera el compilador | |||
hyper docs API.md | Genera la referencia de la API |
En HyperEZ Editor tienes colores, errores mientras escribes, autocompletado (Ctrl+Espacio), F5 para ejecutar y Ctrl+Mayús+F para formatear: mira su guía.
En VS Code tienes errores mientras escribes, autocompletado, documentación al pasar el ratón, F12 para ir a la definición, F2 para renombrar, F5 para ejecutar y Ctrl+Alt+F5 para ejecutar cada vez que guardas.
HyperEZ