Giter Site home page Giter Site logo

ts2c's Introduction

JavaScript/TypeScript to C transpiler

Produces readable C89 code from JS/TS code.

For example, this JavaScript:

console.log("Hello world!");

transpiles to the following C code:

#include <stdio.h>

int main() {
    printf("Hello world!\n");
    return 0;
}

No excessive code that is not actually needed is ever generated.

The output is as readable as possible and mostly maps well to the original code.

Another example:

var obj = { key: "hello" };
obj["newKey"] = "test";
console.log(obj);

transpiles to the following C code:

#include <stdlib.h>
#include <assert.h>
#include <stdio.h>

struct obj_t {
    const char * key;
    const char * newKey;
};

static struct obj_t * obj;
int main(void) {

    obj = malloc(sizeof(*obj));
    assert(obj != NULL);
    obj->key = "hello";
    obj->newKey = "test";

    printf("{ ");
    printf("key: \"%s\"", obj->key);
    printf(", ");
    printf("newKey: \"%s\"", obj->newKey);
    printf(" }\n");

    free(obj);

    return 0;
}

Project status

Work in progress: it works, but only about 70% of ES3 specification is currently supported: statements and expressions - 95%, built-in objects - 17%.

Notable NOT supported features include, for example: float and big numbers (all numbers are int16_t currently), eval, Date, Math, etc.

Detailed information about supported and planned features can be found in COVERAGE.md.

Contributions are welcome! See src/README.md

Live demo

You can try it out yourself online:

Rationale

The main motivation behind this project was to solve problem that IoT and wearables cannot be currently efficiently programmed with JavaScript.

The thing is, for sustainable IoT devices that can work for a long time on single battery, things like Raspberry Pi won't do. You'll have to use low-power microcontrollers, which usually have very little memory available.

RAM ranges literally from 512 bytes to 120KB, and ROM/Flash from 1KB to 4MB. In such conditions, even optimized JS interpreters like JerryScript, Espruino or V7 are sometimes too much of an overhead and usually lead to the increased battery drain and/or don't leave a lot of system resources to your program.

Of course, transpiler cannot map 100% of the JavaScript language and some things are have to be left out, notably eval. Still, current conclusion is, that it is possible to transpile most of the language.

Targets

Planned transpilation targets:

Usage

Command line:

npm install -g ts2c

Syntax:

ts2c <files to transpile>

Node.js:

npm install ts2c
const ts2c = require("ts2c");
const cCode = ts2c.transpile("console.log('Hello world!')");
console.log(cCode);

In browser:

<script src="https://unpkg.com/typescript"></script>
<script src="ts2c.bundle.js"></script>
<script>
    var cCode = ts2c.transpile("console.log('Hello world!')");
    alert(cCode);
</script>

ts2c's People

Contributors

andrei-markeev avatar atybot avatar dependabot[bot] avatar endel avatar georgy7 avatar hirse avatar npmcdn-to-unpkg-bot 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  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  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

ts2c's Issues

Support C++

It'd be nice if C++ support was also available. I was specifically thinking of supporting Arduino libraries from Typescript, and those are all C++. I was going to take a stab at it at first by replacing C templates and support code with C++ one, incrementally, see what falls out and then figure out how to merge the two.

But perhaps you have some idea of how the split would be best implemented, and I would then try and follow this path from the beginning.

Unable to compile 100 lines of code in 1 minute.

This is the beginning of an es6 file generated by tsc.

function LANG_ERROR() {
    throw "TheLanguage PANIC";
}
function LANG_ASSERT(x) {
    if (!x) {
        return LANG_ERROR();
    }
}
const atom_t = 0;
const construction_t = 1;
const null_t = 2;
const data_t = 3;
const error_t = 4;
const just_t = 5;
const delay_evaluate_t = 6;
const delay_builtin_func_t = 7;
const delay_builtin_form_t = 8;
const delay_apply_t = 9;
const comment_t = 11;
const hole_t = 10;
function new_comment(comment, x) {
    return [comment_t, comment, x];
}
function comment_p(x) {
    return x[0] === comment_t;
}
function comment_comment(x) {
    return x[1];
}
function comment_x(x) {
    return x[2];
}
function un_comment_all(x) {
    while (comment_p(x)) {
        x = comment_x(x);
    }
    return x;
}
function atom_p(x) {
    return x[0] === atom_t;
}
function new_atom(x) {
    return [atom_t, x];
}
function un_atom(x) {
    return x[1];
}
function atom_equal_p(x, y) {
    if (x === y) {
        return true;
    }
    if (un_atom(x) === un_atom(y)) {
        lang_assert_equal_set_do(x, y);
        return true;
    }
    else {
        return false;
    }
}
function new_construction(x, y) {
    return [construction_t, x, y];
}
function construction_p(x) {
    return x[0] === construction_t;
}
function construction_head(x) {
    return x[1];
}
function construction_tail(x) {
    return x[2];
}
const null_v = [null_t];
function null_p(x) {
    return x[0] === null_t;
}
function new_data(x, y) {
    return [data_t, x, y];
}
function data_p(x) {
    return x[0] === data_t;
}
function data_name(x) {
    return x[1];
}
function data_list(x) {
    return x[2];
}
function new_error(x, y) {
    return [error_t, x, y];
}
function error_p(x) {
    return x[0] === error_t;
}
function error_name(x) {
    return x[1];
}
function error_list(x) {
    return x[2];
}
function just_p(x) {
    return x[0] === just_t;
}

Header Files

Is is possible to use this to generate a header file from a typescript declaration file?

Three dots in an object in TypeScript

regex.ts:101, current revision (05d3ffe).

The line

tokens.push({ anyOf: true, tokens: [NOTHING, { ...last, oneOrMore: true }] });

leads to this JS code:

while (i < template.length) {
    var last = lastToken();
    if (template[i] == '^' && tokens.length == 0)
        tokens.push(FIXED_START);
    else if (template[i] == '$' && i == template.length - 1 || template.slice(i, i + 2) == '$)' || template.slice(i, i + 2) == '$|')
        tokens.push(FIXED_END);
    else if (template[i] == '\\')
        i++, tokens.push({ anyOf: true, tokens: this.parseEscaped(template[i]) });
    else if (template[i] == '.')
        tokens.push({ anyCharExcept: true, tokens: [] });
    else if (template[i] == '*') {
        tokens.pop();
        if (typeof last === "string")
            tokens.push({ anyOf: true, tokens: [NOTHING, { tokens: [last], oneOrMore: true }] });
        else
            tokens.push({ anyOf: true, tokens: [NOTHING, {}].concat(last, [oneOrMore, true]) });
    }
    ;
}
if (template[i] == '?')
    tokens.push({ anyOf: true, tokens: [NOTHING, tokens.pop()] });
else if (template[i] == '+')

So, the while loop ends unexpectedly.

Did you mean something like

tokens.push({ anyOf: true, tokens: [NOTHING, { tokens: last, oneOrMore: true }] });

?


node v6.10.3
npm v3.10.10
tsc 2.3.3

