/** * 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.m.erlang; import erjang.BIF; import erjang.EObject; import erjang.ECons; import erjang.ESeq; import erjang.ERT; import erjang.ESmall; import erjang.ETuple; import java.util.LinkedList; /** * */ public class ErlList { @BIF(name="--") public static ECons listDiff(EObject a1, EObject a2) { ESeq l1, l2; if ((l1 = a1.testSeq()) == null || (l2 = a2.testSeq()) == null) throw ERT.badarg(a1,a2); if (l1.isNil()) return l1; // Step 1: Copy l1 to a temporary place. final EObject[] tmp = l1.toArray(); // Step 2: Delete elements occurring l2 (but only once) int tmp_start = 0; for (ESeq cur = l2; !cur.isNil(); cur=cur.tail()) { EObject elm = cur.head(); for (int i=tmp_start; i<tmp.length; i++) { if (tmp[i] != null && tmp[i].equalsExactly(elm)) { // Delete element tmp[i] = null; // Update tmp_start if (i==tmp_start) { do { tmp_start++; } while (tmp_start<tmp.length && tmp[tmp_start]==null); if (tmp_start == tmp.length) // No elements left. return ERT.NIL; } break; // Delete only one. } } } // Step 3: Convert back into list return ESeq.fromArraySkippingNulls(tmp, tmp_start, tmp.length); } @BIF public static EObject delete_element(EObject idx0, EObject tup0) { ESmall idx = idx0.testSmall(); ETuple tup = tup0.testTuple(); if (idx == null || tup == null || idx.value < 1 || idx.value > tup.arity()) throw ERT.badarg(idx0, tup0); EObject[] vals = new EObject[tup.arity()-1]; int target = 0; for (int i = 0; i < tup.arity(); i++) { if ((i+1) != idx.value) { vals[target++] = tup.elm(i+1); } } return ETuple.make(vals); } @BIF public static EObject insert_element(EObject idx0, EObject tup0, EObject term) { ESmall idx = idx0.testSmall(); ETuple tup = tup0.testTuple(); if (idx == null || tup == null || idx.value < 1 || idx.value > tup.arity()+1) throw ERT.badarg(idx0, tup0); EObject[] vals = new EObject[tup.arity()+1]; int target = 0; for (int i = 0; i < tup.arity(); i++) { if ((i+1) == idx.value) { vals[target++] = term; } vals[target++] = tup.elm(i+1); } return ETuple.make(vals); } }