Skip to content

CLI/Lib Refactor #393

@dustinlacewell

Description

@dustinlacewell

Motive

Currently there is not enough seperation between the implementation of parts within TSTL. While TSTL does offer a library-like interface this is mostly incidental. TSTL was originally designed with command-line usage in mind.

Objective

Let's identify and discuss changes that will strengthen a separation of concerns between the core implementation, and those bits which implement the CLI

  • Core: Everything to do with the business of transpilation
  • CLI: Everything to do with translating command-line arguments and execution environment (variables) into parametric calls into core and reporting issues back to users through stderr/logging, etc.

Core Should Be Easily Composed

Here is a pseudo-code example of what may be possible. The methods of Parser, Transformer and FileEmitter and variants all return some structured object which is suitable for consumption by the next applicable processor in the pipeline making them easy to compose together as shown. Each ... in the example is a point where configuration can be injected, including plugin objects. Additionally, these objects can be subclassed for more control. Finally, they can be replaced entirely for ultimate control.

Missing here is exception handling clauses which would catch exception variants raised from inside core. Each client application is more easily able to handle all aspects of using TSTL this way. The CLI implementation should also become more focused and narrow as a result.

import * as tstl from 'tstl';

const
    myInputFiles: File[],
    parser = tstl.Parser(...),
    transformer = tstl.Transformer(...),
    emitter = tstl.FileEmitter(...);

for (const file of myInputFiles) {
    for (const ast of parser.parseFile(f)) {
        const result = transformer.transform(ast);
        // emitter(result);
        customEmissionHandler(result, ...);
    });
}

Currently Identified Issues

Core Catches Exceptions

Currently there are core-ish routines which catch and handle exceptions on behalf of the CLI use-case. This is problematic for library use-cases wherein those errors need to be handled specifically by calling code.

Cases:
https://github.com/Perryvw/TypescriptToLua/blob/master/src/LuaTranspiler.ts#L115

Core Interacts With Process

Core routines should not be in the business of doing things like calling process.exit or participating in any other process management such as watchers.

Cases:
https://github.com/Perryvw/TypescriptToLua/blob/master/src/LuaTranspiler.ts#L49

Reporting

The core should never directly utilize functions like console.log to report information to the user. Instead the core should return structured information to the caller. TSTL's CLI can interpret and format this information for outputting to the console or any other log destination. Similiarly, library users can handle reporting in the way that makes sense in the context of each use-case (such as IDE extensions).

Cases:
https://github.com/Perryvw/TypescriptToLua/blob/master/src/LuaTranspiler.ts#L147
https://github.com/Perryvw/TypescriptToLua/blob/master/src/LuaTranspiler.ts#L149

Core Parametricity

Core routines should take in all of their configuration through parameter arguments and should never reach out to the environment or depend on configuration files. The CLI should be responsible for translating configuration artifacts, environment variables and commnand-line arguments into the correct core routine arguments.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions