Giter Club home page Giter Club logo

wollok-language's Introduction

image

Wollok Language

This is the repository for the Wollok Language definition, and also the main access point for all resources.

What is Wollok?

Wollok is a language designed to satisfy our main goals for teaching OO concepts. You can see Wollok site for further information.

About this repository

It is a Wollok Project which contains

  • Wollok core libraries: strings, numbers, dates, booleans, etc. in src folder
  • Wollok language specification, in form of unit tests: in test folder you'll see our sanity tests where you can check how should you use Wollok objects from core libraries, and syntax definitions.

All files follow a standard coding convention, please read them before collaborating.

Changes

  • If you want to propose a change, please open a new issue. Ideally, a new feature proposal should have: a) what do you want to achieve, b) why do you want the new feature, c) (optional) if it could solved with Wollok-side implementation or it could require native implementations, d) (optional, nice-to-have) acceptance tests. We have a sort of consensus instead of a bureaucratic committee, and will evaluate and prioritize the proposal. Pending task: add a template
  • Once approved, we should add it to the changelog file, which could also be useful in case you need to migrate your examples according to different versions.

Current work

Another useful repositories

  • wollok-xtext: our first & stable implementation, is Eclipse Xtext-based.
  • wollok-ts: next generation interpreter Typescript-based, which has...
    • wollok-run-client: A proof of concept using Wollok Game, first prototype of a dynamic diagram, a new console REPL and wollok-ts interpreter
    • wollok-lsp-ide: A Work-in-Progress implementation of Language Server Protocol, supported for a lot of IDEs (especially Visual Studio Code)
  • wollok-highlight-vscode, a highlighter plugin for Visual Studio Code which should be integrated with Wollok-Sublime project
  • wollok-cli: Wollok CLI for tasks automation (Travis integration, bash scripting, etc.)
  • wollok-site: Main content of our Wollok site (hosted in github pages with Jekyll)

Experimental tools for Wollok

We also have several ideas currently suspended, that eventually anybody could resume at any time:

How to contribute?

Open an issue here, and we will contact you!

wollok-language's People

Contributors

alete89 avatar angelimatias avatar asanzo avatar ezequielpereyra avatar fabianfrangella avatar fdodino avatar ferrommu avatar gomezdn avatar ivojawer avatar juanbono avatar juancete avatar julimr avatar kalafuente avatar nicolas-alv3 avatar npasserini avatar nscarcella avatar nullspace1 avatar palumbon avatar tfloxolodeiro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wollok-language's Issues

Renombrar este proyecto a wollok-language

Propongo que renombremos este proyecto a wollok-language y se convierta en el concentrador de todas las definiciones del lenguaje Wollok, punto de encuentro entre las especificaciones.

Eventualmente código wollok-sdk se mudaría aquí, posiblemente tendríamos dos carpetas sdk y sanity-tests. La alternativa es dejar esto como está y crear un wollok-sdk cuando se pueda independizar, pero me parece que tener centralizadas todas las definiciones compartidas puede ser útil.

@nscarcella @fdodino @PalumboN ¿Qué opinan?

Agregar en keyboard método let(l) similar a num(n) pero para letras

En algunos juegos resultaría util poder parametrizar a qué letra se la quiere asociar con la acción que se realiza al presionarlas, tal como se hace con los números.
Por ejemplo en los casos de más de un jugador, donde cada uno tiene sus teclas para moverse u otra acción.

Por ejemplo
class Jugador {
const teclaDisparo
keyboard.let(teclaDisparo).onPressDo{self.disparar()}

new Jugador(teclaDisparo = "q")
new Jugador(teclaDisparo = "p")

Puede hacerse del lado wollok, agregando un metodo, lo que incluso permitiría refactorizar los métodos de cada letra

const letras = ["a","b" ... ]
method let(l) = new Key(keyCodes = [28 + letras.indexOf(l)])
method a() = self.let("a")

Deal with internationalization and localization

Extracted from discussion on #26 .

We should think how to deal with translations and localization in this project to reuse as much as possible.

Besides the general discussion of where and how we should store translations and similar stuff, there are some concrete issues to discuss:

  • The method Object.generateDoesNotUnderstandMessage(target, messageName, parametersSize) is currently implemented as native. This is, as I understand, mainly because it relies on localization (please, correct me if I'm wrong), but it would be nice to have it shared.
  • Date toStrings depend on localization which is not tested anywhere. I believe it would be good to avoid this dependency or model the localization in the language somehow, otherwise we are coupled with the fact the code runs on an IDE that knows the system language.
  • The text of exceptions could be shared by all implementations if we move it here.

Imports más consistentes

Buenas,

Estuve trabajando un poco en el linker de TS y en el proceso saltaron algunas cosas sobre cómo se comportan los packages e imports que me gustaría discutir. No estoy seguro cuántas de estas cosas son bugs, cuántas son así por diseño y cuántas son sólo muy difíciles y no valen la pena, pero yo tiro todo lo que fui encontrando y vamos viendo (y de paso queda la discusión en el proyecto).

Pensé en crear tickets separados, pero creo que se puede poner confuso, así que voy a crear un uber-issue acá para discutir (tratando de ser lo más prolijo posible) y, de ser necesario, podemos ir brancheando tickets a criterio.

Empiezo:


A) Los imports tienen mayor precedencia que las definiciones locales

Si se define en el scope local una entidad con el mismo nombre que otra importada, la entidad importada oculta la local. La versión actual de Wollok-Xtext muestra un warning en la definición local indicando que el nombre ya está definido, pero me parece que de todos modos la definición local debería tapar la importada (de otro modo la definición local es inreferenciable).

Estructura

├ p.wlk
│ └ o
└ t.wtest
  └ o

Código

// p.wlk

object o { method m() = "imported" }
// t.wtest

import p.*

object o { method m() = "local" }

test "Las definiciones locales sobreescriben a las importadas" {
  assert.equals("local", o.m()) // FALLA! o es p.o
}

Esto es especialmente choto porque, si en lugar de importar usas referencias calificadas el comportamiento es el esperado:

Estructura

├ p.wlk
│ └ C
└ t.wtest
  └ p
    └ C

Código

// p.wlk

class C { method m() = "imported" }
// t.wtest

import p.*

package p {
  class C { method m() = "local" }
}

test "Las definiciones locales sobreescriben a las externas" {
  assert.equals("local", new p.C().m())  // Esto sí funciona
}

Expectativa

El test pasa, porque la definición local de o tiene precedencia por sobre lo importado.

Situación Actual

El test falla, porque o se resuelve al objeto importado.

Propuesta

  • Hacer que las definiciones locales tengan precedencia por encima de los imports
  • Convertir el warning en un error (o sea, tratarlo igual que cuando definís dos entidades con el mismo nombre en el mismo package)

B) Se pueden importar packages (pero no sirve para nada)

Actualmente se puede hacer imports de packages o archivos (que yo siempre trato como packages de todos modos), pero ese import no parece cambiar la definición de ninguna forma.

Estructura

├ p.wlk
│ └ q
│   └ C
└ t.wtest
  └ D

Código

// p.wlk

package q {
	class C { }
}
// t.wtest

import p.q.C // OK
import p.q   // OK, pero no hace nada?
import q.C   // ERROR! No se puede resolver q.C

class D inherits q.C { } // ERROR! No se puede resolver q.C

test "importar packages no hace nada?" {
  new C()     // OK
  new p.q.C() // OK
  new q.C()   // ERROR! No se puede resolverq.C
}

Expectativa

Todas las entidades importadas afectan el namespace local

Situación Actual

Importar packages no parece servir para nada, ya que ninguna referencia calificada puede partir del package importado.

Propuesta

Entiendo que la idea atrás de esto es tener definiciones más declarativas, entonces tiene sentido, por ejemplo, no permitir que un package "vea" al otro, porque esto hace que el orden de los imports sea relevante:

import p.q
import q.C

Con lo cual, si la idea es preservar esa declaratividad, propongo agregar una validación que impida importar packages.

Si no, deberíamos agregar el package importado al scope para que cualquier referencia calificada pueda resolverse a partir de él, y hacer que en el test que muestro anden todos los casos, pero si vamos por esto hay que tener cuidado con algunos casos complicados (como el del punto C).


C) Sobrecarga de símbolos

Actualmente se puede tener en el mismo contexto entidades con el mismo nombre, siempre y cuando cumplan "roles" diferentes. Por ejemplo, se pueden tener objects y packages con el mismo nombre, en el mismo nivel.

Para ser justos, esto no causa ninguna ambigüedad (o, al menos, a mi no se me ocurre ninguna), dado que los packages sólo pueden mencionarse en el código como raíz de una referencia calificada y ninguna otra cosa puede ponerse en ese lugar, pero pensé en mencionarlo porque creo que podría generar situaciones confusas.

Un caso fácil de ver es cuando un package contiene algo con su mismo nombre (por ejemplo p.q.p, donde q.p podría ser un objeto). Alguien que hace un import de ese objeto tiene al mismo tiempo una referencia a p package y a p objeto. Como es fácil olvidarse de mirar los imports, alguien podría confundirse aunque no hayan ambigüedades (especialmente si consideramos el problema descrito en (B)).

Estructura

└ t.wtest
  ├ x (object)
  └ x (package)

Código

// t.wtest

package x {
	object y { } 
}

object x {
	const property y = 5
}

test "Sobrecarga de símbolos" {
  assert.that(x.y != 5) // Esto funciona, pero podría confundir a alguien que viene de un lenguaje con atributos públicos (Ej: JS).
}

Expectativa

Dejarme sobrecargar el namespace es un poco raro...

Situación Actual

Puedo definir objetos y constantes al mismo nivel de packages con el mismo nombre.

Propuesta

Bien podríamos dejar todo tal cual está. No me molesta. Sólo no sé si esto es intencional o simplemente emergente. También podríamos poner un warning. No sé si da poner un error porque, como dije, no produce ambigüedades.


D) Multiples imports a la misma referencia

Esto no es realmente un problema, pero suena a una redundancia que sería prolijo evitar.
Ahora mismo podemos importar la misma entidad tantas veces como queramos y Wollok no se queja.

Estructura

├ p.wlk
│ └ C
└ t.wtest

Código

// p.wlk

class C { }
// t.wtest
import p.*
import p.C // Al pedo
import p.C // Doblemente al pedo
import p.*  // Al pedo al cubo

Expectativa

Cuando pongo un import redundante alguien me sugiere que pare.

Situación Actual

Podés poner todos los imports que quieras.

Propuesta

Meterle un warning a los imports redundantes.


E) Diferencias entre archivos y packages

Hay algunas diferencias entre los "packages" definidos por un archivo y los packages creados explicitamente por código:

  • Los archivos pueden definir constantes a nivel raíz, pero los packages no.
  • Los archivos pueden anidarse, pero los packages no.
    Capaz se me escapa alguna otra, pero bueno... El punto es que no entiendo para qué tenemos estas restricciones. El metamodelo se hace mucho más simple tratando a cualquier directorio/archivo como un package más. No me parece que se gane nada obligandome a extraer un archivo solamente para poder crear una constante o anidar un package y, si eventualmente le ponemos fichas a un IDE web, podría estar bueno pensar en anidamiento de packages en lugar de estructuras de directorios.

Estructura

├ p.wlk
│ ├ q
│ └ c
└ t.wtest

Código

// p.wlk

const c = 5 // Funciona
package q { } // Funciona
// t.wtest

package p {
  const c = 5 // ERROR! No se pueden poner constantes en packages.
  package q { } // ERROR! No se pueden anidar packages.
}

Expectativa

Los archivos y directorios son tratados como packages.

Situación Actual

Los packages son más restrictivos que los archivos.

Propuesta

Permitir a los packages hacer todo lo que hacen los archivos para poder prescindir de la idea de archivo en el metamodelo.


F) Imports ambiguos

Este me parece el caso más fulero de todos. Actualmente no tenemos ninguna manera de referenciar en una expresión dos entidades que se llaman igual. Con lo cual, si necesitás importar dos objects con el mismo nombre de dos packages diferentes la tenés super adentro.
Es más, si importás los dos el compilador no se queja, ignora el segundo import y toma la primer referencia importada.

Estructura

├ p.wlk
│ └ o
├ q.wlk
│ └ o
└ t.wtest

Código

// p.wlk

object o {method m() = "Vengo de P"}
// q.wlk

object o {method m() = "Vengo de Q"}
// t.wtest

import p.o
import q.o

test "imports ambiguos" {
  assert.equals("Vengo de Q", o.m())   // FALLA! o es p.o
  assert.equals("Vengo de Q", q.o.m()) // ERROR! no se puede usar una referencia calificada acá
}

Expectativa

La duplicidad de importación es una ambigüedad y debería ser marcada como un error. Debería haber una forma de referenciar dos cosas que fueron creadas con el mismo nombre.

Situación Actual

No se marca el error de la ambigüedad en los imports.
No hay forma de hacer convivir los dos objetos o.

Propuesta

A corto plazo: Agregar el error en los imports.
Para 3.0: Extender la sintaxis para incorporar la posibilidad de crear alias para los imports:

import p.o as po
import p.C as PC

Supongo que es discutible, pero me parece un feature bastante simple de implementar que nos ahorraría varios dolores de cabeza.


Perdón, por el issue larguísimo... Le mando un saludo a @fdodino, @npasserini, @PalumboN, mi tía Nelly y todos los que me conocen. La radio está buenísima.

Besis.

Agregarle `indexOf` a las listas

Eso, si usamos las listas como listas, o sea le damos bola al orden, podríamos preguntar p.ej. quiénes llegaron antes que una determinada persona. Eso tiene una resolución simple y elegante:

gente.take(gente.indexOf(persona)+1)

peeeero me falta el indexOf.

Mensaje de error con el testeo de Exception

¡Buenas!

Cuando estamos testeando excepciones, en particular con throwsExceptionLike* como se puede ver en este ejemplo

