package com.laytonsmith.core.compiler;
import com.laytonsmith.annotations.api;
import com.laytonsmith.core.MethodScriptCompiler;
import com.laytonsmith.core.ParseTree;
import com.laytonsmith.core.exceptions.ConfigCompileException;
import com.laytonsmith.core.exceptions.ConfigCompileGroupException;
import com.laytonsmith.core.functions.CompiledFunction;
import com.laytonsmith.core.functions.FunctionBase;
import com.laytonsmith.core.functions.FunctionList;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* The static compiler uses the dynamic compiler, but using a platform specific framework,
* ends up with output that can be written to out to disk, and run natively, or compiles
* to another language entirely.
*
*/
public final class MethodScriptStaticCompiler {
private MethodScriptStaticCompiler(){}
/**
* Compiles the script, converting it into mid level object code, or in
* the case of a language compiler, the other language's source code.
* @param script
* @param platform
* @return
*/
public static String compile(String script, api.Platforms platform, File file) throws ConfigCompileException, ConfigCompileGroupException{
//First, we optimize. The "core" functions are always run through
//the native interpreter's compiler for optimization.
ParseTree tree = MethodScriptCompiler.compile(MethodScriptCompiler.lex(script, file, true));
StringBuilder b = new StringBuilder();
for(ParseTree node : tree.getChildren()){
go(node, b, platform);
}
return b.toString();
}
private static void go(ParseTree node, StringBuilder b, api.Platforms platform) throws ConfigCompileException{
if(node.hasChildren()){
FunctionBase f = FunctionList.getFunction(node.getData(), platform);
if(!(f instanceof CompiledFunction)){
throw new ConfigCompileException("The function " + f.getName() + " is unknown in this platform.", node.getData().getTarget());
}
CompiledFunction cf = (CompiledFunction)f;
List<String> children = new ArrayList<String>();
for(ParseTree baby : node.getChildren()){
StringBuilder bb = new StringBuilder();
go(baby, bb, platform);
children.add(bb.toString());
}
b.append(cf.compile(node.getData().getTarget(), children.toArray(new String[children.size()])));
} else {
if(platform.getResolver() == null){
b.append(node.getData().val());
} else {
b.append(platform.getResolver().outputConstant(node.getData()));
}
}
}
}