Giter Club home page Giter Club logo

wollok-ts's Introduction

Wollok-TS npm version codecov

TypeScript based Wollok language implementation

Usage

For an in-dept explanation of the API and how to use it please refer to the documentation page.

Contributing

All contributions are welcome! Feel free to report issues on the project's issue tracker, or fork the project and create a Pull Request. If you've never collaborated with an open source project before, you might want to read this guide.

If you plan to contribute with code, here are some hints to help you start:

Working Environment

Before anything else, you will need a TypeScript editor. We recomend Visual Studio Code along with the following plugins:

Node

You need to install node > 11, which provides VM environment, and nvm - Node Version Manager. Before anything make sure you'll use the right version of node by running this command:

nvm use

Expected output is the node version that will be used, for example:

Found '/home/dodain/workspace/wollok-dev/wollok-ts/.nvmrc' with version <v11.15.0>
Now using node v11.15.0 (npm v6.7.0)

NPM

You will also need to install NPM. (Node.js version 8 or greater) If you are not familiar with dependency manager tools, you can think of this program as the entry point for all the important tasks development-related tasks, like installing dependencies and running tests. After installing the client, go to the project root folder and run:

# This will install all the project dependencies. Give it some time.
npm install

After that, you are ready to start working. You can run the tests and style checks by typing:

# This will run tests for all the modules. Try to do this often and avoid commiting changes if any test fails.
npm test

A full list of the available scripts is listed on the package.json file, on the root folder.

File Description

[[TODO]]: Describe what is each file

  • src/model.ts: It has all the type declarations of the nodes in each stage.
  • src/parser.ts: Parsing stage functions.
  • src/filler.ts: Filling stage functions.
  • src/log.ts and src/cache.ts: logging and optimization.
  • src/tools.ts: Utils for managing the tree structure.

Dependencies

[[TODO]]: Describe what we are usinng, give links, and explain what docs to read based on what you will be touching.

wollok-ts's People

Contributors

angelimatias avatar asanzo avatar dependabot[bot] avatar ezequielpereyra avatar fdodino avatar ferrommu avatar gomezdn avatar guillep avatar ivanpuchalka avatar ivojawer avatar juanbono avatar juancete avatar juanfds avatar julimr avatar kalafuente avatar mind-ar avatar nscarcella avatar palumbon avatar rodr0m4 avatar rodroma avatar tfloxolodeiro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar

wollok-ts's Issues

Truncar los x y de las position

Esto ya se está haciendo al dibujar los objetos, para que todos estén en una celda y no "a la mitad".

Faltaría hacerlo al compararlas acá para que funcione los colliders en función a cómo se muestra en la pantalla.

Fix ** precedence

Currently the parser has a TODO in the operators where the ** is duplicated. Removing the first instance of ** causes the parsing of WRE to fail (Probably an ambiguity with the comment syntax or the * having more precedence than the **, making the sencond * an issue).

Adding a lookAhead might fix the problem but it would be nice to make it generic so we don't need to handle that case separately from the current implementation. Maybe something in the lines of checking after an operator that the next character is not another operator?

Fix: Agregado automático de badge de coverage

Hoy está fallando el build de CI cuando se aprueba un PR porque la acción

    - name: Coverage badge
      uses: demyanets/angular-coverage-badges-action@v1
      with:
        coverage-summary-path: coverage/coverage-summary.json
        github_token: ${{ secrets.GITHUB_TOKEN }}

levanta y graba directamente el directorio badge a master que tiene protección de escritura directa. Lo que podemos hacer es que este proceso corra solo cuando se cree un PR, de manera que al aprobarlo se actualice el badge (sin ejecutar el proceso).

Sintaxis funcionalosa + return

CREO que si se define un método como

method m() = return "Hola"

Rompe.

Esto puede que esté correcto, en ese caso habría que agregarlo a los sanities.

Should add unraw as a dependency in the readme?

Branch: next

I tried to run the tests using

$ npm test

And I got a compile time error because unraw was not available. I got after it doing npm install unraw but it is not clear this is the way to go...

Catch up with Wollok-xtend v1.8.1