assert.throwsExceptionLike(new BusinessException(message="lalala"), {throw new BusinessException(message="lelele")})

Estaría esperando que el mensaje me pueda decir que el test pincha debido a que esperaba una BusinessException[message="lalala"] pero obtuvo una BusinessException[message="lelele"], pero ocurre

The Exception expected was BusinessException but got BusinessException

Lo cual es un mensaje confuso. Tal vez se pueda redefinir el comportamiento del toString en particular para esta clase a fin de que podamos obtener un mensaje de error más descriptivo.

Otra alternativa que podemos realizar es cambiar el mensaje del thow dentro de throwsExceptionLike concatenando con el mensaje.

Suma y Concatenación

Se resolvió que deberíamos:

  • Dejar la suma (+) sólo para los números.
  • Hacer que todos los objetos entiendan ++ que retorne siempre un String:
class Object {
  method ++ (otro)  = self.toString() ++ otro
}

class String {
  method ++ (otro)  = self ++ otro.toString()
}
  • Reemplazar el + en listas por concat.
  • Eliminar el concat de string.

En resumen:

  • Sólo los iterables ordenados (listas y rango) deberían entender concat (que acepta iterables ordenados y retorna un iterable ordenado (en concreto una lista)).
  • Todos los objetos deberían entender ++ (que retorna strings).
  • Sólo los Números deberían entender el + (que espera un número y retorna un número).
  • Los Sets entienden union (que retorna sets).

relacionado: uqbar-project/wollok#1202

Diferenciacion de objetos del dominio y visuales

Hay dos caminos cuando se quiere visualizar en Game un objeto de dominio:

  1. agregarle al mismo objeto image/position y la lógica necesaria de movimiento, colisión, etc
  2. hacer un objeto nuevo, que actúe como visual del objeto real

a grandes rasgos, el 1 es mas simple el modelo y fácil de manipular y el 2 es mas profesional separando la vista del modelo. (aunque esto último es discutible, dependiendo del dominio: en un juego vista y modelo tienden a confluir)

