Package scriptingLanguage.variables

Source Code of scriptingLanguage.variables.JavaObject

package scriptingLanguage.variables;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

import scriptingLanguage.Interpreter;
import scriptingLanguage.Token;
import scriptingLanguage.Type;
import scriptingLanguage.errors.InterpreterException;
import scriptingLanguage.errors.NullAccessException;
import scriptingLanguage.errors.UndefinedResultException;
import scriptingLanguage.errors.UnexpectedTokenException;
import scriptingLanguage.errors.UnexpectedTypeException;
import scriptingLanguage.errors.VariableNotFoundException;
import scriptingLanguage.frames.AbstractFrame;

public class JavaObject<T> extends AbstractObject<T> {
 
  public JavaObject(JavaClass<T> type) {
    super((AbstractClass<T>) type);
  }
 
  public JavaObject(JavaClass<T> type, T source) {
    super((AbstractClass<T>) type, source);
  }
 
  @Override
  public Token eval(AbstractClass<?> caller, Token parameters, AbstractFrame frame) throws InterpreterException {
    if (!parameters.getCarType().equals(Interpreter.identifierType))
      throw new UnexpectedTokenException("Expected an identifier, got a " + parameters.getCarType().getName() + ".  " + parameters.toString());
    Object data = getSource();
    String name = (String) parameters.getCar();
    if ((parameters = parameters.getNextToken()).getCarType().equals(Interpreter.parenthesesType)) {
      ArrayList<Token> args = Interpreter.evalFunctionArguments(caller, (Token) parameters.getCar(), frame);
      Class<?> source = (Class<?>) (getSource() instanceof Class<?> ? getSource() : getSource().getClass());
      try {
        Class<?>[] params = new Class<?>[args.size()];
        for (int i = 0; i < args.size(); i++)
          params[i] = (Class<?>) (args.get(i).getCar() instanceof JavaObject ? ((JavaObject<?>) args.get(i).getCar()).getType().getSource() : getClass(((AbstractObject<?>) args.get(i).getCar()).getType().getSource()));
        Method method = null, methods[] = source.getMethods();
        try {
          method = source.getMethod(name, params);
        }
        catch (NoSuchMethodException e) {
          int accuracy = 0;
          method = null;
          for (Method m : methods) {
            Class<?>[] types = m.getParameterTypes();
            //TODO add support for var args
            if (types.length != params.length) //These have different parameter lengths
              continue;
            boolean good = true;
            int a = 0;
            for (int i = 0; i < types.length; i++) {
              if (types[i].equals(params[i]))
                a += 2; //Same type
              else if (types[i].isAssignableFrom(params[i]))
                a++; //Different types, but subclass
              else {
                good = false;
                break;
              }
            }
            if (good && a > accuracy) {
              accuracy = a;
              method = m;
            }
          }
          if (method == null)
            throw new NoSuchMethodException();
        }
        Object[] arguments = new Object[args.size()];
        for (int i = 0; i < args.size(); i++)
          arguments[i] = ((JavaObject<?>) args.get(i).getCar()).getSource();
        //If source is an instance of Class<?>, then this is a static class reference.
        data = method.invoke(getSource() instanceof Class<?> ? null : getSource(), arguments);
      }
      catch (ClassCastException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        e.printStackTrace();
        throw new VariableNotFoundException(frame.getInterpreter().evalFunctionName(name, args) + " is not defined in the current frame.");
      }
    }
    else
      try {
        Class<?> source = (Class<?>) (getSource() instanceof Class<?> ? getSource() : getSource().getClass());
        Field field = source.getField(name);
        data = field.get(getSource() instanceof Class<?> ? null : getSource());
      }
      catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
        throw new VariableNotFoundException(name + " is not defined in the current frame.");
      }
    if (data == null)
      return new Token();
    AbstractClass<?> output = determineType(data, frame);
    return new Token(output instanceof JavaClass ? new JavaObject<Object>((JavaClass<Object>) output, data) :
        ((PrimitiveClass<?>) output).makePrimitiveObject(data), (Type<Object>) output.getTokenType());
  }
 
  @Override
  public AbstractObject<?> castData(AbstractClass<?> output, AbstractFrame frame) throws UnexpectedTypeException, UndefinedResultException, NullAccessException {
    if (output.equals(Interpreter.stringClass))
      return new JavaObject<String>(Interpreter.stringClass, toString());
    if (!(output instanceof JavaClass))
      throw new UnexpectedTypeException("Instances of the " + getType().getName() + " type cannot be cast to " + output.getName());
    switch (getType().extend(output)) {
      case -1:
        throw new UnexpectedTypeException("Instances of the " + getType().getName() + " type cannot be cast to " + output.getName());
      case 0: //They are the same type
        return this;
      default:
        return new JavaObject<Object>((JavaClass<Object>) output, getSource());
    }
  }
 
  @Override
  public int extend(AbstractClass<?> type) throws NullAccessException {
    return getType().extend(type) + 1;
  }
 
  @Override
  public String toString() {
    if (getSource() instanceof Array) {
      String output = "";
      int length = Array.getLength(getSource());
      for (int i = 0; i < length; i++)
        output = output + ", " + Array.get(getSource(), i).toString();
      if (length > 0)
        output = output.substring(2);
      return "[" + output + "]";
    }
    return getSource().toString();
  }

  @Override
  public Variable<T> clone() {
    return new JavaObject<T>((JavaClass<T>) getType(), getSource());
  }
}
TOP

Related Classes of scriptingLanguage.variables.JavaObject

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.