PsyFormalDict.java
package coneforest.psylla.core;
import coneforest.psylla.runtime.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* The representation of {@code formaldict}, an abstraction of a dictionary.
*
* @param <V> a type of contained values.
*/
@Type("formaldict")
public interface PsyFormalDict<V extends PsyObject>
extends
PsyContainer<V>,
PsyIndexed<PsyString, V>,
PsySequential<V>
{
/**
* Context action of the {@code undef} operator.
*/
@SuppressWarnings("rawtypes")
@OperatorType("undef")
public static final ContextAction PSY_UNDEF
=ContextAction.<PsyFormalDict, PsyString>ofBiConsumer(PsyFormalDict::psyUndef);
@Override
public default void psyForAll(final PsyObject oProc, final PsyContext oContext)
throws PsyErrorException
{
final var ostack=oContext.operandStack();
final var keysIterator=psyKeys().stream().iterator();
//oContext.pushLoopLevel();
oContext.executionStack().enterLoop();
oContext.executionStack().push(new PsyOperator("#forall_continue")
{
@Override
public void perform(final PsyContext oContext1)
throws PsyErrorException
{
if(keysIterator.hasNext())
{
final var oKey=keysIterator.next();
ostack.push(oKey);
ostack.push(psyGet(oKey));
oContext1.executionStack().push(this);
oProc.invoke(oContext1);
}
else
//oContext1.popLoopLevel();
oContext1.executionStack().exitLoop();
}
});
}
public V get(final String key)
throws PsyUndefinedException;
@Override
public default V psyGet(final PsyString oKey)
throws PsyUndefinedException
{
return get(oKey.stringValue());
}
/*
@Override
public default PsyFormalArray<V> psyGetAll(final PsyIterable<PsyTextual> oEnumeration)
throws PsyLimitCheckException, PsyRangeCheckException, PsyUndefinedException
{
final PsyFormalArray<V> oResult=(PsyFormalArray<V>)new PsyArray();
for(final var oKey: oEnumeration)
oResult.psyAppend(psyGet(oKey));
return oResult;
}
*/
public void put(final String key, final V oValue);
@Override
public default void psyPut(final PsyString oKey, final V oValue)
{
put(oKey.stringValue(), oValue);
}
public boolean known(final String key);
@Override
public default PsyBoolean psyKnown(final PsyString oKey)
{
return PsyBoolean.of(known(oKey.stringValue()));
}
public void undef(final String key);
/**
* Deletes a key and associated value from this dictionary.
*
* @param oKey a {@code string} key.
*/
public default void psyUndef(final PsyString oKey)
{
undef(oKey.stringValue());
}
@Override
public default PsyFormalStream<PsyString> psyKeys()
{
return PsyFormalStream.<PsyString>of(keys().map(PsyString::new));
}
public Stream<String> keys();
@Override
public default void psyDelete(final PsyString oKey)
throws PsyUndefinedException
{
psyUndef(oKey);
}
@Override
public default V psyExtract(final PsyString oKey)
throws PsyUndefinedException
{
final V oResult=psyGet(oKey);
psyUndef(oKey);
return oResult;
}
@Override
public PsyFormalDict<V> psySlice(final PsyIterable<PsyString> oKeys)
throws PsyUndefinedException;
@Override
public default PsyStream psyEntries()
{
return new PsyStream(StreamSupport.<PsyObject>stream(new PsyIterable<PsyObject>()
{
@Override
public Iterator<PsyObject> iterator()
{
return new Iterator<PsyObject>()
{
private boolean flag=false;
private PsyString oKey;
private Iterator<PsyString> parentIterator
=psyKeys().stream().iterator();
@Override
public boolean hasNext()
{
return parentIterator.hasNext() || flag;
}
@Override
public PsyObject next()
{
try
{
return (flag=!flag)?
oKey=parentIterator.next(): psyGet(oKey);
}
catch(final PsyErrorException e)
{
throw new AssertionError(e);
}
}
};
}
}.spliterator(),
false));
}
@Override
public default String toSyntaxString()
{
return toSyntaxStringHelper(new HashSet<PsyContainer<? extends PsyObject>>());
}
@Override
public default String toSyntaxStringHelper(final Set<PsyContainer<? extends PsyObject>> processed)
{
if(!processed.add(this))
return '%'+typeName()+'%';
final var sj=new StringJoiner(" ", "<", ">");
psyEntries().stream().forEach(o->
sj.add(o instanceof PsyContainer<? extends PsyObject> oContainer?
oContainer.toSyntaxStringHelper(processed):
o.toSyntaxString()));
return sj.toString();
}
@Override
public default void psyClear()
{
psyKeys().stream().forEach(this::psyUndef);
}
}