hay algunos metodos que quedan a mitad camino, tipo
addVisualIn( ) que requiere que el objeto a mostrar tenga image, pero no necesariamente position. (si tiene position, no se lo usa, similar a visualCharacter uqbar-project/wollok#1733 )

Se puede ir hacia un lado y exigir que siempre tengan image y position, o para el otro y hacer un
addVisulInImage(objeto, position, "image,jpg") para mostrar cualquier objeto sin alterarlo.

despues estan los metodos de Position, como drawElement y drawCharacter (tambien say), que no creo que se usen mucho, , porque son equivalentes a los addVisual, y se podrian eliminar

Eliminar los operadores ++, --

Los operadores ++, --, -= y += en wollok-ts no están implementados adrede. Teníamos pendiente cargar este issue, y luego definir si no lo queremos más.

Ver si wollok-ts puede guardar el texto de los bloques.

test "Assert throws exception failing" {
	
	var a = 0
	assert.throwsExceptionLike(
		// TODO NicoS: es posible hacer que wollok-ts nos dé el código acá?
		new AssertionException(message = "Block { a + 1 } should have failed"),
		{ assert.throwsException({ a + 1 }) }
	)

}

Rename de game.whenCollideDo

Me parece importante tener una buena separación en el nombre y también en el "javadoc" entre onCollideDo y el actual whenCollideDo. Hoy son casi idénticas las documentaciones y casi idénticos los nombres cuando en realidad el primero lo hace muchas veces y el segundo sólo una vez.

Propongo renombrar el game.whenCollideDo a game.whileCollideRepeat, y agregar a las respectivas documentaciones la comparación y alguna cosita más que falta:

whenCollideDo
Adds a block that will be executed once when the given object collides with other.
Two objects collide when are in the same position.

The block should expect the other object as parameter.

Example:
game.onCollideDo(pepita, { comida => pepita.comer(comida) })

If there are more objects colliding, the block will be executed once for each collider. 

Compare with whileCollideRepeat.
whileCollideRepeat
Adds a block that will be executed repeatedly while the given object is colliding with other.
Two objects collide when are in the same position.

The block should expect the other object as parameter. Example:
game.whileCollideRepeat(pepita, { comida => pepita.comer(comida) })

If there are more objects colliding, the block will be executed repeatedly for each collider. 

Compare with onCollideDo.

Configuraciones default para juegos

En Wollok xtext cuando no se setean algunas configuraciones (title, ground, etc.) se le asignan valores por default. Hay varios juegos van a romper en web por este motivo.

image

Unificar implementaciones de Wollok Game

Luego de este PR: uqbar-project/wollok-ts#33, donde comenzamos una implementación de WG en Wollok-TS, se amplió la grieta con Wollok-Xtext :(

Estaría bueno tratar de llegar a un equilibrio y compartir detalles de las implementaciones, pero para esto me gustaría tener medida la performance, ya que actualmente estamos teniendo problemas de lag.

  • Unificar las KeyCode: esto es prioritario ya que sino no funcionan los juegos en ambas versiones. TS espera una lista de strings mientras que Xtext espera un número (#61)
  • El objeto io: TS maneja los eventos con un objeto wollok el cual no está en Xtext porque se hace de forma nativa. El tenerlo del lado de Wollok está bueno para hacer sanity tests de los eventos (tests que ahora están en forma nativa en Xtext), pero hay que controlar la performance, especialmente en este caso.
  • Revisar los native methods: Relacionado con arriba, al manejar los eventos del lado de Wollok muchas veces se hace más fácil despacharlos directo desde game object. En TS se creó un mirror especialmente para hacer esto y mantener la interfaz de método nativos sincronizada con Xtext.

Vuelvo a resaltar el tema de la performance al estar pasando código nativo a Wollok. @tfloxolodeiro comenzó a hacer algunas pruebas acá https://github.com/tfloxolodeiro/prueba-lag-wollok-game, se podría aprovechar ese proyecto para tener unos benchmark "oficiales".

Los niños añoran la "Ñ"

Podemos porfa agregar la ñ (y ya que estamos, á, é, í, ó, ú y ü) como caracteres válidos para los selectores?

Tengo un ejercicio buenísimo de ñandúes que bañan pingüinos y no se entiende un carajo.

Poder definir un Error Handler para los juegos

Ahora WollokGame muestra un mensajito si se lanza una excepción mientras se está ejecutando. Estaría bueno poder sobreescribir ese comportamiento, en el caso que se quiera llevar a cabo alguna acción con el juego ante una excepción, sin necesidad de mostrar try catch.

Podría ser

game.errorHandler({ err => if (err.message() == "PERDER") game.stop() })

Habría que ver si esto pisa o se agrega al comportamiento actual. Quizá se quiera tener muchos handlers y métodos addErrorHandler(), clearErrorHandlers()?

Try to avoid abstract and native methods in abstract classes as much as possible

Extracted from discussion on #26 .

This ticket is being made specially thinking in Collections, but might apply to other places.

Currently, collection defines many abstract and some native methods (such as findOrElse(predicate, continuation)).

I believe it would be a better idea to implement as many as these methods as possible, even if it's in a naive way. This would allow some implementations to delegate on this implementations if performance is not an issue and would provide good defaults for new Collection subclasses.

Well known subclasses as Set, Dictionary and List could override these methods with natives as needed, so there would be no performance impact.

En wollok-xtext toString de collection no llama al toString de objetos sino a otro método.

	object myObject {
		override method toString() = "My Object"
	}

	test "testToStringWithObjectRedefiningToStringInWollok" {
	
		const a = [23, 2, 1, myObject]
		assert.equals("[23, 2, 1, My Object]", a.toString())
		
	}

El problema de llamar los toStrings de forma anidada es que ante relaciones circulares entre objetos podría entrar en loop, por eso la versión xtext redefine así:

		object myObject {
			override method internalToSmartString(alreadyShown) = "My Object"
		}

Unificar sintaxis de linearización

@fdodino @npasserini @PalumboN
Buenas y santas,

Ahora mismo tenemos dos sintaxis diferentes para la linearización de mixines en dos lugares distintos del lenguaje:

En las entidades nombradas (por ejemplo, las clases) usamos la palabra clave mixed with para el primer mixin, seguida de and como separador para las demás:

ClasesNombradas

Ej:

  clase MiClase mixed with MiMixin and MiOtroMixin

Por otro lado, en las clases anónimas que se crean producto de linearizar una clase al hacer new usamos la palabra clave with:

ClasesAnónimas

Ej:

new MiOtraClase() with MiMixin with MiMixin

Imagino que esta diferencia es más bien producto de un descuido y no tiene ningún propósito, pero hace la gramática innecesariamente compleja y me gustaría que optemos por tener la misma notación en todos los casos.

Dicho eso, quisiera proponer el envión para que nos deshagamos de la palabra clave mixed with porque son dos palabras y eso nos atormenta a mi y a mi lexer pero sobre todo porque no está conjugada de la misma forma que inherits y el texto termina sugiriendo que es la superclase la que está mixeada y no la clase que definís:

class MyClass inherits Other mixed with Something

Qué se yo... Podríamos usar la palabra mixing.

También me perturba un poco que and es al mismo tiempo un separador de mixines y un alias del operador &&, pero bue... No me quiero ir por las ramas.

Sé que estamos medio anticipando algún overhaul de las Clases y los Mixines, pero siendo que eso no está ni definido todavía y este es un cambio bastante sencillo podría estar bueno para meter en el próximo release que suba el mayor de la versión.

La otra diferencia importante de sintaxis es la que tenemos en el inherits de los singletons:

object miObjeto inherits MiClase(p1, p2) with MiMixin

Si eliminamos los constructores, esa linea debería ser:

object miObjeto inherits MiClase(arg1 = p1, arg2 = p2) with MiMixin

Yo propongo que también dejemos pasar parámetros al linearizar el mixin:

object miObjeto inherits MiClase(arg1 = p1, arg2 = p2) with MiMixin(argDelMixin = otraCosa)

Eliminar el constructor de Pair requiere cambiar el type system

Actualmente tenemos

PairType.constructor(PKEY, PVALUE)
PairType.variable("key", PKEY)
PairType.variable("value", PVALUE)

etc.

Si intentamos comentar la primera línea, borramos el constructor y actualizamos el resto del sistema (algo que queremos hacer para terminar de volar los constructores), cuando corremos los tests nos aparece:

ERROR [main] (CompositeEValidator.java:155) - Error executing EValidator
org.uqbar.project.wollok.typesystem.TypeSystemException: Type system: Missing type information for const key
	at org.uqbar.project.wollok.typesystem.constraints.variables.TypeVariablesRegistry.lambda$8(TypeVariablesRegistry.java:180)
	at org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_doubleArrow(ObjectExtensions.java:139)
	at org.uqbar.project.wollok.typesystem.constraints.variables.TypeVariablesRegistry.tvar(TypeVariablesRegistry.java:183)
	at org.uqbar.project.wollok.typesystem.constraints.InitializerConstraintsGenerator.generate(InitializerConstraintsGenerator.java:33)
	at org.uqbar.project.wollok.typesystem.constraints.InitializerConstraintsGenerator.generate(InitializerConstraintsGenerator.java:1)
	at org.uqbar.project.wollok.typesystem.constraints.CrossReferenceConstraintsGenerator.lambda$0(CrossReferenceConstraintsGenerator.java:33)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.uqbar.project.wollok.typesystem.constraints.CrossReferenceConstraintsGenerator.run(CrossReferenceConstraintsGenerator.java:35)
	at org.uqbar.project.wollok.typesystem.constraints.ConstraintGenerator.addCrossReferenceConstraints(ConstraintGenerator.java:558)
	at org.uqbar.project.wollok.typesystem.constraints.ConstraintBasedTypeSystem.inferTypes(ConstraintBasedTypeSystem.java:175)
	at org.uqbar.project.wollok.tests.typesystem.TypeSystemTestValidatorExtension.check(TypeSystemTestValidatorExtension.java:23)
	at org.uqbar.project.wollok.validation.WollokDslValidator.lambda$1(WollokDslValidator.java:261)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1080)
	at org.uqbar.project.wollok.validation.WollokDslValidator.checkValidationExtensions(WollokDslValidator.java:264)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.eclipse.xtext.validation.AbstractDeclarativeValidator$MethodWrapper.invoke(AbstractDeclarativeValidator.java:118)
	at org.uqbar.project.wollok.validation.AbstractConfigurableDslValidator$MethodWrapperDecorator.invoke(AbstractConfigurableDslValidator.java:73)
	at org.eclipse.xtext.validation.AbstractDeclarativeValidator.internalValidate(AbstractDeclarativeValidator.java:312)
	at org.eclipse.xtext.validation.AbstractInjectableValidator.validate(AbstractInjectableValidator.java:71)
	at org.eclipse.xtext.validation.CompositeEValidator.validate(CompositeEValidator.java:151)
	at org.eclipse.emf.ecore.util.Diagnostician.doValidate(Diagnostician.java:171)
	at org.eclipse.emf.ecore.util.Diagnostician.validate(Diagnostician.java:158)
	at org.eclipse.emf.ecore.util.Diagnostician.validate(Diagnostician.java:137)
	at org.eclipse.xtext.validation.CancelableDiagnostician.validate(CancelableDiagnostician.java:39)
	at org.eclipse.emf.ecore.util.Diagnostician.validate(Diagnostician.java:120)
	at org.eclipse.xtext.validation.ResourceValidatorImpl.validate(ResourceValidatorImpl.java:146)
	at org.eclipse.xtext.validation.ResourceValidatorImpl.validate(ResourceValidatorImpl.java:124)
	at org.eclipse.xtext.validation.ResourceValidatorImpl.validate(ResourceValidatorImpl.java:90)
	at org.xpect.ui.services.XtResourceValidator.validateDelegate(XtResourceValidator.java:68)
	at org.xpect.xtext.lib.tests.ValidationTestModuleSetup$TestingResourceValidator.validateDelegateAndMapByOffset(ValidationTestModuleSetup.java:117)
	at org.xpect.xtext.lib.tests.ValidationTestModuleSetup$IssuesByLineProvider.collectIssuesByLine(ValidationTestModuleSetup.java:86)
	at org.xpect.xtext.lib.tests.ValidationTestModuleSetup$IssuesByLineProvider.collectIssues(ValidationTestModuleSetup.java:79)
	at org.xpect.xtext.lib.setup.XtextValidatingSetup.getIssues(XtextValidatingSetup.java:93)
	at org.xpect.xtext.lib.setup.XtextValidatingSetup.validate(XtextValidatingSetup.java:118)
	at org.xpect.runner.XpectFileRunner.run(XpectFileRunner.java:135)
	at org.xpect.runner.XpectRunner.runChild(XpectRunner.java:208)
	at org.xpect.runner.XpectRunner.runChild(XpectRunner.java:1)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.xpect.runner.XpectRunner.run(XpectRunner.java:194)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Revisión general de toStrings

Hay varios issues relacionados con los toString que me gustaría mirar de forma global y proponer una estrategia. Tal vez sea un cambio grande y haya que pensarlo para Wollok 2.0 (aka Wollok 2020).

  • uqbar-project/wollok#1772 ¿Eliminar los atributos del toString?
  • #37 El toString de colecciones debería mostrar el toString de los elementos.
  • uqbar-project/wollok#1692 Cambiar algunos toStrings de lang, ¿en qué estado está esto?
  • Creo que sería importante tener una definición clara de para qué sirven todos los métodos asociados que hoy tenemos y cuál se usa en cada caso: toString, printString, etc.

Estas definiciones deberían ser globales y parte de la definición de wollok-language.

Obtener la posicion de un elemento en la lista

Estudiantes me transmitieron la sugerencia o necesidad de agregar un metodo:

Seria util en ocasiones, conociendo un elemento, saber en qué lugar de la lista se encuentra.,

Se espera obtener un número con la posición de la primera aparición en la lista
si no se encuentra, lanza excepción

Sería sólo para las listas. podria llamarse index( ) o indexOf()

Error en la documentación del metodo substring de la clase String

En la docuemtnación (https://www.wollok.org/documentacion/wollokdoc/), dice que la firma es:

substring(startIndex, length)

Lo que pareciera indicar que le paso desde que índice comenzar el nuevo string y cuantos caracteres desde ese deberíá contener, pero luego en el uso dice:

Answers a substring of this string beginning
from an inclusive index up to another inclusive index

O sea que en realidad lo que le paso según eso es el índice de comienzo y de final.

image

Eso significa que dependiendo de cual de las dos cosas sean correctas, el siguiente código va a funcionar de diferentes maneras:

"yvan eth nioj".substring(3,4)

Si funciona como dice en la firma (substring(startIndex, length)) el resultado sería "n et". Si funciona como dice en la descripción el resultado sería "n".

Lo probé en el REPL y funciona como dice en la descripción, o sea los parámetros en realidad son el startIndex y el endIndex.

Unify equality

Currently, the language has two main methods for defining equality: == and equals.

This duality is error prone and presents many implementation difficulties along with concerns related to overriding these methods or mixing them from mixins. Many objects of the wollok.lang and wollok.lib packages rely on the concept of equality and would be good to have a single interface to support it.

Necessary steps:

  • Ensure all equality in the WRE uses the == message instead of equals.
  • Drop sanity tests stating that overriding equals should impact the previous mentioned classes behavior.
  • On each implementation, change implementation of Set, assert, Dictionary and any other equality-based class to use only == and disregard equals.
  • Optionally, we could completely remove the equals method, or just leave it as it is now (only a method in Object that calls ==).

Add tests for global variables

Right now there aren't any tests to check consts at package level. I know because we don't support it on TS and still pass the tests...

We should add some for 1.8

Inicializaciones de atributos

LINK AL DOCUMENTO CON LA VERSIÓN FINAL: https://docs.google.com/document/d/1DnRnRKnO3IDQya3NZJqj-U-6ICrAhgUhaqpuZfGjRFk/edit#

class C inherits D {
  const a
  const b = 2
  const c
  const d
  
  method initialize() {
    super()
  // Analizar qué cosas se inicializan (y sus dependecias) puede ser complejo
    a = a + 1 // acá es necesario pasar un a
    // a = algo.cosaLoca(self) // Acá es más difícil
    d = 1
  }
}

new C(a=1, c=3) // OK

new C(c=3) // ERROR: Falta a (caso complicado)

new C() // ERROR: Falta a y c

new C(a=1, b=5, c=3) // -> b queda con 5

new C(d=0, c=3) // WARNING: valor d está siendo definido en el initialize()

Tanto para var como const (sino forzar la inicialización a = null).

Revisar los sanity tests de Game

Ahora quedaron muchos tests de Game en las implementaciones de cada lenguaje. Estaría bueno ver en qué estado están los sanities de Game y ver si se pueden mover algunos de los tests que ahora están en xtext / ts.

Cleaner interfaces: Move introspection-related methods to mirror

Extracted from discussion on #26 .

Currently, wollok.lang has several methods (mainly in class Object) whose main purpose seems to be the implementation of native behavior. Most of these are not meant to be used by students and having them in lang pollutes the interfaces. So, the proposal is to move these methods to the mirror package, to keep thinks clean.

The methods I'm thinking about these (feel free to comment and add your own):

  • Object.instanceVariables()
  • Object.instanceVariableFor(name)
  • Object.resolve(name)
  • Object.kindName()
  • Object.className()
  • Object.identity() (I believe @fdodino does not agree on moving this one)

We also need to define a wollok class for the return of instanceVariables methods (possible InstanceVariable ?) so we can istantiate those on all implementations and not rely on xtext classes.

Annotations

After it came up in several discussions I think it would be a good idea to make an actual proposal for this and see if we can push this in for the next version.

Basically, we have a bunch of use cases for some form of metadata notation:

  • Assign types for the TS
  • Mark methods as private in the WRE
  • Mark methods and tests as deprecated
  • Mark pieces of code as "should fail" or similar, to be able to define sanities containing invalid wollok definitions (so we can test what Wollok "is not").
  • Help to internally represent stuff (like what is discussed on uqbar-project/wollok-ts#27)

and Annotations could be a great fit for this.

A simple approach could use the following syntax:

@parameterlessClassAnnotation
@parameterizedClassAnnotation(p1=5, p2=["text", true])
class C {
  @fieldAnnotation
  var f = 5

  @methodAnnotation
  method m() = 7
}

Annotations would be applied to the next non-annotation entity or member and simply store the annotated name along with any annotated parameters in the node. This allows for easy to extend and easy to ignore handling.

We don't necessarily need to provide an interface to read annotations, as long as we can access them in the backend implementations, but if we do, we could add that logic to the wre/mirror package, in order to keep the interfaces clean.

The main purpose for adding these would be to enrich the low-level definitions an allow a more standardized and cleaner cross-platform handling of many phases of the language. There would be no need to show annotations in class and should have no direct impact in the current syllabus and examples.

Once we agree on the general syntax and approach I can write some sanity tests for this to guide the implementation.

¿¿El 2 no es primo??

¡¡Wollok!!
Wollok dice que el número 2 no es primo.

1.isPrime() // false, bien
3.isPrime() // true, bien
2.isPrime() // false???????

También adjunto una captura porque esto es insólito, yo tampoco lo creí:

image

Que el mensaje times pueda recibir bloques sin parámetro

¿Habrá alguna forma de que esto sea válido?

test "Message times allows blocks without parameters and works" {
    var a = 0
    3.times({ a += 1 })
    assert.equals(3, a)
}

Ahora mismo, eso no anda. El bloque hoy debe tener un parámetro: { valor => a += 1 }, lo cual es confuso.

Cambiar las KeyCode de Game

Actualmente los códigos para las teclas de Wollok Game están basadas en unos números raros de LibGDX.

Ahora que estamos sacando la versión web con otra tecnología eso no tiene mucho sentido, así que estaría bueno formalizar la interfaz.

Este cambio habría que hacerlo junto a las implementaciones de Xtext y TS

Definir mensaje predeterminado para un nuevo tipo de excepción

Trabajando en un TP de Paradigmas de Programación me encontré con la siguiente situación:

Tenía un modelado de un objeto con cierta función que tenía un caso de excepción, solucionado en clase de la siguiente forma (resumido un poco, y con otros nombres para evitar explicar la temática del TP):

class SinCondicionException inherits Exception {}
object algo {
   var algunaCondicion = true
   //..otros metodos
   method metodoExcepcion(){
      if(algunaCondicion)
         throw new SinCondicionException(message="No se cumple la condición.")
      else {  // ... el resto  }
   }
}

Sin embargo, cada vez que yo quiero lanzar una excepción de tipo SinCondicionException, tengo que definir un nuevo mensaje. Lo ideal sería poder lanzarla así:

throw SinCondicionException

Al intentar implementar esta solución vimos que no es posible modificar el mensaje dado que está definido como constante:

class SinCondicionException inherits Exception {
   override method initialize(){
      message = "No se cumple la condición."
      // Wollok alerta que "no se puede modificar una constante"
   }
}

Vimos que en la clase Exception el valor de message está definido como const property, haciendo que esto no pueda modificarse.

Alternativas:

  • Cambiar a var
  • Definir un método que permita inicializar el mensaje predeterminado de una nueva excepción

Un saludo.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.