Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save applideveloper/4ae1810464249fce0d693deccd8ce9f3 to your computer and use it in GitHub Desktop.
Save applideveloper/4ae1810464249fce0d693deccd8ce9f3 to your computer and use it in GitHub Desktop.
JavaScript generator for nub.
// Input:
// def printRange(from, to) { let i = from; while(i < to) { println(i); i = i + 1; } } printRange(1, 10); // Loop
// Raw output:
// (function(){ let __last__ = 0;let printRange = function(from,to){ let __last__ = 0;let i = from;__last__ = i;__last__ = (function(){ let __last__ = 0;while( (i<to) ){__last__ = console.log(i);;__last__ = (i = (i+1));}return __last__;})();;return __last__;};__last__ = printRange;__last__ = (printRange)(1,10);return __last__;})();
(function() {
let __last__ = 0;
let printRange = function(from, to) {
let __last__ = 0;
let i = from;
__last__ = i;
__last__ = (function() {
let __last__ = 0;
while ((i < to)) {
__last__ = console.log(i);;
__last__ = (i = (i + 1));
}
return __last__;
})();;
return __last__;
};
__last__ = printRange;
__last__ = (printRange)(1, 10);
return __last__;
})();
package com.github.kmizu.nub;
import java.util.*;
public class JavaScriptGenerator implements AstNode.ExpressionVisitor<Object> {
private Set<String> functions = new HashSet<>();
private StringBuilder stringBuilder = new StringBuilder();
public Object visitBinaryOperation(AstNode.BinaryOperation node) {
switch (node.operator()) {
case "+":
case "-":
case "*":
case "<=":
case ">=":
case "<":
case ">":
case "&&":
case "||":
stringBuilder.append('(');
node.lhs().accept(this);
stringBuilder.append(node.operator());
node.rhs().accept(this);
stringBuilder.append(')');
return null;
case "/":
stringBuilder.append("((");
node.lhs().accept(this);
stringBuilder.append(node.operator());
node.rhs().accept(this);
stringBuilder.append("|0)");
return null;
case "==":
stringBuilder.append('(');
node.lhs().accept(this);
stringBuilder.append("===");
node.rhs().accept(this);
stringBuilder.append(')');
return null;
case "!=":
stringBuilder.append('(');
node.lhs().accept(this);
stringBuilder.append("!==");
node.rhs().accept(this);
stringBuilder.append(')');
return null;
default:
throw new RuntimeException("cannot reach here");
}
}
@Override
public Object visitNumber(AstNode.Number node) {
stringBuilder.append(node.value());
return null;
}
@Override
public Object visitLetExpression(AstNode.LetExpression node) {
stringBuilder.append("let ");
stringBuilder.append(node.variableName());
stringBuilder.append(" = ");
Object value = node.expression().accept(this);
return null;
}
@Override
public Object visitAssignmentOperation(AstNode.AssignmentOperation node) {
stringBuilder.append("(");
stringBuilder.append(node.variableName());
stringBuilder.append(" = ");
Object value = node.expression().accept(this);
stringBuilder.append(")");
return null;
}
@Override
public Object visitPrintExpression(AstNode.PrintExpression node) {
stringBuilder.append("console.log(");
node.target().accept(this);
stringBuilder.append(");");
return null;
}
@Override
public Object visitPrintlnExpression(AstNode.PrintlnExpression node) {
stringBuilder.append("console.log(");
node.target().accept(this);
stringBuilder.append(");");
return null;
}
private void visitExpressions(List<AstNode.Expression> nodes)
{
for (AstNode.Expression e : nodes) {
if(e instanceof AstNode.DefFunction) {
e.accept(this);
stringBuilder.append(";");
stringBuilder.append("__last__ = ");
stringBuilder.append(((AstNode.DefFunction)e).name());
} else if(e instanceof AstNode.LetExpression) {
e.accept(this);
stringBuilder.append(";");
stringBuilder.append("__last__ = ");
stringBuilder.append(((AstNode.LetExpression)e).variableName());
} else {
stringBuilder.append("__last__ = ");
e.accept(this);
}
stringBuilder.append(";");
}
}
@Override
public Object visitExpressionList(AstNode.ExpressionList node) {
stringBuilder.append("(function(){ let __last__ = 0;"); {
visitExpressions(node.expressions());
stringBuilder.append("return __last__;})();");
}
return null;
}
@Override
public Object visitWhileExpression(AstNode.WhileExpression node) {
stringBuilder.append("(function(){ let __last__ = 0;");
{
stringBuilder.append("while( ");
node.condition().accept(this);
stringBuilder.append(" ){");
{
visitExpressions(node.body());
stringBuilder.append("}");
}
stringBuilder.append("return __last__;})();");
}
return null;
}
@Override
public Object visitIfExpression(AstNode.IfExpression node) {
stringBuilder.append("(function(){ let __last__ = 0;"); {
stringBuilder.append("if( ");
node.condition().accept(this);
stringBuilder.append(" ){");
{
visitExpressions(node.thenClause());
stringBuilder.append("}");
}
if(node.elseClause().size() > 0) {
stringBuilder.append("else{"); {
visitExpressions(node.elseClause());
stringBuilder.append("}");
}
}
stringBuilder.append("return __last__;})();");
}
return null;
}
@Override
public Object visitDefFunction(AstNode.DefFunction node) {
stringBuilder.append("let ");
stringBuilder.append(node.name());
stringBuilder.append(" = function(");
boolean isFirst = true;
for(String e:node.args()) {
stringBuilder.append(e);
if(isFirst){
isFirst = false;
stringBuilder.append(",");
}
}
stringBuilder.append("){ let __last__ = 0;"); {
visitExpressions(node.body());
stringBuilder.append("return __last__;}");
}
return null;
}
@Override
public Object visitIdentifier(AstNode.Identifier node) {
stringBuilder.append(node.name());
return null;
}
public Object evaluate(AstNode.ExpressionList program) {
stringBuilder = new StringBuilder();
program.accept(this);
return stringBuilder.toString();
}
@Override
public Object visitFunctionCall(AstNode.FunctionCall node) {
//if(!functions.contains(node.name())) {
// throw new NubRuntimeException("function " + node.name().name() + " is not defined");
//}
{
stringBuilder.append("(");
node.name().accept(this);
stringBuilder.append(")(");
boolean isFirst = true;
for(AstNode.Expression e:node.params()) {
e.accept(this);
if(isFirst){
isFirst = false;
stringBuilder.append(",");
}
}
stringBuilder.append(")");
return null;
}
}
@Override
public Object visitReturn(AstNode.Return node) {
stringBuilder.append("return ");
node.expression().accept(this);
stringBuilder.append(";");
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment