- 5BA13C52F966E15D2DAF2FDFE29F0515010B7E23BEAD59AAD66B61828DAF3724CB7D32D82AAA2EDB9DFB65641BECF7B2834900D916B12512DD02DE62E54E2E3A
+ BCE22003B01F819063B2830325BC6530636F003BA6E88A555E396D6F1E2656F1B05253DFED92043282F869BCE10E42B4C519555344217D5AFAC2C4D2303CC24E
ffa/ffacalc/ffa_calc.adb
(136 . 6)(136 . 9)
488 -- Carry/Borrow Flag set by certain arithmetical Ops:
489 Flag : WBool := 0;
490
491 -- 'Cutout'-segregated Carry/Borrow Flag:
492 CO_Flag : WBool := 0;
493
494 -- Odometer:
495 Ticks : Natural := 0;
496
(144 . 11)(147 . 11)
498 CommLevel : Natural := 0;
499 CondLevel : Natural := 0;
500
501 -- Whether we are currently inside a Proposed Subroutine Name:
502 SubNameMode : Boolean := False;
503 -- The possible Modes of the reader:
504 type Modes is (Normal, SubName, SubBody, PrefixOp);
505
506 -- Whether we are currently inside a Proposed Subroutine Body:
507 SubBodyMode : Boolean := False;
508 -- Currently-active reader Mode:
509 Mode : Modes := Normal;
510
511 -- Current levels of nestable Blocks when reading a Subroutine Body:
512 SubQuoteLevel : Natural := 0;
(164 . 9)(167 . 8)
514 Cutout_Armed : Boolean := False;
515 Cutout : Cutouts;
516
517 -- Prefixed Operators
518 -- Prefix for Prefixed Operators
519 PrevC : Character := ' ';
520 HavePrefix : Boolean := False;
521
522 -- Current Verdict. We run while 'Mu', Tape remains, and Ticks under max.
523 Verdict : Peh_Verdicts := Mu;
(245 . 10)(247 . 14)
525 end Zap_Registers;
526
527
528 -- Zero the Overflow Flag:
529 -- Zero the currently-active Overflow Flag:
530 procedure Zap_Flag is
531 begin
532 Flag := 0;
533 if Use_CO_Registers then
534 CO_Flag := 0;
535 else
536 Flag := 0;
537 end if;
538 end Zap_Flag;
539
540
(483 . 12)(489 . 18)
542 end if;
543 Write_Newline;
544
545 -- Print Overflow-Flag, Ticks and IP:
546 Write_String("Flag :" & WBool'Image(Flag));
547 -- Print active Overflow-Flag, then Ticks and IP:
548
549 if Use_CO_Registers then
550 Write_String("Flag (CO) :" & WBool'Image(CO_Flag));
551 else
552 Write_String("Flag :" & WBool'Image(Flag));
553 end if;
554
555 Write_Newline;
556 Write_String("Ticks :" & Natural'Image(Ticks));
557 Write_String("Ticks :" & Natural'Image(Ticks));
558 Write_Newline;
559 Write_String("IP :" & Tape_Positions'Image(IP));
560 Write_String("IP :" & Tape_Positions'Image(IP));
561 Write_Newline;
562 end Print_Trace;
563
(843 . 7)(855 . 13)
565 Y => Stack(SP),
566 Difference => Stack(SP - 1),
567 Underflow => F);
568 Flag := FFA_Word_NZeroP(F);
569
570 -- If we are in the Cutout, write the CO_Flag instead of Flag:
571 if Use_CO_Registers then
572 CO_Flag := FFA_Word_NZeroP(F);
573 else
574 Flag := FFA_Word_NZeroP(F);
575 end if;
576 Drop;
577
578 -- Add
(853 . 7)(871 . 13)
580 Y => Stack(SP),
581 Sum => Stack(SP - 1),
582 Overflow => F);
583 Flag := FFA_Word_NZeroP(F);
584
585 -- If we are in the Cutout, write the CO_Flag instead of Flag:
586 if Use_CO_Registers then
587 CO_Flag := FFA_Word_NZeroP(F);
588 else
589 Flag := FFA_Word_NZeroP(F);
590 end if;
591 Drop;
592
593 -- Divide and give Quotient and Remainder
(980 . 7)(1004 . 12)
595 -- Put the Overflow flag on the stack
596 when 'O' =>
597 Push;
598 FFA_WBool_To_FZ(Flag, Stack(SP));
599 -- If we are in the Cutout, read CO_Flag instead of Flag:
600 if Use_CO_Registers then
601 FFA_WBool_To_FZ(CO_Flag, Stack(SP));
602 else
603 FFA_WBool_To_FZ(Flag, Stack(SP));
604 end if;
605
606 -- Print the FZ on the top of the stack
607 when '#' =>
(1040 . 7)(1069 . 8)
609 |
610 '$' -- Pop top of Stack into the following Register...
611 =>
612 HavePrefix := True;
613 -- Set the Prefixed Op Mode. Next Symbol is treated as prefixed:
614 Mode := PrefixOp;
615
616 -----------
617 -- Loops --
(1083 . 7)(1113 . 7)
619 -- Save the NEXT IP as the first Symbol of the proposed Name:
620 Proposed_Sub.Name.L := Next_IP_On_Tape;
621 -- Enter the Name mode:
622 SubNameMode := True;
623 Mode := SubName;
624 -- We will remain in Name mode until we see a @ or ! .
625
626 -- '!' invokes a previously-defined Subroutine:
(1201 . 7)(1231 . 7)
628 when 'D' =>
629 Zap_Data_Stack;
630
631 -- ... Overflow Flag:
632 -- ... Overflow Flag (if in Cutout, zaps CO_Flag) :
633 when 'F' =>
634 Zap_Flag;
635
(1401 . 7)(1431 . 138)
637
638 ------------------------------------------------------------------------
639
640 -- Process a Symbol
641 -- Process a character in a proposed Subroutine Name:
642 procedure SubName_Symbol(C : in Character) is
643 begin
644 case C is
645 -- Attempt to INVOKE the named Subroutine:
646 when '!' =>
647 -- Detect attempt to invoke a Sub with no Name:
648 if IP = Proposed_Sub.Name.L then
649 E("Attempted to invoke a nameless Subroutine!");
650 end if;
651 -- Exit the Sub Name mode and enter Normal mode:
652 Mode := Normal;
653 -- Attempt to invoke the subroutine:
654 Invoke_Named_Subroutine(Proposed_Sub.Name);
655
656 -- Attempt to read a body for a Subroutine Definition:
657 when '@' =>
658 -- Detect attempt to define a Sub with no Name:
659 if IP = Proposed_Sub.Name.L then
660 E("Attempted to define a nameless Subroutine!");
661 end if;
662 -- Save NEXT IP as the beginning of the proposed Body:
663 Proposed_Sub.Payload.L := Next_IP_On_Tape;
664 -- Exit the Name mode and enter Sub Body mode:
665 Mode := SubBody;
666
667 -- Any permissible Symbol in a Subroutine Name:
668 when '0' .. '9' | 'A' .. 'Z' | 'a' .. 'z' | '-' | '_' =>
669 -- Save IP as the potential end of the proposed Sub Name:
670 Proposed_Sub.Name.R := IP;
671
672 when others =>
673 E("Symbol '" & C & "' is prohibited in a Subroutine Name !");
674 end case;
675 end SubName_Symbol;
676
677 ------------------------------------------------------------------------
678
679 -- Process a character in a proposed Subroutine Body:
680 procedure SubBody_Symbol(C : in Character) is
681
682 -- Name of Proposed Subroutine (for eggogs) :
683 Name : String
684 := String(Tape(Proposed_Sub.Name.L .. Proposed_Sub.Name.R));
685
686 begin
687 case C is
688 -- Subroutine Terminator:
689 when ';' =>
690 -- Only takes effect if NOT in a Comment or Quote Block:
691 if SubCommLevel = 0 and SubQuoteLevel = 0 then
692 if SubCondLevel /= 0 then
693 E("Conditional Return in Subroutine: '"
694 & Name & "' is Prohibited!" &
695 " (Please check for unbalanced '{'.)'");
696 end if;
697 -- Now, Sub-Comm, Quote, and Cond levels are 0.
698 -- The ';' becomes last Symbol of the new Sub's Body.
699 -- Test for attempt to define a Sub with a null Body:
700 if IP = Proposed_Sub.Payload.L then
701 E("Null Body in Subroutine: '" & Name
702 & "' is prohibited!");
703 end if;
704 -- Intern this new Sub definition:
705 Proposed_Sub.Payload.R := IP;
706 -- Exit the Sub Body mode and enter Normal mode:
707 Mode := Normal;
708 -- Attempt to intern the Proposed Subroutine:
709 Intern_Subroutine(Proposed_Sub);
710 end if;
711
712 -- Begin-Comment inside a Subroutine Body:
713 when '(' =>
714 SubCommLevel := SubCommLevel + 1;
715
716 -- End-Comment inside a Subroutine Body:
717 when ')' =>
718 -- If cannot drop Sub Comment level:
719 if SubCommLevel = 0 then
720 E("Unbalanced ')' in Body of Subroutine: '"
721 & Name & "' !");
722 end if;
723 SubCommLevel := SubCommLevel - 1;
724
725 -- Begin-Quote inside a Subroutine Body:
726 when '[' =>
727 -- Ignore if Commented:
728 if SubCommLevel = 0 then
729 SubQuoteLevel := SubQuoteLevel + 1;
730 end if;
731
732 -- End-Quote inside a Subroutine Body:
733 when ']' =>
734 -- Ignore if Commented:
735 if SubCommLevel = 0 then
736 -- If cannot drop Sub Quote level:
737 if SubQuoteLevel = 0 then
738 E("Unbalanced ']' in Body of Subroutine: '"
739 & Name & "' !");
740 end if;
741 SubQuoteLevel := SubQuoteLevel - 1;
742 end if;
743
744 -- Begin-Conditional inside a Subroutine Body:
745 when '{' =>
746 -- Ignore if Commented or Quoted:
747 if SubCommLevel = 0 and SubQuoteLevel = 0 then
748 SubCondLevel := SubCondLevel + 1;
749 end if;
750
751 -- End-Conditional inside a Subroutine Body:
752 when '}' =>
753 -- Ignore if Commented or Quoted:
754 if SubCommLevel = 0 and SubQuoteLevel = 0 then
755 -- If cannot drop Sub Conditional level:
756 if SubCondLevel = 0 then
757 E("Unbalanced '}' in Body of Subroutine: '"
758 & Name & "' !");
759 end if;
760 SubCondLevel := SubCondLevel - 1;
761 end if;
762
763 -- All other Symbols have no special effect in Sub Body :
764 when others =>
765 null; -- Stay in Body mode until we see the ';'.
766 end case;
767 end SubBody_Symbol;
768
769
770 ------------------------------------------------------------------------
771
772 -- All Peh Symbols begin their processing here :
773 procedure Op(C : in Character) is
774 begin
775
(1454 . 151)(1615 . 42)
777 null; -- Other symbols have no effect on the level
778 end case;
779
780 --- ... in a proposed Subroutine Name:
781 elsif SubNameMode then
782 case C is
783 else
784 --- ... we are not inside a 'Block' :
785
786 case Mode is
787
788 -- Attempt to INVOKE the named Subroutine:
789 when '!' =>
790 -- Detect attempt to invoke a Sub with no Name:
791 if IP = Proposed_Sub.Name.L then
792 E("Attempted to invoke a nameless Subroutine!");
793 end if;
794 -- Exit the Name mode:
795 SubNameMode := False;
796 -- Attempt to invoke the subroutine:
797 Invoke_Named_Subroutine(Proposed_Sub.Name);
798 --- ... a character in a proposed Subroutine Name:
799 when SubName =>
800 SubName_Symbol(C);
801
802 -- Attempt to read a body for a Subroutine Definition:
803 when '@' =>
804 -- Detect attempt to define a Sub with no Name:
805 if IP = Proposed_Sub.Name.L then
806 E("Attempted to define a nameless Subroutine!");
807 end if;
808 -- Save the NEXT IP as the beginning of the proposed Body:
809 Proposed_Sub.Payload.L := Next_IP_On_Tape;
810 -- Exit the Name mode:
811 SubNameMode := False;
812 -- Enter Sub Body mode:
813 SubBodyMode := True;
814 --- ... a character in a proposed Subroutine Body:
815 when SubBody =>
816 SubBody_Symbol(C);
817
818 -- Any permissible Symbol in a Subroutine Name:
819 when '0' .. '9' | 'A' .. 'Z' | 'a' .. 'z' | '-' | '_' =>
820 -- Save IP as the potential end of the proposed Sub Name:
821 Proposed_Sub.Name.R := IP;
822 --- ... the second character of a Prefixed Op:
823 when PrefixOp =>
824 -- Drop prefix-op hammer, until another prefix-op cocks it:
825 Mode := Normal;
826
827 -- Dispatch this op, where prefix is the preceding character
828 Op_Prefixed(Prefix => PrevC, O => C);
829
830 -- This is a Normal Op...
831 when Normal =>
832 -- ... so proceed with the normal rules:
833 Op_Normal(C);
834
835 -- Save the current Symbol as a possible prefix:
836 PrevC := C;
837
838 when others =>
839 E("Symbol '" & C & "' is prohibited in a Subroutine Name !");
840 end case;
841
842 --- ... in a proposed Subroutine Body:
843 elsif SubBodyMode then
844 declare
845 -- Name of Proposed Subroutine (for eggogs) :
846 Name : String
847 := String(Tape(Proposed_Sub.Name.L .. Proposed_Sub.Name.R));
848 begin
849 case C is
850 -- Subroutine Terminator:
851 when ';' =>
852 -- Only takes effect if NOT in a Comment or Quote Block:
853 if SubCommLevel = 0 and SubQuoteLevel = 0 then
854 if SubCondLevel /= 0 then
855 E("Conditional Return in Subroutine: '"
856 & Name & "' is Prohibited!" &
857 " (Please check for unbalanced '{'.)'");
858 end if;
859 -- Now, Sub-Comm, Quote, and Cond levels are 0.
860 -- The ';' becomes last Symbol of the new Sub's Body.
861 -- Test for attempt to define a Sub with a null Body:
862 if IP = Proposed_Sub.Payload.L then
863 E("Null Body in Subroutine: '" & Name
864 & "' is prohibited!");
865 end if;
866 -- Exit Body mode, and intern this new Sub definition:
867 Proposed_Sub.Payload.R := IP;
868 -- Exit the Sub Body mode:
869 SubBodyMode := False;
870 -- Attempt to intern the Proposed Subroutine:
871 Intern_Subroutine(Proposed_Sub);
872 end if;
873
874 -- Begin-Comment inside a Subroutine Body:
875 when '(' =>
876 SubCommLevel := SubCommLevel + 1;
877
878 -- End-Comment inside a Subroutine Body:
879 when ')' =>
880 -- If cannot drop Sub Comment level:
881 if SubCommLevel = 0 then
882 E("Unbalanced ')' in Body of Subroutine: '"
883 & Name & "' !");
884 end if;
885 SubCommLevel := SubCommLevel - 1;
886
887 -- Begin-Quote inside a Subroutine Body:
888 when '[' =>
889 -- Ignore if Commented:
890 if SubCommLevel = 0 then
891 SubQuoteLevel := SubQuoteLevel + 1;
892 end if;
893
894 -- End-Quote inside a Subroutine Body:
895 when ']' =>
896 -- Ignore if Commented:
897 if SubCommLevel = 0 then
898 -- If cannot drop Sub Quote level:
899 if SubQuoteLevel = 0 then
900 E("Unbalanced ']' in Body of Subroutine: '"
901 & Name & "' !");
902 end if;
903 SubQuoteLevel := SubQuoteLevel - 1;
904 end if;
905
906 -- Begin-Conditional inside a Subroutine Body:
907 when '{' =>
908 -- Ignore if Commented or Quoted:
909 if SubCommLevel = 0 and SubQuoteLevel = 0 then
910 SubCondLevel := SubCondLevel + 1;
911 end if;
912
913 -- End-Conditional inside a Subroutine Body:
914 when '}' =>
915 -- Ignore if Commented or Quoted:
916 if SubCommLevel = 0 and SubQuoteLevel = 0 then
917 -- If cannot drop Sub Conditional level:
918 if SubCondLevel = 0 then
919 E("Unbalanced '}' in Body of Subroutine: '"
920 & Name & "' !");
921 end if;
922 SubCondLevel := SubCondLevel - 1;
923 end if;
924
925 -- All other Symbols have no special effect in Sub Body :
926 when others =>
927 null; -- Stay in Body mode until we see the ';'.
928 end case;
929 end;
930 --- ... if in a prefixed op:
931 elsif HavePrefix then
932
933 -- Drop the prefix-op hammer, until another prefix-op cocks it
934 HavePrefix := False;
935
936 -- Dispatch this op, where prefix is the preceding character
937 Op_Prefixed(Prefix => PrevC, O => C);
938
939 else
940 -- This is a Normal Op, so proceed with the normal rules.
941 Op_Normal(C);
942
943 end if;
944
945 -- In all cases, save the current Symbol as possible prefix:
946 PrevC := C;
947
948 end Op;
949
950 ------------------------------------------------------------------------
951
952 -----------------------------
953 -- Start of Tape Execution --
954 -----------------------------
(1652 . 23)(1704 . 33)
956 -- At this point, the Tape has halted.
957
958 ------------------------------------------------------------------
959 -- The following types of Unclosed Blocks trigger a Eggog Verdict:
960 -- Termination in a Mode other than 'Normal' triggers a Eggog Verdict:
961
962 -- Unclosed Subroutine Name at Tape's End:
963 if SubNameMode then
964 E("The Subroutine Name at IP:"
965 & Tape_Positions'Image(Proposed_Sub.Name.L)
966 & " is Unterminated!");
967 end if;
968
969 -- Unclosed Subroutine Body at Tape's End:
970 if SubBodyMode then
971 E("The Body of Subroutine: '"
972 & String(Tape(Proposed_Sub.Name.L .. Proposed_Sub.Name.R))
973 & "' is Unterminated!");
974 end if;
975 case Mode is
976
977 -- Unclosed Subroutine Name at Tape's End:
978 when SubName =>
979 E("The Subroutine Name at IP:"
980 & Tape_Positions'Image(Proposed_Sub.Name.L)
981 & " is Unterminated!");
982
983 -- Unclosed Subroutine Body at Tape's End:
984 when SubBody =>
985 E("The Body of Subroutine: '"
986 & String(Tape(Proposed_Sub.Name.L .. Proposed_Sub.Name.R))
987 & "' is Unterminated!");
988
989 -- Incomplete Prefix Op at Tape's End:
990 when PrefixOp =>
991 E("Prefix Op: '" & PrevC & "' is Unterminated at End of Tape!");
992
993 -- This is the expected Mode at Tape's End:
994 when Normal =>
995 null;
996
997 end case;
998
999 -- Unclosed Cutout:
1000 -- Unclosed Cutout triggers a Eggog Verdict:
1001 if Cutout_Begun and not Cutout_Armed then
1002 E("The Cutout declaration 'LC' at IP:"
1003 & Tape_Positions'Image(Cutout.L) & " is Unterminated!");