Saltar al contenido principal

Sintaxis básica

Cómo se escribe un programa en JARU: en qué orden van sus partes, cómo se separan las instrucciones, cómo se cierran los bloques, cómo se escriben los valores y en qué orden se calculan los operadores. Al final están las trampas en las que más se cae.

Cada parte del lenguaje tiene después su página: Variables y constantes, Operadores, Estructuras de control, Funciones...

Un programa​

Un programa de JARU es un fichero .aru, o varios. No hay una función principal: la VM ejecuta el fichero principal de arriba abajo, y el programa acaba al llegar al final.

Lo habitual es escribirlo en este orden:

use Math                     // 1. Los módulos que usa el programa

const LADO = 4 // 2. Las constantes

func area(lado) // 3. Las funciones
return lado * lado
end

// 4. Lo que hace el programa
var a = area(LADO)
println("Área: ", a) // Área: 16
println("La mayor: ", Math.max(a, 20)) // La mayor: 20
  • use abre los módulos de la VM que vas a usar; caben varios en una línea: use Display, Sprite, Input. Sin él, el programa compila, pero se para en la primera línea que usa el módulo, con el error «Module 'Math' not found or not imported.». Los módulos están en La API.
  • import "Fichero.aru" trae el código de otro fichero del proyecto. Ese código se ejecuta antes que la primera línea del fichero principal, aunque el import esté más abajo. Lo cuenta Programas de varios ficheros.
  • Una función existe desde la línea en que se declara. Si la llamas desde más arriba, el programa se para con el error «Undefined variable». Más en Funciones.
  • El programa también puede terminar antes, con exit: ver Errores y excepciones.

Instrucciones y punto y coma​

Lo normal es escribir una instrucción por línea. El punto y coma del final es opcional:

var vidas = 3
var puntos = 0;

Para poner varias en la misma línea, sepáralas con ;. El compilador también las separa sin él, pero se leen peor:

var x = 10; var y = 20; println(x + y)    // 30

El salto de línea no termina una instrucción: el compilador la da por acabada cuando lo que viene detrás ya no puede formar parte de ella. Por eso una instrucción larga puede seguir en la línea de abajo:

var total = 10 +
20 +
30
println(total) // 60
Una línea que empieza por ++ o --

Como el salto de línea no corta la instrucción, un ++ o un -- al principio de una línea se pega a la línea de arriba si esta acaba en una variable:

var partidas = 0
var puntos = 10
var record = puntos
++partidas // se lee como: var record = puntos++
println(record, " ", puntos, " ", partidas) // 10 11 0

Escribe partidas++ o partidas += 1, o termina con ; la línea de arriba.

Comentarios​

// Comentario de una línea: llega hasta el final de la línea
var vidas = 3 // también detrás de una instrucción

/* Comentario de
varias líneas */
println("10 // 2") // dentro de una cadena, // es texto: imprime 10 // 2
  • Los comentarios pueden llevar tildes y eñes.
  • Un /* … */ no puede ir dentro de otro: el primer */ cierra el comentario, y lo que queda detrás da error.
  • Un /* sin su */ da el error «Detected unterminated comment, expecting '*/'».
/* Un comentario /* dentro de otro */ no se puede */
println("hola")

Bloques: end, paréntesis y then​

Todos los bloques se cierran con end. La sangría no cuenta para el compilador: solo sirve para leer mejor el código.

BloqueSe abre conPágina
Condiciónif (…) then, y dentro elsif (…) then y elseEstructuras de control
Selecciónswitch (…), y dentro case …: y default:Estructuras de control
Buclesfor (…; …; …), foreach (var x in …), while (…) y until (…)Estructuras de control
Funcionesfunc nombre(…) y fn(…):Funciones
Clasesclass Nombre, y dentro def metodo(…)Clases y objetos
Structs y enumeradosstruct Nombre y enum NombreStructs y Enumerados
Errorestry, y dentro catch (var e)Errores y excepciones

Las reglas que más se olvidan:

  • La condición va entera entre paréntesis en if, elsif, while, until y switch.
  • if y elsif llevan siempre then. while y until no llevan ni then ni do.
  • Es elsif, ni elif ni else if. Un else if abre un if nuevo dentro del else, que necesita su propio end. Si falta, el compilador lo dice: «missing 'end' at the end of the 'else' block (check the 'else if' on line 4: in JARU it is 'elsif')».
  • Un bloque corto cabe en una línea: if (vidas == 0) then println("Fin") end.
var vidas = 2
var tiempo = 30

if (vidas > 0 and tiempo > 0) then
println("Sigue jugando")
elsif (vidas > 0) then
println("Se acabó el tiempo")
else
println("Fin de la partida")
end

Estos tres no compilan:

var vidas = 2
if vidas > 0 then // falta el paréntesis
println("Sigue jugando")
end
var vidas = 2
var tiempo = 30
if (vidas > 0) and (tiempo > 0) then // la condición se acaba en el primer )
println("Sigue jugando")
end
var nivel = 2
if (nivel == 1) then
println("Fácil")
elif (nivel == 2) then // es elsif
println("Normal")
end

Literales​

Así se escribe cada valor directamente en el código:

