LispInterpreter.java
No OneTemporary

File Metadata

Created
Mon, Aug 24, 10:05 AM

LispInterpreter.java

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.xreate.grammatic.lisp;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.antlr.runtime.*;
import org.jllvm.*;
import org.jllvm.bindings.*;
import org.xreate.TestRunner2;
/**
*
* @author pgess
*/
public class LispInterpreter {
static Map<String, String> htable;
static Map<String, LLVMType> ttable;
public Map<String, String> opcodes = Maps.newLinkedHashMap();
public Map<String, LLVMFunction> functions = Maps.newLinkedHashMap();
protected LLVMInstructionBuilder builder = new LLVMInstructionBuilder();
protected LLVMModule module = new LLVMModule("script");
//"/private/prg/code/xreate/scripts/opcode.li"
public void run(String filename) throws IOException, RecognitionException, Exception{
ANTLRStringStream in = new ANTLRFileStream(filename);
Lexer l = new LispLexer(in);
CommonTokenStream tokens = new CommonTokenStream(l);
LispParser p = new LispParser(tokens);
while (true){
ASTLispNode node = p.statement(null);
handle(node);
}
}
public void opcodeDef(ASTLispNode node){
ArrayList<ASTLispNode> params = node.parameters;
opcodes.put(params.get(0).caption, params.get(1).caption);
}
public void functionDef(ASTLispNode node) throws Exception{
ArrayList<ASTLispNode> nodes_vars = node.get("vars-list").parameters;
int nsize = nodes_vars.size();
LLVMType[] arg_types = new LLVMType[nsize];
for (int i=0; i<nsize; i++){
String type_caption = nodes_vars.get(i).get("type").parameters.get(0).caption;
arg_types[i] = ttable.get(type_caption);
}
LLVMType ret_type = ttable.get(node.get("return").get("type").parameters.get(0).caption);
String func_name = node.get("name").parameters.get(0).caption;
LLVMFunctionType func_type =new LLVMFunctionType(ret_type, arg_types, false);
LLVMFunction func = new LLVMFunction(module, func_name, func_type);
LLVMBasicBlock entry = func.appendBasicBlock("entry");
builder.positionBuilderAtEnd(entry);
LLVMValue[] values = func.getParameters();
String[] vars = new NodeFunctionVarsList(node.get("vars-list")).getVarNames();
LLVMValue func_body = new Evaluator(vars, values).eval(node.get("body").parameters.get(0));
new LLVMReturnInstruction(builder, func_body);
SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1);
int x = Analysis.LLVMVerifyFunction(func.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction);
x = Analysis.LLVMVerifyModule(module.getInstance(), LLVMVerifierFailureAction.LLVMReturnStatusAction, outerrs);
ExecutionEngine.delete_StringArray(outerrs); outerrs = null;
functions.put(func_name, func);
}
public int main(ASTLispNode node) throws Exception{
String func_main_name = node.parameters.get(0).caption;
LLVMFunction func_main = functions.get(func_main_name);
if (null == func_main){
throw new Exception("Main function not found!");
}
boolean isNative = LLVMTargetData.initializeNativeTarget();
LispJITRunnerWrapper program = new LispJITRunnerWrapper(module);
LLVMGenericValue resultRef = program.runFunction(func_main, new LLVMGenericValue[0]);
BigInteger resultBig = ExecutionEngine.LLVMGenericValueToInt(resultRef.getInstance(), 0);
int result = resultBig.intValue();
return result;
/*
TestRunner2 runner = new TestRunner2();
runner.setModule(module);
runner.runBody(func_main);
return 0;
*
*/
}
public Object handle(ASTLispNode node) throws Exception{
String caption = node.caption;
String method = htable.get(caption);
if (method == null) {
throw new Exception();
}
Method invoker = this.getClass().getDeclaredMethod(method, ASTLispNode.class);
return invoker.invoke(this, node);
}
public LispInterpreter(){
}
static {
/*
* Handler table хранит информацию о соответствии метода и команды
*/
htable = new ImmutableMap.Builder<String, String>()
.put("opcode", "opcodeDef")
.put("function", "functionDef")
.put ("calculate", "calculate")
.put("main", "main")
.build();
/*
* Types Table - хранит информацию о соответствии типов
*/
ttable = new ImmutableMap.Builder<String, LLVMType>()
.put ("i32", LLVMIntegerType.i32)
.put ("i16", LLVMIntegerType.i16)
.put ("i8", LLVMIntegerType.i8)
.build();
}
class Evaluator{
Map<String, LLVMValue> arguments;
public Evaluator(String[] names, LLVMValue[] values) {
int size = names.length;
arguments = Maps.newHashMapWithExpectedSize(size);
for(int i=0; i<size; i++){
arguments.put(names[i], values[i]);
}
}
public LLVMValue LLVMAddInstruction(ASTLispNode node) throws Exception{
LLVMValue arg1 = eval(node.parameters.get(0));
LLVMValue arg2 = eval(node.parameters.get(1));
return new LLVMAddInstruction(builder, arg1, arg2, false, "add");
}
public LLVMValue LLVMDivideInstruction(ASTLispNode node) throws Exception{
LLVMValue arg1 = eval(node.parameters.get(0));
LLVMValue arg2 = eval(node.parameters.get(1));
return new LLVMDivideInstruction(builder, arg1, arg2, LLVMDivideInstruction.DivisionType.UNSIGNEDINT, "div");
}
public LLVMValue LLVMCallFunctionInstruction(ASTLispNode node) throws Exception{
LLVMFunction func = functions.get(node.caption);
int size = node.parameters.size();
LLVMValue[] args = new LLVMValue[size];
for (int i=0; i<size; i++){
args[i] = eval(node.parameters.get(i));
}
// long argsNum = Core.LLVMCountParamTypes(Core.LLVMTypeOf(func.getInstance()));
SWIGTYPE_p_p_LLVMOpaqueValue args_opaque = Core.new_LLVMValueRefArray(args.length);
for(int i=0;i<args.length;i++)
Core.LLVMValueRefArray_setitem(args_opaque,i,args[i].getInstance());
SWIGTYPE_p_LLVMOpaqueValue instance = Core.LLVMBuildCall(builder.getInstance(),func.getInstance(),args_opaque,args.length, node.caption + "aaa");
Core.delete_LLVMValueRefArray(args_opaque);
return new LLVMValue(instance);
//return new LLVMCallInstruction(builder, func, args, node.caption);
}
public LLVMValue eval(ASTLispNode node) throws Exception{
if (node instanceof ASTLispConstantNode){
return LLVMConstantInteger.constantInteger(LLVMIntegerType.i32, ((ASTLispConstantNode) node).value, false);
}
String instruction = opcodes.get(node.caption);
if (instruction != null) {
Method invoker = this.getClass().getDeclaredMethod(instruction, ASTLispNode.class);
return (LLVMValue) invoker.invoke(this, node);
}
LLVMValue arg = arguments.get(node.caption);
if (arg != null){
return arg;
}
if (functions.containsKey(node.caption)){
return LLVMCallFunctionInstruction(node);
}
throw new Exception("Cant evaluate symbol: " + node.caption);
}
}
}
class LispJITRunnerWrapper extends LLVMExecutionEngine{
LispJITRunnerWrapper(LLVMModule module) throws Exception{
super();
SWIGTYPE_p_p_LLVMOpaqueExecutionEngine engines = ExecutionEngine.new_LLVMExecutionEngineRefArray(1);
SWIGTYPE_p_p_char outerrs = ExecutionEngine.new_StringArray(1);
int success = ExecutionEngine.LLVMCreateJITCompilerForModule(engines,module.getInstance(), 0, outerrs);
String outerr = ExecutionEngine.StringArray_getitem(outerrs,0);
ExecutionEngine.delete_StringArray(outerrs); outerrs = null;
instance = ExecutionEngine.LLVMExecutionEngineRefArray_getitem(engines,0);
ExecutionEngine.delete_LLVMExecutionEngineRefArray(engines); engines = null;
/*
if(success == 0)
throw new Exception(outerr);
*
*/
}
}

Event Timeline