UNPKG

puppy-transpiler

Version:
1,706 lines 54.7 kB
"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __spreadArrays = (this && this.__spreadArrays) || function () {
    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
    for (var r = Array(s), k = 0, i = 0; i < il; i++)
        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
            r[k] = a[j];
    return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var puppy_parser_1 = require("./puppy-parser");
var INDENT = '\t';
var MUST = '';
/* Type System */
var Type = /** @class */ (function () {
    function Type(code) {
        this.code = code;
    }
    Type.prototype.isOptional = function () {
        return this.code !== MUST;
    };
    Type.prototype.getValue = function () {
        return this.code;
    };
    Type.prototype.toString = function () {
        return '?';
    };
    Type.prototype.rtype = function () {
        return this;
    };
    Type.prototype.psize = function () {
        return 0;
    };
    Type.prototype.ptype = function (index) {
        return this;
    };
    // public equals(ty: Type, update: boolean): boolean {
    //   return false;
    // }
    Type.prototype.accept = function (ty, update) {
        return false;
    };
    Type.prototype.realType = function () {
        return this;
    };
    Type.prototype.isPattern = function () {
        return false;
    };
    Type.prototype.hasAlpha = function () {
        return false;
    };
    Type.prototype.toVarType = function (map) {
        return this;
    };
    return Type;
}());
exports.Type = Type;
var BaseType = /** @class */ (function (_super) {
    __extends(BaseType, _super);
    function BaseType(name, code) {
        var _this = _super.call(this, code) || this;
        _this.name = name;
        return _this;
    }
    BaseType.prototype.toString = function () {
        return this.name;
    };
    BaseType.prototype.accept = function (ty, update) {
        var v = ty.realType();
        if (v instanceof BaseType) {
            return this.name === v.name;
        }
        if (v instanceof VarType) {
            return v.must(this, update);
        }
        return false;
    };
    BaseType.prototype.isPattern = function () {
        return this.name === 'a' || this.name === 'b';
    };
    BaseType.prototype.hasAlpha = function () {
        return this.name === 'a' || this.name === 'b';
    };
    BaseType.prototype.toVarType = function (map) {
        if (this.hasAlpha()) {
            var ty = map[this.name];
            if (ty === undefined) {
                map[this.name] = new VarType(map.env, map.t);
            }
            return map[this.name];
        }
        return this;
    };
    return BaseType;
}(Type));
var VoidType = /** @class */ (function (_super) {
    __extends(VoidType, _super);
    function VoidType() {
        return _super.call(this, 'void', MUST) || this;
    }
    VoidType.prototype.accept = function (ty, update) {
        var v = ty.realType();
        if (v instanceof VarType) {
            v.must(this, update);
        }
        return true;
    };
    return VoidType;
}(BaseType));
var AnyType = /** @class */ (function (_super) {
    __extends(AnyType, _super);
    function AnyType(code) {
        return _super.call(this, 'any', code) || this;
    }
    AnyType.prototype.accept = function (ty, update) {
        var v = ty.realType();
        if (v instanceof VoidType) {
            return false;
        }
        return true;
    };
    AnyType.prototype.isPattern = function () {
        return true;
    };
    AnyType.prototype.hasAlpha = function () {
        return true;
    };
    AnyType.prototype.toVarType = function (map) {
        return new VarType(map.env, map.t);
    };
    return AnyType;
}(BaseType));
var FuncType = /** @class */ (function (_super) {
    __extends(FuncType, _super);
    function FuncType() {
        var types = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            types[_i] = arguments[_i];
        }
        var _this = _super.call(this, MUST) || this;
        _this.types = types;
        return _this;
    }
    FuncType.prototype.toString = function () {
        var ss = ['('];
        for (var i = 1; i < this.types.length; i += 1) {
            if (i > 1) {
                ss.push(',');
            }
            ss.push(this.types[i].toString());
        }
        ss.push(')->');
        ss.push(this.types[0].toString());
        return ss.join('');
    };
    FuncType.prototype.rtype = function () {
        return this.types[0];
    };
    FuncType.prototype.psize = function () {
        return this.types.length - 1;
    };
    FuncType.prototype.ptype = function (index) {
        return this.types[index + 1];
    };
    FuncType.prototype.accept = function (ty, update) {
        var v = ty.realType();
        if (v instanceof FuncType && this.psize() == v.psize()) {
            for (var i = 0; i < this.types.length; i += 1) {
                if (!this.types[i].accept(v.types[i], update)) {
                    return false;
                }
                return true;
            }
        }
        if (v instanceof VarType) {
            return v.must(this, update);
        }
        return false;
    };
    FuncType.prototype.isPattern = function () {
        for (var _i = 0, _a = this.types; _i < _a.length; _i++) {
            var ty = _a[_i];
            if (ty.isPattern())
                return true;
        }
        return false;
    };
    FuncType.prototype.hasAlpha = function () {
        for (var _i = 0, _a = this.types; _i < _a.length; _i++) {
            var ty = _a[_i];
            if (ty.hasAlpha())
                return true;
        }
        return false;
    };
    FuncType.prototype.toVarType = function (map) {
        if (this.hasAlpha()) {
            var v = [];
            for (var _i = 0, _a = this.types; _i < _a.length; _i++) {
                var ty = _a[_i];
                v.push(ty.toVarType(map));
            }
            return new (FuncType.bind.apply(FuncType, __spreadArrays([void 0], v)))();
        }
        return this;
    };
    return FuncType;
}(Type));
var ListType = /** @class */ (function (_super) {
    __extends(ListType, _super);
    function ListType(param, code) {
        if (code === void 0) { code = MUST; }
        var _this = _super.call(this, code) || this;
        _this.param = param;
        return _this;
    }
    ListType.prototype.toString = function () {
        return "List[" + this.param.toString() + "]";
    };
    ListType.prototype.psize = function () {
        return 1;
    };
    ListType.prototype.ptype = function (index) {
        return this.param;
    };
    ListType.prototype.realType = function () {
        var p = this.param.realType();
        if (p !== this.param) {
            return new ListType(p, this.code);
        }
        return this;
    };
    ListType.prototype.accept = function (ty, update) {
        var v = ty.realType();
        if (v instanceof ListType) {
            if (this.param == tAny) {
                return true;
            }
            return this.param.accept(v.param, update);
        }
        if (v instanceof VarType) {
            return v.must(this, update);
        }
        return false;
    };
    ListType.prototype.isPattern = function () {
        return this.param.isPattern();
    };
    ListType.prototype.hasAlpha = function () {
        return this.param.hasAlpha();
    };
    ListType.prototype.toVarType = function (map) {
        if (this.hasAlpha()) {
            return new ListType(this.param.toVarType(map));
        }
        return this;
    };
    return ListType;
}(Type));
var UnionType = /** @class */ (function (_super) {
    __extends(UnionType, _super);
    function UnionType() {
        var types = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            types[_i] = arguments[_i];
        }
        var _this = _super.call(this, MUST) || this;
        _this.types = types;
        return _this;
    }
    UnionType.prototype.toString = function () {
        var ss = [];
        for (var i = 0; i < this.types.length; i += 1) {
            if (i > 0) {
                ss.push('|');
            }
            ss.push(this.types[i].toString());
        }
        return ss.join('');
    };
    UnionType.prototype.psize = function () {
        return this.types.length;
    };
    UnionType.prototype.ptype = function (index) {
        return this.types[index];
    };
    UnionType.prototype.accept = function (ty, update) {
        for (var _i = 0, _a = this.types; _i < _a.length; _i++) {
            var ty0 = _a[_i];
            if (ty0.accept(ty, false)) {
                return true;
            }
        }
        console.log("FAIL " + ty + " " + this.toString());
        return false;
    };
    UnionType.prototype.isPattern = function () {
        return true;
    };
    UnionType.prototype.hasAlpha = function () {
        for (var _i = 0, _a = this.types; _i < _a.length; _i++) {
            var ty = _a[_i];
            if (ty.hasAlpha()) {
                return true;
            }
        }
        return false;
    };
    UnionType.prototype.toVarType = function (map) {
        if (this.hasAlpha()) {
            var ts = [];
            for (var _i = 0, _a = this.types; _i < _a.length; _i++) {
                var ty = _a[_i];
                ts.push(ty.toVarType(map));
            }
            return new (UnionType.bind.apply(UnionType, __spreadArrays([void 0], ts)))();
        }
        return this;
    };
    return UnionType;
}(Type));
var union = function () {
    var types = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        types[_i] = arguments[_i];
    }
    if (types.length === 1) {
        return types[0];
    }
    return new (UnionType.bind.apply(UnionType, __spreadArrays([void 0], types)))();
};
var tAny = new AnyType(MUST);
var tVoid = new VoidType();
var tBool = new BaseType('bool', MUST);
var tInt = new BaseType('number', MUST);
var tInt_ = new BaseType('number', 'undefined');
var tFloat = tInt;
var tInt0 = new BaseType('number', '0');
var tInt1 = new BaseType('number', '1');
var tFloat0 = new BaseType('number', '0.0');
var tString = new BaseType('string', MUST);
var tString_ = new BaseType('string', "''");
var tA = new BaseType('a', MUST);
var tListA = new ListType(tA, MUST);
var tListInt = new ListType(tInt, MUST);
var tListAny = new ListType(tAny, MUST);
var tStringOrList = union(tListAny, tString);
var tMatter = new BaseType('Object', MUST);
var tObject = tMatter;
var tVec = new BaseType('Vec', MUST);
var tVec0 = new BaseType('Vec', 'lib.vec(0,0)');
//const tUndefined = new BaseType('undefined');
var EmptyNumberSet = [];
var unionSet = function (a, b, c) {
    var A = [];
    for (var _i = 0, a_1 = a; _i < a_1.length; _i++) {
        var id = a_1[_i];
        if (A.indexOf(id) === -1) {
            A.push(id);
        }
    }
    for (var _a = 0, b_1 = b; _a < b_1.length; _a++) {
        var id = b_1[_a];
        if (A.indexOf(id) === -1) {
            A.push(id);
        }
    }
    if (c !== undefined) {
        for (var _b = 0, c_1 = c; _b < c_1.length; _b++) {
            var id = c_1[_b];
            if (A.indexOf(id) === -1) {
                A.push(id);
            }
        }
    }
    return A;
};
var VarType = /** @class */ (function (_super) {
    __extends(VarType, _super);
    function VarType(env, ref) {
        var _this = _super.call(this, MUST) || this;
        _this.varMap = env.getroot('@varmap');
        _this.varid = _this.varMap.length;
        _this.varMap.push(EmptyNumberSet);
        _this.ref = ref;
        return _this;
    }
    VarType.prototype.toString = function () {
        var v = this.varMap[this.varid];
        if (v instanceof Type) {
            return v.toString();
        }
        return 'any';
    };
    VarType.prototype.realType = function () {
        var v = this.varMap[this.varid];
        return v instanceof Type ? v : this;
    };
    VarType.prototype.accept = function (ty, update) {
        var v = this.varMap[this.varid];
        if (v instanceof Type && v !== this) {
            return v.accept(ty, update);
        }
        return this.must(ty.realType(), update);
    };
    VarType.prototype.must = function (ty, update) {
        var v1 = ty.realType();
        if (update) {
            if (v1 instanceof VarType) {
                if (v1.varid === this.varid) {
                    return true;
                }
                var u = unionSet(this.varMap[this.varid], this.varMap[v1.varid], [v1.varid, this.varid]);
                for (var _i = 0, u_1 = u; _i < u_1.length; _i++) {
                    var id = u_1[_i];
                    this.varMap[id] = u;
                }
                return true;
            }
            if (!v1.isPattern()) {
                var u = this.varMap[this.varid];
                for (var _a = 0, u_2 = u; _a < u_2.length; _a++) {
                    var id = u_2[_a];
                    this.varMap[id] = v1;
                }
                this.varMap[this.varid] = v1;
            }
        }
        return true;
    };
    VarType.prototype.hasAlpha = function () {
        return false;
    };
    return VarType;
}(Type));
var OptionType = /** @class */ (function (_super) {
    __extends(OptionType, _super);
    function OptionType(options) {
        var _this = _super.call(this, JSON.stringify(options)) || this;
        _this.options = options;
        return _this;
    }
    OptionType.prototype.toString = function () {
        return this.code;
    };
    OptionType.prototype.accept = function (ty) {
        var v = ty.realType();
        if (v instanceof OptionType) {
            return true;
        }
        return false;
    };
    OptionType.prototype.equals = function (ty, update) {
        return this.accept(ty);
    };
    OptionType.prototype.isPattern = function () {
        return false;
    };
    OptionType.prototype.hasAlpha = function () {
        return false;
    };
    OptionType.prototype.toVarType = function (map) {
        return this;
    };
    return OptionType;
}(Type));
var Symbol = /** @class */ (function () {
    function Symbol(code, ty, options) {
        this.isMatter = false;
        this.isMutable = false;
        this.code = code;
        this.ty = ty.realType();
        if (options !== undefined) {
            this.isMatter = options.isMatter === undefined ? false : options.isMatter;
            this.isMutable =
                options.isMutable == undefined ? false : options.isMutable;
        }
    }
    Symbol.prototype.isGlobal = function () {
        return this.code.indexOf('vars[') == 0;
    };
    return Symbol;
}());
var tColor = new UnionType(tString, tInt);
var tOption = new OptionType({});
var tFuncFloatFloat = new FuncType(tFloat, tFloat);
var tFuncFloatFloatFloat = new FuncType(tFloat, tFloat, tFloat);
var tFuncShape = new FuncType(tMatter, tInt, tInt, tOption);
var import_math = {
    pi: new Symbol('3.14159', tFloat),
    sin: new Symbol('Math.sin', tFuncFloatFloat),
    cos: new Symbol('Math.cos', tFuncFloatFloat),
    tan: new Symbol('Math.tan', tFuncFloatFloat),
    sqrt: new Symbol('Math.sqrt', tFuncFloatFloat),
    log: new Symbol('Math.log', tFuncFloatFloat),
    log10: new Symbol('Math.log10', tFuncFloatFloat),
    pow: new Symbol('Math.pow', tFuncFloatFloatFloat),
    hypot: new Symbol('Math.hypot', tFuncFloatFloatFloat),
    gcd: new Symbol('puppy.gcd', tFuncFloatFloatFloat),
};
var import_python = {
    // 'math.': IMPORT_MATH,
    // 'random.': IMPORT_RANDOM,
    input: new Symbol('await puppy.input', new FuncType(tString, tString_)),
    print: new Symbol('puppy.print', new FuncType(tVoid, tAny, tOption), {
        isMatter: true,
    }),
    //# 返値, 引数..None はなんでもいい
    len: new Symbol('lib.len', new FuncType(tInt, union(tString, tListA))),
    //可変長引数
    range: new Symbol('lib.range', new FuncType(tListInt, tInt, tInt_, tInt_)),
    //append
    '.append': new Symbol('lib.append', new FuncType(tVoid, tListA, tA)),
    // 変換
    int: new Symbol('lib.int', new FuncType(tInt, union(tBool, tString, tInt))),
    float: new Symbol('lib.float', new FuncType(tFloat, union(tBool, tString, tInt))),
    str: new Symbol('lib.str', new FuncType(tString, tAny)),
};
var import_random = {
    random: new Symbol('Math.random', new FuncType(tInt)),
};
var import_matterjs = {
    // # 時間
    getTime: new Symbol('puppy.getTimeStamp.bind(puppy)', new FuncType(tInt)),
    // # クラス
    World: new Symbol('puppy.World', tFuncShape, { isMatter: true }),
    Circle: new Symbol('puppy.Circle', tFuncShape, { isMatter: true }),
    Rectangle: new Symbol('puppy.Rectangle', tFuncShape, { isMatter: true }),
    Polygon: new Symbol('puppy.Polygon', tFuncShape, { isMatter: true }),
    Label: new Symbol('puppy.Label', tFuncShape, { isMatter: true }),
    // 'Ball': new Symbol('puppy.Circle', tFuncShape),
    // 'Block': new Symbol('puppy.Ball', tFuncShape),
    // # 物体メソッド
    '.setPosition': new Symbol('lib.setPosition', new FuncType(tVoid, tMatter, tInt, tInt)),
    '.applyForce': new Symbol('lib.applyForce', new FuncType(tVoid, tMatter, tInt, tInt, tInt, tInt)),
    '.rotate': new Symbol('lib.rotate', new FuncType(tVoid, tMatter, tInt, tInt_, tInt_)),
    '.scale': new Symbol('lib.scale', new FuncType(tVoid, tMatter, tInt, tInt, tInt_, tInt_)),
    '.setAngle': new Symbol('lib.setAngle', new FuncType(tVoid, tMatter, tInt)),
    '.setAngularVelocity': new Symbol('lib.setAngularVelocity', new FuncType(tVoid, tMatter, tInt)),
    '.setDensity': new Symbol('lib.setDensity', new FuncType(tVoid, tMatter, tInt)),
    '.setMass': new Symbol('lib.setMass', new FuncType(tVoid, tMatter, tInt)),
    '.setStatic': new Symbol('lib.setStatic', new FuncType(tVoid, tMatter, tBool)),
    '.setVelocity': new Symbol('lib.setVelocity', new FuncType(tVoid, tMatter, tInt)),
};
var modules = {
    math: import_math,
    random: import_random,
    matterjs: import_matterjs,
};
var symbolPackageMap = {};
var checkSymbolNames = function () {
    for (var _i = 0, _a = Object.keys(modules); _i < _a.length; _i++) {
        var pkgname = _a[_i];
        for (var _b = 0, _c = Object.keys(modules[pkgname]); _b < _c.length; _b++) {
            var name_1 = _c[_b];
            symbolPackageMap[name_1] = pkgname;
        }
    }
};
checkSymbolNames();
var KEYTYPES = {
    width: tInt0,
    height: tInt0,
    x: tInt0,
    y: tInt0,
    image: tString_,
    lineWidth: tInt,
    strokeStyle: tString,
    fillStyle: tString,
    restitution: tFloat0,
    angle: tFloat0,
    position: tVec0,
    mass: tInt0,
    density: tInt0,
    area: tInt0,
    friction: tFloat0,
    frictionStatic: tFloat0,
    airFriction: tFloat0,
    torque: tFloat0,
    stiffness: tFloat0,
    isSensor: tBool,
    isStatic: tBool,
    damping: tFloat0,
    in: new FuncType(tVoid, tMatter, tMatter),
    out: new FuncType(tVoid, tMatter, tMatter),
    over: new FuncType(tVoid, tMatter, tMatter),
    clicked: new FuncType(tVoid, tMatter),
    font: tString_,
    fontColor: tString,
    textAlign: tString,
    value: tInt,
    text: tString,
};
var valueOfType = function (ty) {
    if (ty.isOptional()) {
        return ty.getValue();
    }
    if (ty instanceof ListType) {
        return '[]';
    }
    if (ty instanceof BaseType) {
        var name_2 = ty.toString();
        if (name_2 === tString.toString()) {
            return "''";
        }
        if (name_2 === tBool.toString()) {
            return 'false';
        }
        if (name_2 === tVec.toString()) {
            return 'lib.vec(0,0)';
        }
        return '0';
    }
    return 'undefined';
};
//const ty1 = this.check(tleft(op), env, t['left'], out1);
//const ty2 = this.check(tright(op, ty1), env, t['right'], out2);
//return tbinary(env, t, ty1, out1.join(''), ty2, out1.join(''), out);
var tCompr = union(tInt, tString);
var opset = {
    and: '&&',
    or: '||',
    not: '!',
    '+=': '+',
    '-=': '-',
    '*=': '*',
    '//=': '//',
    '/=': '/',
    '<<=': '<<',
    '>>=': '>>',
    '|=': '|',
    '&=': '&',
    '^=': '^',
};
var operator = function (op) {
    var op2 = opset[op];
    if (op2 !== undefined) {
        return op2;
    }
    return op;
};
var tleftMap = {
    '+': union(tInt, tString, tListAny),
    '-': tInt,
    '**': tInt,
    '*': union(tInt, tString, tListAny),
    '/': tInt,
    '//': tInt,
    '%': tInt,
    '==': tAny,
    '!=': tAny,
    in: tAny,
    '<': tCompr,
    '<=': tCompr,
    '>': tCompr,
    '>=': tCompr,
    '^': tInt,
    '|': tInt,
    '&': tInt,
    '<<': tInt,
    '>>': tInt,
};
var tleft = function (op) {
    var ty = tleftMap[op];
    if (ty === undefined) {
        console.log("FIXME undefined '" + op + "'");
        return tAny;
    }
    return ty;
};
var tright = function (op, ty) {
    if (op == 'in') {
        return union(new ListType(ty, MUST), tString);
    }
    var ty2 = tleftMap[op];
    if (ty2 === tAny || ty2 === tInt || op === '*') {
        return ty2;
    }
    return ty; // 左と同じ型
};
var setpos = function (s, pos, elog) {
    var max = Math.min(pos + 1, s.length);
    var r = 1;
    var c = 0;
    for (var i = 0; i < max; i += 1) {
        if (s.charCodeAt(i) == 10) {
            r += 1;
            c = 0;
        }
        c += 1;
    }
    elog.pos = pos;
    elog.row = r;
    elog.col = c;
    return elog;
};
var Env = /** @class */ (function () {
    function Env(env) {
        this.vars = {};
        if (env === undefined) {
            this.root = this;
            this.parent = null;
            this.vars['@varmap'] = [];
            this.vars['@logs'] = [];
            this.vars['@trace'] = [];
            this.vars['@indent'] = INDENT;
        }
        else {
            this.root = env.root;
            this.parent = env;
        }
    }
    Env.prototype.get = function (key, value) {
        var e = this;
        while (e !== null) {
            var v = e.vars[key];
            if (v !== undefined) {
                return v;
            }
            e = e.parent;
        }
        return value;
    };
    Env.prototype.has = function (key) {
        return this.get(key) !== undefined;
    };
    Env.prototype.set = function (key, value) {
        this.vars[key] = value;
        return value;
    };
    Env.prototype.getroot = function (key, value) {
        return this.root.vars[key] || value;
    };
    Env.prototype.setroot = function (key, value) {
        this.root.vars[key] = value;
        return value;
    };
    Env.prototype.from_import = function (pkg, list) {
        for (var _i = 0, _a = Object.keys(pkg); _i < _a.length; _i++) {
            var name_3 = _a[_i];
            //console.log(name);
            if (list === undefined || list.indexOf(name_3) !== -1) {
                this.vars[name_3] = pkg[name_3];
            }
        }
    };
    Env.prototype.setModule = function (name, options) {
        this.set(name, new Symbol('undefined', new OptionType(options)));
    };
    Env.prototype.isModule = function (name) {
        var s = this.get(name);
        if (s !== undefined &&
            s.code === 'undefined' &&
            s.ty instanceof OptionType) {
            return true;
        }
        return false;
    };
    Env.prototype.getModule = function (pkgname, name) {
        var s = this.get(pkgname);
        if (s !== undefined &&
            s.code === 'undefined' &&
            s.ty instanceof OptionType) {
            var options = s.ty.options;
            return options[name];
        }
        return undefined;
    };
    Env.prototype.inferSymbolType = function (name) {
        var ty = KEYTYPES[name];
        if (ty === undefined) {
            var symbol = this.get(name);
            if (symbol === undefined) {
                return undefined;
            }
        }
        return ty;
    };
    Env.prototype.perror = function (t, elog) {
        var logs = this.root.vars['@logs'];
        if (elog.type === undefined) {
            elog.type = 'error';
        }
        if (elog.pos === undefined) {
            var pos = t.begin();
            elog.pos = pos[0];
            elog.row = pos[1];
            elog.col = pos[2];
        }
        if (elog.len === undefined) {
            elog.len = t.epos - t.spos;
        }
        logs.push(elog);
    };
    Env.prototype.trace = function (t) {
        var trace = this.getroot('@trace');
        var id = trace.length;
        var pos = t.begin();
        trace.push([pos[0], pos[1], pos[2], t.epos - t.spos]);
        return "," + id;
    };
    Env.prototype.setInLoop = function () {
        this.set('@inloop', true);
        return true;
    };
    Env.prototype.inLoop = function () {
        return this.get('@inloop') === true;
    };
    Env.prototype.setFunc = function (data) {
        this.set('@func', data);
        return data;
    };
    Env.prototype.inFunc = function () {
        return this.get('@func') !== undefined;
    };
    Env.prototype.foundFunc = function (t, symbol) {
        if (symbol.isMatter) {
            var data = this.get('@func');
            if (data !== undefined) {
                data['isMatter'] = true;
            }
            else {
                var pos = setpos(t.inputs, t.spos, { type: '', key: '' });
                this.setroot('@yeild', pos.row);
            }
        }
    };
    Env.prototype.isUtf8Name = function (s) {
        for (var i = 0; i < s.length; i += 1) {
            if (s.charCodeAt(i) > 128) {
                return true;
            }
        }
        return false;
    };
    Env.prototype.local = function (s) {
        if (this.isUtf8Name(s)) {
            var map = this.getroot('@utf8map');
            if (map === undefined) {
                this.setroot('@utf8map', {});
                return this.local(s);
            }
            var vname = map[name];
            if (vname === undefined) {
                var id = Object.keys(map).length;
                vname = "_v" + id;
                map[name] = vname;
            }
            return vname;
        }
        return s;
    };
    Env.prototype.declVar = function (name, ty) {
        var code = this.inFunc() || this.inLoop() ? this.local(name) : "vars['" + name + "']";
        var symbol = new Symbol(code, ty);
        symbol.isMutable = true;
        return this.set(name, symbol);
    };
    Env.prototype.emitAutoYield = function (out) {
        var yieldparam = this.getroot('@yeild');
        if (yieldparam !== undefined && !this.inFunc()) {
            out.push("; yield " + yieldparam + ";\n");
            this.setroot('@yeild', undefined);
        }
        else {
            out.push('\n');
        }
    };
    return Env;
}());
var PuppyError = /** @class */ (function () {
    function PuppyError() {
    }
    return PuppyError;
}());
var FIXME_subs = function (t) {
    return t instanceof puppy_parser_1.ParseTree ? t.subs() : [];
};
var Transpiler = /** @class */ (function () {
    function Transpiler() {
    }
    Transpiler.prototype.conv = function (env, t, out) {
        //console.log(t.toString());
        try {
            return this[t.tag](env, t, out);
        }
        catch (e) {
            if (e instanceof PuppyError) {
                throw e;
            }
            if (this[t.tag] === undefined) {
                //console.log(e);
                env.perror(t, {
                    type: 'error',
                    key: 'UndefinedParseTree',
                    subject: t.toString(),
                });
                return this.skip(env, t, out);
            }
            throw e;
        }
    };
    Transpiler.prototype.skip = function (env, t, out) {
        throw new PuppyError();
        // out.push('undefined');
        // return tAny;
    };
    Transpiler.prototype.check = function (req, env, t, out, elog) {
        var ty = this.conv(env, t, out);
        if (req !== undefined) {
            if (req.accept(ty, true)) {
                return ty;
            }
            if (elog === undefined) {
                elog = {
                    key: 'TypeError',
                    subject: req.toString(),
                };
            }
            elog.request = req;
            elog.given = ty;
            env.perror(t, elog);
            return this.skip(env, t, out);
        }
        return ty;
    };
    Transpiler.prototype.checkBinary = function (env, t, op, ty1, left, ty2, right, out) {
        if (op === '==' || op === '!=') {
            out.push(left + " " + op + "= " + right);
            return tBool;
        }
        ty1 = ty1.realType();
        ty2 = ty2.realType();
        if (op === '+') {
            if (tInt.accept(ty1, false) && tInt.accept(ty2, false)) {
                out.push("(" + left + " + " + right + ")");
                return tInt;
            }
            if (ty1.accept(ty2, true)) {
                out.push("lib.anyAdd(" + left + "," + right + ")");
                return ty1;
            }
            env.perror(t, {
                key: 'BinaryTypeError',
                subject: op,
                request: ty1,
                given: ty2,
            });
            return this.skip(env, t, out);
        }
        if (op === '*') {
            if (tInt.accept(ty1, false) && tInt.accept(ty2, false)) {
                out.push("(" + left + " * " + right + ")");
                return tInt;
            }
            out.push("lib.anyMul(" + left + "," + right + ")");
            if (ty1 === tInt || tListAny.accept(ty2, false))
                return ty2;
            if (ty2 === tInt || tListAny.accept(ty1, false))
                return ty1;
            return ty1;
        }
        if (op === '//') {
            out.push("((" + left + "/" + right + ")|0)");
            return tInt;
        }
        if (op === '**') {
            out.push("Math.pow(" + left + "," + right + ")");
            return tInt;
        }
        if (ty1.accept(ty2, true)) {
            out.push("(" + left + " " + op + " " + right + ")");
            if (tleftMap[op] === tCompr) {
                return tBool;
            }
            return ty1;
        }
        env.perror(t, {
            key: 'BinaryTypeError',
            subject: op,
            request: ty1,
            given: ty2,
        });
        return this.skip(env, t, out);
    };
    Transpiler.prototype.err = function (env, t, out) {
        env.perror(t, {
            type: 'error',
            key: 'SyntaxError',
        });
        return tVoid;
    };
    Transpiler.prototype.FromDecl = function (env, t, out) {
        var name = t.tokenize('name');
        var pkg = modules[name];
        if (pkg === undefined) {
            env.perror(t.get('name'), {
                type: 'warning',
                key: 'UnknownPackageName',
            });
            return tVoid;
        }
        env.from_import(pkg); // FIXME
        return tVoid;
    };
    Transpiler.prototype.ImportDecl = function (env, t, out) {
        var name = t.tokenize('name');
        var alias = t.tokenize('alias', name);
        var pkg = modules[name];
        if (pkg === undefined) {
            env.perror(t.get('name'), {
                type: 'warning',
                key: 'UnknownPackageName',
            });
            return tVoid;
        }
        env.setModule(alias, pkg);
        return tVoid;
    };
    Transpiler.prototype.Source = function (env, t, out) {
        for (var _i = 0, _a = FIXME_subs(t); _i < _a.length; _i++) {
            var subtree = _a[_i];
            try {
                var out2 = [];
                out2.push(env.get('@indent'));
                this.conv(env, subtree, out2);
                env.emitAutoYield(out2);
                out.push(out2.join(''));
            }
            catch (e) {
                if (!(e instanceof PuppyError)) {
                    throw e;
                }
            }
        }
        return tVoid;
    };
    Transpiler.prototype.Block = function (penv, t, out) {
        var indent = penv.get('@indent');
        var nested = INDENT + indent;
        var env = new Env(penv);
        env.set('@indent', nested);
        out.push('{\n');
        for (var _i = 0, _a = FIXME_subs(t); _i < _a.length; _i++) {
            var subtree = _a[_i];
            out.push(env.get('@indent'));
            this.conv(env, subtree, out);
            env.emitAutoYield(out);
        }
        out.push(indent + '}');
        return tVoid;
    };
    Transpiler.prototype.IfExpr = function (env, t, out) {
        out.push('((');
        this.check(tBool, env, t['cond'], out);
        out.push(') ? (');
        var ty = this.conv(env, t['then'], out);
        out.push(') : (');
        this.check(ty, env, t['else'], out);
        out.push('))');
        return ty;
    };
    Transpiler.prototype.IfStmt = function (env, t, out) {
        out.push('if (');
        this.check(tBool, env, t['cond'], out);
        out.push(') ');
        this.conv(env, t['then'], out);
        if (t['elif'] !== undefined) {
            for (var _i = 0, _a = FIXME_subs(t['elif']); _i < _a.length; _i++) {
                var stmt = _a[_i];
                this.conv(env, stmt, out);
            }
        }
        if (t['else'] !== undefined) {
            out.push('else ');
            this.conv(env, t['else'], out);
        }
        return tVoid;
    };
    Transpiler.prototype.ElifStmt = function (env, t, out) {
        out.push('else if (');
        this.check(tBool, env, t['cond'], out);
        out.push(') ');
        this.conv(env, t['then'], out);
        return tVoid;
    };
    Transpiler.prototype.ForStmt = function (env, t, out) {
        // if (t['each'].tag !== 'Name') {
        //   env.perror(t['each'], {
        //     type: 'error', key: 'RequiredIdentifier',
        //   });
        //   return tVoid;
        // }
        var name = t['each'].tokenize();
        var ty = new VarType(env, t['each']);
        out.push("for (let " + name + " of ");
        this.check(new ListType(ty), env, t['list'], out);
        out.push(')');
        var lenv = new Env(env);
        lenv.setInLoop();
        lenv.declVar(name, ty);
        this.conv(lenv, t['body'], out);
        return tVoid;
    };
    Transpiler.prototype.FuncDecl = function (env, t, out) {
        var name = t.tokenize('name');
        var types = [new VarType(env, t['name'])];
        var names = [];
        var lenv = new Env(env);
        var funcData = lenv.setFunc({
            name: name,
            return: types[0],
            hasReturn: false,
            isMatter: false,
        });
        for (var _i = 0, _a = FIXME_subs(t['params']); _i < _a.length; _i++) {
            var p = _a[_i];
            var pname = p.tokenize('name');
            var ptype = new VarType(env, p['name']);
            var symbol_1 = lenv.declVar(pname, ptype);
            names.push(symbol_1.code);
            types.push(ptype);
        }
        var funcType = new (FuncType.bind.apply(FuncType, __spreadArrays([void 0], types)))();
        var symbol = env.declVar(name, funcType);
        var defun = symbol.isGlobal() ? '' : 'var ';
        out.push("" + defun + symbol.code + " = (" + names.join(', ') + ") => ");
        this.conv(lenv, t['body'], out);
        symbol.isMatter = funcData['isMatter'];
        if (!funcData['hasReturn']) {
            types[0].accept(tVoid, true);
        }
        console.log("DEFINED " + name + " :: " + funcType);
        return tVoid;
    };
    Transpiler.prototype.FuncExpr = function (env, t, out) {
        var types = [new VarType(env, t)];
        var names = [];
        var lenv = new Env(env);
        var funcData = lenv.setFunc({
            return: types[0],
            hasReturn: false,
        });
        for (var _i = 0, _a = FIXME_subs(t['params']); _i < _a.length; _i++) {
            var p = _a[_i];
            var pname = p.tokenize('name');
            var ptype = new VarType(env, p['name']);
            var symbol = lenv.declVar(pname, ptype);
            names.push(symbol.code);
            types.push(ptype);
        }
        var funcType = new (FuncType.bind.apply(FuncType, __spreadArrays([void 0], types)))();
        out.push("(" + names.join(', ') + ") => ");
        this.conv(lenv, t['body'], out);
        if (!funcData['hasReturn']) {
            types[0].accept(tVoid, true);
        }
        return funcType;
    };
    Transpiler.prototype.Return = function (env, t, out) {
        if (!env.inFunc()) {
            env.perror(t, {
                type: 'warning',
                key: 'OnlyInFunction',
                subject: 'return',
            });
            return tVoid;
        }
        var funcData = env.get('@func');
        funcData['hasReturn'] = true;
        if (t['expr'] !== undefined) {
            out.push('return ');
            this.check(funcData['return'], env, t['expr'], out);
        }
        else {
            out.push('return');
        }
        return tVoid;
    };
    Transpiler.prototype.Continue = function (env, t, out) {
        if (!env.inLoop()) {
            env.perror(t, {
                type: 'warning',
                key: 'OnlyInLoop',
                subject: 'continue',
            });
            return tVoid;
        }
        out.push('continue');
        return tVoid;
    };
    Transpiler.prototype.Break = function (env, t, out) {
        if (!env.inLoop()) {
            env.perror(t, {
                type: 'warning',
                key: 'OnlyInLoop',
                subject: 'break',
            });
            return tVoid;
        }
        out.push('break');
        return tVoid;
    };
    Transpiler.prototype.Pass = function (env, t, out) {
        return tVoid;
    };
    Transpiler.prototype.VarDecl = function (env, t, out) {
        var left = t['left'];
        if (left.tag === 'Name') {
            var name_4 = left.tokenize();
            var symbol = env.get(name_4);
            if (symbol === undefined || (env.inFunc() && symbol.isGlobal())) {
                var ty_1 = new VarType(env, left);
                var out1 = [];
                this.check(ty_1, env, t['right'], out1);
                symbol = env.declVar(name_4, ty_1);
                var qual = symbol.isGlobal() ? '' : 'var ';
                out.push("" + qual + symbol.code + " = " + out1.join(''));
                return tVoid;
            }
        }
        t['left'].tag = "Set" + t['left'].tag;
        var ty = this.conv(env, t['left'], out);
        out.push(' = ');
        this.check(ty, env, t['right'], out);
        return tVoid;
    };
    Transpiler.prototype.NLPSymbol = function (env, t, out) {
        env.perror(t, {
            type: 'error',
            key: 'NLPSymbol',
            subject: t.tokenize(),
        });
    };
    Transpiler.prototype.Name = function (env, t, out) {
        var name = t.tokenize();
        var symbol = env.get(name);
        if (symbol === undefined) {
            env.perror(t, {
                type: 'error',
                key: 'UndefinedName',
                subject: name,
            });
            return this.skip(env, t, out);
        }
        out.push(symbol.code);
        return symbol.ty;
    };
    Transpiler.prototype.SetName = function (env, t, out) {
        var name = t.tokenize();
        var symbol = env.get(name);
        if (symbol === undefined) {
            env.perror(t, {
                type: 'error',
                key: 'UndefinedName',
                subject: name,
            });
            return this.skip(env, t, out);
        }
        if (!symbol.isMutable) {
            env.perror(t, {
                type: 'error',
                key: 'Immutable',
                subject: name,
            });
            return this.skip(env, t, out);
        }
        out.push(symbol.code);
        return symbol.ty;
    };
    Transpiler.prototype.And = function (env, t, out) {
        this.check(tBool, env, t['left'], out);
        out.push(' && ');
        this.check(tBool, env, t['right'], out);
        return tBool;
    };
    Transpiler.prototype.Or = function (env, t, out) {
        this.check(tBool, env, t['left'], out);
        out.push(' || ');
        this.check(tBool, env, t['right'], out);
        return tBool;
    };
    Transpiler.prototype.Not = function (env, t, out) {
        out.push('!(');
        this.check(tBool, env, t[0], out);
        out.push(')');
        return tBool;
    };
    Transpiler.prototype.Infix = function (env, t, out) {
        var op = operator(t.tokenize('name'));
        var out1 = [];
        var out2 = [];
        var ty1 = this.check(tleft(op), env, t['left'], out1);
        var ty2 = this.check(tright(op, ty1), env, t['right'], out2);
        return this.checkBinary(env, t, op, ty1, out1.join(''), ty2, out2.join(''), out);
    };
    Transpiler.prototype.Unary = function (env, t, out) {
        var op = t.tokenize('name');
        if (op === '!' || op === 'not') {
            out.push(op + "(");
            this.check(tBool, env, t['expr'], out);
            out.push(')');
            return tBool;
        }
        else {
            out.push(op + "(");
            this.check(tInt, env, t['expr'], out);
            out.push(')');
            return tInt;
        }
    };
    Transpiler.prototype.ApplyExpr = function (env, t, out) {
        var name = t.tokenize('name');
        var symbol = env.get(name);
        if (symbol === undefined) {
            var pkgname = symbolPackageMap[name];
            if (pkgname !== undefined) {
                console.log("importing " + pkgname + " ...");
                env.from_import(modules[pkgname]);
                env.perror(t['name'], {
                    type: 'info',
                    key: 'InferredPackage',
                    subject: pkgname,
                    code: "from " + pkgname + " import *",
                });
                return this.ApplySymbolExpr(env, t, env.get(name), undefined, out); // Again
            }
        }
        return this.ApplySymbolExpr(env, t, symbol, undefined, out);
    };
    Transpiler.prototype.ApplySymbolExpr = function (env, t, symbol, recv, out) {
        if (symbol === undefined) {
            env.perror(t['name'], {
                type: 'error',
                key: 'UnknownName',
                subject: t['name'].tokenize(),
            });
            return this.skip(env, t, out);
        }
        out.push(symbol.code);
        out.push('(');
        var args = t['params'].subs();
        if (recv !== undefined) {
            args.unshift(recv);
        }
        var funcType = symbol.ty;
        if (!(funcType instanceof FuncType)) {
            env.perror(t['name'], {
                type: 'error',
                key: 'NotFunction',
                subject: t['name'].tokenize(),
            });
            return this.skip(env, t, out);
        }
        if (funcType.hasAlpha()) {
            funcType = funcType.toVarType({ env: env, ref: t });
            //console.log(funcType.toString());
        }
        for (var i = 0; i < args.length; i += 1) {
            if (!(i < funcType.psize())) {
                env.perror(args[i], {
                    type: 'warning',
                    key: 'TooManyArguments',
                    subject: args[i],
                });
                break;
            }
            if (i > 0) {
                out.push(',');
            }
            var ty = funcType.ptype(i);
            this.check(ty, env, args[i], out);
        }
        if (args.length < funcType.psize()) {
            if (!funcType.ptype(args.length)) {
                env.perror(t['name'], setpos(t.inputs, t['params'].epos, {
                    type: 'error',
                    key: 'RequiredArguments',
                }));
            }
        }
        out.push(')');
        env.foundFunc(t, symbol);
        return funcType.rtype();
    };
    Transpiler.prototype.MethodExpr = function (env, t, out) {
        var recv = t.tokenize('recv');
        if (env.isModule(recv)) {
            var symbol_2 = env.getModule(recv, t.tokenize('name'));
            return this.ApplySymbolExpr(env, t, symbol_2, undefined, out);
        }
        var methodname = "." + t.tokenize('name');
        var symbol = env.get(methodname);
        return this.ApplySymbolExpr(env, t, symbol, t['recv'], out);
    };
    //"[#SelfAssign left=[#Name 'a'] name=[# '+='] right=[#Int '1']]"
    Transpiler.prototype.SelfAssign = function (env, t, out) {
        var tag = t['left'].tag;
        t['left'].tag = "Set" + tag;
        this.conv(env, t['left'], out);
        out.push(' = ');
        t['left'].tag = tag;
        this.Infix(env, t, out);
        return tVoid;
    };
    Transpiler.prototype.GetExpr = function (env, t, out) {
        var recv = t.tokenize('recv');
        if (env.isModule(recv)) {
            var symbol = env.getModule(recv, t.tokenize('name'));
            out.push(symbol.code);
            return symbol.ty;
        }
        out.push('lib.get(');
        this.check(tMatter, env, t['recv'], out);
        var name = t.tokenize('name');
        var ty = env.inferSymbolType(name);
        if (ty === undefined) {
            env.perror(t['name'], {
                key: 'UnknownName',
                subject: name,
            });
            return this.skip(env, t, out);
        }
        var code = valueOfType(ty);
        out.push(",'" + name + "'," + code + env.trace(t['name']) + ")");
        return ty;
    };
    Transpiler.prototype.SetGetExpr = function (env, t, out) {
        var recv = t.tokenize('recv');
        if (env.isModule(recv)) {
            env.perror(t, {
                type: 'error',
                key: 'Immutable',
                subject: t.tokenize(),
            });
            return this.skip(env, t, out);
        }
        var name = t.tokenize('name');
        this.check(tMatter, env, t['recv'], out);
        out.push("." + name);
        var ty = KEYTYPES[name] || new VarType(env, t['name']);
        return ty instanceof UnionType ? ty.ptype(0) : ty;
    };
    Transpiler.prototype.IndexExpr = function (env, t, out) {
        out.push('lib.index(');
        var ty = this.check(union(new ListType(new VarType(env, t)), tString), env, t['recv'], out);
        out.push(',');
        this.check(tInt, env, t['index'], out);
        out.push(env.trace(t['index']) + ")");
        return ty instanceof ListType ? ty.ptype(0) : ty;
    };
    Transpiler.prototype.SetIndexExpr = function (env, t, out) {
        var ty = this.check(tListAny, env, t['recv'], out);
        out.push('[');
        this.check(tInt, env, t['index'], out);
        out.push(']');
        return ty instanceof ListType ? ty.ptype(0) : ty;
    };
    Transpiler.prototype.Slice = function (env, t, out) {
        out.push('lib.slice(');
        var ty = this.check(tStringOrList, env, t['recv'], out);
        out.push(',');
        var left = t['left'];
        if (left === undefined) {
            out.push('0');
        }
        else {
            this.check(tInt, env, left, out);
        }
        out.push(',');
        var right = t['right'];
        if (right === undefined) {
            out.push('undefined');
        }
        else {
            this.check(tInt, env, right, out);
        }
        out.push(env.trace(t) + ")");
        return ty;
    };
    Transpiler.prototype.Data = function (env, t, out) {
        out.push('{');
        for (var _i = 0, _a = FIXME_subs(t); _i < _a.length; _i++) {
            var sub = _a[_i];
            this.conv(env, sub, out);
            out.push(',');
        }
        out.push('}');
        return tOption;
    };
    Transpiler.prototype.KeyValue = function (env, t, out) {
        var name = t.tokenize('name');
        if (t['name'].tag === 'Name') {
            out.push("'" + name + "': ");
            var ty = env.inferSymbolType(name);
            if (ty === undefined) {
                env.perror(t['name'], {
                    type: 'warning',
                    key: 'UnknownName',
                    subject: name,
                    fix: 'EncloseQuote',
                });
            }
            this.check(ty, env, t['value'], out);
            return ty;
        }
        else {
            out.push(name + ": ");
            this.conv(env, t['value'], out);
        }
        return tVoid;
    };
    Transpiler.prototype.Tuple = function (env, t, out) {
        var subs = FIXME_subs(t);
        if (subs.length > 2) {
            env.perror(t, {
                type: 'warning',
                key: 'SyntaxError',
                fix: 'EncloseBrace',
            });
            return this.List(env, t, out);
        }
        if (subs.length == 1) {
            out.push('(');
            var ty = this.conv(env, subs[0], out);
            out.push(')');
            return ty;
        }
        out.push('lib.vec(');
        this.check(tInt, env, subs[0], out);
        out.push(',');
        this.check(tInt, env, subs[1], out);
        out.push(')');
        return tVec;
    };
    Transpiler.prototype.List = function (env, t, out) {
        var ty = new VarType(env, t);
        out.push('[');
        for (var _i = 0, _a = FIXME_subs(t); _i < _a.length; _i++) {
            var sub = _a[_i];
            ty = this.check(ty, env, sub, out, {
                type: 'error',
                key: 'AllTypeAsSame',
            });
            out.push(',');
        }
        out.push(']');
        return new ListType(ty);
    };
    Transpiler.prototype.Format = function (env, t, out) {
        var c = 0;
        out.push('(');
        for (var _i = 0, _a = FIXME_subs(t); _i < _a.length; _i++) {
            var e = _a[_i];
            if (c > 0) {
                out.push('+');
            }
            if (e.tag === 'StringPart') {
                out.push("'" + e.tokenize() + "'");
            }
            else {
                var out2 = [];
                var ty = this.conv(env, e, out2);
                if (ty === tString) {
                    out.push(out2.join(''));
                }
                else {
                    out.push("lib.str(" + out2.join('') + ")");
                }
            }
            c++;
        }
        out.push(')');
        return tString;
    };
    Transpiler.prototype.TrueExpr = function (env, t, out) {
        out.push('true');
        return tBool;
    };
    Transpiler.prototype.FalseExpr = function (env, t, out) {
        out.push('false');
        return tBool;
    };
    Transpiler.prototype.Int = function (env, t, out) {
        out.push(t.tokenize());
        return tInt;
    };
    Transpiler.prototype.Float = function (env, t, out) {
        out.push(t.tokenize());
        return tFloat;
    };
    Transpiler.prototype.Double = function (env, t, out) {
        out.push(t.tokenize());
        return tFloat;
    };
    Transpiler.prototype.String = function (env, t, out) {
        out.push(t.tokenize()); // FIXME
        return tString;
    };
    Transpiler.prototype.Char = function (env, t, out) {
        out.push(t.tokenize()); // FIXME
        return tString;
    };
    Transpiler.prototype.MultiString = function (env, t, out) {
        out.push(JSON.stringify(JSON.parse(t.tokenize())));
        return tString;
    };
    return Transpiler;
}());
var parser = puppy_parser_1.generate('Source');
var transpile = function (s) {
    var t = parser(s);
    var env = new Env();
    env.from_import(import_python);
    var ts = new Transpiler();
    var out = [];
    ts.conv(env, t, out);
    //console.log('DEBUG: ERROR LOGS')
    //console.log(JSON.stringify(env.get('@logs')));
    console.log(env.get('@logs'));
    return out.join('');
};
exports.compile = function (s) {
    //const start = performance.now();
    var t = parser(s.source);
    var env = new Env();
    env.from_import(import_python);
    var ts = new Transpiler();
    var out = [];
    ts.conv(env, t, out);
    var jscode = out.join('');
    var main = "\nreturn {\n  main: async function*(puppy) {\n\tconst lib = puppy.lib;\n\tconst vars = puppy.vars;\n" + jscode + "\n  },\n}";
    var code = {};
    try {
        code = new Function(main)();
    }
    catch (e) {
        env.perror(t, {
            type: 'error',
            key: 'CompileError',
            subject: e.toString(),
        });
    }
    //const end = performance.now();
    code['world'] = {};
    code['tree'] = t; //
    code['code'] = jscode;
    code['errors'] = env.get('@logs');
    //code['time'] = end - start;
    return code;
};
exports.puppy_version = function () { return '1.0.0 (alpha)'; };
exports.utest = function (s) {
    var src = { source: s };
    var code = exports.compile(src);
    if (code.errors.length > 0) {
        return code.errors[0].key;
    }
    var ss = code.code.split('\n');
    if (ss.length > 1) {
        var s_1 = ss[ss.length - 2].trim();
        return s_1 === '}' ? ss[ss.length - 3].trim() : s_1;
    }
    return '';
};
// console.log(transpile(`
// '''
// This is a apple.
// I'm from Chiba.
// '''
// `));
console.log(transpile("\nfrom matterjs import *\nWorld(1600, 900, background=\"white\")\n\nRectangle(800, 900, width=1600, height=100, isStatic=true)\nfor x in range(100, 701, 100):\n  Rectangle(x*1.5, 100, width=40, height=300)\n\nRectangle(100, 200, width=200, height=200)\n"));
// console.log(transpile(`
// World(1600, 900, background="white");
//
// Rectangle(800, 900, width=1600, height=100, isStatic=true)
//
// for x in range(100, 701, 100):
//     Rectangle(x*1.5, 100, width=40, height=300)
//
// Rectangle(100, 200, width=200, height=200)
// `));
// console.log(transpile(`
// for x in range(1,2):
//   for y in range(x,2):
//     x+y
// `));
// console.log(transpile(`
// def f(x,y):
//   return x*y;
// `));
console.log(transpile("\n{\n  'hoge': 1,\n  hogo: 2\n}\n"));
console.log(transpile("\nv = (1,2)\n"));