Package scriptingLanguage.variables

Source Code of scriptingLanguage.variables.InterpreterMethod

package scriptingLanguage.variables;

import java.util.ArrayList;

import lipstone.joshua.customStructures.tuples.Pair;
import scriptingLanguage.Interpreter;
import scriptingLanguage.Token;
import scriptingLanguage.Type;
import scriptingLanguage.errors.InterpreterException;
import scriptingLanguage.errors.InvalidAccessException;
import scriptingLanguage.errors.UnexpectedTokenException;
import scriptingLanguage.errors.UnexpectedTypeException;
import scriptingLanguage.frames.AbstractFrame;
import scriptingLanguage.frames.Frame;

public class InterpreterMethod extends AbstractMethod<Token> {
  private AbstractClass<?> container;
  private Parameter[] parameters;
 
  public InterpreterMethod(InterpreterMethodClass type) {
    super(type, null, null);
    container = null;
    parameters = null;
  }
 
  public InterpreterMethod(InterpreterMethod base, AbstractFrame newFrame) {
    this((InterpreterMethodClass) base.getType(), base.container, base.getSource(), newFrame, base.getParameters());
  }
 
  public InterpreterMethod(InterpreterMethodClass type, AbstractClass<?> container, Token source, AbstractFrame declared, Parameter... parameters) {
    super(type, source, declared);
    this.container = container;
    this.parameters = parameters;
  }
 
  public static Pair<String, InterpreterMethod> initMethod(AbstractClass<?> caller, Token type, Token parameters, Token body, AbstractFrame declared) throws InterpreterException {
    return initMethod(caller, "", (AbstractClass<?>) (type.getCar() instanceof String ? declared.getType((String) type.getCar()) : type.getCar()), parameters, body, declared);
  }
 
  public static Pair<String, InterpreterMethod> initMethod(AbstractClass<?> caller, Token source, AbstractFrame declared) throws InterpreterException {
    //source s/b [type] [name](<args>) { body } or [type] (<args>) { body }
    if (!source.getCarType().equals(Interpreter.identifierType))
      throw new UnexpectedTokenException("Expected an identifier, got a " + source.getCarType().getName() + ".  " + source.toString());
    String t = (String) source.getCar();
    while ((source = source.getNextToken()).equals(Interpreter.callType))
      t = t + ((String) source.getCar()) + (source = source.getNextToken()).getCar();
    AbstractClass<?> type = declared.getType(declared.getImport(t));
    if (source.getCarType().equals(Interpreter.parenthesesType))
      return initMethod(caller, "", type, (Token) (source = source.getNextToken()).getCar(), source.getNextToken(), declared);
    return initMethod(caller, (String) source.getCar(), type, (Token) (source = source.getNextToken()).getCar(), source.getNextToken(), declared);
  }
 
  public static Pair<String, InterpreterMethod> initMethod(AbstractClass<?> caller, String name, AbstractClass<?> type, Token params, Token body, AbstractFrame declared) throws InterpreterException {
    name = name + ":{";
    ArrayList<Parameter> parameters = new ArrayList<>();
    String typeName = type.getName() + ":{" + params.toString() + "}";
    Token par = params;
    while (!params.isNull()) {
      String p = (String) params.getCar();
      while ((params = params.getNextToken()).equals(Interpreter.callType))
        p = p + ((String) ((Variable<?>) params.getCar()).getSource()) + ((Variable<?>) (params = params.getNextToken()).getCar()).getSource();
      name = name + p + ", ";
      parameters.add(new Parameter(declared.getType(p), (String) params.getCar()));
      if ((params = params.getNextToken()).getCarType().equals(Interpreter.separatorType)) {
        params = params.getNextToken();
        continue;
      }
    }
    if (name.endsWith(", "))
      name = name.substring(0, name.length() - 2);
    name = name + "}";
    InterpreterMethodClass finalType = new InterpreterMethodClass(typeName, par, type, declared, new Type<Object>(typeName));
    if (parameters.size() > 0)
      return new Pair<String, InterpreterMethod>(name, new InterpreterMethod(finalType, caller, (Token) body.getCar(), declared, parameters.toArray(new Parameter[parameters.size()])));
    else
      return new Pair<String, InterpreterMethod>(name, new InterpreterMethod(finalType, caller, (Token) body.getCar(), declared));
  }
 
  /**
   * @param caller
   *            the object that called this method
   */
  @Override
  public Token eval(AbstractClass<?> caller, Token parameters, AbstractFrame frame) throws InterpreterException {
    ArrayList<Token> args = new ArrayList<>();
    for (int i = 0; i < this.getParameters().length && !parameters.isNull(); i++) {
      Token arg = parameters.singular(), head = arg;
      while (!(parameters = parameters.getNextToken()).getCarType().equals(Interpreter.separatorType) && !parameters.isNull())
        head = head.append(parameters.singular());
      Token value = frame.getInterpreter().eval(caller, arg, frame);
      //TODO add type length checking, var args
      if (((AbstractObject<?>) value.getCar()).getType().extend(this.getParameters()[i].getType()) == -1)
        throw new UnexpectedTypeException(((AbstractObject<?>) value.getCar()).getType().getName() + " cannot be cast to " + this.getParameters()[i].getType().getName());
      args.add(arg);
      parameters = parameters.getNextToken();
    }
    return eval(args);
  }
 
  @Override
  public Token eval(ArrayList<Token> args) throws ArrayIndexOutOfBoundsException, IllegalArgumentException, InterpreterException {
    Frame base = new Frame(getDeclared(), getDeclared().getInterpreter());
    for (int i = 0; i < args.size(); i++)
      base.writeVariable(this.getParameters()[i].getName(), args.get(i), true);
    Token result = getDeclared().getInterpreter().eval(container, getSource(), base);
    AbstractClass<?> returnType = ((AbstractMethodClass) getType()).getReturnType();
    if (returnType.equals(Interpreter.voidClass) && !result.isNull())
      throw new UnexpectedTypeException("Cannot return a value from a void function.");
    if (((Variable<?>) (result = result.getNextToken()).getCar()).getType().extend(returnType) == -1)
      if (Interpreter.isPrimitive(getType()) && Interpreter.isPrimitive(((Variable<?>) result.getCar()).getType()))
        return ((PrimitiveClass<?>) returnType).eval(((PrimitiveClass<?>) ((Variable<?>) result.getCar()).getType()).cast(((Variable<?>) result.getCar()).getSource(), (PrimitiveClass<?>) returnType));
      else
        throw new UnexpectedTypeException("Cannot return a " + ((Variable<?>) result.getCar()).getType() + " from a function that should return a " + getType());
    return result;
  }
 
  /**
   * @return the parameters
   */
  public Parameter[] getParameters() {
    return parameters;
  }
 
  @Override
  public void write(Variable<?> data) throws InvalidAccessException {
    super.write(data);
    InterpreterMethod newData = (InterpreterMethod) data;
    container = newData.container;
    parameters = newData.parameters;
  }
 
  @Override
  public Variable<Token> clone() {
    return new InterpreterMethod((InterpreterMethodClass) getType(), container, getSource(), getDeclared(), parameters);
  }
}
TOP

Related Classes of scriptingLanguage.variables.InterpreterMethod

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.