/*
 * map.lmn - Map module
 *
 *   Copyright (c) 2008, Ueda Laboratory LMNtal Group <lmntal@ueda.info.waseda.ac.jp>
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions are
 *   met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *    3. Neither the name of the Ueda Laboratory LMNtal Group nor the
 *       names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior
 *       written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */


/*
NAME
	Map module

SYNOPSIS
	r=get(put(put(put(map.new, jack, enigma), nina, myers), jack, bauer), jack, jack_is)
	===>
	jack_is(bauer), r(map.new(_72)), {myers('.'(nina)), bauer('.'(jack)), obj(_72)}, @602
	
	r=map.of_queue(push(push(push(push(queue.new,k0),v0),k1),v1))
	===>
	r(map.new(_144)), nil(queue.new(_156,_156)), {v0('.'(k0)), v1('.'(k1)), obj(_144)}, @602, @604
	
AUTHOR
	Koji Hara

HISTORY
	2004/05/22(Sat)

*/

{
module(map).

/**
 * new : unit -> Map
 * 
 */
H=map.new :- H=map.new(X), { obj(X) }.

/**
 * put
 * 
 */
H=put(map.new(X), Key, Value), {obj(X), '.'(E_Key, E_Value), $o} :-
	unary(Key), unary(Value), Key=E_Key, unary(E_Value) |
	H=map.new(X), {obj(X), '.'(Key, Value), $o}.
H=put(map.new(X), Key, Value), {obj(X), $o} :-
	unary(Key), unary(Value) |
	H=map.new(X), {obj(X), '.'(Key, Value), $o}.

/**
 * get
 * 
 */
H=get(map.new(X), Key, Return), {obj(X), '.'(E_Key, E_Value), $o}
	:- unary(Key), unary(E_Value), Key=E_Key |
	H=map.new(X), {obj(X), '.'(E_Key, E_Value), $o}, Return=E_Value.

/**
 * remove
 * 
 */
H=get(map.new(X), Key), {obj(X), '.'(E_Key, E_Value), $o}
	:- unary(Key), unary(E_Value), Key=E_Key |
	H=map.new(X), {obj(X), $o}.

/**
 * remove_all
 * 
 * FEATURE NOT IMPLEMENTED: untyped process context must be linear: $o
 * SYSTEM ERROR: error recovery for the previous error is not implemented
 */
//H=remove_all(map.new(X)), {obj(X), $o} :-
//	H=map.new(X), {obj(X)}.

/**
 * is_empty
 * 
 */
H=is_empty(map.new(X), Return), {obj(X)} :-
	H=map.new(X), {obj(X)}, Return=true.

/**
 * keys
 * 
 * Map -> List of keys
 */

/**
 * values
 * 
 * Map -> List of values
 */


/**
 * of_queue
 * 
 * Queue -> Map
 * [k0, v0, k1, v1] -> { k0 => v0, k1 => v1 }
 */
H=map.of_queue(queue.new(Head, Tail)) :-
	H=map.of_queue_s0(queue.new(Head, Tail), map.new).

H=map.of_queue_s0(Queue, Map) :-
	H=map.of_queue_s0(is_empty(Queue, IsEmpty), Map, IsEmpty).

H=map.of_queue_s0(Queue, Map, true) :-
	H=Map, nil(Queue).

H=map.of_queue_s0(Queue, Map, false) :-
	H=map.of_queue_s0(shift(shift(Queue, K), V), put(Map, K, V)).

map.test :-
	t0=get(put(put(put(map.new, jack, enigma), nina, myers), jack, bauer), jack, jack_is),
	t1=map.of_queue(push(push(push(push(queue.new,k0),v0),k1),v1)).

}



/*

// unary map
// can be ground map if ground() implemented
map : {
	map.new($self)
	 :- unary($self)|{name($self)}.
	 
	// override exist key
	map.put($self, $k, $v), {name($name), assoc($ok, $ov), $p}
	 :- unary($k),unary($v),$name=$self,$ok=$k,unary($ov) | {name($name), assoc($k, $v), $p}.
	
	// add new key
	map.put($self, $k, $v), {name($name), $p}
	 :- unary($k),unary($v),$name=$self | {name($name), assoc($k, $v), $p}.
	
	map.get($self, $k, V), {name($name), assoc($mk, $mv), $p}
	 :- unary($k),$name=$self,$k=$mk,unary($mv) | V=$mv, {name($name), assoc($mk, $mv), $p}.
}.

*/