Transpilation failed. TypeError: Cannot read property 'length' of undefined

https://andrei-markeev.github.io/ts2c/

function h(){throw"TheLanguage PANIC";}function aa(a){return function(){return[!1,a]}}function ca(a){return function(){return[!0,a()]}}function da(a){for(a=a();a[0];)a=a[1]();return a[1]}function ea(a,b){return[10,a,b]}function q(a){return 10===a[0]}function fa(a){for(;q(a);)a=a[2];return a}function r(a){return 0===a[0]}function u(a,b){return a===b?!0:a[1]===b[1]?(v(a,b),!0):!1}function ha(a,b){return[1,a,b]}function w(a){return 1===a[0]}function ia(a){return a[1]}function ja(a){return a[2]}
function x(a){return 2===a[0]}function ka(a,b){return[3,a,b]}function z(a){return 3===a[0]}function la(a){return a[1]}function ma(a){return a[2]}function na(a){return 4===a[0]}function oa(a){return a[2]}function A(a,b){return[6,a,b]}function pa(a,b){return[8,a,b]}function qa(a){a=B(a);if(z(a)||w(a)||q(a))a[1]=qa(a[1]),a[2]=qa(a[2]);return a}
function ra(a){var b=ua(a);if(z(b)||w(b))if(b[1]=qa(b[1]),b[2]=qa(b[2]),q(b[1])||q(b[2])){a=[9];va(a,b);var c=b[2];b=ra(b[1]);c=ra(c);a[1]=b;a[2]=c}else a=b;else a=b;return a}function v(a,b){a!==b&&(a===C&&(a=b,b=C),a[0]=4,a[1]=b,a[2]=!1,a[3]=!1)}function va(a,b){9===a[0]||h();9!==b[0]||h();a[0]=b[0];a[1]=b[1];a[2]=b[2];a[3]=b[3]}function wa(a){return[3,xa,[1,D,[1,a,C]]]}function F(a){for(var b=C,c=a.length-1;0<=c;c--)b=[1,a[c],b];return b}
function ya(a,b,c){for(var d=[];w(a);)d.push(a[1]),a=a[2];return x(a)?b(d):c(d,a)}function G(a){return ya(a,function(b){return b},function(){return!1})}function H(){for(var a=[],b=0;b<arguments.length;b++)a[b]=arguments[b];return F(a)}function I(a){if(!na(a))return a;for(var b=[];na(a);)b.push(a),a=a[1];for(var c=0;c<b.length;c++)v(b[c],a);return a}function za(a){return 5===a[0]||7===a[0]||6===a[0]||8===a[0]}function J(a){return na(a)||za(a)}function Aa(a){return J(a)||q(a)}
function Ba(a){if(5===a[0])return a;if(7===a[0])throw"WIP";if(6===a[0])throw"WIP";if(8===a[0])throw"WIP";return h()}
function B(a,b,c,d){function f(M){v(n,M);for(var E=0;E<d.length;E++)v(d[E],M);return M}function l(){c[1]=!0;return g(Ca)}function g(M){f(M);return J(M)?(d.push(n),B(M,b,[!1,!1],d)):M}function k(){var M={},E;for(E in m)M[E]=!0;for(E in b)M[E]=!0;return M}void 0===b&&(b={});void 0===c&&(c=[!1,!1]);void 0===d&&(d=[]);var m={},n=a;for(a=0;J(n)&&32>a;a++)d.push(n),n=N(n);for(;J(n);){a=O(n);if(!0===b[a])return l();if(!0===m[a]){c[0]=!0;if(5===n[0])return l();if(6===n[0]){a=n[1];for(var y=n[2],K=!1,S=0,
ba=[Da,Ea,Fa,Ga,Ha,Ia,Ja,Ka];S<ba.length;S++)if(P(ba[S],a)){K=!0;break}if(K)return 1===y.length||h(),!1===c[1]||h(),y=B(y[0],k(),c),c[1]?g(A(a,[y])):h();if(P(a,La)||P(a,Ma)||P(a,Na))return l();if(P(a,Oa)&&(3===y.length||h(),!1===c[1]||h(),a=B(y[0],k(),c),c[1]))return g(A(Oa,[a,y[1],y[2]]))}else if(7===n[0]||8===n[0])return l();return h()}m[a]=!0;d.push(n);n=N(n)}return f(n)}
function N(a){var b=I(a);!na(b)||h();a=5===b[0]?Pa(b[1],b[2],a):7===b[0]?Qa(b[1],b[2],b[3]):6===b[0]?Ra(b[1],b[2],a):8===b[0]?Sa(b[1],b[2],a):b;a=I(a);v(b,a);return a}function ua(a){for(;J(a)||q(a);)a=B(fa(a));return a}function Ta(a){for(;q(a);)a=a[2];for(a=N(a);q(a);)a=a[2];return a}function Ua(a,b,c,d){var f=[],l=[];a=I(a);for(var g=!0;;){if(x(a))return d(l,f);if(q(a))l.push(a[1]),a=a[2];else if(w(a))f.push(a[1]),a=a[2];else if(J(a))if(g)g=!1,a=N(a);else return c();else return b()}}
function Va(a){Aa(a)&&(a=Ta(a));if(Aa(a))return null;if(r(a))return!0;if(!z(a))return!1;a=a[1];Aa(a)&&(a=Ta(a));return Aa(a)?null:r(a)?u(a,Q):!1}function Wa(a,b,c){for(var d=[],f=0;f<a.length;f+=2){if(P(a[f],b)){d[f]=b;d[f+1]=c;for(f+=2;f<a.length;f+=2)d[f]=a[f],d[f+1]=a[f+1];return d}d[f]=a[f];d[f+1]=a[f+1]}d[a.length]=b;d[a.length+1]=c;return d}function Xa(a,b,c){for(var d=0;d<a.length;d+=2)if(P(a[d],b))return a[d+1];return c}
function Ya(a,b){for(var c=0;c<a.length;c+=2)if(P(a[c],b))return a[c+1];return h()}function R(a){for(var b=C,c=0;c<a.length;c+=2)b=[1,H(a[c],a[c+1]),b];return[3,Za,H(b)]}function fb(a,b){for(var c=0;c<a.length;c+=2)b(a[c],a[c+1])}
function gb(a){a=B(a);if(!z(a))return!1;var b=B(a[1]);if(!r(b)||!u(b,Za))return!1;b=B(a[2]);if(!w(b)||!x(B(b[2])))return!1;a=[];for(b=B(b[1]);!x(b);){if(!w(b))return!1;var c=B(b[1]);b=B(b[2]);if(!w(c))return!1;var d=c[1];c=B(c[2]);if(!w(c))return!1;var f=c[1];if(!x(B(c[2])))return!1;c=!0;for(var l=0;l<a.length;l+=2)if(P(a[l],d)){a[l+1]=f;c=!1;break}c&&a.push(d,f)}return a}
function Pa(a,b,c){function d(){return wa(H(hb,H(Na,H(R(a),f))))}var f=N(b);if(J(f))return c;if(w(f))return Ua(f,d,function(){return c},function(l,g){if(0!==l.length)throw"WIP";if(P(g[0],ib)){if(1===g.length)return d();for(var k=g[1],m=[],n=2;n<g.length;n++)m.push(g[n]);return[7,a,k,m]}if(P(g[0],jb)){if(1===g.length)return d();k=B([5,a,g[1]]);if(!z(k))return d();m=N(k[1]);if(J(m))return c;if(!r(m)||!u(m,T))return d();m=N(k[2]);if(J(m))return c;if(!w(m))return d();k=m[1];m=N(m[2]);if(J(m))return c;
if(!x(m))return d();m=[R(a)];for(n=2;n<g.length;n++)m.push(g[n]);return[8,k,m]}if(P(g[0],hb)){if(1===g.length)return d();k=g[1];m=[];for(n=2;n<g.length;n++)m.push([5,a,g[n]]);return[6,k,m]}k=[5,a,g[0]];m=[];for(n=1;n<g.length;n++)m.push([5,a,g[n]]);return[8,k,m]});if(x(f))return f;b=Va(f);return null===b?c:!0===b?Xa(a,f,d()):d()}
function Sa(a,b,c){function d(){return wa(H(hb,H(Ma,H(a,F(b)))))}a=N(a);if(J(a))return c;if(!z(a))return d();var f=B(a[1]);if(!r(f)||!u(f,U))return d();var l=B(a[2]);if(!w(l))return d();f=qa(l[1]);l=B(l[2]);if(!w(l)||!x(B(l[2])))return d();l=l[1];for(var g=kb,k=0;!x(f);){var m=Va(f);if(null===m)return c;if(!0===m){m=C;for(var n=b.length-1;n>=k;n--)m=[1,b[n],m];g=Wa(g,f,m);k=b.length;f=C}else if(w(f))if(k<b.length)m=b[k],k++,g=Wa(g,f[1],m),f=f[2];else return d();else return d()}return b.length!==k?
d():[5,g,l]}function Ra(a,b,c){function d(){return wa(H(hb,H(a,F(b))))}for(var f=0;f<lb.length;f++){var l=lb[f];if(P(a,l[0])){if(b.length!==l[1])break;return 1===l[1]?l[2](b[0],d,c):2===l[1]?l[2](b[0],b[1],d,c):3===l[1]?l[2](b[0],b[1],b[2],d,c):h()}}return d()}function Qa(a,b,c){function d(){return wa(H(ib,H(R(a),b,F(c))))}return P(b,mb)?1!==c.length?d():c[0]:P(b,nb)?2!==c.length?d():ob(a,c[0],c[1],d):P(b,pb)?2!==c.length?d():[10,c[0],[5,a,c[1]]]:d()}
function ob(a,b,c,d){b=ra(b);for(var f=[],l=!1,g=b;!x(g);){var k=Va(g);null!==k||h();if(k)f.push(g),l=!0,g=C;else if(w(g))f.push(g[1]),g=g[2];else return d()}g=l?F(f):b;var m=[];fb(a,function(n){for(var y=0;y<f.length;y++)if(P(f[y],n))return;m.push(n)});d=g;for(l=m.length-1;0<=l;l--)d=[1,m[l],d];for(l=m.length-1;0<=l;l--)g=ha(H(ib,mb,Ya(a,m[l])),g);return[3,U,H(b,[1,H(ib,mb,[3,U,H(d,c)]),g])]}
function qb(a,b){function c(f,l,g,k){g=qb(g(f),g(l));k=qb(k(f),k(l));return!0===g&&!0===k?(v(f,l),!0):!1!==g&&!1!==k?null:!1}if(a===b)return!0;a=B(a);b=B(b);if(a===b)return!0;if(q(a)){var d=qb(fa(a),b);!0===d&&(d=null);return d}if(q(b))return d=qb(a,fa(b)),!0===d&&(d=null),d;if(x(a)){if(!x(b))return!1;v(a,b);return!0}return r(a)?r(b)?u(a,b):!1:w(a)?w(b)?c(a,b,ia,ja):!1:z(a)?z(b)?c(a,b,la,ma):!1:h()}function P(a,b){return!1!==qb(a,b)}
function V(a,b){function c(d,f,l,g){return V(l(d),l(f))&&V(g(d),g(f))?(v(d,f),!0):!1}if(a===b)return!0;a=I(a);b=I(b);if(a===b)return!0;if(x(a)){if(!x(b))return!1;v(a,C);v(b,C);return!0}return r(a)?r(b)?u(a,b):!1:w(a)?w(b)?c(a,b,ia,ja):!1:z(a)?z(b)?c(a,b,la,ma):!1:za(a)?!1:h()}
function O(a){a=I(a);var b;if(x(a))return"()";if(w(a)){var c="(";for(b="";w(a);)c+=b+O(a[1]),b=" ",a=I(a[2]);return x(a)?c+")":c+(" . "+O(a)+")")}return z(a)?"#"+O([1,a[1],a[2]]):r(a)?a[1]:q(a)?";("+O(a[1])+" "+O(a[2])+")":5===a[0]?"$("+O(R(a[1]))+" "+O(a[2])+")":6===a[0]?"%("+O(a[1])+" "+O(F(a[2]))+")":7===a[0]?"@("+O(R(a[1]))+" "+O(a[2])+" "+O(F(a[3]))+")":8===a[0]?"^("+O(a[1])+" "+O(F(a[2]))+")":h()}
function tb(a){function b(){return $a.length===sa}function c(){!b()||h();var e=$a[sa];sa++;return e}function d(e){$a[sa-1]===e||h();sa--}function f(e){void 0===e&&(e="");throw"TheLanguage parse ERROR!"+e;}function l(e){return" "===e||"\n"===e||"\t"===e||"\r"===e}function g(){if(b())return!1;var e=c();if(!l(e))return d(e),!1;for(;l(e)&&!b();)e=c();l(e)||d(e);return!0}function k(){if(b())return!1;var e=c(),p="";if(!K(e))return d(e),!1;for(;K(e)&&!b();)p+=e,e=c();K(e)?p+=e:d(e);return[0,p]}function m(){if(b())return!1;
var e=c();if("("!==e)return d(e),!1;for(var p=[9],t=p;;){g();if(b())return f();e=c();if(")"===e)return va(p,C),t;if("."===e){g();e=S();va(p,e);g();if(b())return f();e=c();return")"!==e?f():t}d(e);e=S();var L=[9];va(p,[1,e,L]);p=L}}function n(){if(b())return!1;var e=c();if("#"!==e)return d(e),!1;e=m();return!1!==e&&w(e)?[3,e[1],e[2]]:f()}function y(e,p){return function(){if(b())return!1;var t=c();if(t!==e)return d(t),!1;t=m();if(!1===t||!w(t))return f();var L=t[2];return w(L)&&x(L[2])?p(t[1],L[1]):
f()}}function K(e){if(l(e))return!1;for(var p=0,t="()!#.$%^@~/->_:?[]&;".split("");p<t.length;p++)if(t[p]===e)return!1;return!0}function S(){g();for(var e=0,p=[m,Mb,n,ab,bb,cb,db,eb];e<p.length;e++){var t=(0,p[e])();if(!1!==t)return t}return f()}function ba(e){return!1===e?f():e}function M(e){ba(!b());ba(c()===e)}function E(e){function p(){M("[");var ta=E();M("]");return ta}void 0===e&&(e=!1);var t=0;for(e=e?[m,k,p,n,ab,bb,cb,db,eb]:[m,rb,n,ab,bb,cb,db,eb];t<e.length;t++){var L=(0,e[t])();if(!1!==
L)return L}return f()}function sb(e){if(b())return e;var p=c();if("."===p)return p=E(),H(W,H(U,H(e),X),p);if(":"===p)return p=E(),H(W,p,e);if("~"===p)return H(Y,e);if("@"===p)return p=E(),H(W,H(U,[1,e,X],X),p);if("?"===p)return H(W,U,H(Y,e));if("/"===p){for(e=[e];;){p=E(!0);e.push(p);if(b())break;p=c();if("/"!==p){d(p);break}}return H(ub,F(e))}d(p);return e}function rb(){if(b())return!1;var e=c();if("&"===e){ba(!b());e=c();if("+"===e)return e=E(),H(T,H(D,e));d(e);e=E();return H(T,e)}if(":"===e){ba(!b());
e=c();if("&"===e)return M(">"),e=E(),H(W,H(T,H(U,X,e)),vb);if(">"===e)return e=E(),H(W,H(U,X,e),vb);d(e);e=E();return H(W,e,vb)}if("+"===e)return e=E(),H(D,e);if("["===e)return e=E(),M("]"),sb(e);if("_"===e)return M(":"),e=E(),H(W,e,X);d(e);e=k();return!1===e?!1:sb(e)}function Mb(){var e=rb();return!1===e?!1:r(e)?e:[3,Q,[1,D,[1,e,C]]]}var $a=a,sa=0,ab=y("$",function(e,p){var t=gb(e);return!1===t?f():[5,t,p]}),bb=y("%",function(e,p){var t=ya(p,function(L){return L},function(){return f()});return[6,
e,t]}),cb=function(e,p){return function(){if(b())return!1;var t=c();if(t!==e)return d(t),!1;t=m();if(!1===t||!w(t))return f();var L=t[2];if(!w(L))return f();var ta=L[2];return w(ta)&&x(ta[2])?p(t[1],L[1],ta[1]):f()}}("@",function(e,p,t){t=ya(t,function(L){return L},function(){return f()});e=gb(e);return!1===e?f():[7,e,p,t]}),db=y("^",function(e,p){var t=ya(p,function(L){return L},function(){return f()});return[8,e,t]}),eb=y(";",function(e,p){return[10,e,p]});return S()}
function Z(a){function b(f,l){function g(K){return l?"["+K+"]":K}if(r(f))return f[1];var k=G(f);if(!1!==k&&3===k.length&&V(k[0],W)){var m=G(k[1]);if(!1!==m&&3===m.length&&V(m[0],U)){var n=m[1],y=G(n);if(!1!==y&&1===y.length&&V(m[2],X))return g(b(y[0],!0)+"."+b(k[2],!0));if(w(n)&&V(n[2],X)&&V(m[2],X))return g(b(n[1],!0)+"@"+b(k[2],!0));if(V(n,X)&&V(k[2],vb))return g(":>"+b(m[2],!0))}n=G(k[2]);if(V(k[1],U)&&!1!==n&&2===n.length&&V(n[0],Y))return g(b(n[1],!0)+"?");if(!1!==m&&2===m.length&&V(k[2],vb)&&
V(m[0],T)&&(m=G(m[1]),!1!==m&&3===m.length&&V(m[0],U)&&V(m[1],X)))return g(":&>"+b(m[2],!0));m=void 0;m=V(k[2],X)?"_":V(k[2],vb)?"":b(k[2],!0);return g(m+":"+b(k[1],!0))}if(!1!==k&&2===k.length){if(V(k[0],T))return m=G(k[1]),!1!==m&&2===m.length&&V(m[0],D)?g("&+"+b(m[1],!0)):g("&"+b(k[1],!0));if(V(k[0],Y))return g(b(k[1],!0)+"~");if(V(k[0],D))return g("+"+b(k[1],!0));if(V(k[0],ub)&&(k=G(k[1]),!1!==k&&1<k.length)){m=b(k[0],!0);for(n=1;n<k.length;n++)m+="/"+b(k[n],!0);return g(m)}}return l?O(f):O([3,
Q,[1,D,[1,f,C]]])}a=tb(O(a));var c="",d="";if(x(a))return"()";if(w(a)){c="(";for(d="";w(a);)c+=d+Z(a[1]),d=" ",a=a[2];return c=x(a)?c+")":c+(" . "+Z(a)+")")}return z(a)?(c=a[1],a=a[2],d=G(a),!1!==d&&2===d.length&&V(c,Q)&&V(d[0],D)?b(d[1],!1):"#"+Z([1,c,a])):r(a)?a[1]:q(a)?";("+Z(a[1])+" "+Z(a[2])+")":5===a[0]?"$("+Z(R(a[1]))+" "+Z(a[2])+")":6===a[0]?"%("+Z(a[1])+" "+Z(F(a[2]))+")":7===a[0]?"@("+Z(R(a[1]))+" "+Z(a[2])+" "+Z(F(a[3]))+")":8===a[0]?"^("+Z(a[1])+" "+Z(F(a[2]))+")":h()}
function wb(a,b,c,d,f){void 0===f&&(f=!1);c=B(c);if(z(c)){var l=c[1],g=c[2];if(P(l,xb)){if(g=B(g),w(g)&&(l=g[1],g=B(g[2]),x(g))){if(!1===f){var k=l;l=function(){return a(k,d)}}else{var m=l;l=function(){return wb(a,b,[8,f,m],d)}}return ca(l)}}else if(P(l,yb)&&(g=B(g),w(g)&&(l=g[1],g=B(g[2]),w(g)))){var n=g[1];g=B(g[2]);if(x(g)){if(!1===f){var y=l;l=function(){return wb(a,b,y,d,n)}}else l=function(){throw"WIP";};return ca(l)}}}return!1===f?ca(function(){return b(c,d,a)}):ca(function(){return b(c,d,
function(K,S){return ca(function(){return wb(a,b,pa(f,[K]),S)})})})}function zb(a,b,c){c=N(c);return J(c)?A(a,[c]):b(c)?Ab:Bb}function Cb(a,b,c,d,f){d=N(d);return J(d)?A(a,[d]):b(d)?c(d):f()}
var C=[2],xa=[0,"\u8b2c\u8aa4"],D=[0,"\u592a\u59cb\u521d\u6838"],X=[0,"\u7701\u7565\u4e00\u7269"],Ca=[3,xa,[1,D,[1,[1,[0,"\u5b87\u5b99\u4ea1\u77e3"],[1,X,C]],C]]],Q=[0,"\u7b26\u540d"],T=[0,"\u5f0f\u5f62"],U=[0,"\u5316\u6ec5"],hb=[3,Q,[1,D,[1,[1,T,[1,[1,D,[1,U,C]],C]],C]]],W=[0,"\u4e00\u985e\u4f55\u7269"],Na=[3,Q,[1,D,[1,[1,W,[1,U,[1,[0,"\u89e3\u7b97"],C]]],C]]],Za=[0,"\u6620\u8868"],ib=[3,Q,[1,D,[1,[1,T,[1,[1,D,[1,T,C]],C]],C]]],jb=[3,Q,[1,D,[1,[1,T,[1,T,C]],C]]],mb=[3,Q,[1,D,[1,[1,W,[1,T,[1,[0,"\u5f15\u7528"],
C]]],C]]],vb=[0,"\u7279\u5b9a\u5176\u7269"],nb=[3,Q,[1,D,[1,[1,W,[1,[1,T,[1,[1,U,[1,X,[1,U,C]]],C]],[1,vb,C]]],C]]],Db=[0,"\u8a3b\u758f"],pb=[3,Q,[1,D,[1,[1,W,[1,T,[1,Db,C]]],C]]],Y=[0,"\u662f\u975e"],Eb=[0,"\u69cb\u7269"],Fa=[3,Q,[1,D,[1,[1,W,[1,U,[1,[1,Y,[1,[1,W,[1,Eb,[1,X,C]]],C]],C]]],C]]],Fb=[0,"\u723b\u967d"],Ab=[3,Fb,C],Gb=[0,"\u723b\u9670"],Bb=[3,Gb,C],Da=[3,Q,[1,D,[1,[1,W,[1,[1,U,[1,[1,Eb,C],[1,X,C]]],[1,Q,C]]],C]]],Hb=[0,"\u5217\u5e8f"],Ea=[3,Q,[1,D,[1,[1,W,[1,[1,U,[1,[1,Eb,C],[1,X,C]]],
[1,Hb,C]]],C]]],Ka=[3,Q,[1,D,[1,[1,W,[1,U,[1,[1,Y,[1,[1,W,[1,[0,"\u9593\u7a7a"],[1,X,C]]],C]],C]]],C]]],Ib=[0,"\u9023\u9838"],Ga=[3,Q,[1,D,[1,[1,W,[1,U,[1,[1,Y,[1,[1,W,[1,Ib,[1,X,C]]],C]],C]]],C]]],Ha=[3,Q,[1,D,[1,[1,W,[1,[1,U,[1,[1,Ib,C],[1,X,C]]],[1,[0,"\u9996\u59cb"],C]]],C]]],Ia=[3,Q,[1,D,[1,[1,W,[1,[1,U,[1,[1,Ib,C],[1,X,C]]],[1,[0,"\u5c3e\u672b"],C]]],C]]],La=[3,Q,[1,D,[1,[1,W,[1,U,[1,[1,Y,[1,[0,"\u7b49\u540c"],C]],C]]],C]]],Oa=[3,Q,[1,D,[1,[1,W,[1,U,[1,[0,"\u5982\u82e5"],C]]],C]]],Ma=[3,Q,[1,
D,[1,[1,W,[1,[1,U,[1,[1,U,X],[1,X,C]]],[1,[0,"\u61c9\u7528"],C]]],C]]],Ja=[3,Q,[1,D,[1,[1,W,[1,U,[1,[1,Y,[1,[1,W,[1,[0,"\u8a5e\u7d20"],[1,X,C]]],C]],C]]],C]]],Jb=[0,"\u4e4b\u7269"],Kb=[3,Q,[1,D,[1,[1,W,[1,[1,U,[1,[1,Hb,C],[1,X,C]]],[1,[1,W,[1,Jb,[1,X,C]]],C]]],C]]],lb=[[Fa,1,function(a){return zb.call(this,Fa,z,a)}],[[3,Q,[1,D,[1,[1,W,[1,[1,U,[1,X,[1,Eb,C]]],[1,vb,C]]],C]]],2,ka],[Da,1,function(a,b){return Cb.call(this,Da,z,la,a,b)}],[Ea,1,function(a,b){return Cb.call(this,Ea,z,ma,a,b)}],[Ka,1,function(a){return zb.call(this,
Ka,x,a)}],[[3,Q,[1,D,[1,[1,W,[1,[1,U,[1,X,[1,Ib,C]]],[1,vb,C]]],C]]],2,ha],[Ga,1,function(a){return zb.call(this,Ga,w,a)}],[Ha,1,function(a,b){return Cb.call(this,Ha,w,ia,a,b)}],[Ia,1,function(a,b){return Cb.call(this,Ia,w,ja,a,b)}],[La,2,function(a,b){function c(d,f,l,g){l=A(La,[l(d),l(f)]);d=A(La,[g(d),g(f)]);return A(Oa,[l,d,Bb])}if(a===b)return Ab;a=N(a);b=N(b);if(J(a)||J(b))return A(La,[a,b]);if(a===b)return Ab;!J(a)||h();return x(a)?x(a)?Ab:Bb:r(a)?r(b)?u(a,b)?Ab:Bb:Bb:z(a)?z(b)?c(a,b,la,ma):
Bb:w(a)?w(b)?c(a,b,ia,ja):Bb:h()}],[Ma,2,function(a,b,c){var d=[];for(b=B(b);w(b);)d.push(b[1]),b=B(b[2]);return x(b)?[8,a,d]:c()}],[Na,2,function(a,b,c){a=gb(a);return!1===a?c():[5,a,b]}],[Ja,1,function(a){return zb.call(this,Ja,r,a)}],[Kb,1,function(a,b){a=N(a);return J(a)?A(Kb,[a]):w(a)?a[1]:b()}],[Oa,3,function(a,b,c,d){a=N(a);if(J(a))return A(Oa,[a,b,c]);if(!z(a))return d();a=B(a[1]);return r(a)?u(a,Fb)?b:u(a,Gb)?c:d():d()}],[[3,Q,[1,D,[1,[1,W,[1,U,[1,Db,C]]],C]]],2,ea]],kb=[],ub=[0,"\u5176\u5b50"],
Lb=[0,"\u6548\u61c9"],xb=[3,Q,[1,D,[1,[1,ub,[1,[1,Lb,[1,[1,W,[1,Jb,[1,X,C]]],C]],C]],C]]],yb=[3,Q,[1,D,[1,[1,ub,[1,[1,Lb,[1,Ib,C]],C]],C]]];
module.exports={trampoline_return:aa,trampoline_delay:ca,run_trampoline:da,new_comment:ea,comment_p:q,comment_comment:function(a){return a[1]},comment_x:function(a){return a[2]},un_comment_all:fa,atom_p:r,new_atom:function(a){return[0,a]},un_atom:function(a){return a[1]},atom_equal_p:u,new_construction:ha,construction_p:w,construction_head:ia,construction_tail:ja,null_v:C,null_p:x,new_data:ka,data_p:z,data_name:la,data_list:ma,just_p:na,evaluate:function(a,b){return[5,a,b]},apply:pa,force_all_rec:qa,
force_uncomment_all_rec:ra,unlazy_all_rec:ra,jsArray_to_list:F,maybe_list_to_jsArray:G,new_list:H,un_just_all:I,un_just_comment_all:function(a){for(;na(a)||q(a);)a=I(fa(a));return a},delay_p:za,delay_just_p:J,lazy_p:Aa,delay_env:function(a){return Ba(a)[1]},delay_x:function(a){return Ba(a)[2]},force1:N,force_all:function(a){return B(a)},force_uncomment_all:ua,force_uncomment1:function(a){return q(a)?a[2]:N(a)},unlazy1:Ta,env_null_v:kb,env_set:Wa,env_get:Xa,env2val:R,env_foreach:fb,val2env:gb,equal_p:P,
simple_print:O,complex_parse:tb,complex_print:Z,machinetext_parse:function(a){function b(n){void 0===n&&(n="");throw"MT parse ERROR "+n;}function c(n){if(!n)return b()}function d(){c(0!==l);l--;return a[l]}function f(n){var y=g.pop(),K=g.pop();return void 0===K||void 0===y?b():g.unshift(n(K,y))}for(var l=a.length,g=[];0!==l;){var k=d();if("^"===k){for(k="";;){var m=d();if("^"===m)break;k=m+k}g.unshift([0,k])}else if("."===k)f(ha);else if("#"===k)f(ka);else if("$"===k)f(function(n,y){var K=gb(n);return!1===
K?b():[5,K,y]});else if("_"===k)g.unshift(C);else return b()}c(0===l);c(1===g.length);return g[0]},machinetext_print:function(a){function b(){for(var f=[],l=0,g=c;l<g.length;l++){var k=g[l];k=I(k);var m=function(n,y,K,S){d+=y;return f.push(K(n),S(n))};if(r(k))d+="^"+k[1]+"^";else if(w(k))m(k,".",ia,ja);else if(x(k))d+="_";else if(z(k))m(k,"#",la,ma);else if(za(k))k=Ba(k),m(k,"$",function(n){return R(n[1])},oa);else return{value:h()}}c=f}for(var c=[a],d="";0!==c.length;)if(a=b(),"object"===typeof a)return a.value;
return d},return_effect_systemName:xb,bind_effect_systemName:yb,new_effect_bind:function(a,b){return[3,yb,H(a,b)]},new_effect_return:function(a){return[3,xb,a]},run_monad_trampoline:function(a,b,c,d){return wb(a,b,c,d)},run_monad_stackoverflow:function(a,b,c,d){return da(wb(function(f,l){return aa(a(f,l))},function(f,l,g){return aa(b(f,l,function(k,m){return da(g(k,m))}))},c,d))}};

