Skip to content

Instantly share code, notes, and snippets.

@munro
Last active December 10, 2015 16:48
Show Gist options
  • Select an option

  • Save munro/4463356 to your computer and use it in GitHub Desktop.

Select an option

Save munro/4463356 to your computer and use it in GitHub Desktop.
PyScript
import ast
import json
import operator as op
import inspect
f = open(inspect.getfile(inspect.currentframe()))
code = ast.parse(f.read())
def tab_over(code):
return '\n'.join([' ' + line for line in \
filter(op.truth, code.split('\n'))])
def compile_op(op):
if isinstance(op, ast.Add):
return '+'
if isinstance(op, ast.Sub):
return '-'
if isinstance(op, ast.Gt):
return '>'
if isinstance(op, ast.Lt):
return '-'
if isinstance(op, ast.Eq):
return '==='
if isinstance(op, ast.And):
return '&&'
if isinstance(op, ast.Or):
return '||'
if isinstance(op, ast.Not):
return '!'
if isinstance(op, ast.Mod):
# TODO! String interpolation.... JavaScript doesn't support operator
# overloading
return '%'
if isinstance(op, ast.In):
raise 'Nope, handle this higher up.'
print('----OP %s----' % op.__class__.__name__)
print(ast.dump(op))
return '----OP %s----' % op.__class__.__name__
def wrap_expr(fn):
def wrapper(node):
fuck = {'you': ''}
def add_statement(text):
fuck['you'] += text
out = fn(node, add_statement)
# return out if isinstance(out, str) else out[0]
return (out, fuck['you']) \
if isinstance(out, str) \
else (out[0], code + fuck['you'])
return wrapper
def is_literal(node):
return any([isinstance(node, t) for t in [ast.Str, ast.Num]]) \
or (isinstance(node, ast.Name) and (node.id in ['True', 'False']))
@wrap_expr
def compile_expr(node, add_statement):
def expr(node):
expr, stmt = compile_expr(node)
add_statement(stmt)
return expr
if isinstance(node, ast.List) or isinstance(node, ast.Tuple):
return '[' + ', '.join([expr(elt) for elt in node.elts]) + ']'
if isinstance(node, ast.Dict):
if any([not is_literal(key) for key in node.keys]):
raise 'YOU SUCK! TODO'
return '{\n ' + ',\n'.join([
'%s: %s' % (expr(key), expr(value))
for key, value in zip(node.keys, node.values)
]) + '\n}'
if isinstance(node, ast.Name):
if node.id == 'True':
return 'true'
if node.id == 'False':
return 'false'
return node.id
if isinstance(node, ast.Compare):
def handle_comparator(left, op, right):
if isinstance(op, ast.In):
return '%s.some(function (_v) {\n return _v === %s;\n})' % (
expr(right),
expr(left),
)
return expr(left) + ' ' + \
compile_op(op) + ' ' + \
expr(right)
return ' && '.join([
handle_comparator(left, op, right)
for left, op, right in zip(
[node.left] + node.comparators[:-1],
node.ops,
node.comparators,
)
])
if isinstance(node, ast.Num):
return str(node.n)
if isinstance(node, ast.Str):
return json.dumps(node.s)
if isinstance(node, ast.Lambda):
return 'function (%s) {\n return %s;\n}' % (
', '.join([expr(arg) for arg in node.args.args]),
tab_over(expr(node.body)).lstrip()
)
if isinstance(node, ast.Attribute):
# TODO: Handle reserved keywords & invalid methods properly
return expr(node.value) + '.' + node.attr
if isinstance(node, ast.BoolOp):
# TODO: Wtf? why is this a list...? :/
return expr(node.values[0]) + ' ' + \
compile_op(node.op) + ' ' + \
expr(node.values[1])
if isinstance(node, ast.BinOp):
return expr(node.left) + ' ' + compile_op(node.op) + ' ' + \
expr(node.right)
if isinstance(node, ast.UnaryOp):
return compile_op(node.op) + expr(node.operand)
if isinstance(node, ast.Call):
return expr(node.func) + '(' + ', '.join(
[expr(arg) for arg in node.args]
) + ')'
if isinstance(node, ast.Index):
return expr(node.value)
if isinstance(node, ast.IfExp):
return '(%s ? %s : %s)' % (
expr(node.test),
expr(node.body),
expr(node.orelse),
)
if isinstance(node, ast.Subscript):
if isinstance(node.slice, ast.Slice):
return '(function (list) {\n var a = %s,\n b = %s;\n return list.slice(a, b < 0 ? list.length - b : b);\n}(%s))' % (
# ast.dump(node.slice),
expr(node.slice.lower) if node.slice.lower else '0',
expr(node.slice.upper) if node.slice.upper else 'list.length',
expr(node.value),
)
return '%s[%s]' % (expr(node.value), expr(node.slice))
if isinstance(node, ast.Slice):
raise 'NOPE'
if isinstance(node, ast.ListComp):
def compile_gen(code, gen):
if isinstance(gen.target, ast.Tuple):
return '%s.map(function (__temp__) {\n%s\n return %s;\n})' % (
expr(gen.iter),
'\n'.join([ # copy-pasta
' %s%s = __temp__[%s];' % (
'var ' if isinstance(elt, ast.Name) else '',
expr(elt),
str(i),
)
for i, elt in enumerate(gen.target.elts)
]),
tab_over(code).lstrip(),
)
return '%s.map(function (%s) {\n return %s;\n})' % (
expr(gen.iter),
expr(gen.target),
tab_over(code).lstrip(),
)
return reduce(
compile_gen,
node.generators,
'%s' % expr(node.elt),
) + ''.join(['.reduce(function (a, b) {\n return a.concat(b);\n})' for _ in range(len(node.generators) - 1)])
if isinstance(node, ast.alias):
return (node.asname or node.name) + ' = require(' + \
json.dumps(node.name) + ')'
print('----EXPR %s----' % node.__class__.__name__)
# print(node)
# print(dir(node))
print(ast.dump(node))
return '----EXPR %s----' % node.__class__.__name__
# print(n)
# print({k : getattr(n, k) for k in n._attributes})
# print({k : getattr(n, k) for k in n._fields})
# print(dir(n.func))
# print('----')
# print(n.func.value)
# print(dir(n.func.value))
def wrap_statement(fn):
def wrapper(node):
fuck = {'you': ''}
def add_statement(text):
fuck['you'] += text
out = fn(node, add_statement)
return (fuck['you'] and fuck['you'] + '\n') + out
# return out if isinstance(out, str) else out[0]
return (out, fuck['you']) \
if isinstance(out, str) \
else (out[0], code + fuck['you'])
return wrapper
# return lambda n, tabs=0: '\n'.join(
# [(' ' if tabs else '') + line for line in fn(n, tabs).split('\n')]
# ) + '\n'
@wrap_statement
def compile_statement(node, add_statement):
# expr = compile_expr
def expr(node):
expr, stmt = compile_expr(node)
add_statement(stmt)
return expr
def sub_statement(body):
return '\n'.join([
' ' + line \
for line \
in filter(op.truth, '\n'.join(
[compile_statement(sub_node) for sub_node in body]
).split('\n'))
])
if isinstance(node, ast.FunctionDef):
decs = [expr(dec) + '(' for dec in node.decorator_list]
return 'var %s = %sfunction (%s) {\n' % (
node.name,
''.join(decs),
', '.join([arg.id for arg in node.args.args])
) + sub_statement(node.body) + '\n}%s' % (
''.join(map(lambda x: ')', decs)) # meh
) + ';'
if isinstance(node, ast.Return):
return 'return ' + expr(node.value) + ';'
if isinstance(node, ast.Expr):
return expr(node.value) + ';'
if isinstance(node, ast.Pass):
return ''
if isinstance(node, ast.Import):
return '\n'.join(
['var ' + expr(name) + ';' for name in node.names]
)
if isinstance(node, ast.Assign):
# TODO: HANDLE SCOPING CORRECTLY
if len(node.targets) > 1:
raise 'wtf? when does this happen?'
if isinstance(node.targets[0], ast.Tuple):
return 'var __temp__ = %s;\n' % expr(node.value) + '\n'.join([
'%s%s = __temp__[%s];' % (
'var ' if isinstance(elt, ast.Name) else '',
expr(elt),
str(i),
)
for i, elt in enumerate(node.targets[0].elts)
])
return (
'var ' + expr(node.targets[0]) + ' = ' +
expr(node.value) + ';'
)
if isinstance(node, ast.Print):
return 'console.log(%s);' % ', '.join(
[expr(arg) for arg in node.values]
)
if isinstance(node, ast.ClassDef):
# decorator_list????
js = 'function %s(???) {\n' % (node.name)
js += sub_statement(node.body) + '\n'
js += '}\n'
js += '\n'.join(
[node.name + '.prototype = Object.create(' + expr(base) + \
');' for base in node.bases]
)
return js
if isinstance(node, ast.Raise):
return 'throw %s;' % expr(node.type)
def compile_if(node):
js = '\n'.join(
['if ({test}) {{'.format(test=expr(node.test))] +
[sub_statement(node.body)] +
['}']
)
if len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If):
js += ' else ' + compile_if(node.orelse[0])
elif len(node.orelse):
js += ' else {\n' + sub_statement(node.orelse) + '\n}'
return js
if isinstance(node, ast.If):
return compile_if(node)
if isinstance(node, ast.AugAssign):
return expr(node.target) + ' ' + compile_op(node.op) + '= ' + \
expr(node.value)
print('----STMT %s----' % node.__class__.__name__)
print(ast.dump(node))
return '----STMT %s----' % node.__class__.__name__
print('\n'.join(filter(op.truth, [compile_statement(node) or '' for node in code.body])))
var ast = require("ast");
var json = require("json");
var op = require("operator");
var inspect = require("inspect");
var f = open(inspect.getfile(inspect.currentframe()));
var code = ast.parse(f.read());
var tab_over = function (code) {
return "\n".join(filter(op.truth, code.split("\n")).map(function (line) {
return " " + line;
}));
};
var compile_op = function (op) {
if (isinstance(op, ast.Add)) {
return "+";
}
if (isinstance(op, ast.Sub)) {
return "-";
}
if (isinstance(op, ast.Gt)) {
return ">";
}
if (isinstance(op, ast.Lt)) {
return "-";
}
if (isinstance(op, ast.Eq)) {
return "===";
}
if (isinstance(op, ast.And)) {
return "&&";
}
if (isinstance(op, ast.Or)) {
return "||";
}
if (isinstance(op, ast.Not)) {
return "!";
}
if (isinstance(op, ast.Mod)) {
return "%";
}
if (isinstance(op, ast.In)) {
throw "Nope, handle this higher up.";
}
console.log("----OP %s----" % op.__class__.__name__);
console.log(ast.dump(op));
return "----OP %s----" % op.__class__.__name__;
};
var wrap_expr = function (fn) {
var wrapper = function (node) {
var fuck = {
"you": ""
};
var add_statement = function (text) {
fuck["you"] += text
};
var out = fn(node, add_statement);
return (isinstance(out, str) ? [out, fuck["you"]] : [out[0], code + fuck["you"]]);
};
return wrapper;
};
var is_literal = function (node) {
return any([ast.Str, ast.Num].map(function (t) {
return isinstance(node, t);
})) || isinstance(node, ast.Name) && ["True", "False"].some(function (_v) {
return _v === node.id;
});
};
var compile_expr = wrap_expr(function (node, add_statement) {
var expr = function (node) {
var __temp__ = compile_expr(node);
var expr = __temp__[0];
var stmt = __temp__[1];
add_statement(stmt);
return expr;
};
if (isinstance(node, ast.List) || isinstance(node, ast.Tuple)) {
return "[" + ", ".join(node.elts.map(function (elt) {
return expr(elt);
})) + "]";
}
if (isinstance(node, ast.Dict)) {
if (any(node.keys.map(function (key) {
return !is_literal(key);
}))) {
throw "YOU SUCK! TODO";
}
return "{\n " + ",\n".join(zip(node.keys, node.values).map(function (__temp__) {
var key = __temp__[0];
var value = __temp__[1];
return "%s: %s" % [expr(key), expr(value)];
})) + "\n}";
}
if (isinstance(node, ast.Name)) {
if (node.id === "True") {
return "true";
}
if (node.id === "False") {
return "false";
}
return node.id;
}
if (isinstance(node, ast.Compare)) {
var handle_comparator = function (left, op, right) {
if (isinstance(op, ast.In)) {
return "%s.some(function (_v) {\n return _v === %s;\n})" % [expr(right), expr(left)];
}
return expr(left) + " " + compile_op(op) + " " + expr(right);
};
return " && ".join(zip([node.left] + (function (list) {
var a = 0,
b = -1;
return list.slice(a, b < 0 ? list.length - b : b);
}(node.comparators)), node.ops, node.comparators).map(function (__temp__) {
var left = __temp__[0];
var op = __temp__[1];
var right = __temp__[2];
return handle_comparator(left, op, right);
}));
}
if (isinstance(node, ast.Num)) {
return str(node.n);
}
if (isinstance(node, ast.Str)) {
return json.dumps(node.s);
}
if (isinstance(node, ast.Lambda)) {
return "function (%s) {\n return %s;\n}" % [", ".join(node.args.args.map(function (arg) {
return expr(arg);
})), tab_over(expr(node.body)).lstrip()];
}
if (isinstance(node, ast.Attribute)) {
return expr(node.value) + "." + node.attr;
}
if (isinstance(node, ast.BoolOp)) {
return expr(node.values[0]) + " " + compile_op(node.op) + " " + expr(node.values[1]);
}
if (isinstance(node, ast.BinOp)) {
return expr(node.left) + " " + compile_op(node.op) + " " + expr(node.right);
}
if (isinstance(node, ast.UnaryOp)) {
return compile_op(node.op) + expr(node.operand);
}
if (isinstance(node, ast.Call)) {
return expr(node.func) + "(" + ", ".join(node.args.map(function (arg) {
return expr(arg);
})) + ")";
}
if (isinstance(node, ast.Index)) {
return expr(node.value);
}
if (isinstance(node, ast.IfExp)) {
return "(%s ? %s : %s)" % [expr(node.test), expr(node.body), expr(node.orelse)];
}
if (isinstance(node, ast.Subscript)) {
if (isinstance(node.slice, ast.Slice)) {
return "(function (list) {\n var a = %s,\n b = %s;\n return list.slice(a, b < 0 ? list.length - b : b);\n}(%s))" % [(node.slice.lower ? expr(node.slice.lower) : "0"), (node.slice.upper ? expr(node.slice.upper) : "list.length"), expr(node.value)];
}
return "%s[%s]" % [expr(node.value), expr(node.slice)];
}
if (isinstance(node, ast.Slice)) {
throw "NOPE";
}
if (isinstance(node, ast.ListComp)) {
var compile_gen = function (code, gen) {
if (isinstance(gen.target, ast.Tuple)) {
return "%s.map(function (__temp__) {\n%s\n return %s;\n})" % [expr(gen.iter), "\n".join(enumerate(gen.target.elts).map(function (__temp__) {
var i = __temp__[0];
var elt = __temp__[1];
return " %s%s = __temp__[%s];" % [(isinstance(elt, ast.Name) ? "var " : ""), expr(elt), str(i)];
})), tab_over(code).lstrip()];
}
return "%s.map(function (%s) {\n return %s;\n})" % [expr(gen.iter), expr(gen.target), tab_over(code).lstrip()];
};
return reduce(compile_gen, node.generators, "%s" % expr(node.elt)) + "".join(range(len(node.generators) - 1).map(function (_) {
return ".reduce(function (a, b) {\n return a.concat(b);\n})";
}));
}
if (isinstance(node, ast.alias)) {
return node.asname || node.name + " = require(" + json.dumps(node.name) + ")";
}
console.log("----EXPR %s----" % node.__class__.__name__);
console.log(ast.dump(node));
return "----EXPR %s----" % node.__class__.__name__;
});
var wrap_statement = function (fn) {
var wrapper = function (node) {
var fuck = {
"you": ""
};
var add_statement = function (text) {
fuck["you"] += text
};
var out = fn(node, add_statement);
return fuck["you"] && fuck["you"] + "\n" + out;
return (isinstance(out, str) ? [out, fuck["you"]] : [out[0], code + fuck["you"]]);
};
return wrapper;
};
var compile_statement = wrap_statement(function (node, add_statement) {
var expr = function (node) {
var __temp__ = compile_expr(node);
var expr = __temp__[0];
var stmt = __temp__[1];
add_statement(stmt);
return expr;
};
var sub_statement = function (body) {
return "\n".join(filter(op.truth, "\n".join(body.map(function (sub_node) {
return compile_statement(sub_node);
})).split("\n")).map(function (line) {
return " " + line;
}));
};
if (isinstance(node, ast.FunctionDef)) {
var decs = node.decorator_list.map(function (dec) {
return expr(dec) + "(";
});
return "var %s = %sfunction (%s) {\n" % [node.name, "".join(decs), ", ".join(node.args.args.map(function (arg) {
return arg.id;
}))] + sub_statement(node.body) + "\n}%s" % "".join(map(function (x) {
return ")";
}, decs)) + ";";
}
if (isinstance(node, ast.Return)) {
return "return " + expr(node.value) + ";";
}
if (isinstance(node, ast.Expr)) {
return expr(node.value) + ";";
}
if (isinstance(node, ast.Pass)) {
return "";
}
if (isinstance(node, ast.Import)) {
return "\n".join(node.names.map(function (name) {
return "var " + expr(name) + ";";
}));
}
if (isinstance(node, ast.Assign)) {
if (len(node.targets) > 1) {
throw "wtf? when does this happen?";
}
if (isinstance(node.targets[0], ast.Tuple)) {
return "var __temp__ = %s;\n" % expr(node.value) + "\n".join(enumerate(node.targets[0].elts).map(function (__temp__) {
var i = __temp__[0];
var elt = __temp__[1];
return "%s%s = __temp__[%s];" % [(isinstance(elt, ast.Name) ? "var " : ""), expr(elt), str(i)];
}));
}
return "var " + expr(node.targets[0]) + " = " + expr(node.value) + ";";
}
if (isinstance(node, ast.Print)) {
return "console.log(%s);" % ", ".join(node.values.map(function (arg) {
return expr(arg);
}));
}
if (isinstance(node, ast.ClassDef)) {
var js = "function %s(???) {\n" % node.name;
js += sub_statement(node.body) + "\n"
js += "}\n"
js += "\n".join(node.bases.map(function (base) {
return node.name + ".prototype = Object.create(" + expr(base) + ");";
}))
return js;
}
if (isinstance(node, ast.Raise)) {
return "throw %s;" % expr(node.type);
}
var compile_if = function (node) {
var js = "\n".join(["if ({test}) {{".format()] + [sub_statement(node.body)] + ["}"]);
if (len(node.orelse) === 1 && isinstance(node.orelse[0], ast.If)) {
js += " else " + compile_if(node.orelse[0])
} else if (len(node.orelse)) {
js += " else {\n" + sub_statement(node.orelse) + "\n}"
}
return js;
};
if (isinstance(node, ast.If)) {
return compile_if(node);
}
if (isinstance(node, ast.AugAssign)) {
return expr(node.target) + " " + compile_op(node.op) + "= " + expr(node.value);
}
console.log("----STMT %s----" % node.__class__.__name__);
console.log(ast.dump(node));
return "----STMT %s----" % node.__class__.__name__;
});
console.log("\n".join(filter(op.truth, code.body.map(function (node) {
return compile_statement(node) || "";
}))));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment