|
var parser = require('./parser'); |
|
var fs = require('fs'); |
|
|
|
var indent_level = 0; |
|
|
|
var indent = function(s) { |
|
var lines = s.split('\n'); |
|
var indentation = ""; |
|
for(var i = 0; i < indent_level; i++) |
|
indentation += " "; |
|
var result = lines.reduce(function(acc, line) { |
|
return acc + "\n" + indentation + line; |
|
}, indentation + lines.shift()); |
|
indent_level--; |
|
return result; |
|
}; |
|
|
|
var map_infix_operation = function(op){ |
|
switch (op) { |
|
case "=": return "==="; |
|
default: return op; |
|
} |
|
}; |
|
|
|
var compile_expression = function(expr) { |
|
switch (expr.type) { |
|
case 'function_application': |
|
return compile_expression(expr['function']) + |
|
"(" + compile_expression(expr['argument']) + ")"; |
|
case 'function_definition': |
|
indent_level++; |
|
return "function(" + compile_expression(expr.parameter) + ") {\n" + |
|
indent("return " + compile_expression(expr.body) + ";") + |
|
"\n}"; |
|
case "if": |
|
indent_level++; |
|
return "if_func$(" + compile_expression(expr.condition) + ", \n" + |
|
indent(compile_expression(expr['true']) + ",\n" + |
|
compile_expression(expr['false']) + ")"); |
|
case 'range': |
|
return "range_func$(" + compile_expression(expr.stop) + ")"; |
|
case 'map': |
|
return compile_expression(expr.range) + ".map(" + |
|
compile_expression(expr.transformation) + ")"; |
|
case 'reduce': |
|
indent_level++; |
|
return compile_expression(expr.range) + |
|
".reduce(function(" + compile_expression(expr.accumulator) + ", " + compile_expression(expr.reducer.parameter) + ") {\n" + |
|
indent("return " + compile_expression(expr.reducer.body) + ";") + |
|
"\n}, " + |
|
compile_expression(expr.initial) + ")"; |
|
case 'filter': |
|
return compile_expression(expr.range) + ".filter(" + |
|
compile_expression(expr.predicate) + ")"; |
|
case 'pipe': |
|
return compile_expression(expr.target) + "(" + |
|
compile_expression(expr.source) + ")"; |
|
case 'identifier': |
|
return expr.value.replace('-', '_'); |
|
case 'int': |
|
return expr.value; |
|
case 'infix': |
|
return "(" + compile_expression(expr.left) + |
|
" " + map_infix_operation(expr.operation) + " " + |
|
compile_expression(expr.right) + ")"; |
|
case 'comment': |
|
return ""; |
|
default: |
|
throw "Unknown expression type: " + expr.type + " " + expr; |
|
} |
|
}; |
|
|
|
var core = "function if_func$(c, t, f) { if(c){ return t } return f; }\n"; |
|
core += "function range_func$(stop) { " + |
|
" var range = [];" + |
|
" for(var i=0;i<=stop;i++){ range.push(i); }" + |
|
" return range;}\n"; |
|
|
|
var compile = function(ast) { |
|
return core + ast.reduce(function(acc, expr) { |
|
return acc + " " + compile_expression(expr); |
|
}, 'console.log(') + ')'; |
|
}; |
|
|
|
var input_file = process.argv[2]; |
|
fs.readFile(input_file, function(err, source) { |
|
if(err) |
|
return console.log(err); |
|
|
|
var result = parser.parse(source.toString()); |
|
|
|
console.log(compile(result)); |
|
}); |