145 WARNING: unexpected binary expression! ts2c.bundle.js:6142
Uncaught TypeError: Cannot read property 'length' of undefined
    at ts2c.bundle.js:6459
    at Array.forEach (<anonymous>)
    at Object.getType (ts2c.bundle.js:6451)
    at TypeHelper.resolveTypes (ts2c.bundle.js:6536)
    at TypeHelper.inferTypes (ts2c.bundle.js:6515)
    at newConstructor.CProgram (ts2c.bundle.js:2713)
    at new newConstructor (ts2c.bundle.js:5608)
    at Object.transpile (ts2c.bundle.js:6805)
    at transpile ((index):54)
    at HTMLButtonElement.onclick ((index):28)

ES6 module

function id(x){
  return x;
}
export {id};
void id(void x)
{
    return x;

}

int main(void) {
    /* Unsupported node: export {id}; */;

    return 0;
}

Allow programmatic use

This is a great project.

I am trying to use this in a project of mine, but I would like to use ts2c programmatically from node:

var ts2c = require('ts2c');

var jsCode = 'console.log("Hello world!");';
var cCode = ts2c.transpile(jsCode);

console.log(cCode);

However, that is currently not possible as an import (require('ts2c')) already tries to transpile files passed as arguments and makes the whole program fail.

Performance

Hey, this seems really interesting!
I just tested the performance of https://github.com/andrei-markeev/ts2c/blob/master/tests/realworld/gray.ts with 1000000 itterations. But C doesn't come out nicely:

  • JavaScript: 110ms
  • c: 777ms

Do you think there are some major performance improvements possible? (for example setting the array capacity reduces the c version to 480ms)
Or will wil this method inherently be slower than running in an interpreter?

`as`

var a=("a" as any) as string;
static const char * a;
int main(void) {
    a = /* Unsupported node: ("a" as any) as string */;
     ;

    return 0;
}

Can not compile class

I try some code in playground, and I get a Error when I try to write class.

// code:
function A() {
  this.a = 2
}

A.prototype.change = function () {
  this.a = 3
}

and I got the Error:

Transpilation failed. TypeError: Cannot read property 'length' of undefined

This project is cool ~

type alias

type st=string;
var s: st = "Hello world!";
console.log(s);
#include <stdio.h>
static const char * s;
int main(void) {
    /* Unsupported node: type st=string; */;
    s = "Hello world!";
    printf("%s\n", s);

    return 0;
}

var a=function(){var x=0;return (function(){return x;})};

var a=function(){var x=0;return (function(){return x;})};
a()();
typedef short int16_t;

struct a_func_t {
    int16_t (*func)(struct a_func_t *);
    int16_t x;
};

static struct a_func_t * (*a)();
int16_t func(int16_t x)
{
    return x;

}
struct a_func_t * a_func()
{
    int16_t x;
    x = 0;
    return (func);

}

int main(void) {
    a = a_func;
    a()(x);

    return 0;
}

Type definitions are sometimes omitted

I recently found another bug in the compiler. I wrote a small program that converts two strings into numbers and prints their sum:

console.log(parseInt("3")+parseInt("4"));

When I compile this program using the online editor, the generated code doesn't define the int16_t type:

#include <stdio.h>
int16_t parse_int16_t(const char * str) {
    int r;
    sscanf(str, "%d", &r);
    return (int16_t) r;
}
int main(void) {
    printf("%d\n", parse_int16_t("3") + parse_int16_t("4"));

    return 0;
}

Inner functions' variables are freed

Having the following js:

function foo() {
    var s = "a";
    function bar(a) {
        s += " hello " + a;
    }
    bar(5);
    return s;
}
console.log(foo());

The expected result is of course a hello 5. However, when checking the c code:

...
void bar(int16_t a, const char ** s)
{
    char * tmp_result_2 = NULL;
    char * tmp_result = NULL;
    tmp_result_2 = malloc(strlen(" hello ") + STR_INT16_T_BUFLEN + 1);
    assert(tmp_result_2 != NULL);
    tmp_result_2[0] = '\0';
    strcat(tmp_result_2, " hello ");
    str_int16_t_cat(tmp_result_2, a);
    tmp_result = malloc(strlen(*s) + strlen(tmp_result_2) + 1);
    assert(tmp_result != NULL);
    tmp_result[0] = '\0';
    strcat(tmp_result, *s);
    strcat(tmp_result, tmp_result_2);
    (*s = tmp_result);
    free((char *)tmp_result); // <===== This should not be freed here!!!
    free((char *)tmp_result_2);
}
const char * foo()
{
    const char * s;
    s = "a";
    bar(5, &s);
    return s;
}
...

