Created
January 22, 2017 04:52
-
-
Save anonymous/a499a8d8f9f895ae444f3190848a42c5 to your computer and use it in GitHub Desktop.
JavaScript generator for nub.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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__; | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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