Package scriptingLanguage.variables

Source Code of scriptingLanguage.variables.InterpreterClass

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.NullAccessException;
import scriptingLanguage.errors.UnendedLineException;
import scriptingLanguage.errors.UnexpectedTokenException;
import scriptingLanguage.frames.AbstractFrame;
import scriptingLanguage.frames.Frame;
import scriptingLanguage.frames.ObjectFrame;

public class InterpreterClass extends AbstractClass<Token> {
  private final AbstractClass<?> superclass;
  private final Frame[] frames;
  private final ArrayList<Pair<Access, Token>> objects, methods, variables;
 
  /**
   * @param name
   *            the name of the class
   * @param source
   *            the source for the object described by this class
   * @param frame
   *            the frame in which this was created
   * @throws ArrayIndexOutOfBoundsException
   * @throws IllegalArgumentException
   * @throws InterpreterException
   */
  public InterpreterClass(String name, Token source, AbstractFrame frame) throws ArrayIndexOutOfBoundsException, IllegalArgumentException, InterpreterException {
    this(name, source, frame, new Type<InterpreterClass>(name));
  }
 
  public InterpreterClass(String name, Token source, AbstractFrame frame, Type<?> tokenType) throws ArrayIndexOutOfBoundsException, IllegalArgumentException, InterpreterException {
    super(name, source, tokenType);
    Interpreter interpreter = frame.getInterpreter();
    frames = new Frame[4];
    frames[0] = new Frame(frame, interpreter);
    frames[1] = new Frame(frames[0], interpreter);
    frames[2] = new Frame(frames[1], interpreter);
    frames[3] = new Frame(frames[2], interpreter);
    objects = new ArrayList<>();
    methods = new ArrayList<>();
    variables = new ArrayList<>();
    if (source.getCarType().equals(Interpreter.extendsType)) {
      if (!source.getCarType().equals(Interpreter.identifierType))
        throw new UnexpectedTokenException("Expected an identifier, got a " + source.getCarType().getName() + ".  " + source.toString());
      String extend = "";
      while (!(source = source.getNextToken()).getCarType().equals(Interpreter.curlyBracesType))
        extend = extend + source.getCar();
      superclass = frame.getType(extend);
    }
    else
      superclass = Interpreter.ObjectClass;
    if (!source.getCarType().equals(Interpreter.curlyBracesType))
      throw new UnendedLineException("An object declaration must have a body.");
    source = (Token) source.getCar();
    ArrayList<Token> lines = Interpreter.splitLines(source);
    ArrayList<Pair<Access, Token>> staticObjects = new ArrayList<>(), staticMethods = new ArrayList<>(), staticVariables = new ArrayList<>();
    while (lines.size() > 0) {
      Token line = lines.remove(0);
      Access access = Access.DEFAULT;
      boolean use = false;
      while (!line.isNull()) {
        if (line.getCarType().equals(interpreter.importType)) {
          use = true;
          access = Access.PUBLIC;
          break;
        }
        else if (line.getCarType().equals(Interpreter.scopeType)) {
          access = Access.getAccess((String) line.getCar());
        }
        else if (line.getCarType().equals(Interpreter.staticType))
          use = true;
        else
          break;
        line = line.getNextToken();
      }
      //object [name] (extends <type>)? {body}
      if (line.getCarType().equals(Interpreter.classType)) {
        if (use) {
          staticObjects.add(new Pair<>(access, line));
          String nme;
          frames[access.intValue()].addType((nme = (String) (line = line.getNextToken()).getCar()),
              new InterpreterClass(nme, (line = line.getNextToken()).getNextToken(), frames[3], new Type<InterpreterClass>(nme)));
        }
        else
          objects.add(new Pair<>(access, line));
      }
      else {
        //Constructor
        if (!use && line.getCar().equals(getName()) && line.getNextToken().getCarType().equals(Interpreter.parenthesesType))
          methods.add(new Pair<>(access, line));
        //Function
        else if (line.getCarType().equals(Interpreter.identifierType) && line.getNextToken().getCarType().equals(Interpreter.identifierType) &&
            line.getNextToken().getNextToken().getCarType().equals(Interpreter.parenthesesType))
          if (use)
            staticMethods.add(new Pair<>(access, line));
          else
            methods.add(new Pair<>(access, line));
        //Variables
        else if (use)
          staticVariables.add(new Pair<>(access, line));
        else
          variables.add(new Pair<>(access, line));
      }
    }
    construct(staticObjects, staticMethods, staticVariables, frames);
    frames[0].writeVariable("class", new Token(this, getTokenType()), true); //Adds .class
  }
 
  //For cloning
  private InterpreterClass(String name, Token source, Type<?> tokenType, AbstractClass<?> superclass, Frame[] frames,
      ArrayList<Pair<Access, Token>> objects, ArrayList<Pair<Access, Token>> methods, ArrayList<Pair<Access, Token>> variables) {
    super(name, source, tokenType);
    this.superclass = superclass;
    this.frames = frames;
    this.objects = objects;
    this.methods = methods;
    this.variables = variables;
  }
 
  protected void construct(ArrayList<Pair<Access, Token>> objects, ArrayList<Pair<Access, Token>> methods,
      ArrayList<Pair<Access, Token>> variables, Frame[] frames) throws InterpreterException {
    for (Pair<Access, Token> p : objects) {
      Token line = p.getY();
      String nme;
      frames[p.getX().intValue()].addType((nme = (String) (line = line.getNextToken()).getCar()),
          new InterpreterClass(nme, (line = line.getNextToken()).getNextToken(), frames[3], new Type<InterpreterClass>(nme)));;
    }
    for (Pair<Access, Token> p : methods) {
      Pair<String, InterpreterMethod> method = InterpreterMethod.initMethod(this, p.getY(), frames[3]);
      if (method.getX().indexOf(':') == 0) //This is a constructor
        frames[p.getX().intValue()].writeVariable(getName() + method.getX(), new Token(InterpreterConstructor.init(method.getY()),
            method.getY().getType().getTokenType()), true);
      frames[p.getX().intValue()].writeVariable(method.getX(), new Token(method.getY(), method.getY().getType().getTokenType()), true);
    }
    for (Pair<Access, Token> p : variables)
      Interpreter.evalVariableDeclaration(this, p.getY(), frames[3], frames[p.getX().intValue()]);
  }
 
  @Override
  public Token eval(AbstractClass<?> caller, Token parameters, AbstractFrame frame) throws InterpreterException, IllegalArgumentException {
    Access access = Access.getAccess(caller, getType());
    if (parameters.getCarType().equals(Interpreter.callType)) { //This is a static method call
      if (!(parameters = parameters.getNextToken()).getNextToken().getCarType().equals(Interpreter.parenthesesType)) {
        if (!frames[access.intValue()].hasVariable((String) parameters.getCar()))
          return superclass.eval(caller, parameters, frame);
        return frames[access.intValue()].readVariable((String) parameters.getCar());
      }
      String name = (String) parameters.getCar();
      ArrayList<Token> arguments = Interpreter.evalFunctionArguments(caller, (Token) parameters.getNextToken().getCar(), frame);
      name = Interpreter.evalFunctionName(name, arguments);
      if (!frames[access.intValue()].hasVariable(name))
        return superclass.eval(caller, parameters, frame);
      return ((AbstractMethod<?>) frames[access.intValue()].readVariable(name).getCar()).eval(arguments);
    }
    ArrayList<Pair<Access, Token>> objects = new ArrayList<>(), methods = new ArrayList<>(), variables = new ArrayList<>();
    for (Pair<Access, Token> pair : this.objects)
      objects.add(new Pair<>(pair.getX(), pair.getY().clone()));
    for (Pair<Access, Token> pair : this.methods)
      methods.add(new Pair<>(pair.getX(), pair.getY().clone()));
    for (Pair<Access, Token> pair : this.variables)
      variables.add(new Pair<>(pair.getX(), pair.getY().clone()));
    ObjectFrame[] frames = new ObjectFrame[4];
    frames[0] = new ObjectFrame(this.frames[0].getPrevious(), this.frames[0].getInterpreter(), this.frames[0]);
    frames[1] = new ObjectFrame(frames[0], this.frames[1].getInterpreter(), this.frames[1]);
    frames[2] = new ObjectFrame(frames[1], this.frames[2].getInterpreter(), this.frames[2]);
    frames[3] = new ObjectFrame(frames[2], this.frames[3].getInterpreter(), this.frames[3]);
    construct(objects, methods, variables, frames);
    String name = getName().substring(getName().lastIndexOf('.') + 1); //This works because it returns -1 if there is no match, and -1 + 1 = 0 = complete String
    ArrayList<Token> arguments = Interpreter.evalFunctionArguments(caller, parameters, frame);
    name = Interpreter.evalFunctionName(name, arguments);
    InterpreterConstructor constructor = (InterpreterConstructor) frames[access.intValue()].readVariable(name).getCar();
    AbstractObject<?> superObject = constructor.initSuperclass(caller, superclass, parameters, frame);
    Token result = new Token(new InterpreterObject(this, superObject, frames), getTokenType());
    //Initialize keywords
    frames[3].writeVariable("this", result, true);
    frames[3].writeVariable("super", new Token(superObject, superclass.getTokenType()), true);
    constructor.eval(arguments);
    return result;
  }
 
  @Override
  public boolean equals(Object o) {
    if (!(o instanceof InterpreterClass))
      return false;
    return getType().equals(((InterpreterClass) o).getType());
  }
 
  @Override
  public int extend(AbstractClass<?> type) throws NullAccessException {
    if (type.equals(this))
      return 0;
    int result = superclass.extend(type);
    return result == -1 ? result : result + 1;
  }
 
  @Override
  public Variable<Token> clone() {
    return new InterpreterClass(getName(), getSource(), getTokenType(), superclass, frames, objects, methods, variables);
  }

  @Override
  public Token makePlaceholder() {
    return new Token(new InterpreterObject(this, null, null), getTokenType());
  }
}
TOP

Related Classes of scriptingLanguage.variables.InterpreterClass

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.