// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/data/Terms.java
// public static TermList newList(final Term term) {
//   return new TermList(term);
// }
// 
// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/data/Terms.java
// public static TermStruct newStruct(final Term functor) {
//   return new TermStruct(functor);
// }
// 
// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/utils/Utils.java
// public static TermList createOrAppendToList(final TermList nullableList, final Term term) {
//   final TermList newList = Terms.newList(term);
// 
//   if (nullableList != null && !nullableList.isNullList()) {
//     newList.setTail(nullableList.getTail());
//     nullableList.setTail(newList);
//   }
// 
//   return newList;
// }
// 
// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/exceptions/ProlCriticalError.java
// public class ProlCriticalError extends Error {
// 
//   private static final long serialVersionUID = 1340153646373377400L;
// 
//   public ProlCriticalError(final Throwable cause) {
//     super(cause);
//   }
// 
//   public ProlCriticalError(final String message, final Throwable cause) {
//     super(message, cause);
//   }
// 
//   public ProlCriticalError(final String message) {
//     super(message);
//   }
// 
//   public ProlCriticalError() {
//     super();
//   }
// 
// }


import static com.igormaznitsa.jprol.data.TermType.LIST;
import static com.igormaznitsa.jprol.data.TermType.VAR;
import static com.igormaznitsa.jprol.data.Terms.newList;
import static com.igormaznitsa.jprol.data.Terms.newStruct;
import static com.igormaznitsa.jprol.utils.Utils.createOrAppendToList;
import com.igormaznitsa.jprol.exceptions.ProlCriticalError;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
/*
 * Copyright 2014 Igor Maznitsa (http://www.igormaznitsa.com).
 *
 * 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 com.igormaznitsa.jprol.data;




public final class TermList extends TermStruct {

  private static final int INDEX_HEAD = 0;
  private static final int INDEX_TAIL = 1;

  TermList() {
    super(Terms.LIST_FUNCTOR, null);
  }

  TermList(final Term term) {
    super(Terms.LIST_FUNCTOR, new Term[] {term, Terms.NULL_LIST});
  }

  TermList(final Term head, final Term tail) {
    super(Terms.LIST_FUNCTOR, new Term[] {head, tail});
  }

  public static TermList asTermList(final Term... elements) {
    if (elements.length == 0) {
      return Terms.NULL_LIST;
    } else if (elements.length == 1) {
      final Term element = elements[0];
      switch (element.getTermType()) {
        case LIST:
          return (TermList) element;
        case STRUCT: {
          final TermStruct struct = (TermStruct) element;
          final TermList result = newList(struct.getFunctor());
          TermList curResult = result;
          final int arity = struct.getArity();
          for (int li = 0; li < arity; li++) {
// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/data/Terms.java
// public static TermList newList(final Term term) {
//   return new TermList(term);
// }
// 
// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/data/Terms.java
// public static TermStruct newStruct(final Term functor) {
//   return new TermStruct(functor);
// }
// 
// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/utils/Utils.java
// public static TermList createOrAppendToList(final TermList nullableList, final Term term) {
//   final TermList newList = Terms.newList(term);
// 
//   if (nullableList != null && !nullableList.isNullList()) {
//     newList.setTail(nullableList.getTail());
//     nullableList.setTail(newList);
//   }
// 
//   return newList;
// }
// 
// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/exceptions/ProlCriticalError.java
// public class ProlCriticalError extends Error {
// 
//   private static final long serialVersionUID = 1340153646373377400L;
// 
//   public ProlCriticalError(final Throwable cause) {
//     super(cause);
//   }
// 
//   public ProlCriticalError(final String message, final Throwable cause) {
//     super(message, cause);
//   }
// 
//   public ProlCriticalError(final String message) {
//     super(message);
//   }
// 
//   public ProlCriticalError() {
//     super();
//   }
// 
// }


// Path: engine/jprol-core/src/main/java/com/igormaznitsa/jprol/data/TermList.java
import static com.igormaznitsa.jprol.data.TermType.LIST;
import static com.igormaznitsa.jprol.data.TermType.VAR;
import static com.igormaznitsa.jprol.data.Terms.newList;
import static com.igormaznitsa.jprol.data.Terms.newStruct;
import static com.igormaznitsa.jprol.utils.Utils.createOrAppendToList;
import com.igormaznitsa.jprol.exceptions.ProlCriticalError;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

/*
 * Copyright 2014 Igor Maznitsa (http://www.igormaznitsa.com).
 *
 * 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 com.igormaznitsa.jprol.data;




public final class TermList extends TermStruct {

  private static final int INDEX_HEAD = 0;
  private static final int INDEX_TAIL = 1;

  TermList() {
    super(Terms.LIST_FUNCTOR, null);
  }

  TermList(final Term term) {
    super(Terms.LIST_FUNCTOR, new Term[] {term, Terms.NULL_LIST});
  }

  TermList(final Term head, final Term tail) {
    super(Terms.LIST_FUNCTOR, new Term[] {head, tail});
  }

  public static TermList asTermList(final Term... elements) {
    if (elements.length == 0) {
      return Terms.NULL_LIST;
    } else if (elements.length == 1) {
      final Term element = elements[0];
      switch (element.getTermType()) {
        case LIST:
          return (TermList) element;
        case STRUCT: {
          final TermStruct struct = (TermStruct) element;
          final TermList result = newList(struct.getFunctor());
          TermList curResult = result;
          final int arity = struct.getArity();
          for (int li = 0; li < arity; li++) {
            curResult = createOrAppendToList(curResult, struct.getElement(li));