Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #197 c center immutable offset wrapper resolve all issues #211

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
ef5f300
game with a mutable reference to center to update center when game st…
isaiaslafon Oct 4, 2024
721dea7
alternative to center as a mutable position, start at 0,0 and collect…
isaiaslafon Oct 5, 2024
020bf37
#197 c inmutable center with offset wrapper.
isaiaslafon Oct 8, 2024
9311d4a
Fix #197 draft with immutable center position wrapper to update to a …
isaiaslafon Oct 8, 2024
63d35d2
spaces blank line added
isaiaslafon Oct 8, 2024
22ba1c1
Fix #86 implementacion de floor (#210)
rodriguez-guillermo Oct 8, 2024
25a0763
visual characater no se sale de los limites (#209)
lspigariol Oct 8, 2024
4192701
Fix #139 (#205)
fdodino Oct 8, 2024
dd9503e
Hot fix! Validation error
fdodino Oct 8, 2024
757c256
Update CHANGELOG v3.2.6
PalumboN Oct 8, 2024
75f4a6c
Tests for cyclic const instance references
PalumboN Oct 22, 2024
842d544
Cálculo de promedio para una colección
Juancete Nov 7, 2024
724e36a
Update src/wollok/lang.wlk
Juancete Nov 9, 2024
8f3337c
Update src/wollok/lang.wlk
Juancete Nov 9, 2024
a7ff30f
Update src/wollok/lang.wlk
Juancete Nov 9, 2024
a316af7
Update src/wollok/lang.wlk
Juancete Nov 9, 2024
c28592b
Update test/sanity/collections/collections.wtest
Juancete Nov 9, 2024
0dd8a58
Merge pull request #221 from uqbar-project/feat#220-collection-average
Juancete Nov 9, 2024
d25a568
Testing indirect cyclic references
PalumboN Nov 11, 2024
f52bd6d
Merge pull request #217 from uqbar-project/fixes-varios
PalumboN Nov 11, 2024
f09e1a8
Mejoras al manejo de void (y algo de nulls), especialmente para bloqu…
fdodino Nov 11, 2024
0c4ee0e
Add tests for https://github.com/uqbar-project/wollok-ts/issues/264
fdodino Nov 15, 2024
fdeb33a
Merge pull request #223 from uqbar-project/fix-#264-shouldUseOverride…
PalumboN Nov 19, 2024
a2e48f7
Add regression test (#224)
fdodino Nov 19, 2024
c90b4f0
Update CHANGELOG v3.2.7
PalumboN Nov 26, 2024
713dcef
wrap actions using io.runHandler
lgassman Nov 30, 2024
2e3e90d
add tests for user error on handlers
lgassman Dec 10, 2024
a80461d
redefine identity adding tests + validations messages (#231)
MVitelli Dec 13, 2024
285881d
corrección retorno flatmap (#228)
Nalens10 Dec 13, 2024
2c65b80
documentacion dias string (#227)
alymarquez Dec 13, 2024
4078365
Add validation test (#232)
fdodino Dec 13, 2024
d23959c
Fix flatten (#233)
fdodino Dec 13, 2024
582ae90
POC unicode identifiers (#234)
fdodino Dec 20, 2024
853c9d5
Merge pull request #230 from uqbar-project/fix_blocks_error_handling_…
ivojawer Dec 28, 2024
7a02cb5
Update CHANGELOG v3.3.0
PalumboN Jan 13, 2025
bb2781a
Refactor without state/strategy, fixed round method CenterOffset. Add…
isaiaslafon Jan 22, 2025
b19290c
Fix #197 c center immutable offset wrapper resolve all issues update …
isaiaslafon Jan 22, 2025
e62fbf1
Merge branch '#197-c-center-inmutable-offset-wrapper-resolve-all-issu…
isaiaslafon Feb 6, 2025
3c10058
Changed CenterOffset.round() assuming board height with are rounded n…
isaiaslafon Feb 6, 2025
b341420
Added rounded CenterOffset tests
isaiaslafon Feb 6, 2025
6430fd9
Fixed missing const declaration in round method refactor
isaiaslafon Feb 10, 2025
68e8938
fixed test var to const
isaiaslafon Feb 10, 2025
c0cb0ec
game center and center round tests fixed
isaiaslafon Feb 10, 2025
5318f73
game addVIsualCharacter enmend not used new code that control charact…
isaiaslafon Feb 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ package-lock.json
.classpath
build.properties
.project
META-INF
META-INF
.DS_Store
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ Currently, the Wollok language does not adhere to [Semantic Versioning](https://

Hopefully, we will be able to do that in the near future.

## v3.3.0
- Support unicode identifiers by @fdodino in #234
- Wrap game actions using io.runHandler by @lgassman in #230
- Documentation for string days representation by @alymarquez in #227
- Fix flatten return by @fdodino in #233
- Fix `flatmap` return by @Nalens10 in #228
- More sanity tests: redefine identity by @MVitelli in #231

## v3.2.7
- New `average()` method for collections by @Juancete in #221
- Better use of `void` methods by @fdodino in #218
- Fix `shouldUseOverrideKeyword` validation for properties by @fdodino in #223
- More sanity tests
- Cyclic const instance references by @PalumboN in #217
- Super call inside closures by @fdodino in #224

## v3.2.6
- Test removing a float from a list by @PalumboN in #198
- Implementacion de floor by @rodriguez-guillermo in #210
- Visual characater no se sale de los limites by @lspigariol in #209
- Agregar a language las descripciones de los errores by @fdodino in #205

## v3.2.5
- Packages with dashes by @ivojawer in #191
- Validation for new import system by @PalumboN in #193
Expand Down
61 changes: 61 additions & 0 deletions src/resources/validationMessages/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"catchShouldBeReachable": "Unreachable catch block",
"codeShouldBeReachable": "Unreachable code",
"getterMethodShouldReturnAValue": "Getter should return a value",
"linearizationShouldNotRepeatNamedArguments": "Reference {0} is initialized more than once during linearization",
"methodShouldExist": "Method does not exist or invalid number of arguments",
"methodShouldHaveDifferentSignature": "Duplicated method",
"nameShouldBeginWithLowercase": "The name {0} must start with lowercase",
"nameShouldBeginWithUppercase": "The name {0} must start with uppercase",
"nameShouldNotBeKeyword": "The name {0} is a keyword, you should pick another one",
"namedArgumentShouldExist": "Reference {0} not found in {1}",
"namedArgumentShouldNotAppearMoreThanOnce": "Reference {0} is initialized more than once",
"overridingMethodShouldHaveABody": "Overriding method must have a body",
"parameterShouldNotDuplicateExistingVariable": "Duplicated Name",
"possiblyReturningBlock": "This method is returning a block, consider removing the '=' before curly braces.",
"shouldCatchUsingExceptionHierarchy": "Can only catch wollok.lang.Exception or a subclass of it",
"shouldDefineConstInsteadOfVar": "Variable should be const",
"shouldHaveAssertInTest": "Tests must send at least one message to assert object",
"shouldHaveBody": "Method without body. You must implement it",
"shouldHaveNonEmptyName": "Tests must have a non-empty description",
"shouldImplementAllMethodsInHierarchy": "Methods in hierachy without super implementation: {0}",
"shouldImplementInheritedAbstractMethods": "You must implement all inherited abstract methods",
"shouldInitializeAllAttributes": "You must provide initial value to the following references: {0}",
"shouldInitializeGlobalReference": "Reference is never initialized",
"shouldMatchFileExtension": "The file extension doesn't allow this definition",
"shouldMatchSuperclassReturnValue": "Override method {0} does not match the returned type from its superclass (should either return a value o act as a side-effect method)",
"shouldNotAssignValueInLoop": "Infinite loop in value assignment",
"shouldNotBeEmpty": "Should not make an empty definition.",
"shouldNotCompareEqualityOfSingleton": "Comparing against named object is discouraged (missing polymorphism?)",
"shouldNotDefineEmptyDescribe": "Describe should not be empty",
"shouldNotDefineGlobalMutableVariables": "Global 'var' references are not allowed. You should use 'const' instead.",
"shouldNotDefineMoreThanOneSuperclass": "Bad Linearization: you cannot define multiple parent classes",
"shouldNotDefineUnnecesaryIf": "Unnecessary if always evaluates to true!",
"shouldNotDefineUnnecessaryCondition": "Unnecessary condition",
"shouldNotDefineUnusedVariables": "Unused variable",
"shouldNotDuplicateEntities": "This name is already defined (imported from {0})",
"shouldNotDuplicateFields": "There is already a field with this name in the hierarchy",
"shouldNotDuplicateGlobalDefinitions": "There is already a definition with this name in the hierarchy",
"shouldNotDuplicateLocalVariables": "There is already a local variable with this name in the hierarchy",
"shouldNotDuplicatePackageName": "Duplicated package",
"shouldNotDuplicateVariables": "There is already a variable with this name in the hierarchy",
"shouldNotDuplicateVariablesInLinearization": "There are attributes with the same name in the hierarchy: [{0}]",
"shouldNotHaveLoopInHierarchy": "Infinite loop in hierarchy",
"shouldNotImportMoreThanOnce": "This file is already imported",
"shouldNotImportSameFile": "Cannot import same file",
"shouldNotMarkMoreThanOneOnlyTest": "You should mark a single test with the flag 'only' (the others will not be executed)",
"shouldNotReassignConst": "Cannot modify constants",
"shouldNotUseOverride": "Method does not override anything",
"shouldNotUseReservedWords": "{0} is a reserved name for a core element",
"shouldNotUseVoidMethodAsValue": "Message send \"{0}\" produces no value (missing return in method?)",
"shouldNotUseVoidSingleton": "Named object 'void' produces no value, use 'null' instead",
"shouldOnlyInheritFromMixin": "Mixin can only inherit from another mixin",
"shouldPassValuesToAllAttributes": "{0} cannot be instantiated, you must pass values to the following attributes: {1}",
"shouldUseBooleanValueInIfCondition": "Expecting a boolean",
"shouldUseBooleanValueInLogicOperation": "Expecting a boolean",
"shouldUseConditionalExpression": "Bad usage of if! You must return the condition itself without using if.",
"shouldUseOverrideKeyword": "Method should be marked as override, since it overrides a superclass method",
"shouldUseSelfAndNotSingletonReference": "Don't use the name within the object. Use 'self' instead.",
"superclassShouldBeLastInLinearization": "Bad Linearization: superclass should be last in linearization",
"shouldNotRedefineIdentity": "Identity '===' operator should not be overriden."
}
61 changes: 61 additions & 0 deletions src/resources/validationMessages/es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"catchShouldBeReachable": "Este catch nunca se va a ejecutar debido a otro catch anterior",
"codeShouldBeReachable": "Este código nunca se va a ejecutar",
"getterMethodShouldReturnAValue": "El método getter debe retornar un valor",
"linearizationShouldNotRepeatNamedArguments": "La referencia {0} está inicializada más de una vez",
"methodShouldExist": "El método no existe o número incorrecto de argumentos",
"methodShouldHaveDifferentSignature": "Método duplicado",
"nameShouldBeginWithLowercase": "El nombre {0} debe comenzar con minúsculas",
"nameShouldBeginWithUppercase": "El nombre {0} debe comenzar con mayúsculas",
"nameShouldNotBeKeyword": "El nombre {0} es una palabra reservada, debe cambiarla",
"namedArgumentShouldExist": "No se encuentra la referencia {0} en {1}",
"namedArgumentShouldNotAppearMoreThanOnce": "La referencia {0} está inicializada más de una vez",
"overridingMethodShouldHaveABody": "Si sobrescribe debe especificar el cuerpo del método",
"parameterShouldNotDuplicateExistingVariable": "Nombre duplicado",
"possiblyReturningBlock": "Este método devuelve un bloque, si no es la intención elimine el '=' antes de las llaves.",
"shouldCatchUsingExceptionHierarchy": "Solo se puede aplicar 'catch' a un objeto de tipo wollok.lang.Exception o una subclase",
"shouldDefineConstInsteadOfVar": "Esta variable debería ser una constante",
"shouldHaveAssertInTest": "Los tests deben enviar al menos un mensaje al WKO \"assert\"",
"shouldHaveBody": "El método debe tener una implementación",
"shouldHaveNonEmptyName": "Los tests deben tener una descripción no vacía",
"shouldImplementAllMethodsInHierarchy": "Existen métodos en la jerarquía que requieren implementación en super: {0}",
"shouldImplementInheritedAbstractMethods": "Debe implementar todos los métodos abstractos heredados",
"shouldInitializeAllAttributes": "Debe proveer un valor inicial a las siguientes referencias: {0}",
"shouldInitializeGlobalReference": "La referencia nunca se inicializa",
"shouldMatchFileExtension": "La extensión del archivo no permite esta definición",
"shouldMatchSuperclassReturnValue": "El método ${0} que sobreescribe la subclase debe respetar el mismo tipo que el método de su superclase (sea un método que solo produce efecto o que devuelve un valor).",
"shouldNotAssignValueInLoop": "Se genera un loop infinito en la asignación del valor",
"shouldNotBeEmpty": "El elemento no puede estar vacío: falta escribir código.",
"shouldNotCompareEqualityOfSingleton": "No se aconseja comparar objetos nombrados, considere utilizar polimorfismo.",
"shouldNotDefineEmptyDescribe": "El describe no debería estar vacío",
"shouldNotDefineGlobalMutableVariables": "Solo se permiten las variables globales de tipo const",
"shouldNotDefineMoreThanOneSuperclass": "Linearización: no se puede definir más de una superclase",
"shouldNotDefineUnnecesaryIf": "If innecesario. Siempre se evalúa como verdadero",
"shouldNotDefineUnnecessaryCondition": "Condición innecesaria",
"shouldNotDefineUnusedVariables": "Esta variable nunca se utiliza",
"shouldNotDuplicateEntities": "Este nombre ya está definido (importado de {0})",
"shouldNotDuplicateFields": "Ya existe un atributo con este nombre en la jerarquía",
"shouldNotDuplicateGlobalDefinitions": "Ya existe una definición con este nombre en la jerarquía",
"shouldNotDuplicateLocalVariables": "Ya existe una variable local con este nombre en la jerarquía",
"shouldNotDuplicatePackageName": "Package duplicado",
"shouldNotDuplicateVariables": "Ya existe una variable con este nombre en la jerarquía",
"shouldNotDuplicateVariablesInLinearization": "En la jerarquía hay atributos con el mismo nombre: [{0}]",
"shouldNotHaveLoopInHierarchy": "La jerarquía de clases produce un ciclo infinito",
"shouldNotImportMoreThanOnce": "Este archivo ya está importado",
"shouldNotImportSameFile": "No se puede importar el mismo archivo",
"shouldNotMarkMoreThanOneOnlyTest": "Solo un test puede marcarse como 'only' (los otros no se ejecutarán)",
"shouldNotReassignConst": "No se pueden modificar las referencias constantes",
"shouldNotUseOverride": "Este método no sobrescribe ningún otro método",
"shouldNotUseReservedWords": "{0} es una palabra reservada por la biblioteca de Wollok",
"shouldNotUseVoidMethodAsValue": "El mensaje \"{0}\" no retorna ningún valor (quizás te falte un return en el método)",
"shouldNotUseVoidSingleton": "El objeto nombrado 'void' no retorna ningún valor (puede usar 'null' en su lugar)",
"shouldOnlyInheritFromMixin": "Los mixines solo pueden heredar de otros mixines",
"shouldPassValuesToAllAttributes": "No se puede instanciar {0}. Falta pasar valores a los siguientes atributos: {1}",
"shouldUseBooleanValueInIfCondition": "Se espera un booleano",
"shouldUseBooleanValueInLogicOperation": "Se espera un booleano",
"shouldUseConditionalExpression": "Estás usando incorrectamente el if. Devolvé simplemente la expresión booleana.",
"shouldUseOverrideKeyword": "Debería marcarse el método con 'override', ya que sobrescribe el de sus superclases",
"shouldUseSelfAndNotSingletonReference": "No debe usar el nombre del objeto dentro del mismo. Use 'self'.",
"superclassShouldBeLastInLinearization": "Linearización: la superclase debería estar última en linearización",
"shouldNotRedefineIdentity": "No se debe redefinir el operador de identidad '==='."
}
106 changes: 89 additions & 17 deletions src/wollok/game.wlk
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ object game {
const visuals = []
/** Is Game running? */
var property running = false

/**
* Allows to configure a visual component as "error reporter".
* Then every error in game board will be reported by this visual component,
Expand All @@ -24,7 +25,7 @@ object game {
self.height(5)
self.cellSize(50)
self.ground("ground.png")
}
}

/**
* Adds an object to the board for drawing it.
Expand All @@ -46,11 +47,16 @@ object game {
*/
method addVisualCharacter(visual) {
self.addVisual(visual)
keyboard.up().onPressDo({ visual.position(visual.position().up(1)) })
keyboard.down().onPressDo({ visual.position(visual.position().down(1)) })
keyboard.left().onPressDo({ visual.position(visual.position().left(1)) })
keyboard.right().onPressDo({ visual.position(visual.position().right(1)) })
keyboard.up().onPressDo({
if(visual.position().y() < self.height()-1) visual.position(visual.position().up(1)) })
keyboard.down().onPressDo({
if(visual.position().y() > 0) visual.position(visual.position().down(1)) })
keyboard.right().onPressDo({
if (visual.position().x() < self.width()-1) visual.position(visual.position().right(1)) })
keyboard.left().onPressDo({
if (visual.position().x() > 0) visual.position(visual.position().left(1)) })
}

/**
* Removes an object from the board for stop drawing it.
*
Expand Down Expand Up @@ -83,7 +89,6 @@ object game {
io.addEventHandler(event, action)
}


/**
* Adds a block that will be executed while the given object collides with other.
* Two objects collide when are in the same position.
Expand All @@ -94,9 +99,9 @@ object game {
* game.whenCollideDo(pepita, { comida => pepita.comer(comida) })
*/
method whenCollideDo(visual, action) {
io.addCollitionHandler(visual.identity(), { =>
self.colliders(visual).forEach({it => action.apply(it)})
})
io.addCollitionHandler(visual.identity(), { =>
self.colliders(visual).forEach({it => io.runHandler({action.apply(it)})})
})
}

/**
Expand All @@ -112,7 +117,7 @@ object game {
var lastColliders = []
io.addCollitionHandler(visual.identity(), { =>
const colliders = self.colliders(visual)
colliders.forEach({ it => if (self.hasVisual(visual) and !lastColliders.contains(it)) action.apply(it) })
colliders.forEach({ it => if (self.hasVisual(visual) and !lastColliders.contains(it)) io.runHandler{action.apply(it)} })
lastColliders = colliders
})
}
Expand All @@ -128,7 +133,7 @@ object game {
method onTick(milliseconds, name, action) {
var times = 0
const initTime = io.currentTime()
io.addTimeHandler(name, { time => if (milliseconds == 0 or (time - initTime).div(milliseconds) > times) { action.apply(); times+=1 } })
io.addTimeHandler(name, { time => if (milliseconds == 0 or (time - initTime).div(milliseconds) > times) { io.runHandler(action); times+=1 } })
}

/**
Expand All @@ -141,7 +146,7 @@ object game {
method schedule(milliseconds, action) {
const name = action.identity()
self.onTick(milliseconds, name, {
action.apply()
io.runHandler(action)
io.removeTimeHandler(name)
})
}
Expand Down Expand Up @@ -225,7 +230,7 @@ object game {
const reporter = if (errorReporter == null) exception.source() else errorReporter
self.say(reporter, exception.message())})
}

/**
* Returns a position for given coordinates.
*/
Expand All @@ -239,10 +244,27 @@ object game {
method origin() = self.at(0, 0)

/**
* Returns the center board position (rounded down).
* Returns the x coordinate of the center of the board.
*/
method center() = self.at(self.width().div(2), self.height().div(2))
method xCenter(){ //DELETE COMMENT To not duplicade code, could be duplicated. Is also used by CenterOffset, could be implemented there and duplicated in center method.
return self.width().div(2)
}

/**
* Returns the y coordinate of the center of the board.
*/
method yCenter(){ //DELETE COMMENT To not duplicade code, could be duplicated. Is also used by CenterOffset.
return self.height().div(2)
}

/**
* Returns a center board position (rounded down).
* ////DELETE COMMENT (Before game start is 0,0 then offset to current Game Board Size).
*/
method center() {
return if (running) { new Position(x = self.xCenter(), y = self.yCenter()) } else { new CenterOffset() }
}

/**
* Sets game title.
*/
Expand Down Expand Up @@ -400,7 +422,6 @@ class AbstractPosition {
* Returns a new position with its coordinates rounded
*/
method round() = self.createPosition(self.x().round(), self.y().round())

}

/**
Expand Down Expand Up @@ -448,6 +469,57 @@ class MutablePosition inherits AbstractPosition {

}

class CenterOffset inherits AbstractPosition{

/** x and y offset values to save transformations before the game Runs. */
const xOffset = 0
const yOffset = 0

/** x taking the offset into account. */
override method x() = game.xCenter() + xOffset

/** y taking the offset into account. */
override method y() = game.yCenter() + yOffset

/**
* Returns a new Position n steps right from this one while Running, or a lazy center with offset while idle.
*/
override method right(n) = if (game.running()) { new Position(x = self.x() + n, y = self.y()) } else { new CenterOffset(xOffset = xOffset + n, yOffset = yOffset) }

/**
* Returns a new Position n steps left from this one while Running, or a lazy center with offset while idle.
*/
override method left(n) = if (game.running()) { new Position(x = self.x() - n, y = self.y()) } else { new CenterOffset(xOffset = xOffset - n, yOffset = yOffset) }

/**
* Returns a new Position n steps up from this one while Running, or a lazy center with offset while idle.
*/
override method up(n) = if (game.running()) { new Position(x = self.x(), y = self.y() + n) } else { new CenterOffset(xOffset = xOffset, yOffset = yOffset + n)}

/**
* Returns a new Position, n steps down from this one while Running, or a lazy center with offset while idle.
*/
override method down(n) = if (game.running()) { new Position(x = self.x(), y = self.y() - n) } else { new CenterOffset(xOffset = xOffset, yOffset = yOffset - n) }

/**
* Returns a new Position is the game is Running with the same coordinates, or a lazy center with offset while idle.
*/
override method clone() = if (game.running()) { new Position(x = self.x(), y = self.y()) } else { new CenterOffset(xOffset = xOffset, yOffset = yOffset) }

override method createPosition(_x, _y) = new Position(x = _x, y = _y)

/**
* Returns a new position with its coordinates rounded if Running, or a lazy center with rounded offset while idle.
*/
override method round(){
//DELETE COMMENT To not duplicate code.
const xOffsetRounded = xOffset.round()
const yOffsetRounded = yOffset.round()

return if(game.running()){ new Position(x = game.xCenter() + xOffsetRounded, y = game.yCenter() + yOffsetRounded) }
else { new CenterOffset(xOffset = xOffsetRounded, yOffset = yOffsetRounded) }
}
}

/**
* Keyboard object handles all keys movements. There is a method for each key.
Expand Down Expand Up @@ -687,7 +759,7 @@ class Tick {
**/
method start() {
if (self.isRunning()) {game.error("This tick is already started.")}
if (inmediate) {action.apply()}
if (inmediate) {io.runHandler(action)}
game.onTick(interval, name, action)
}

Expand Down
Loading