puppy-transpiler
Version:
Puppy Transpiler
1,706 lines • 54.7 kB
JavaScript
"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"));