Function type / global function as value

var exports={}
function id(x){
  return x
}
exports.id=id
exports.k=0
console.log(id(exports.k))
console.log(exports.id("k"))
console.log(exports.id(-1))
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
typedef int int16_t;

struct struct_0_t {
    int16_t id;
    int16_t k;
};

static struct struct_0_t * exports;
int16_t id(int16_t x)
{
    return x;

}

int main(void) {
    exports = malloc(sizeof(*exports));
    assert(exports != NULL);
    exports->id = id;
    exports->k = 0;
    printf("%d\n", id(exports->k));
    printf(/* Unsupported printf expression */);
    printf(/* Unsupported printf expression */);
    free(exports);

    return 0;
}

Destructuring function arguments result in TypeError

This works:

function multiplyByTwo(arg){
  return 2 * arg;
}

This does not work:

function multiplyByTwo({ arg }){
  return 2 * arg;
}

I get the following error:

Transpilation failed. TypeError: Cannot read property 'name' of undefined

With this error in the console:

Uncaught TypeError: Cannot read property 'name' of undefined
    at TypeHelper.generateStructure (ts2c.bundle.js:6618)
    at TypeHelper.convertType (ts2c.bundle.js:6601)
    at TypeHelper.getCType (ts2c.bundle.js:6245)
    at ts2c.bundle.js:6519
    at Array.forEach (<anonymous>)
    at TypeHelper.resolveTypes (ts2c.bundle.js:6519)
    at TypeHelper.inferTypes (ts2c.bundle.js:6515)
    at newConstructor.CProgram (ts2c.bundle.js:2713)
    at new newConstructor (ts2c.bundle.js:5608)
    at Object.transpile (ts2c.bundle.js:6805)

