/**
* 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.ByteArrayOutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public abstract class ESeq extends ECons {
public ESeq testSeq() {
return this;
}
public String stringValue() {
throw ERT.badarg(this);
}
@Override
public abstract ESeq tail();
public abstract ESeq cons(EObject h);
public EObject[] toArray() {
List<EObject> out = new ArrayList<EObject>();
ESeq curr = this;
while (!curr.isNil()) {
out.add(curr.head());
curr = curr.tail();
}
return out.toArray(new EObject[out.size()]);
}
public int length() {
int count = 0;
ESeq curr = this;
while (!curr.isNil()) {
count += 1;
curr = curr.tail();
}
return count;
}
/**
* @param args
* @return
*/
public static ESeq fromArray(EObject[] args) {
ESeq res = ERT.NIL;
for (int i = args.length-1; i >= 0; i--) {
res = res.cons(args[i]);
}
return res;
}
public static ESeq fromArraySkippingNulls(EObject[] args, int start, int end) {
ESeq res = ERT.NIL;
for (int i = end-1; i >= start; i--) {
if (args[i] != null) res = res.cons(args[i]);
}
return res;
}
public static ESeq fromList(List<? extends EObject> args) {
ESeq res = ERT.NIL;
ListIterator<? extends EObject> iter = args.listIterator(args.size());
while (iter.hasPrevious()) {
res = res.cons(iter.previous());
}
return res;
}
/**
* @param o1
* @return
*/
public ESeq cons(int o1) {
if ((o1&0xff)==o1) {
return new EBinList((byte)o1, this).testSeq();
} else {
return cons(ERT.box(o1));
}
}
/**
* @param o1
* @return
*/
public ESeq cons(double o1) {
return cons(ERT.box(o1));
}
/**
* @param o1
* @return
*/
public ESeq cons(BigInteger o1) {
return cons(ERT.box(o1));
}
public EString testString() {
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ESeq list = this;
while (!list.isNil()) {
EObject head = list.head();
if (head == null) {
// BAD!
ERT.log.warning("null head in "+list.getClass());
}
ESmall intval;
if ((intval = head.testSmall()) == null) {
return null;
}
int byteValue = intval.value & 0xff;
if (intval.value != byteValue) {
return null;
}
barr.write( byteValue );
list = list.tail();
}
return new EString(barr.toByteArray(), 0);
}
/**
* @return
*/
public ESeq reverse() {
ESeq result = ERT.NIL;
if (this.isNil())
return result;
EObject[] val = this.toArray();
for (int i = 0; i < val.length; i++) {
result = result.cons(val[i]);
}
return result;
}
/**
* @param c1
* @return
*/
public ESeq prepend(ESeq list) {
// first, rlist=lists:reverse(list)
ESeq rlist = ERT.NIL;
while (!list.isNil()) {
rlist = rlist.cons(list.head());
list = list.tail();
}
// then, prepend rlist on this
ESeq r = this;
while(!rlist.isNil()) {
r = r.cons(rlist.head());
rlist = rlist.tail();
}
return r;
}
@Override
public int hashCode() {
int h = 0;
ESeq curr = this;
do {
h = 31*h + curr.head().hashCode();
curr = curr.tail();
} while (curr != ERT.NIL);
return h;
}
}