Giter Club home page Giter Club logo

transpiler's Introduction

npm (scoped) npm (scoped) Build Status Slack

abaplint

Linter for ABAP, code must be serialized using abapGit.

Versioning: semantic versioning is currently not followed, recommend fixing usage to a specific version.

Online playground

Support

Support the project by finding bugs, fixing code, or sponsoring.

abaplint.app is available via GitHub marketplace for single click installation and setup.

For commercial support agreements please [email protected]

Documentation

Getting started (local installation)

Configuration and rule documentation

Continuous Integration setup

Visual Studio Code extension

Development

Syntax diagrams

Design documentation

Development

Code Coverage

transpiler's People

Contributors

arcanist123 avatar burnerpat avatar dependabot-preview[bot] avatar dependabot[bot] avatar dwivedirahul44 avatar joltdx avatar larshp avatar mbtools avatar milosz1234517 avatar mrsimpson avatar schmelto avatar thorsten-wolf-neptune avatar zeatynis avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

transpiler's Issues

associativity

the following two examples give different outputs, it should not

output = 100 * noun + verb.
output = ( 100 * noun ) + verb.

Async run()

Probably easier now than later.
Proposal: async and promise everything

[Q&A] What is the intention of this project?

Out of curiosity, how come you came up with this project?
What does it do, simply a transform like: ABAP => Java => Output?

I began to learn ABAP recently and reluctantly, and found this project quite amazing. But ABAP is not a popular language.
Why you are willing to work on this project?

remove javascript identifier restriction

currently its not possible to have an ABAP variable called if

as IF is a javascript keyword

remove this restriction by automatically renaming all identifiers that clash with JS

types downport, some error

lines is a ddic string_table,

    DATA(lines) = get_lines( input ).

    LOOP AT lines INTO DATA(lv_line).

lv_line becomes a table, should be typed like the table row,

    let lines = new abap.types.Table(new abap.types.String());
    let lv_line = new abap.types.Table(new abap.types.String());

workaround: don't inline lv_line

probably a bug in abaplint

LOOP AT - "WHERE" is ignored

LOOP AT inputtab INTO DATA(string2) WHERE table_line <> string1.