This is an Epic to remember we should work towards matching the wollok-xtend implementation of v1.8.1 so we can start syncing up.

This of course heavily relies on updating and keeping up with the sanity tests.

Related issues:

Atrapar las Excepcions y mostrarlas como el `game.say`

Esto se puede resolver desde el objeto io.

  • Meter un try catch al consumir los eventos en el io diferenciando entre DomainException (que debería poner el carteito) y Exception (se puede hacer algo??)

La lógica de cada evento (dentro del forEach, debería ser algo como

try {
  callback.apply()
} catch e: Exception { 
  if (e.source() !== null && game.hasVisual(e.source())) {
    game.say(e.source(), e.message())
  }
  // else ?????
}

Quasiquotes

So... Yeah. We have a lot (and I mean, A LOT) of manually constructed Nodes, specially in the tests. Since Nodes are not always trivially mapped to the code they represent, this can make understanding those constructions a bit harsh.

We also have a bunch of situations where we need to "extract" a Node of certain type we know must be present from deep within another Node, which usually involves a fairly large amount of casting and long extraction chains. We could deal with some of these issues by using lenses or something along that line, but we might be able to tackle the two issues at the same time by implementing some for of quasiquotes, like Scala does.

So the general proposal would be to have some construction that allows us to:

  • Convert a string expressing valid Wollok code to its equivalent Node. (So far so good, this is just parsing...)
  • Allow interpolating other nodes in said string. (This would allow us to nest quasiquotes or combine previous results)
  • Use a string of Wollok code as deconstruction pattern to "extract" portions of a Node.
  • Ideally, parameterize (or overload) these definitions so they can be as type sound as possible.

TypeScript provides most of the necessary infrastructure we need for this, except some Type nuisances and the fact that StringTemplates can't be used as lvalue. We might be able to workaround this by making the quasiquote return an array (which is a valid lvalue) and adding some sort of marker to identify the "extracted" portions.

To be honest I didn't give much though to the idea, but I did create a little naive prototype. Not sure how poorly would this approach be performance-wise, but it seems to only relay on some regex, the parser function and an encoder function to act as the inverse of the parser (that I so cleverly called unparse), so we might be able to implement an actual prototype in the not-so-far future.

///////////////////////////////////////////////////////////////////////////////////
// SIMPLIFIED NODE MODEL
///////////////////////////////////////////////////////////////////////////////////

type Exp = Num | Mul | Add

interface Num { kind: 'Num', value: number }
interface Mul { kind: 'Mul', left: Exp, right: Exp }
interface Add { kind: 'Add', left: Exp, right: Exp }

///////////////////////////////////////////////////////////////////////////////////
// DATA EXAMPLE
///////////////////////////////////////////////////////////////////////////////////

// 2 * 3 + 4 * 5
const exp = {
    kind: 'Add',
    left: {
        kind: 'Mul',
        left: {kind: 'Num', value: 2},
        right: {kind: 'Num', value: 3},
    },
    right: {
        kind: 'Mul',
        left: {kind: 'Num', value: 4},
        right: {kind: 'Num', value: 5},
    },
} as const

///////////////////////////////////////////////////////////////////////////////////
// MOCK FUNCTIONS
///////////////////////////////////////////////////////////////////////////////////

function parse(input: string): Exp {
    if(input === '2 * 3 + 4 * 5') return exp;
    if(input === '4 * 5') return exp.right;
    throw new Error(`Don't know how to parse ${input}`)
}

function unparse(input: Exp): string {
    switch(JSON.stringify(input)){
        case JSON.stringify(exp): return '2 * 3 + 4 * 5'
        case JSON.stringify(exp.left.right): return '3'
        case JSON.stringify(exp.right): return '4 * 5'
        default: throw new Error(`Don't know how to unparse ${JSON.stringify(input)}`)
    }
}

///////////////////////////////////////////////////////////////////////////////////
// QUASIQUOTES IMPLEMENTATION
///////////////////////////////////////////////////////////////////////////////////

const _ = Symbol('Extract')

const w = <T extends unknown>(parts: TemplateStringsArray, ...args: Exp[]): T => {
    const unparsed = parts.map((part, i) =>
        `${part}${args[i] ? unparse(args[i]) : ''}`
    ).join('')

    return parse(unparsed) as T
}

const wd = (parts: TemplateStringsArray, ...args: any[]) => (subject: Exp): Exp[] => {
    // There is an npm library that does this...
    const escapeRegex = (str: string) => {
        const specials = ["-","[", "]", "/", "{", "}", "(", ")", "*", "+", "?", ".", "\\", "^", "$", "|"]
        return str.replace(RegExp('[' + specials.join('\\') + ']', 'g'), "\\$&")
    }

    const replace = (val: any) =>
        val === undefined ? '' :
        val === _ ? "(.*)" :
        escapeRegex(`${val}`)

    const regex = '^' + parts.map((part, i) =>
        `${escapeRegex(part)}${replace(args[i])}`
    ).join('') + '$'

    const unparsed = unparse(subject)

    const matched = (RegExp(regex).exec(unparsed)?? []).slice(1)

    console.log({replace, regex, unparsed, matched})

    return matched.map(parse)
}

///////////////////////////////////////////////////////////////////////////////////
// TEST
///////////////////////////////////////////////////////////////////////////////////

console.log("w")
const exp1: Add = w`2 * ${exp.left.right} + ${exp.right}`

console.log("wd")
const [r2] = wd`2 * ${3} + ${_}`(exp)

if(exp1 !== exp) throw Error(`Falló el w`)
if(r2 !== exp.right) throw Error(`Falló el wd`)
console.log("Ok, todo lindo")

Notice I created two functions, one for constructing and one for deconstructing. The types are bullshit but I believe we can improve them (maybe with some overloading or defining separate functions for expressions, entities and so).

Again this is only an idea and definitely not a high priority, but it might be a nice thing to have.

Make parser fail safe

Right now the parser stops at the first failure point returning a parse error. The general idea is to allow the parser to continue parsing after an error occurs, making it able to provide multiple parse errors at one time.

The proposed approach for doing so (at least the best we can think of right now) is to add a new node Error to the model and extend some of the current parsing rules so, in case every other alternative fails, it will accept any input until the next significant token and create an Error node instead of failing.

So, for example, we could change the definition for Entity from:

type Entity<S extends Stage> = Package<S> | Program<S> | Test<S> | Describe<S> | Module<S>

to:

type Entity<S extends Stage> = Package<S> | Program<S> | Test<S> | Describe<S> | Module<S> | Error<S>

and alter the entity parser to accept any string until another entity identifier and build an error node with it:

const entity: Parser<Entity<Raw>> = lazy(() => alt(
  packageEntity,
  classEntity,
  singletonEntity,
  mixinEntity,
  programEntity,
  describeEntity,
  testEntity,
  error // read anything until the next keyword "package", "class",  "object", "mixin", "program", "describe" or "test"
))

Doing this for Entities, Members, Sentences and Expressions should improve the current handling a lot.

Errors should contain the text that caused them and the source information (just as any other node).

We should also add a rule on the validator to reject any Error node as a problem.

Validación: salta shouldReturnAValueOnAllFlows con super() cuando no corresponde

class A {
    method a(){}
}

class B inherits A {
    var cumple = false
    override method a(){
        if(cumple){
            cumple = false
        } else {
            super()
        }   
    }
}

Ese código, levantado con el repl de wollok-ts-cli, tira el siguiente error:

[ERROR]: shouldReturnAValueOnAllFlows at src/minimo.wlk:8 (la línea del if)

y no debería tirarlo. Lo loco es que el error desaparece si hacés en lugar de super(), cumple = super()

TypeError: Cannot read properties of undefined (reading 'defaultFieldValues')

Intentando correr github.com/pdepjm/2020-o-tpi-juego-wolollok

alf@q2alf:~/repos/pdep/2020/objetos/2020-o-tpi-juego-wolollok (master u=)$ ./wollok-ts-cli-linux test
Running all tests on /home/alf/repos/pdep/2020/objetos/2020-o-tpi-juego-wolollok
Reading project files: 14.771ms
Building environment: 2.014s
/snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/validator.js:339
    (_a = node.defaultFieldValues()) === null || _a === void 0 ? void 0 : _a.forEach((value, field) => {
               ^

TypeError: Cannot read properties of undefined (reading 'defaultFieldValues')
    at getUninitializedAttributes (/snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/validator.js:339:16)
    at getUninitializedAttributesForInstantation (/snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/validator.js:334:12)
    at /snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/validator.js:123:83
    at /snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/validator.js:37:116
    at /snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/validator.js:542:42
    at Array.map (<anonymous>)
    at /snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/validator.js:542:14
    at applyReduce (/snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/model.js:150:12)
    at /snapshot/wollok-ts-cli/node_modules/wollok-ts/dist/model.js:149:20
    at Array.reduce (<anonymous>)

Colisiones de FQN

El siguiente program:
game.wpgm

import wollok.game.*

program game {
    game.start()
}

Rompe con [ERROR]: Error: LOAD of missing local "game" on context {"id":"250c07f4-241c-4230-a40b-c81539a9ef92","parent":"root","locals":{}}

Al parecer hay un problema al tener el archivo y el program llamados game, como el objeto al que se le quiere hacer start(), ya que al renombrarlos el error desaparece.

Cyclic references

Habría que hacer que pasen este test de referencias cruzadas al instancias con named args.

El problema es un StackOverflow que se da al compilar el new. Habría que postergar la compilación de named args.

  • Después habría que _des_ignorar esos sanity.

WG: Features del character

Actualmente el único tratamiento que tiene el character es moverse con las flechas. Pero en la versión de xtext hay otras cuestiones relacionadas:

  • Solamente se puede tener un character. (Ver si se agrega una validación en lang).
  • El movimiento del character no permite que se vaya de los límites de la pantalla.
  • Al lanzar una excepción desde un objeto no visual, el character lo dice (#69).
  • Y también queríamos deprecar el método game.addVisualCharacterIn(#62)

Implement Fixtures

Current implementation does not support fixtures as wollok-xtext does. Either implement it or start and win a war to remove fixtures from the language.

Probably better to just implement it.

Don't forget to unskip the sanity tests for this.

Compile Describe and Tests as Classes/Objects and Methods

Currently, describes and tests are separate reified nodes on the AST. The current implementation if fine, but there is quite a lot of redundancy, since Describes, not being Modules, still can define methods and variables. The only difference with regular Modules is that they can define Fixtures, which, if I understand correctly, might be soon deprecated in favor of init blocks. Test have a similar redundancy with methods too, which makes some parts of the pipeline unnecessarily reiterative and the whole model more complex.

So...

Talking with @npasserini, he mentioned that in his head he though of describes and tests as just a separate domain specific syntax to define classes and methods. I was a little resilient at first, but after some time I grow fond of the idea. Maybe we could implement Describes and Tests as just Modules and Methods. We could identify Describes by making them extend a Describe superclass, including a Describe mixin or just using annotations (if we eventually include them). Tests might be identified either with annotations or by a name preface injected at parse. We could alternatively just add a new field in Class and Method nodes.

Mind you this is not a proposal for a syntax change. The test writing would be exactly the same, is just a matter of internal representation.

I believe this might be a good idea to keep the project simple, but I would like your feedback. I would be specially interested to know if you all share the idea that describes/test can be think like classes/methods, or if you are thinking of taking the abstractions in a very different direction.

Problemas con el orden de inicialización

Tengo este programa

object o {
  var property x = pepita.energia() / 2
}

object pepita {
  var property energia

  method initialize() {
    energia = 2
  }
}

test "TEST" {
  assert.equals(1, o.x())
}

Que rompe con Error: LOAD of missing local "energia" on context ...


Supongo que el problema es el orden en el que se crean e inicializan los singletons. Este mismo programa pero con la definición de lo objetos al revés (primero pepita) funciona.

Implement a Garbage Collector for interpreter

We should add a garbageCollect function that receives an Evaluation and cleans the unreferenced instances. We could probably just implement some simple Mark and Sweep algorithm, no point in getting fancy.

Something to consider is that we should never garbage collect named singletons or well known objects such as null, true and false.

Reference to describe?

Now the linker make a reference with a describe node (with the same name) as target. Could this scenario be possible?

Example test:

    it('should target describe??', () => {
      const environment = link([
        Package('p', {
          imports: [
            Import(Reference('r.G')),
          ],
        })(
          Describe('G')(
            Fixture()(
              Reference('G'),
            )
          )
        ),
        Package('r')(
          Class('G')(),
        ),
      ] as PackageNode<Filled>[], WRE)

      const describe = environment.getNodeByFQN<DescribeNode>('p.G')
      const clazz = environment.getNodeByFQN<ClassNode>('r.G')
      const reference = describe.fixtures()[0].body.sentences[0] as ReferenceNode<Linked>

      reference.should.target(describe)
    })

Bloques dentro de bloques confunde self

Este test:

object o {
	var property block = null

	method prueba() { 
		{
			self.block({ self.magia() }) 
		}.apply()
	}

	method magia() { 
		console.println("PIOLA")
	}
}

test "Se confunde self" {
	o.prueba()
	o.block().apply()
}

Tira este error diciendo que el bloque grande no entiende magia()

     wollok.lang.MessageNotUnderstoodException: {
			self.block({ self.magia() }) 
		} does not undersand magia()
			self.block({ self.magia() }) 
		} does not undersand magia()
	at wollok.lang.Object.messageNotUnderstood(messageName, parameters) [wollok/lang.wlk:206:3]
	at wollok.lang.Closure#c31fb331-ab7c-4fd7-a82f-3e5cfd4beb6e.<apply>() [src/tests.wtest:14:15]
	at wollok.lang.Closure.apply(parameters) [wollok/lang.wlk:2757:3]
	at src.tests."Se confunde self" [src/tests.wtest:23:1]
	at root [--:--]
     Derived from TypeScript stack

Implement top level constants

Currently Wollok-ts supports constants outside of entities. We need to add support for this on 1.8.1, and update the tests and sanities.

Mover código Wollok a Language

Para la implementación de Game se tuvieron que agregar algunas definiciones (y tests) escritos en Wollok que estaría bueno tener en Language.

Ver los directorios src/wre y test/game.

toString de un Object

object pepita {}

Si en xtext hacemos pepita.toString() nos devuelve "pepita" (el nombre del objeto).

Pero si lo hacemos en wollok-ts, nos devuelve el FQN.

Habría que ver con qué versión nos queremos quedar y agregar los sanity tests correspondientes a wollok-language.

Printear el stack trace

Estaría bueno implementar los natives que faltan para dar más información de los errores que se tiran.

  • El mensaje, mínimo.
  • El stacktrace completo si es posible.

Faltan operador not

Este programa

object o {
	method m(b){
		if ( not b ) { }
	}
}

rompe el parser

Error: Failed to parse src/objects.wlk: 
-- PARSING FAILED --------------------------------------------------

  4 | 		if ( not b ) { }
  5 | 	}
> 6 | }
    | ^
  7 | 
  8 | 

Expected one of the following: 

'class', 'const', 'describe', 'mixin', 'object', 'package', 'program', 'test', 'var', /\/\*(.|[\r\n])*?\*\/|\/\/.*/, EOF, whitespace

Puede ser que falte el not en el lenguaje?

Referencias a excepciones en try-catch

Si hacemos algo como:

try {
	...
}
catch e: wollok.lang.DomainException {
	...
}

Falla el parseo con el siguiente error:

-- PARSING FAILED --------------------------------------------------

  4 |           throw new DomainException()
  5 |   }
> 6 |   catch e: wollok.lang.DomainException {}
    |                 ^
  7 |
  8 |   assert.that(true)

Expected one of the following:

'@', '{', comment, sentence, whitespace

Dejo este repo con una prueba chiquita para este caso.

Make linker fail-resilient

Currently, during linking, if a reference can't be found the linker throws an exception. We should make it so the linker can present multiple failures at the same time.

Maybe we could replace references targets with Error the nodes we talk about on #14.

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.