Lenguaje de programación para el desarrollo fácil de aplicaciones interactivas gráficamente intensivas.
Compilador y ejecutor. Compila uno o más archivos de código fuente para gererar un archivo binario compilado en wasm. Con la opción -x se ejecuta el resultado localmente una vez compilado con éxito.
Cuando se compila para web se genera, además, otro archivo con todos los recursos (imágenes, tipografías o los archivos auxiliares que se necesiten).
Ejecutor. Ejecuta, localmente, el resultado del programa anterior. Si se quiere ejecutar en web se usa la versión web que consta de dos programas xirt.wasm y xirt.js. Éste carga el archivo compilado por xig y lo integra como un objeto dinámico. Similar a las .dll o .so de los sistemas operativos actuales.
Editor. Es una herramienta gráfica que nos permite diseñar una aplicación sin necesidad de escribirla en lenguaje de programación. Permite la declaración de los objetos componentes y su configuración en forma gráfica. Se puede probar el resultado dentro del editor y generar el código fuente resultante que puede ser luego compilado con xig.
El cásico programa que imprime "Hola mundo" por la consola sería así ('hola.hua'):
pub void main(List)
{
cout() << "Hola mundo\n";
}
Para compilarlo y ejecutarlo se usaría la orden:
xig -x hola.hua
Para ejecutar el resultado compilado:
xirt hola.wasm
El código fuente es una sucesión elementos de estos tipos:
enum, object o struct nuevos.main que es el inicio del programa.1, 32, 99, 0xFF1L, 32L, 99L1.0f, 3.2f, 9.9f1.0, 3.2, 9.9"hola mundo"true o falseNombre simbólico definido en una enumeración. Otro alias del tipo int. Se declara como:
enum UnitType {
Prota = 0,
Alien = 2,
Missil = 3,
}
Se escribe un valor literal como UnitType:Alien. En este caso sería equivalente a 2.
function.Cada función definida corresponde a un tipo de función automáticamente creado. Se le puede asignar un nombre al tipo con la sintaxis:
function rtype nombre(args);
El literal de este tipo se puede escribir como:
Estructura. Es la combinación de tipos simples u otras estructuras. Se declaran como en este ejemplo:
struct Cosa {
int a1;
float num;
}
No hay una forma de escribir un literal de objeto concreto. Siempre se usa una referencia que es el resultado de una expresión o variable. Las referencias a objetos no se pueden incluir en estructuras, pero sí pueden ser atributos de otros objetos. Se declara una clase de objeto nuevo en la forma:
object MiObjeto : Base {
OtroObjeto world;
Cosa a1;
double a2;
}
Si no se indica la base se supone que es 'Obj'. Que es de la que todos los objetos se derivan en última instancia.
Todas la variables deben ser declaradas antes de ser usadas. Las variables de tipo referencia a objeto deben de ser asignadas en la declaración, las de otro tipo no es necesario. Se declaran de forma similar a C:
int x=1, y=33+x; float a, b, c; MiObjeto o = null;
El ámbito de las variables está acotado al bloque (código entre '{' y '}') en que se han declarado o son globales si se declaran fuera de todo bloque.
Las expresiones son similares a C, javascript y otros lenguajes. Se componen de términos, operadores, y llamadas a función. La precedencia de los operadores son como en C. Se puede alterar la precedencia usando paréntesis. Por ejemplo:
(10+10)/5 sin(a)*r
+ - * / %-== != < <= > >=&& ||!~<< >> >>>+= -* *= /* %= &= |= ^= <<= >>= >>>=Estos operadores pueden ser redefinidos para otros tipos de datos.
El operador binario << entre una referencia a un objeto de tipo BIO (base de los objetos IO) y un dato de otro tipo origina la escritura de una representación textual de dicho dato en un flujo de salida. Devuelve el objeto original. Ejemplo:
cout() << "diga " << 33 << "\n";
Produce:
diga 33
(La función cout() retorna una referencia a un objeto global predefinido que representa la consola)
$ antepuesto a un nombre de tipo devuelve un entero que es el identificador de dicho tipo. El mismo identificador es devuelto por la pseudo función typeid. Ejemplo, estas expresiones se evalúan como true:
typeid(55+1) == $int; $UnitType == typeid(UnitType:Prota);
Todos los objetos tienen un identificador único que es un número de 64 bits. Algunos objetos pueden ser etiquetados con una cadena de caracteres única que puede servir como identificador.
& antepuesto a un dato de tipo long devuelve el objeto cuyo identificador es dicho dato.
& antepuesto a un dato de tipo str devuelve el objeto cuya etiqueta de texto es dicho dato.
` antepuesto a un nombre de función ...
` intercalado entre un nombre de tipo de función y un nombre de función ...
Un dato de un tipo numérico será convertido a otro automáticamente para adecuarse a lo esperado en la expresión si sólo hay una posibilidad. Si hubiera más de una se debe de hacer la conversión explícitamente.
Una conversión explícita se consigue usando el nombre del tipo como si fuera una función:
int x = 33; float f = 0.5 * float(x); int c = a;
Lo mismo se aplica a las estructuras.
Vec2 v = (1f, 0f); Vec2 r = Vec2(2,5) + v;
Cuando se cambia un dato de un tipo numérico a otro hay un cambio de valor que en algunos casos implica truncamiento o pérdida de precisión. Por ejemplo en el cambio de double a float.
En el caso de la conversión de tipo de objeto no existe la posibilidad de modificación del valor. En tiempo de ejecución se comprueba si una referencia a objeto puede reinterpretarse como de un tipo dado. Si no se puede se devuelve null (objeto nulo). Cualquier operación con el objeto null no tiene efecto.
Label l = Label(&"titulo");
Las conversiones automáticas son informadas por el compilador.
No debe confundirse la conversión de tipo con el constructor. Éste es una funcion que se llama igual que el tipo devuelto. Es usado para construir estructuras u objetos a partir de unos parámetros.
No hay una distinción clara entre el constructor de una estructura y una conversión de tipo de estructura. Cuando el nombre de la estructura se antepone a una tupla de exactamente el mismo número de componentes que la estructura y en el que cada componente puede ser convertido al tipo correspondiente, entonces las conversión se genera automáticamente y se considera una conversión de tipo. Ejemplo: Vec2(2,5).
Un constructor es una función que se llama igual que un tipo de objeto o estructura. Para ser legal debe devolver un valor de ese mismo tipo. Puede tener cualquier número de parámetros de cualquier tipo.
En el caso del constructor de un objeto debe de usarse anteponiendo la palabra reservada new. Ejemplo:
String s = new String("hola mundo");
Existe un constructor implícito en la mayoría de clases de objetos. Se usa sin argumentos. Ejemplo:
Widget w = new Widget;
De algunas clases no se pueden crear objetos de esta forma y sólo pueden crearse objetos de clase derivada. Les llamamos clases abstractas.
Para acceder a un miembro de una estructura se usa el nombre de dicho miembro prefijado con '.' a continuación de una expresión de tipo estructura. Por ejemplo:
struct Vec2 {
float x, y;
}
Vec2 v = (1.0f, 2.5f);
float d2 = v.x * v.x + v.y * v.y;
float x2 = (v * v).x;
Para los atributos de los objeto se usa la misma sintaxis. Es posible que un atributo de objeto sea de sólo lectura. En ese caso el compilador producirá un error.
return
function
if else
for
while
do while
break
continue
null