is transpiled to:

    for (let unique3 of inputtab.array()) {
      string1.set(unique3);

so the "WHERE" part is ignored here

unit testing, give json output

handle DIV

lv_iterations = ev_size DIV lv_length.

BETWEEN does not care about NOT

IF foo NOT BETWEEN 5 AND 10.
is transpiled to:
if (abap.compare.between(foo, constant_5, constant_10)) {

Adding parantheses helps...
IF NOT ( foo BETWEEN 5 AND 10 ).
transpiles to:
if (!(abap.compare.between(foo, constant_5, constant_10))) {

READ TABLE WITH KEY

workaround: just loop everything

  it("READ TABLE WITH KEY", async () => {
    const code = `
TYPES: BEGIN OF ty_structure,
         field TYPE i,
       END OF ty_structure.

DATA tab TYPE STANDARD TABLE OF ty_structure WITH DEFAULT KEY.
DATA line LIKE LINE OF tab.

line-field = 2.
APPEND line TO tab.
line-field = 5.
APPEND line TO tab.
ASSERT lines( tab ) = 2.

CLEAR line.

READ TABLE tab INTO line WITH KEY field = 2.
ASSERT sy-subrc = 0.
ASSERT line-field = 2.

READ TABLE tab INTO line WITH KEY field = 123.
ASSERT sy-subrc = 4.`;
    const js = await run(code);
    const f = new Function("abap", js);
    f(abap);
  });

bug, SPLIT AT

SPLIT input AT |\n| INTO TABLE DATA(table).

if input is empty, then the table should also be empty

Can't transpile a single file with 2 classes

The following fails. Each class definition transpiles OK individually.

    CLASS zcl_ret DEFINITION.
      PUBLIC SECTION.
        DATA bar TYPE i.
        CLASS-METHODS
          foo
            IMPORTING
              iv_imp type string
            RETURNING
              VALUE(rv_ret) type string.
    ENDCLASS.
    CLASS zcl_ret IMPLEMENTATION.
      METHOD foo.
        rv_ret = 'X'.
      ENDMETHOD.
    ENDCLASS.
    CLASS zcl_ret2 DEFINITION.
      PUBLIC SECTION.
        DATA bar TYPE i.
        CLASS-METHODS
          blahblah
            IMPORTING
              iv_imp type string
            RETURNING
              VALUE(rv_ret) type string.
    ENDCLASS.
    CLASS zcl_ret2 IMPLEMENTATION.
      METHOD blahblah.
        rv_ret = iv_imp.
      ENDMETHOD.
    ENDCLASS.
    DATA foo TYPE REF TO zcl_ret2.
    CREATE OBJECT foo.
    WRITE foo->blahblah( iv_imp = 'Y' ).

Operator precedence

The following ABAP snippet:

a = a * b + c * d.

is transpiled to the following JavaScript code:

a.set(a.multiply(b.add(c.multiply(d))));

If you set a, b, c, d to 2, 3, 4, 5, the result of the transpiled expression will be 2 * (3 + (4 * 5) = 46, due to the way the expression is constructed. The correct result would be 26.

This happens because the syntax tree abaplint creates for this expression looks like this:

Class methods should transpile to static methods rather than instance methods

    CLASS zcl_ret DEFINITION.
      PUBLIC SECTION.
        DATA bar TYPE i.
        CLASS-METHODS:
          run RETURNING VALUE(rv_ret) TYPE string.
    ENDCLASS.

    CLASS zcl_ret IMPLEMENTATION.
      METHOD run.
        rv_ret = 'X'.
      ENDMETHOD.
    ENDCLASS.

is transpiled to

class zcl_ret {
  constructor() {
    this.bar = new abap.types.Integer();
  }
  run() {
    let rv_ret = new abap.types.String();
    rv_ret.set('X');
    return rv_ret;
  }
}

But it should be transpiled to the following or similar.

class zcl_ret {
  constructor() {
    this.bar = new abap.types.Integer();
  }
  static run() {
    let rv_ret = new abap.types.String();
    rv_ret.set('X');
    return rv_ret;
  }
}

FIND, bug

        FIND REGEX ' (\d+) (\w+ \w+)' IN lv_line
          MATCH OFFSET DATA(lv_offset)
          MATCH LENGTH DATA(lv_length)
          SUBMATCHES DATA(lv_count) lv_color.

to
abap.statements.find(lv_line, {regex: ' (\\d+) (\\w+ \\w+)', offset: lv_offset, length: lv_length, submatches: [lv_offset,lv_length,lv_count,lv_color]});

LOOP does not support REFERENCE with inline declarations

DATA table TYPE STANDARD TABLE OF string.
DATA declared_line TYPE string.

" These works just fine:
LOOP AT table INTO declared_line.
LOOP AT table REFERENCE INTO declared_line.
LOOP AT table INTO DATA(inline_1).

" This one does not:
LOOP AT table REFERENCE INTO DATA(inline_2).

Workarounds are plenty.

Bug, FIND with "bad" types should work

  it("FIND, bad types", async () => {
    const code = `
  DATA lv_offset TYPE string.
  FIND REGEX 'aa' IN 'bbaabb' MATCH OFFSET lv_offset.`;
    const js = await run(code);
    const f = new Function("abap", js);
    f(abap);
  });

Setting structures

In order to pass structures into a method (e. g. request of the serverless API), setting them is necessary.

    TYPES: BEGIN OF ty_http,
             headers TYPE ty_headers,
             body    TYPE string,
    END OF ty_http.

    METHODS:
      run
        IMPORTING
          method      TYPE string OPTIONAL
          path        TYPE string OPTIONAL
          query       TYPE string OPTIONAL
          request     TYPE ty_http OPTIONAL

Currently, the following transpiled code fails:

class zcl_handler {
  run(unique1) {
    ...
    let request = new abap.types.Structure({headers: new abap.types.Table(), body: new abap.types.String()});
    if (unique1 && unique1.request) {request.set(unique1.request);}
(node:19352) UnhandledPromiseRejectionWarning: TypeError: request.set is not a function

Which is understandable, since set is currently commented out

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.