
/*
   Stack simulator. Api:
   
   NewStack() - creates a stack simulation
   PushStackFrame(stack,unfenced) - push frame on stack, (un)fenced
   PushStackFrame(stack,fenced) 
   PopStackFrame(stack)   - pop stack frame
   StackDepth(_stack) - return stack depth
   AddToStack(stack,element) - add element to top stack frame

   IsOnStack(stack,element) - returns True if element is accessible
       on current stack, False otherwise
   FindOnStack(stack,element) - return assoc list for element. 
       Check first with IsOnStack that it is available!

*/

NewStack() := {{},{}};

10 # PushStackFrame(_stack,unfenced) 
   <-- 
   [
     DestructiveInsert(stack[1],1,{});
     DestructiveInsert(stack[2],1,True);
   ];
10 # PushStackFrame(_stack,fenced) 
   <-- 
   [
     DestructiveInsert(stack[1],1,{});
     DestructiveInsert(stack[2],1,False);
   ];
PopStackFrame(stack):=
[
  DestructiveDelete(stack[1],1);
  DestructiveDelete(stack[2],1);
];
StackDepth(_stack) <-- Length(stack[1]);

AddToStack(stack,element)  :=
[
  DestructiveInsert(stack[1][1],1,{element,{}});
];

DropOneFrame(_stack) <-- {Tail(stack[1]),Tail(stack[2])};

10 # IsOnStack({{},{}},_element) <-- False;
11 # IsOnStack(_stack,_element)_(stack[1][1][element] != Empty) <-- True;
20 # IsOnStack(_stack,_element)_(StackDepth(stack)>0 And stack[2][1] = True) 
   <-- IsOnStack(DropOneFrame(stack),element);
30 # IsOnStack(_stack,_element) <-- 
[
//Echo("stack depth = ",StackDepth(stack));
//Echo(stack[2][1]);
False;
];
10 # FindOnStack(_stack,_element)_(stack[1][1][element] != Empty) 
   <-- stack[1][1][element];
20 # FindOnStack(_stack,_element)_(StackDepth(stack)>0 And stack[2][1] = True) 
   <-- FindOnStack(DropOneFrame(stack),element);
30 # FindOnStack(_stack,_element) <-- Check(False,"Illegal stack access! Use IsOnStack.");




