- package coneforest.psylla.core;
- import coneforest.psylla.runtime.*;
- import java.util.ArrayList;
- import java.util.HashSet;
- import java.util.Set;
- import java.util.StringJoiner;
- /**
- * The representation of {@code proc}, a procedure.
- */
- @Type("proc")
- public class PsyProc
- extends PsyArray
- implements PsyExecutable
- {
- /**
- * Context action of the {@code bind} operator.
- */
- @OperatorType("bind")
- public static final ContextAction PSY_BIND=oContext->
- {
- final var ostack=oContext.operandStackBacked(1);
- final var oProc=ostack.<PsyProc>getBacked(0);
- ostack.push(oProc.psyBind(oContext));
- };
- //=ContextAction.<PsyProc>ofFunction(PsyProc::psyBind);
- /**
- * Constructs a new empty {@code proc}.
- */
- public PsyProc()
- {
- }
- protected PsyProc(final ArrayList<PsyObject> array)
- {
- super(array);
- }
- @Override
- public void invoke(final PsyContext oContext)
- {
- final var estack=oContext.executionStack();
- try
- {
- for(int i=length()-1; i>=0; i--)
- estack.push(get(i));
- }
- catch(final PsyRangeCheckException e)
- {
- // NOP
- }
- }
- @SuppressWarnings("unchecked")
- @Override
- public PsyProc psyClone()
- {
- return new PsyProc((ArrayList<PsyObject>)array.clone());
- }
- @Override
- public String toSyntaxString()
- {
- return toSyntaxStringHelper(new HashSet<PsyContainer<? extends PsyObject>>());
- }
- @Override
- public String toSyntaxStringHelper(final Set<PsyContainer<? extends PsyObject>> processed)
- {
- if(!processed.add(this))
- return '%'+typeName()+'%';
- final var sj=new StringJoiner(" ", "{", "}");
- for(final var o: this)
- sj.add(o instanceof PsyContainer<? extends PsyObject> oContainer?
- oContainer.toSyntaxStringHelper(processed):
- o.toSyntaxString());
- return sj.toString();
- }
- public PsyProc psyBind(final PsyContext oContext)
- {
- final var dstack=oContext.dictStack();
- final var agenda=new ArrayList<PsyProc>();
- final var bound=new HashSet<PsyProc>();
- agenda.add(this);
- while(!agenda.isEmpty())
- {
- final var oProc=agenda.remove(0);
- if(!bound.add(oProc))
- break;
- for(int i=0; i<oProc.length(); i++)
- {
- try
- {
- final var o=oProc.get(i);
- if(o instanceof PsyProc)
- agenda.add((PsyProc)o);
- else if(o instanceof PsyName oName)
- {
- final var oNew=dstack.load(oName);
- if(oNew instanceof PsyOperator
- || oNew instanceof PsyMark
- || oNew instanceof PsyNull)
- oProc.put(i, oNew);
- }
- }
- catch(final PsyRangeCheckException|PsyUndefinedException e)
- {
- // NOP
- }
- }
- }
- return this;
- }
- }