ValorEjemplosCómo se escribe
Entero42, -7, 0x1F, 0xffEn decimal, o en hexadecimal con 0x delante
Decimal3.14, .5, 1e3, 2.5e-2Con punto o con exponente
Cadena"hola", 'hola'Entre comillas dobles o simples
Booleanotrue, false, on, offon es true, y off es false
Sin valornil
Lista, mapa y array[1, 2], {"x": 1}, {1, 2}Ver Listas, mapas y arrays
println(0x1F)          // 31
println(0xff) // 255
println(1e3) // 1000
println(on == true) // true

En hexadecimal, las letras valen en mayúsculas y en minúsculas. Un número con exponente es siempre decimal, aunque println escriba 1000. El rango de los enteros, lo que pasa con un número que no cabe en 32 bits y los hexadecimales por encima de 0x7FFFFFFF están en Tipos de datos.

Cadenas​

Una cadena acaba con la misma comilla con la que empieza, así que la otra puede ir dentro: 'Dijo "hola"', "It's". La barra \ empieza un escape: \n (salto de línea), \r, \t y \\ (una barra).

  • \" no es un escape. La cadena no se corta ahí, pero la barra se queda dentro: "dijo \"hola\"" imprime dijo \"hola\". Para meter comillas dobles, escribe la cadena entre comillas simples.
  • Cuidado con las rutas de Windows: "C:\nivel" lleva un salto de línea. Escribe "C:\\nivel".
  • Una cadena no acaba al final de la línea. Si se te olvida cerrarla, sigue en las líneas de abajo, y el error, «String without terminating quotation mark», sale más abajo de donde falta la comilla.
  • Las tildes y la eñe valen dentro de las cadenas, pero no en los nombres.

Qué pone cada escape y cómo se escribe una cadena de varias líneas está en Escribir cadenas.

Prioridad de los operadores​

Cuando una expresión tiene varios operadores, se calculan antes los de las filas de arriba. Los de una misma fila se calculan de izquierda a derecha, salvo ? : y las asignaciones, que van de derecha a izquierda.

OperadoresQué son
1a.b, a[i], f(x)Propiedad o método, índice y llamada
2-x, +x, not x, !x, ~x, ++x, --x, x++, x--Operadores de un solo valor
3*, /, %, div, modMultiplicación y división
4+, -Suma y resta
5<<, >>Desplazamiento de bits
6&, |, ^Bit a bit
7<, <=, >, >=Comparación
8==, !=Igualdad
9and, orLógicos
10? :Condicional
11=, +=, -=, *=, /=, %=Asignación

Tres cosas cambian respecto a otros lenguajes:

println(not 1 == 2)                  // false: es (not 1) == 2
println(not (1 == 2)) // true
println(6 & 3 == 2) // true: es (6 & 3) == 2
println(4 | 1 & 2) // 0: es (4 | 1) & 2
println(true or false and false) // false: es (true or false) and false
println(true or (false and false)) // true
  • not y ! se calculan antes que las comparaciones. Para negar una comparación, ponla entre paréntesis.
  • Los operadores bit a bit van antes que las comparaciones, al revés que en C, y &, | y ^ tienen la misma prioridad.
  • and y or también tienen la misma prioridad:
and y or tienen la misma prioridad

En la mayoría de los lenguajes, and se calcula antes que or. En JARU no: se calculan de izquierda a derecha, así que a or b and c es (a or b) and c. Cuando mezcles and y or, pon paréntesis.

Trampas​

Todos los problemas conocidos de JARU, juntos, están en Problemas conocidos.

Cadena + número​

+ une dos cadenas, pero no una cadena y un número. "Vidas: " + vidas compila, pero el programa se para al llegar a esa línea, con el error «Unsupported operand types for operator '+'.». Convierte antes el número con toString(), como en "Vidas: " + vidas.toString(), o pasa las partes a println por separado: println("Vidas: ", vidas). Lo cuenta Unir cadenas.

.. no es un operador de JARU: el compilador da el error «Operator '..' doesn't exist in JARU. Use '+' to join strings.».

var vidas = 3
println("Vidas: " .. vidas)

Métodos sobre un literal o un paréntesis​

Un método va detrás de una variable, de un elemento o de una propiedad: nombre.size(), lista[0].toString(), jugador.vidas.toString(). Detrás de un literal o de un paréntesis no compila, con el error «Expected identifier in method name.»:

println("hola".size())
var a = 2
var b = 3
println((a + b).toString())

Guarda antes el valor en una variable:

var saludo = "hola"
println(saludo.size()) // 4

var a = 2
var b = 3
var suma = a + b
println(suma.toString()) // 5

Con un número es peor: en 5.toString(), el compilador lee 5. como el decimal 5.0, y toString() como otra instrucción. Una línea como var s = 5.toString() compila, y el programa se para con «Undefined variable 'toString'.».

Indexar lo que devuelve una llamada​

f(x)[0] compila, pero no indexa lo que devuelve f: el programa se para con el error «This object type is not indexable.». Con un método es peor: mapa.keys()[0] hace que el compilador se cierre sin explicar el error, y lista.copy()[0] para el programa con un error que no se entiende («List has no property ''.»). Guarda antes el resultado en una variable:

func extremos(lista)
return [lista[0], lista[lista.size() - 1]]
end

var numeros = [4, 8, 15]
// println(extremos(numeros)[0]) <- se para al ejecutarse
var e = extremos(numeros)
println(e[0], " ", e[1]) // 4 15