Package erjang

Source Code of erjang.EList

/**
* This file is part of Erjang - A JVM-based Erlang VM
*
* Copyright (c) 2009 by Trifork
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

package erjang;

import java.io.IOException;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

public final class EList extends ESeq {
 
  private final EObject head;
  private final ESeq tail;
 
  public EList(EObject h, ESeq tail) {
    if (tail == null) tail = ERT.NIL;
   
    if (h == null)
      throw new NullPointerException();
   
    this.head = h;
    this.tail = tail;
  }
 
  public ECons testNonEmptyList() {
    return this;
  }
 
  // only for ENil!
  protected EList() {
    head = tail = null;
  }

  @Override
  public EList cons(EObject h) {
    return new EList(h, this);
  }

  @Override
  public EObject head() {
    return head;
  }

  @Override
  public ESeq tail() {
    return tail;
  }
 
  @Override
  public String toString() {
   
    try {
      // TODO: make this faster, we generate too many exceptions
      // on account of this piece of code!
      ESeq str = EString.make(this);
      return str.toString();
    } catch (ErlangException e) {
      // ignor e//
    }
   
    StringBuffer sb = new StringBuffer("[");

    assert (this instanceof EList);
   
    ESeq val = this;
    while ((val.testNil()) == null) {
      if (val != this) { sb.append(","); }
      sb.append(val.head());
      val = val.tail();
    }
   
    sb.append("]");
    return sb.toString();
  }
 

  static Type ELIST_TYPE = Type.getType(EList.class);
  static Type ESEQ_TYPE = Type.getType(ESeq.class);
  static Type ETERM_TYPE = Type.getType(EObject.class);
  static String CONSTRUCTOR_DESC = "(" + ETERM_TYPE.getDescriptor() + ESEQ_TYPE.getDescriptor() + ")V";
 
  @Override
  public Type emit_const(MethodVisitor fa) {
    Type type = ELIST_TYPE;
   
    fa.visitTypeInsn(Opcodes.NEW, type.getInternalName());
    fa.visitInsn(Opcodes.DUP);

    ((EObject)head).emit_const(fa);
    ((EObject)tail).emit_const(fa);

    fa.visitMethodInsn(Opcodes.INVOKESPECIAL,
        type.getInternalName(), "<init>", CONSTRUCTOR_DESC);
   
    return type;
  }

  /**
   * @param messages
   * @return
   */
  public static ESeq make(Object... messages) {
    ESeq result = ERT.NIL;
    for (int i = messages.length-1; i >= 0; i--) {
      result = result.cons((EObject)messages[i]);
    }
    return result;
  }

  public static ESeq make(int... messages) {
    ESeq result = ERT.NIL;
    for (int i = messages.length-1; i >= 0; i--) {
      result = result.cons(ERT.box( messages[i] ));
    }
    return result;
  }

  public static EObject read(EInputStream buf) throws IOException {
        final int arity = buf.read_list_head();
        EObject[] elems;
        EObject tail;
    if (arity > 0) {
            elems = new EObject[arity];
            for (int i = 0; i < arity; i++) {
                elems[i] = buf.read_any();
            }
            /* discard the terminating nil (empty list) or read tail */
            if (buf.peek1() == EExternal.nilTag) {
                buf.read_nil();
                tail = ERT.NIL;
            } else {
              tail = buf.read_any();
            }
           
            EObject res = tail;
            for (int i = arity-1; i >= 0; i--) {
              res = res.cons(elems[i]);
            }
           
            return res;
        } else {
          return ERT.NIL;
        }
  }

  @Override
  public void encode(EOutputStream eos) {
    int len = this.length();
    eos.write_list_head(len);
    ESeq curr = this;
    while (!curr.isNil()) {
      eos.write_any(curr.head());
      curr = curr.tail();
    }
    eos.write_nil();
  }

}
TOP

Related Classes of erjang.EList

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.