It's not important to me that destructuring arguments work, but I couldn't find any info about it in COVERAGE.md. It would save some time debugging if it was added to the coverage document.

Support for throw/catch/errors

First: Amazing project would like to contribute in any way possible.

Now onto the real issue, why the support for runtime errors(throw, catch, and the Error constructor) isn't planned on being supported?

IIFE conversion?

let name = () => {
    declarations;
    return rvalue;
}()

to

type name;
{
    declarations;
    name = rvalue;
}

Function parameter - union types

var exports={}
function id(x){
  return x
}
id(0)
id("a")
#include <stdlib.h>
#include <assert.h>
typedef int int16_t;
static struct struct_0_t * exports;
int16_t id(int16_t x)
{
    return x;

}

int main(void) {
    exports = malloc(sizeof(*exports));
    assert(exports != NULL);
    id(0);
    id("a");
    free(exports);

    return 0;
}

ts2c/src/types.js:625

https://gitlab.com/the-language/the-language/blob/dab7bd014e15d4f06e09fae039679a96a34945e9/core/pure/typescript/lang.ts

$ ts2c lang.ts
/home/zaoqi/.config/yarn/global/node_modules/ts2c/src/types.js:625
            var propType = this.convertType(propTsType, declaration.name) || exports.PointerVarType;
                                                                    ^

TypeError: Cannot read property 'name' of undefined
    at TypeHelper.generateStructure (/home/zaoqi/.config/yarn/global/node_modules/ts2c/src/types.js:625:69)
    at TypeHelper.convertType (/home/zaoqi/.config/yarn/global/node_modules/ts2c/src/types.js:608:35)
    at TypeHelper.getCType (/home/zaoqi/.config/yarn/global/node_modules/ts2c/src/types.js:257:39)
    at /home/zaoqi/.config/yarn/global/node_modules/ts2c/src/types.js:526:80
    at Array.forEach (<anonymous>)
    at TypeHelper.resolveTypes (/home/zaoqi/.config/yarn/global/node_modules/ts2c/src/types.js:526:23)
    at TypeHelper.inferTypes (/home/zaoqi/.config/yarn/global/node_modules/ts2c/src/types.js:522:14)
    at newConstructor.CProgram (/home/zaoqi/.config/yarn/global/node_modules/ts2c/src/program.js:146:25)
    at new newConstructor (/home/zaoqi/.config/yarn/global/node_modules/ts2c/src/template.js:26:35)
    at Object.<anonymous> (/home/zaoqi/.config/yarn/global/node_modules/ts2c/bin/ts2c:14:14)
$ yarn global list
yarn global v1.15.2
warning package.json: No license field
info "[email protected]" has binaries:
   - gulp
info "[email protected]" has binaries:
   - hexo
info "[email protected]" has binaries:
   - ts2c
Done in 0.65s.

errors...errors

[] -> Found initializer-assignment to variable outArray
/usr/local/lib/node_modules/ts2c/src/memory.js:268
console.log(heapNode.getText() + " -> Found passing to function " + call.expression.getText() + " as parameter " + funcDecl.parameters[i_1].name.getText());
^

I was trying to convert this code to check the program:

function convertBase(str, fromBase, toBase) {

    const DIGITS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/";

    const add = (x, y, base) => {
        let z = [];
        const n = Math.max(x.length, y.length);
        let carry = 0;
        let i = 0;
        while (i < n || carry) {
            const xi = i < x.length ? x[i] : 0;
            const yi = i < y.length ? y[i] : 0;
            const zi = carry + xi + yi;
            z.push(zi % base);
            carry = Math.floor(zi / base);
            i++;
        }
        return z;
    }

    const multiplyByNumber = (num, x, base) => {
        if (num < 0) return null;
        if (num == 0) return [];

        let result = [];
        let power = x;
        while (true) {
            num & 1 && (result = add(result, power, base));
            num = num >> 1;
            if (num === 0) break;
            power = add(power, power, base);
        }

        return result;
    }

    const parseToDigitsArray = (str, base) => {
        const digits = str.split('');
        let arr = [];
        for (let i = digits.length - 1; i >= 0; i--) {
            const n = DIGITS.indexOf(digits[i])
            if (n == -1) return null;
            arr.push(n);
        }
        return arr;
    }

    const digits = parseToDigitsArray(str, fromBase);
    if (digits === null) return null;

    let outArray = [];
    let power = [1];
    for (let i = 0; i < digits.length; i++) {
        digits[i] && (outArray = add(outArray, multiplyByNumber(digits[i], power, toBase), toBase));
        power = multiplyByNumber(fromBase, power, toBase);
    }

    let out = '';
    for (let i = outArray.length - 1; i >= 0; i--)
        out += DIGITS[outArray[i]];

    return out;
}

Nice project

This is a cool idea... I'd love to see a fully working ts2c compiler.

Have you had a look at Haxe at all? The Haxe compiler can compile Haxe code to pretty stable C code and works well. The syntax for Haxe is somewhat similar to TypeScript too as they are both descended from Javascript.and use similar types and type annotations. I imagine it could be modified to work with Typescript a lot more easily than starting from scratch.

Why int16 for numbers?

Isn't js using up to 50ish bits for numbers?
All bit-operations use 32 bit, so why not int32?

Converting strings to floating-point numbers

ts2c is not yet able to convert strings into floating-point numbers, though this feature would be relatively easy to implement:

var a = parseFloat("10.0");
console.log(a+2);

It may be possible to do this using using sscanf, but there may be other ways to do it.

Issue with JS file extension.

Foremost, I have to say, this is a great project, and I highly interested in its success. I'm most impressed with zero-dependency output code in pure C, permissive license of the whole software. And also both Typescript and JS are widely known high-level languages. I wish you the best of luck in this endeavor.


The problem, I noticed, was the following.
I wrote the sample code in 100% JS.

console.log("Привет! 嗨".length);

function factorial(n) {
    if (n <= 1) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

console.log(factorial(19));

Then, I save it as hello2.js.

$ ts2c hello2.js
$ cat hello2.c 
int main(void) {
    
    return 0;
}

But, if I rename it to hello2.ts, everything is fine.


The second problem was the integer overflow.
int16_t can't handle 121645100408832000.
It may be double here, but I am not sure, how this could be resolved at compile-time.
So, I got 109641728 instead.


[email protected]
node v4.2.6
npm 3.5.2
Ubuntu 16.04.2 LTS

scanf?

How can I do scanf using this?

Good first features to contribute

There're now several simple-to-implement standard calls which can significantly improve overall range of supported by TS2C ES3 features. Very good for start. If somebody wanted to contribute to the project, here you go, pick one of these:

  • decodeURI
  • decodeURIComponent
  • encodeURI
  • encodeURIComponent
  • String.toLowerCase
  • String.toUpperCase

Let me know which one you picked in the comments.

Notes:

  1. You can use src/standard/string/substring.ts as a reference:
    • implement Resolver
    • implement code template
    • add flag to HeaderFlags in program.ts
    • add function implementation and necessary dependencies to program.ts same as headerFlags.str_substring
  2. Read src/README.md
  3. Read ES3 spec (no need to read the whole spec, but at least read intently about the function that you're implementing)
  4. Remember that ES3 uses UTF-16 encoding and this should be reflected in the implementation. Using ordinary C string operations isn't enough
  5. Remember to use only C89 standard features in C implementation (gcc with flags -ansi -pedantic)
  6. Create tests under tests/strings

Multidimensional arrays

I tried to compile this JavaScript code into C, but it seems that ts2c is not able to convert multidimensional arrays:

var a = 2;
var b= a+1;
var c = [[a,b],[a,b]];
console.log("Hello world!");

There are some errors in the translated code:

#include <stdio.h>
typedef short int16_t;
static int16_t a;
static int16_t b;
static void * c[2];
int main(void) {
    a = 2;
    b = a + 1;
    /* Unsupported assignment c[0][0] = a */;
    /* Unsupported assignment c[0][1] = b */;
    /* Unsupported assignment c[1][0] = a */;
    /* Unsupported assignment c[1][1] = b */;
    printf("Hello world!\n");

    return 0;
}

Is it feasible to translate these multi-dimensional arrays from JavaScript into C?

return;

For whatever reason, argument-less return doesn't work:

function f() {
    return;
}

It should just result in a return from c.

int16_t is not enough and better string implementation needed

This sounds like multiple issues but they are all related. For the following js code:

var s = "";
for (var i = 0; i < 10000; ++i) {
    s += i;
}
console.log(s.length);
  1. The output of the compiled c code is -26646.
  2. If 10000 gets changed to 100000... Assertion 'gc_main->data != NULL' failed....

Both these issues are because int16_t is used (aka short) which is obviously not enough.

  1. However, if something like unsigned long is used, too many allocations will be done and from my experience my system (Arch Linux with 8gb of ram) froze...

I think a solution to this will be first using a something like size_t instead of int16_t. Using size_t is better I guess so that the compiler deals with it and 16-bit microcontrollers stay happy (issue #41).
Then, a better mini string implementation should be done. Many libraries already exist out there. Also C++ implementation does pretty well which I assume can be cloned to C. The following works pretty well:

int main() {
  string s = "";
  for (int i = 0; i < 1000000; ++i) {
    s += to_string(i);
  }
  cout << s << endl;
}

Nice project

Very cool project, but there are quite a few unsupported things. Example program:

var u, i, j, line, num, cnt, arr, names, config, board, s='';
while (line = readline()){
  config = line.split(' ').map(Number);
  board = new Array(config[1]);
  for (i=0; i<board.length; i++)
    board[i] = new Array(config[0]);
  num = +readline();
  names = new Array(num);
  for (u=0; u<num; u++){
    arr = readline().split(' ');
    names[u] = [arr[0], 0];
    for (i=+arr[2]; i<+arr[4]; i++)
      for (j=+arr[1]; j<+arr[3]; j++)
        board[i][j] = (board[i][j] >= -1 ? -1 : u);
  }
  cnt = [0,0];
  for (u=0; u<config[1]; u++)
    for (i=0; i<config[0]; i++){
      if (board[u][i] == null)
        cnt[0]++;
      else if (board[u][i] == -1)
        cnt[1]++;
      else
        names[board[u][i]][1]++;
      board[u][i] = null;
    }
  s += (s != '' ? '\n' : '') + 'Total ' + config[0]*config[1] + '\n' + 'Unallocated ' + cnt[0] + '\n' + 'Contested ' + cnt[1] + '\n';
  for (i=0; i<names.length; i++)
    s += names[i][0] + ' ' + names[i][1] + '\n';
}
console.log(s);

Results in errors like:

* Unsupported node: new Array(config[1]) */;
for (i = /* unsupported expression +arr[2] */;i < /* unsupported expression +arr[4] */;i++)
                for (j = /* unsupported expression +arr[1] */;j < /* unsupported expression +arr[3] */;j++)
                /* Unsupported assignment DICT_GET(board, i)[j] = (board[i][j] >= -1 ? -1 : u) */;
tmp_string_9 = malloc(strlen(/* unsupported expression (s != '' ? '\n' : '') + 'Total ' */) + STR_INT16_T_BUFLEN + 1);
strcpy(tmp_string_12, /* unsupported expression names[i][0] + ' ' + names[i][1] */);

Keep up the good work though.

Prefix increment operator not working in for loops

Some of us use 2-statement style for loops using the prefix increment operator. These don't seem to compile, although in COVERAGE.md it says that prefix increment operators are implemented. Example:

var x: number[] = [];
for (var i = -1; ++i < x.length;)
{
  console.log(i);
}

(Side note: This is a very interesting project. Years ago I posted this on the TypeScript forum and have been following many TypeScript => !JavaScript compiler projects.)

var a=function(){return (function(){})};

var a=function(){return (function(){})};
a()();
static void (*a)()();
void func()
{
    
}
void (*a_func)()()
{
    return (func);

}

int main(void) {
    a = a_func;
    a()();

    return 0;
}

void (*a_func)()() !

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.