| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | separate (H2.Scheme) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | procedure Execute (Interp: in out Interpreter_Record) is | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	LC: IO_Character_Record renames Interp.Input.Iochar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Evaluate_Result is | 
					
						
							|  |  |  | 		pragma Inline (Evaluate_Result); | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		-- The result from the previous frame is stored in the current frame.
 | 
					
						
							|  |  |  | 		-- This procedure takes the result and switch it to an operand and clears it.
 | 
					
						
							|  |  |  | 		-- It is used to evaluate the result of Read_Object in principle.
 | 
					
						
							|  |  |  | 		-- It takes only the head(car) element of the result chain. 
 | 
					
						
							|  |  |  | 		-- Calling this function to evaluate the result of any arbitrary frame 
 | 
					
						
							|  |  |  | 		-- other than 'Read_Object' is not recommended.
 | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		Set_Frame_Operand (Interp.Stack, Get_Frame_Result(Interp.Stack)); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 		Clear_Frame_Result (Interp.Stack); | 
					
						
							|  |  |  | 		Set_Frame_Opcode (Interp.Stack, Opcode_Evaluate_Object); | 
					
						
							|  |  |  | 	end Evaluate_Result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	generic | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		with function Is_Good_Result (X: in Object_Pointer) return Standard.Boolean; | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 	procedure Evaluate_While; | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 	procedure Evaluate_While  is | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 		X: Object_Pointer; | 
					
						
							|  |  |  | 		Y: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 		Opcode: Opcode_Type; | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 	begin	 | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.Stack); | 
					
						
							|  |  |  | 		Y := Get_Frame_Result(Interp.Stack); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 		-- Evaluate_And_Syntax/Evaluate_Or_Syntax has arranged to 
 | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		-- evaluate <test1>. Y must be valid even at the first time 
 | 
					
						
							|  |  |  | 		-- this procedure is called.
 | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		if Is_Good_Result(Y) and then Is_Cons(X) then | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 			-- The result is not what I look for.
 | 
					
						
							|  |  |  | 			-- Yet there are still more tests to evaluate.
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 			--Switch_Frame (Interp.Stack, Get_Frame_Opcode(Interp.Stack), Get_Cdr(X), Nil_Pointer);
 | 
					
						
							|  |  |  | 			--Push_Frame (Interp, Opcode_Evaluate_Object, Get_Car(X));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Opcode := Get_Frame_Opcode(Interp.Stack); | 
					
						
							|  |  |  | 			Switch_Frame (Interp.Stack, Opcode_Evaluate_Object, Get_Car(X), Nil_Pointer); | 
					
						
							|  |  |  | 			Push_SubFrame (Interp, Opcode, Get_Cdr(X)); | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 		else | 
					
						
							|  |  |  | 			-- Return the result of the last expression evaluated.
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 			Return_Frame (Interp, Y); | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 		end if; | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 	end Evaluate_While; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 	function Is_False_Class (X: in Object_Pointer) return Standard.Boolean is | 
					
						
							|  |  |  | 		pragma Inline (Is_False_Class); | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		return X = False_Pointer; | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 	end Is_False_Class; | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 	function Is_True_Class (X: in Object_Pointer) return Standard.Boolean is | 
					
						
							|  |  |  | 		pragma Inline (Is_True_Class); | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		return X /= False_Pointer; | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 	end Is_True_Class; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Do_And_Finish is new Evaluate_While(Is_True_Class); | 
					
						
							|  |  |  | 	procedure Do_Or_Finish is new Evaluate_While(Is_False_Class); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 15:47:10 +00:00
										 |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	procedure Do_Case_Finish is | 
					
						
							|  |  |  | 		pragma Inline (Do_Case_Finish); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		R: Object_Pointer; | 
					
						
							|  |  |  | 		O: Object_Pointer; | 
					
						
							|  |  |  | 		C: Object_Pointer; | 
					
						
							|  |  |  | 		D: Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		R := Get_Frame_Result(Interp.Stack); -- <test> result
 | 
					
						
							|  |  |  | 		O := Get_Frame_Operand(Interp.Stack); -- <clause> list
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		while Is_Cons(O) loop | 
					
						
							|  |  |  | 			C := Get_Car(O); -- <clause>
 | 
					
						
							|  |  |  | 			D := Get_Car(C); -- <datum> list
 | 
					
						
							|  |  |  | 			if D = Interp.Else_Symbol then | 
					
						
							|  |  |  | 				Reload_Frame (Interp, Opcode_Grouped_Call, Get_Cdr(C)); | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			while Is_Cons(D) loop | 
					
						
							|  |  |  | 				if Equal_Values(R, Get_Car(D)) then -- <datum>
 | 
					
						
							|  |  |  | 					Reload_Frame (Interp, Opcode_Grouped_Call, Get_Cdr(C)); | 
					
						
							|  |  |  | 					return; | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 				D := Get_Cdr(D); | 
					
						
							|  |  |  | 			end loop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			O := Get_Cdr(O); | 
					
						
							|  |  |  | 		end loop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		-- no match found;
 | 
					
						
							|  |  |  | 		Pop_Frame (Interp); | 
					
						
							|  |  |  | 	end Do_Case_Finish; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	procedure Do_Cond_Finish is | 
					
						
							|  |  |  | 		pragma Inline (Do_Cond_Finish); | 
					
						
							|  |  |  | 		R: Object_Pointer; | 
					
						
							|  |  |  | 		O: Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		R := Get_Frame_Result(Interp.Stack); -- <test> result
 | 
					
						
							|  |  |  | 		O := Get_Frame_Operand(Interp.Stack); -- <clause> list
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if Is_True_Class(R) then | 
					
						
							|  |  |  | 			O := Get_Cdr(Get_Car(O)); -- <expression> list in <clause>
 | 
					
						
							|  |  |  | 			if Is_Cons(O) then | 
					
						
							|  |  |  | 				Reload_Frame (Interp, Opcode_Grouped_Call, O); | 
					
						
							|  |  |  | 			else | 
					
						
							| 
									
										
										
										
											2014-02-11 09:35:44 +00:00
										 |  |  | 				Pop_Frame (Interp); -- no <expression> to evaluate
 | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 			end if; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			O := Get_Cdr(O); -- next <clause> list
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if not Is_Cons(O) then | 
					
						
							|  |  |  | 				-- no more <clause>
 | 
					
						
							|  |  |  | 				Pop_Frame (Interp); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				R := Get_Car(O); -- next <clause>
 | 
					
						
							|  |  |  | 				if Get_Car(R) = Interp.Else_Symbol then | 
					
						
							|  |  |  | 					-- else <clause>
 | 
					
						
							|  |  |  | 					O := Get_Cdr(R); -- <expression> list in else <clause>
 | 
					
						
							|  |  |  | 					if Is_Cons(O) then | 
					
						
							|  |  |  | 						Reload_Frame (Interp, Opcode_Grouped_Call, O); | 
					
						
							|  |  |  | 					else | 
					
						
							| 
									
										
										
										
											2014-02-11 09:35:44 +00:00
										 |  |  | 						Pop_Frame (Interp); -- no <expression> to evaluate
 | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 					end if; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					Switch_Frame (Interp.Stack, Opcode_Evaluate_Object, Get_Car(R), Nil_Pointer); | 
					
						
							|  |  |  | 					Push_Subframe (Interp, Opcode_Cond_Finish, O); | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 		end if; | 
					
						
							|  |  |  | 	end Do_Cond_Finish; | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 	procedure Do_Define_Finish is | 
					
						
							|  |  |  | 		pragma Inline (Do_Define_Finish); | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		X: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 		Y: aliased Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		-- Manage Y as it's referenced after the gc point. 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		Push_Top (Interp, Y'Unchecked_Access);  | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-20 14:34:55 +00:00
										 |  |  | 		X := Get_Frame_Operand(Interp.Stack); -- symbol
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 		pragma Assert (Is_Symbol(X)); | 
					
						
							| 
									
										
										
										
											2014-01-21 05:08:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Y := Get_Frame_Result(Interp.Stack);  -- value list
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		Set_Current_Environment (Interp, X, Y);  -- gc point
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		Return_Frame (Interp, Y); -- Y is referenced here.
 | 
					
						
							|  |  |  | 		Pop_Tops (Interp, 1); -- Unmanage Y
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 	end Do_Define_Finish; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2014-01-20 14:34:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 15:11:00 +00:00
										 |  |  | 	procedure Do_Do_Binding is | 
					
						
							|  |  |  | 		pragma Inline (Do_Do_Binding); | 
					
						
							|  |  |  | 		X: aliased Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		Push_Top (Interp, X'Unchecked_Access); | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.StacK); | 
					
						
							|  |  |  | 		Set_Parent_Environment (Interp, Get_Car(Get_Car(X)), Get_Frame_Result(Interp.Stack)); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		X := Get_Cdr(X); | 
					
						
							|  |  |  | 		if Is_Cons(X) then | 
					
						
							|  |  |  | 			declare | 
					
						
							|  |  |  | 				Envir: aliased Object_Pointer; | 
					
						
							|  |  |  | 			begin | 
					
						
							|  |  |  | 				pragma Assert (Get_Frame_Opcode(Get_Frame_Parent(Interp.Stack)) = Opcode_Do_Test); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				Push_top (Interp, Envir'Unchecked_Access); | 
					
						
							|  |  |  | 				Envir := Get_Frame_Environment(Get_Frame_Parent(Get_Frame_Parent(Interp.Stack)));  | 
					
						
							|  |  |  | 				Reload_Frame (Interp, Opcode_Do_Binding, X); | 
					
						
							|  |  |  | 				Push_Frame_With_Environment (Interp, Opcode_Evaluate_Object, Get_Car(Get_Cdr(Get_Car(X))), Envir); -- <init>
 | 
					
						
							|  |  |  | 				Pop_Tops (Interp, 1); | 
					
						
							|  |  |  | 			end; | 
					
						
							|  |  |  | 		else  | 
					
						
							|  |  |  | 			Pop_Frame (Interp); | 
					
						
							|  |  |  | 		end if; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		Pop_Tops (Interp, 1); | 
					
						
							|  |  |  | 	end Do_Do_Binding; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	procedure Do_Do_Test is | 
					
						
							|  |  |  | 		pragma Inline (Do_Do_Test); | 
					
						
							|  |  |  | 		X: aliased Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		Push_Top (Interp, X'Unchecked_Access); | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.Stack); | 
					
						
							|  |  |  | 		Reload_Frame (Interp, Opcode_Do_Break, X); | 
					
						
							|  |  |  | 		Push_Frame (Interp, Opcode_Evaluate_Object, Get_Car(Get_Car(Get_Cdr(X)))); -- <test>
 | 
					
						
							|  |  |  | 		Pop_Tops (Interp, 1); | 
					
						
							|  |  |  | 	end Do_Do_Test; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	procedure Do_Do_Break is | 
					
						
							|  |  |  | 		X: aliased Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.Stack); | 
					
						
							|  |  |  | 		if Is_True_Class(Get_Frame_Result(Interp.Stack)) then | 
					
						
							| 
									
										
										
										
											2014-02-18 14:07:41 +00:00
										 |  |  | 			-- <test> is true. arrange to break out of 'do'.
 | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2014-02-17 15:11:00 +00:00
										 |  |  | 			X := Get_Cdr(Get_Car(Get_Cdr(X))); | 
					
						
							|  |  |  | 			if X = Nil_Pointer then | 
					
						
							|  |  |  | 				-- no expression after <test>
 | 
					
						
							|  |  |  | 				-- (do ((x 1)) (#t))
 | 
					
						
							|  |  |  | 				Pop_Frame (Interp); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				Reload_Frame (Interp, Opcode_Grouped_Call, X); | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2014-02-18 14:07:41 +00:00
										 |  |  | 			-- <test> is false. 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 15:11:00 +00:00
										 |  |  | 			Push_Top (Interp, X'Unchecked_Access); | 
					
						
							|  |  |  | 			Reload_Frame (Interp, Opcode_Do_Step, X); | 
					
						
							|  |  |  | 			X := Get_Cdr(Get_Cdr(X)); | 
					
						
							|  |  |  | 			if X /= Nil_Pointer then | 
					
						
							|  |  |  | 				Push_Frame (Interp, Opcode_Grouped_Call, X); | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 			Pop_Tops (Interp, 1); | 
					
						
							|  |  |  | 		end if; | 
					
						
							|  |  |  | 	end Do_Do_Break; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	procedure Do_Do_Step is | 
					
						
							| 
									
										
										
										
											2014-02-18 14:07:41 +00:00
										 |  |  | 		X: aliased Object_Pointer; | 
					
						
							|  |  |  | 		Y: aliased Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-02-17 15:11:00 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		-- arrange to evaluate <step> and update binding <variable>.
 | 
					
						
							| 
									
										
										
										
											2014-02-18 14:07:41 +00:00
										 |  |  | 		Push_Top (Interp, X'Unchecked_Access); | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.Stack); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Reload_Frame (Interp, Opcode_Do_Test, X); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		X := Get_Car(X); | 
					
						
							|  |  |  | 		while Is_Cons(X) loop | 
					
						
							|  |  |  | 			Y := Get_Cdr(Get_Cdr(Get_Car(X))); | 
					
						
							|  |  |  | 			if Is_Cons(Y) then | 
					
						
							|  |  |  | 				Push_Top (Interp, Y'Unchecked_Access); | 
					
						
							|  |  |  | 				Push_Frame (Interp, Opcode_Do_Update, X); | 
					
						
							|  |  |  | 				Push_Frame (Interp, Opcode_Evaluate_Object, Get_Car(Y)); -- first <step>
 | 
					
						
							|  |  |  | 				Pop_Tops (Interp, 1); | 
					
						
							|  |  |  | 				exit; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				-- no <step>
 | 
					
						
							|  |  |  | 				X := Get_Cdr(X); | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 		end loop; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		Pop_Tops (Interp, 1); | 
					
						
							| 
									
										
										
										
											2014-02-17 15:11:00 +00:00
										 |  |  | 	end Do_Do_Step; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Do_Do_Update is | 
					
						
							| 
									
										
										
										
											2014-02-18 14:07:41 +00:00
										 |  |  | 		X: aliased Object_Pointer; | 
					
						
							|  |  |  | 		Y: aliased Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-02-17 15:11:00 +00:00
										 |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-02-18 14:07:41 +00:00
										 |  |  | 		Push_Top (Interp, X'Unchecked_Access); | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.StacK); | 
					
						
							|  |  |  | 		Set_Parent_Environment (Interp, Get_Car(Get_Car(X)), Get_Frame_Result(Interp.Stack)); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		loop | 
					
						
							|  |  |  | 			X := Get_Cdr(X); | 
					
						
							|  |  |  | 			if Is_Cons(X) then | 
					
						
							|  |  |  | 				Y := Get_Cdr(Get_Cdr(Get_Car(X))); | 
					
						
							|  |  |  | 				if Is_Cons(Y) then | 
					
						
							|  |  |  | 					-- if <step> is specified
 | 
					
						
							|  |  |  | 					Push_Top (Interp, Y'Unchecked_Access); | 
					
						
							|  |  |  | 					Reload_Frame (Interp, Opcode_Do_Update, X); | 
					
						
							|  |  |  | 					Push_Frame (Interp, Opcode_Evaluate_Object, Get_Car(Y)); -- <step>
 | 
					
						
							|  |  |  | 					Pop_Tops (Interp, 1); | 
					
						
							|  |  |  | 					exit; | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 			else  | 
					
						
							|  |  |  | 				-- no more <bindings>
 | 
					
						
							|  |  |  | 				Pop_Frame (Interp); | 
					
						
							|  |  |  | 				exit; | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 		end loop; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		Pop_Tops (Interp, 1); | 
					
						
							| 
									
										
										
										
											2014-02-17 15:11:00 +00:00
										 |  |  | 	end Do_Do_Update; | 
					
						
							|  |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 	procedure Do_If_Finish is | 
					
						
							|  |  |  | 		pragma Inline (Do_If_Finish); | 
					
						
							|  |  |  | 		X: Object_Pointer; | 
					
						
							|  |  |  | 		Y: Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-01-20 14:34:55 +00:00
										 |  |  | 		X := Get_Frame_Operand(Interp.Stack); -- cons cell containing <consequent>
 | 
					
						
							|  |  |  | 		pragma Assert (Is_Cons(X));  | 
					
						
							| 
									
										
										
										
											2014-01-21 05:08:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Y := Get_Frame_Result(Interp.Stack);  -- result list of <test>
 | 
					
						
							| 
									
										
										
										
											2014-01-20 14:34:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if Y = False_Pointer then | 
					
						
							|  |  |  | 			-- <test> evaluated to #f.
 | 
					
						
							|  |  |  | 			X := Get_Cdr(X); -- cons cell containing <alternate>
 | 
					
						
							|  |  |  | 			if Is_Cons(X) then | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 				-- Switch the current current to evaluate <alternate> 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 				-- keeping the environment untouched. Use Reload_Frame
 | 
					
						
							|  |  |  | 				-- instead of Switch_Frame for continuation. If continuation
 | 
					
						
							|  |  |  | 				-- has been created in <test>, continuation can be made to 
 | 
					
						
							|  |  |  | 				-- this frame. 
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 				--
 | 
					
						
							|  |  |  | 				-- For example,
 | 
					
						
							|  |  |  | 				--   (if (define xx (call/cc call/cc)) 
 | 
					
						
							|  |  |  | 				--       (+ 10 20) (* 1 2 3 4))
 | 
					
						
							|  |  |  | 				--   (xx 99)
 | 
					
						
							|  |  |  | 				-- When (xx 99) is evaluated, continuation is made to
 | 
					
						
							|  |  |  | 				-- this frame. For this frame to evaluate <consequent> or 
 | 
					
						
							|  |  |  | 				-- <alternate>, its opcode must remain as Opcode_If_Finish.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				--Switch_Frame (Interp.Stack, Opcode_Evaluate_Object, Get_Car(X), Nil_Pointer);
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 				Reload_Frame (Interp, Opcode_Evaluate_Object, Get_Car(X)); | 
					
						
							| 
									
										
										
										
											2014-01-20 14:34:55 +00:00
										 |  |  | 			else | 
					
						
							| 
									
										
										
										
											2014-01-23 15:34:06 +00:00
										 |  |  | 				-- Return nil if no <alternate> is specified
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 				Return_Frame (Interp, Nil_Pointer); | 
					
						
							| 
									
										
										
										
											2014-01-20 14:34:55 +00:00
										 |  |  | 			end if; | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 			-- All values except #f are true values. evaluate <consequent>.
 | 
					
						
							|  |  |  | 			-- Switch the current current to evaluate <consequent> keeping
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 			-- the environment untouched. Use Reload_Frame instead of
 | 
					
						
							|  |  |  | 			-- Switch_Frame for continuation to work.
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 			--Switch_Frame (Interp.Stack, Opcode_Evaluate_Object, Get_Car(X), Nil_Pointer);
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 			Reload_Frame (Interp, Opcode_Evaluate_Object, Get_Car(X)); | 
					
						
							| 
									
										
										
										
											2014-01-20 14:34:55 +00:00
										 |  |  | 		end if; | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 	end Do_If_Finish; | 
					
						
							| 
									
										
										
										
											2014-01-20 14:34:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Do_Procedure_Call is | 
					
						
							|  |  |  | 		pragma Inline (Do_Procedure_Call); | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		R: Object_Pointer; | 
					
						
							|  |  |  | 		X: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		-- Note: if you change the assignment order of R and X, 
 | 
					
						
							|  |  |  | 		--       Push_Top() and Pop_Tops() are needed.
 | 
					
						
							|  |  |  | 		--Push_Top (Interp, X'Unchecked_Access);
 | 
					
						
							|  |  |  | 		--Push_Top (Interp, R'Unchecked_Access);
 | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		R := Make_Cons(Interp.Self, Get_Frame_Result(Interp.Stack), Get_Frame_Intermediate(Interp.Stack)); | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		X := Get_Frame_Operand(Interp.Stack); | 
					
						
							| 
									
										
										
										
											2014-01-26 16:15:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		if Is_Cons(X) then | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 			Switch_Frame (Interp.Stack, Opcode_Evaluate_Object, Get_Car(X), Nil_Pointer); | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 			Push_Subframe_With_Intermediate (Interp, Opcode_Procedure_Call, Get_Cdr(X), R); | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 			-- no more argument to evaluate. 
 | 
					
						
							|  |  |  | 			-- apply the evaluated arguments to the evaluated operator.
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 			R := Reverse_Cons(R); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			-- This frame can be resumed. Switching the current frame to Opcode_Apply
 | 
					
						
							|  |  |  | 			-- affects continuation objects that point to the current frame. However,
 | 
					
						
							|  |  |  | 			-- keeping it unchanged causes this frame to repeat actions that has been 
 | 
					
						
							|  |  |  | 			-- taken previously when it's resumed. So i change the frame to something 
 | 
					
						
							|  |  |  | 			-- special designed for continuation only.
 | 
					
						
							|  |  |  | 			Switch_Frame (Interp.Stack, Opcode_Procedure_Call_Finish, Get_Car(R), Nil_Pointer); | 
					
						
							|  |  |  | 			Pop_Frame (Interp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			-- Replace the current frame popped by a new applying frame.
 | 
					
						
							|  |  |  | 			Push_Frame_With_Intermediate (Interp, Opcode_Apply, Get_Car(R), Get_Cdr(R)); | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 		end if; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		--Pop_Tops (Interp, 2);
 | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 	end Do_Procedure_Call; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 	procedure Do_Procedure_Call_Finish is | 
					
						
							|  |  |  | 		pragma Inline (Do_Procedure_Call_Finish); | 
					
						
							|  |  |  | 		R: Object_Pointer; | 
					
						
							|  |  |  | 		X: Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		-- TODO: is this really correct? verify this.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		-- Note: if you change the assignment order of R and X, 
 | 
					
						
							|  |  |  | 		--       Push_Top() and Pop_Tops() are needed.
 | 
					
						
							|  |  |  | 		--Push_Top (Interp, X'Unchecked_Access);
 | 
					
						
							|  |  |  | 		--Push_Top (Interp, R'Unchecked_Access);
 | 
					
						
							|  |  |  | 		R := Make_Cons(Interp.Self, Get_Frame_Result(Interp.Stack), Nil_Pointer); | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.Stack); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		Reload_Frame_With_Intermediate (Interp, Opcode_Apply, X, R); | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		--Pop_Tops (Interp, 2);
 | 
					
						
							|  |  |  | 	end Do_Procedure_Call_Finish; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Do_Grouped_Call is | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		pragma Inline (Do_Grouped_Call); | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 		X: Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.Stack); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		pragma Assert (Is_Cons(X)); -- The caller must ensure this.
 | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		-- Switch the current frame to evaluate the first 
 | 
					
						
							|  |  |  | 		-- expression in the group.
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		Switch_Frame (Interp.Stack, Opcode_Evaluate_Object, Get_Car(X), Nil_Pointer); | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		X := Get_Cdr(X); | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 		if Is_Cons(X) then | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 			-- Add a new frame for handling the remaining expressions in 
 | 
					
						
							|  |  |  | 			-- the group. Place it below the current frame so that it's 
 | 
					
						
							|  |  |  | 			-- executed after the current frame switched is executed first.
 | 
					
						
							|  |  |  | 			Push_Subframe (Interp, Opcode_Grouped_Call, X); | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 		end if; | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 	end Do_Grouped_Call; | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	-- ----------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 	procedure Do_Let_Binding is | 
					
						
							|  |  |  | 		pragma Inline (Do_Let_Binding); | 
					
						
							|  |  |  | 		O: aliased Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		-- Perform binding in the parent environment.
 | 
					
						
							|  |  |  | 		Set_Parent_Environment (Interp, Get_Frame_Intermediate(Interp.Stack), Get_Frame_Result(Interp.Stack)); | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		O := Get_Frame_Operand(Interp.Stack);	 | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		-- Say, <bindings> is ((x 2) (y 2)).
 | 
					
						
							|  |  |  | 		-- Get_Car(O) is (x 2).
 | 
					
						
							|  |  |  | 		-- To get x, Get_Car(Get_Car(O))
 | 
					
						
							|  |  |  | 		-- To get 2, Get_Car(Get_Cdr(Get_Car(O)))
 | 
					
						
							|  |  |  | 		if Is_Cons(O) then | 
					
						
							|  |  |  | 			Push_Top (Interp, O'Unchecked_Access); | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 			Reload_Frame (Interp, Opcode_Evaluate_Object, Get_Car(Get_Cdr(Get_Car(O)))); | 
					
						
							|  |  |  | 			Push_Subframe_With_Intermediate (Interp, Opcode_Let_Binding, Get_Cdr(O), Get_Car(Get_Car(O))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Pop_Tops (Interp, 1); | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 			Pop_Frame (Interp); -- done. 
 | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 		end if; | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 	end Do_Let_Binding; | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 	procedure Do_Letast_Binding is | 
					
						
							|  |  |  | 		pragma Inline (Do_Letast_Binding); | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		O: aliased Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 		Envir: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		-- Perform binding in the parent environment.
 | 
					
						
							|  |  |  | 		Set_Current_Environment (Interp, Get_Frame_Intermediate(Interp.Stack), Get_Frame_Result(Interp.Stack)); | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		O := Get_Frame_Operand(Interp.Stack);	 | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		-- Say, <bindings> is ((x 2) (y 2)).
 | 
					
						
							|  |  |  | 		-- Get_Car(O) is (x 2).
 | 
					
						
							|  |  |  | 		-- To get x, Get_Car(Get_Car(O))
 | 
					
						
							|  |  |  | 		-- To get 2, Get_Car(Get_Cdr(Get_Car(O)))
 | 
					
						
							|  |  |  | 		if Is_Cons(O) then | 
					
						
							|  |  |  | 			Push_Top (Interp, O'Unchecked_Access); | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  |          		Envir := Make_Environment(Interp.Self, Get_Frame_Environment(Interp.Stack)); | 
					
						
							|  |  |  |          		Set_Frame_Environment (Interp.Stack, Envir);  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 			Reload_Frame (Interp, Opcode_Evaluate_Object, Get_Car(Get_Cdr(Get_Car(O)))); | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 			Push_Subframe_With_Intermediate (Interp, Opcode_Letast_Binding, Get_Cdr(O), Get_Car(Get_Car(O))); | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 			Pop_Tops (Interp, 1); | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | --envir := get_frame_environment(interp.stack);
 | 
					
						
							|  |  |  | --declare
 | 
					
						
							|  |  |  | --w: object_word;
 | 
					
						
							|  |  |  | --for w'address use envir'address;
 | 
					
						
							|  |  |  | --begin
 | 
					
						
							|  |  |  | --ada.text_io.put_line ("i$$$$$$$$$$$$$$$$$$$$$$$$44 ENVIR => " & object_word'image(w));
 | 
					
						
							|  |  |  | --print (interp, envir);
 | 
					
						
							|  |  |  | --end;
 | 
					
						
							|  |  |  | 			-- Get the final environment
 | 
					
						
							|  |  |  | 			Envir := Get_Frame_Environment(Interp.Stack); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			-- Get <body> stored in the Opcode_Grouped_Call frame
 | 
					
						
							|  |  |  | 			-- pushed in Evalute_Letast_Syntax().
 | 
					
						
							|  |  |  | 			O := Get_Frame_Operand(Get_Frame_Parent(Interp.Stack)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Pop_Frame (Interp); -- Current frame
 | 
					
						
							|  |  |  | 			pragma Assert (Get_Frame_Opcode(Interp.Stack) = Opcode_Grouped_Call); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			-- Refresh the Opcode_Grouped_Call frame pushed in Evaluate_Letast_Syntax()
 | 
					
						
							|  |  |  | 			-- with the final environment.
 | 
					
						
							|  |  |  | 			Reload_Frame_With_Environment (Interp, Opcode_Grouped_Call, O, Envir); | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 		end if; | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 	end Do_Letast_Binding; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 	procedure Do_Letrec_Binding is | 
					
						
							|  |  |  | 		pragma Inline (Do_Letrec_Binding); | 
					
						
							|  |  |  | 		O: aliased Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-24 07:58:46 +00:00
										 |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 		-- Perform binding in the parent environment.
 | 
					
						
							|  |  |  | 		Set_Current_Environment (Interp, Get_Frame_Intermediate(Interp.Stack), Get_Frame_Result(Interp.Stack)); | 
					
						
							| 
									
										
										
										
											2014-01-24 07:58:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 		O := Get_Frame_Operand(Interp.Stack);	 | 
					
						
							| 
									
										
										
										
											2014-01-26 14:58:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 		-- Say, <bindings> is ((x 2) (y 2)).
 | 
					
						
							|  |  |  | 		-- Get_Car(O) is (x 2).
 | 
					
						
							|  |  |  | 		-- To get x, Get_Car(Get_Car(O))
 | 
					
						
							|  |  |  | 		-- To get 2, Get_Car(Get_Cdr(Get_Car(O)))
 | 
					
						
							|  |  |  | 		if Is_Cons(O) then | 
					
						
							|  |  |  | 			Push_Top (Interp, O'Unchecked_Access); | 
					
						
							| 
									
										
										
										
											2014-01-26 14:58:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 			Reload_Frame (Interp, Opcode_Evaluate_Object, Get_Car(Get_Cdr(Get_Car(O)))); | 
					
						
							|  |  |  | 			Push_Subframe_With_Intermediate (Interp, Opcode_Letrec_Binding, Get_Cdr(O), Get_Car(Get_Car(O))); | 
					
						
							| 
									
										
										
										
											2014-01-24 07:58:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 			Pop_Tops (Interp, 1); | 
					
						
							| 
									
										
										
										
											2014-01-28 17:03:52 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 			Pop_Frame (Interp); | 
					
						
							| 
									
										
										
										
											2014-01-24 07:58:46 +00:00
										 |  |  | 		end if; | 
					
						
							| 
									
										
										
										
											2014-02-09 17:20:59 +00:00
										 |  |  | 	end Do_Letrec_Binding; | 
					
						
							| 
									
										
										
										
											2014-01-24 07:58:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 	-- --------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2014-01-21 14:55:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 	procedure Do_Set_Finish is | 
					
						
							|  |  |  | 		pragma Inline (Do_Set_Finish); | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		X: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-20 15:47:08 +00:00
										 |  |  | 		Y: aliased Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		Push_Top (Interp, Y'Unchecked_Access); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		X := Get_Frame_Operand(Interp.Stack); -- symbol
 | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		Y := Get_Frame_Result(Interp.Stack);  -- value
 | 
					
						
							| 
									
										
										
										
											2014-02-20 14:51:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-20 15:47:08 +00:00
										 |  |  | 		pragma Assert (Is_Symbol(X)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if Set_Environment(Interp.Self, X, Y) = null then | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 			Ada.Text_IO.Put_LINE ("ERROR: UNBOUND SYMBOL"); | 
					
						
							| 
									
										
										
										
											2014-01-20 15:47:08 +00:00
										 |  |  | 			raise Evaluation_Error; | 
					
						
							|  |  |  | 		end if; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		Return_Frame (Interp, Y); | 
					
						
							| 
									
										
										
										
											2014-01-20 15:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 		Pop_Tops (Interp, 1); | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 	end Do_Set_Finish; | 
					
						
							| 
									
										
										
										
											2014-01-20 15:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 	procedure Evaluate is separate; | 
					
						
							|  |  |  | 	procedure Apply is separate; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 	-- --------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 	procedure Unfetch_Character is | 
					
						
							|  |  |  | 		pragma Inline (Unfetch_Character); | 
					
						
							|  |  |  | 		pragma Assert (not Interp.LC_Unfetched);	 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 		Interp.LC_Unfetched := Standard.True; | 
					
						
							|  |  |  | 	end Unfetch_Character; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	procedure Fetch_Character is | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 	-- TODO: calculate Interp.Input.Row, Interp.Input.Column
 | 
					
						
							|  |  |  | 		if Interp.Input.Pos >= Interp.Input.Last then | 
					
						
							|  |  |  | 			if Interp.Input.Flags /= 0 then | 
					
						
							|  |  |  | 				-- An error has occurred or EOF has been reached previously.
 | 
					
						
							|  |  |  | 				-- Note calling this procedure after EOF results in an error.
 | 
					
						
							|  |  |  | 				Interp.Input.Iochar := (Error_Character, Object_Character'First); | 
					
						
							|  |  |  | 				--return;
 | 
					
						
							|  |  |  | 				raise IO_Error; | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Interp.Input.Pos := Interp.Input.Data'First - 1; | 
					
						
							|  |  |  | 			begin | 
					
						
							|  |  |  | 				Read (Interp.Input.Stream.all, Interp.Input.Data, Interp.Input.Last); | 
					
						
							|  |  |  | 			exception | 
					
						
							|  |  |  | 				when others => | 
					
						
							|  |  |  | 					-- The callee can raise an exception upon errors.
 | 
					
						
							|  |  |  | 					-- If an exception is raised, data read into the buffer 
 | 
					
						
							|  |  |  | 					-- is also ignored.
 | 
					
						
							|  |  |  | 					Interp.Input.Flags := Interp.Input.Flags and IO_Error_Occurred; | 
					
						
							|  |  |  | 					Interp.Input.Iochar := (Error_Character, Object_Character'First); | 
					
						
							|  |  |  | 					--return;
 | 
					
						
							|  |  |  | 					raise IO_Error; | 
					
						
							|  |  |  | 			end; | 
					
						
							| 
									
										
										
										
											2014-03-26 14:28:41 +00:00
										 |  |  | 			if Interp.Input.Last < Interp.Input.Data'First then | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				-- The callee must read 0 bytes on EOF 
 | 
					
						
							|  |  |  | 				Interp.Input.Flags := Interp.Input.Flags and IO_End_Reached; | 
					
						
							|  |  |  | 				Interp.Input.Iochar := (End_Character, Object_Character'First); | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 		end if; | 
					
						
							|  |  |  | 		Interp.Input.Pos := Interp.Input.Pos + 1; | 
					
						
							|  |  |  | 		Interp.Input.Iochar := (Normal_Character, Interp.Input.Data(Interp.Input.Pos)); | 
					
						
							|  |  |  | 	end Fetch_Character; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	function Is_White_Space (X: in Object_Character) return Standard.Boolean is | 
					
						
							|  |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 		return X = Ch_Val.Space or else X = Ch_Val.HT or else X = Ch_Val.VT or else  | 
					
						
							|  |  |  | 		       X = Ch_Val.CR or else X = Ch_Val.LF or else X = Ch_Val.FF; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	end Is_White_Space; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 	function Is_Delimiter (X: in Object_Character) return  Standard.Boolean is | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 		return X = Ch_Val.Left_Parenthesis or else X = Ch_Val.Right_Parenthesis or else | 
					
						
							|  |  |  | 		       X = Ch_Val.Quotation or else X = Ch_Val.Semicolon or else  | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	            Is_White_Space(X); | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 	end Is_Delimiter; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	procedure Skip_Spaces_And_Comments is | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		loop | 
					
						
							|  |  |  | 			exit when LC.Kind /= Normal_Character; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			-- Normal character
 | 
					
						
							|  |  |  | 			if Is_White_Space(LC.Value) then | 
					
						
							|  |  |  | 				Fetch_Character; | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			elsif LC.Value = Ch_Val.Semicolon then | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				-- Comment.
 | 
					
						
							|  |  |  | 				loop | 
					
						
							|  |  |  | 					Fetch_Character; | 
					
						
							|  |  |  | 					exit when LC.Kind = End_Character; -- EOF before LF
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					if LC.Kind = Normal_Character and then LC.Value = Ch_Val.LF then -- TODO: handle different line ending convention
 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 						Fetch_Character; -- Read the next character after LF
 | 
					
						
							|  |  |  | 						exit; | 
					
						
							|  |  |  | 					end if; | 
					
						
							|  |  |  | 				end loop; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				exit; | 
					
						
							|  |  |  | 			end if; | 
					
						
							|  |  |  | 		end loop; | 
					
						
							|  |  |  | 	end Skip_Spaces_And_Comments; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Fetch_Token is | 
					
						
							|  |  |  | 		Tmp: Object_Character_Array(1..10); -- large enough???
 | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		if not Interp.LC_Unfetched then | 
					
						
							|  |  |  | 			Fetch_Character; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			-- Reuse the last character unfetched
 | 
					
						
							|  |  |  | 			Interp.LC_Unfetched := Standard.False; | 
					
						
							|  |  |  | 		end if; | 
					
						
							|  |  |  | 		Skip_Spaces_And_Comments; | 
					
						
							|  |  |  | 		if LC.Kind /= Normal_Character then | 
					
						
							|  |  |  | 			Token.Set (Interp, End_Token); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		end if; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		-- TODO: Pass Token Location when calling Token.Set
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 		-- Use Ch_Code.XXX values instead of Ch_Val.XXX values as gnat complained that 
 | 
					
						
							|  |  |  | 		-- Ch_Val.XXX values are not static. For this reason, "case LC.Value is ..."
 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 		-- changed to use Object_Character'Pos(LC.Value).
 | 
					
						
							|  |  |  | 		case Object_Character'Pos(LC.Value) is | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			when Ch_Code.Left_Parenthesis => | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				Token.Set (Interp, Left_Parenthesis_Token, LC.Value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			when Ch_Code.Right_Parenthesis => | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				Token.Set (Interp, Right_Parenthesis_Token, LC.Value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			when Ch_Code.Period => | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				Token.Set (Interp, Period_Token, LC.Value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			when Ch_Code.Apostrophe => | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				Token.Set (Interp, Single_Quote_Token, LC.Value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			when Ch_Code.Number_Sign =>  | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 				Fetch_Character; | 
					
						
							|  |  |  | 				if LC.Kind /= Normal_Character then | 
					
						
							|  |  |  | 					-- ended prematurely.
 | 
					
						
							|  |  |  | 					-- TODO: Set Error code, Error Number.... Error location
 | 
					
						
							|  |  |  | 					raise Syntax_Error;		 | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				-- #t
 | 
					
						
							|  |  |  | 				-- #f
 | 
					
						
							|  |  |  | 				-- #\C -- character
 | 
					
						
							| 
									
										
										
										
											2014-01-21 14:55:08 +00:00
										 |  |  | 				-- #\xHHHH -- unicode
 | 
					
						
							|  |  |  | 				-- #\xHHHHHHHH -- unicode
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 				-- #( ) -- vector
 | 
					
						
							|  |  |  | 				-- #[ ] -- list
 | 
					
						
							|  |  |  | 				-- #{ } -- hash table
 | 
					
						
							|  |  |  | 				-- #< > -- xxx
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				case Object_Character'Pos(LC.Value) is | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					when Ch_Code.LC_T => -- #t
 | 
					
						
							|  |  |  | 						Token.Set (Interp, True_Token, Ch_Val.Number_Sign); | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 						Token.Append_Character (Interp, LC.Value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					when Ch_Code.LC_F => -- #f
 | 
					
						
							|  |  |  | 						Token.Set (Interp, False_Token, Ch_Val.Number_Sign); | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 						Token.Append_Character (Interp, LC.Value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					when Ch_Code.Backslash => -- #\C, #\space, #\newline
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 						Fetch_Character; | 
					
						
							|  |  |  | 						if LC.Kind /= Normal_Character then | 
					
						
							|  |  |  | 							ada.text_io.put_line ("ERROR: NO CHARACTER AFTER #\"); | 
					
						
							|  |  |  | 							raise Syntax_Error; | 
					
						
							|  |  |  | 						end if; | 
					
						
							|  |  |  | 						Token.Set (Interp, Character_Token, LC.Value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						loop | 
					
						
							|  |  |  | 							Fetch_Character; | 
					
						
							|  |  |  | 							if LC.Kind /= Normal_Character or else  | 
					
						
							|  |  |  | 							   Is_Delimiter(LC.Value) then | 
					
						
							|  |  |  | 								Unfetch_Character; | 
					
						
							|  |  |  | 								exit; | 
					
						
							|  |  |  | 							end if; | 
					
						
							|  |  |  | 							Token.Append_Character (Interp, LC.Value); | 
					
						
							|  |  |  | 						end loop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if Interp.Token.Value.Last > 1 then | 
					
						
							|  |  |  | 							-- TODO: case insensitive match. binary search for more diverse words
 | 
					
						
							| 
									
										
										
										
											2014-01-21 14:55:08 +00:00
										 |  |  | 							-- TODO: #\xHHHH....
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 							if Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last) = Label_Newline then | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 								Token.Set (Interp, Character_Token, Ch_Val.LF);  -- reset the token to LF
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 							elsif Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last) = Label_Space then | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 								Token.Set (Interp, Character_Token, Ch_Val.Space); -- reset the token to Space
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 							else | 
					
						
							|  |  |  | 								-- unknown character name.
 | 
					
						
							|  |  |  | 								ada.text_io.put ("ERROR: UNKNOWN CHARACTER NAME "); | 
					
						
							|  |  |  | 								for I in 1 .. interp.token.value.last loop | 
					
						
							|  |  |  | 									ada.text_io.put (standard.character'val(object_character'pos(interp.token.value.ptr.all(i)))); | 
					
						
							|  |  |  | 								end loop; | 
					
						
							|  |  |  | 								ada.text_io.new_line; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								raise Syntax_Error; | 
					
						
							|  |  |  | 							end if; | 
					
						
							|  |  |  | 						end if; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					--when Ch_Code.Left_Parenthesis => -- #(
 | 
					
						
							|  |  |  | 					--	Token.Set (Interp, Vector_Token, Ch_Val.Number_Sign);
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 					--	Token.Append_Character (Interp, LC.Value);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					--when Ch_Code.Left_Bracket => -- $[
 | 
					
						
							|  |  |  | 					--	Token.Set (Interp, List_Token, Ch_Val.Number_Sign);
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 					--	Token.Append_Character (Interp, LC.Value);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					--when Ch_Code.Left_Bracket => -- ${
 | 
					
						
							|  |  |  | 					--	Token.Set (Interp, Table_Token, Ch_Val.Number_Sign);
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 					--	Token.Append_Character (Interp, LC.Value);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					when others => | 
					
						
							|  |  |  | 						-- unknown #letter
 | 
					
						
							|  |  |  | 						-- TODO: Set Error code, Error Number.... Error location
 | 
					
						
							|  |  |  | 						raise Syntax_Error;		 | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 				end case; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			when Ch_Code.Quotation => | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				Fetch_Character; | 
					
						
							|  |  |  | 				Token.Set (Interp, String_Token); | 
					
						
							|  |  |  | 				loop | 
					
						
							|  |  |  | 					if LC.Kind /= Normal_Character then | 
					
						
							|  |  |  | 						-- String ended prematurely.
 | 
					
						
							|  |  |  | 						-- TODO: Set Error code, Error Number.... Error location
 | 
					
						
							|  |  |  | 						raise Syntax_Error;		 | 
					
						
							|  |  |  | 					end if; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					if LC.Value = Ch_Val.Backslash then | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 						Fetch_Character; | 
					
						
							|  |  |  | 						if LC.Kind /= Normal_Character then | 
					
						
							|  |  |  | 							-- String ended prematurely.
 | 
					
						
							|  |  |  | 							-- TODO: Set Error code, Error Number.... Error location
 | 
					
						
							|  |  |  | 							raise Syntax_Error;		 | 
					
						
							|  |  |  | 						end if; | 
					
						
							|  |  |  | 						-- TODO: escape letters??? \n \r \\ etc....
 | 
					
						
							|  |  |  | 						Token.Append_Character (Interp, LC.Value); | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					elsif LC.Value = Ch_Val.Quotation then | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 						exit; | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 						Token.Append_Character (Interp, LC.Value); | 
					
						
							|  |  |  | 						Fetch_Character; | 
					
						
							|  |  |  | 					end if; | 
					
						
							|  |  |  | 				end loop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			when Ch_Code.Zero .. Ch_Code.Nine => | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				-- TODO; negative number, floating-point number, bignum, hexdecimal, etc
 | 
					
						
							|  |  |  | 				Token.Set (Interp, Integer_Token); | 
					
						
							|  |  |  | 				loop | 
					
						
							|  |  |  | 					Token.Append_Character (Interp, LC.Value); | 
					
						
							|  |  |  | 					Fetch_Character; | 
					
						
							|  |  |  | 					if LC.Kind /= Normal_Character or else | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 					   LC.Value not in Ch_Val.Zero .. Ch_Val.Nine  then | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 						-- Unfetch the last character
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 						Unfetch_Character; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 						exit; | 
					
						
							|  |  |  | 					end if; | 
					
						
							|  |  |  | 				end loop; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 			when Ch_Code.Plus_Sign | Ch_Code.Minus_Sign => | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				Tmp(1) := LC.Value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				Fetch_Character; | 
					
						
							|  |  |  | 				if LC.Kind = Normal_Character and then | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 				   LC.Value in Ch_Val.Zero .. Ch_Val.Nine then | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 					Token.Set (Interp, Integer_Token, Tmp(1..1)); | 
					
						
							|  |  |  | 					loop | 
					
						
							|  |  |  | 						Token.Append_Character (Interp, LC.Value); | 
					
						
							|  |  |  | 						Fetch_Character; | 
					
						
							|  |  |  | 						if LC.Kind /= Normal_Character or else | 
					
						
							| 
									
										
										
										
											2014-06-21 16:31:49 +00:00
										 |  |  | 						   LC.Value not in Ch_Val.Zero .. Ch_Val.Nine  then | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 							Unfetch_Character; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 							exit; | 
					
						
							|  |  |  | 						end if; | 
					
						
							|  |  |  | 					end loop; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					Token.Set (Interp, Identifier_Token, Tmp(1..1)); | 
					
						
							|  |  |  | 					loop | 
					
						
							|  |  |  | 				-- TODO: more characters
 | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 						if LC.Kind /= Normal_Character or else  | 
					
						
							|  |  |  | 						   Is_Delimiter(LC.Value) then | 
					
						
							|  |  |  | 							Unfetch_Character; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 							exit; | 
					
						
							|  |  |  | 						end if; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						Token.Append_Character (Interp, LC.Value); | 
					
						
							|  |  |  | 						Fetch_Character; | 
					
						
							|  |  |  | 					end loop; | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when others => | 
					
						
							|  |  |  | 				Token.Set (Interp, Identifier_Token); | 
					
						
							|  |  |  | 				loop | 
					
						
							|  |  |  | 					Token.Append_Character (Interp, LC.Value); | 
					
						
							|  |  |  | 					Fetch_Character; | 
					
						
							|  |  |  | 					--exit when not Is_Ident_Char(C.Value);
 | 
					
						
							|  |  |  | 				-- TODO: more characters
 | 
					
						
							|  |  |  | 					if LC.Kind /= Normal_Character or else | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 					   Is_Delimiter(LC.Value) then | 
					
						
							|  |  |  | 						Unfetch_Character; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 						exit; | 
					
						
							|  |  |  | 					end if; | 
					
						
							|  |  |  | 				end loop; | 
					
						
							|  |  |  | 		end case; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | --Ada.Text_IO.Put (">>>>>>>>>>>>>>>>>>>>>>> Token: " & Interp.Token.Value.Ptr(1..Interp.Token.Value.Last));
 | 
					
						
							|  |  |  | 	end Fetch_Token; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Read_List is | 
					
						
							| 
									
										
										
										
											2014-01-17 13:03:05 +00:00
										 |  |  | 		pragma Inline (Read_List); | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		V: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		-- This procedure reads each token in a list.
 | 
					
						
							|  |  |  | 		-- If the list contains no period, this procedure reads up to the 
 | 
					
						
							|  |  |  | 		-- closing right paranthesis; If a period is contained, it transfers
 | 
					
						
							|  |  |  | 		-- the control over to Read_List_Cdr.
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		Fetch_Token; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		case Interp.Token.Kind is | 
					
						
							|  |  |  | 			when End_Token => | 
					
						
							|  |  |  | Ada.Text_IO.Put_Line ("ERROR: PREMATURE LIST END"); | 
					
						
							|  |  |  | 				raise Syntax_Error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Left_Parenthesis_Token => | 
					
						
							|  |  |  | 				Push_Frame (Interp, Opcode_Read_List, Nil_Pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Right_Parenthesis_Token => | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 				V := Get_Frame_Intermediate(Interp.Stack); | 
					
						
							|  |  |  | 				if Is_Cons(V) then | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 					V := Reverse_Cons(V); | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 				Pop_Frame (Interp);  | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 				Chain_Frame_Intermediate (Interp, Interp.Stack, V); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			when Period_Token => | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 				V := Get_Frame_Intermediate(Interp.Stack); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				if V = Nil_Pointer then | 
					
						
							|  |  |  | 					-- . immediately after (
 | 
					
						
							|  |  |  | 					raise Syntax_Error; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					Set_Frame_Opcode (Interp.Stack, Opcode_Read_List_Cdr); | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Single_Quote_Token => | 
					
						
							| 
									
										
										
										
											2014-02-06 03:28:14 +00:00
										 |  |  | 				Push_Frame (Interp, Opcode_Close_Quote_In_List, Nil_Pointer); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				Push_Frame (Interp, Opcode_Read_Object, Nil_Pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when others => | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 				V := Token_To_Pointer (Interp.Self, Interp.Token); | 
					
						
							|  |  |  | 				if V = null then | 
					
						
							|  |  |  | 					-- TODO: set various error info
 | 
					
						
							|  |  |  | 					raise Syntax_Error; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					Chain_Frame_Intermediate (Interp, Interp.Stack, V); | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 		end case; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	end Read_List; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Read_List_Cdr is | 
					
						
							|  |  |  | 		pragma Inline (Read_List_Cdr); | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		V: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		-- This procedure reads the first token after a period has been read.
 | 
					
						
							|  |  |  | 		-- It transfers the control over to Read_List_End once it has read 
 | 
					
						
							|  |  |  | 		-- and processed the token. It chains the value made of the token  
 | 
					
						
							|  |  |  | 		-- to the front of the frame's return value list expecting Read_List_End
 | 
					
						
							|  |  |  | 		-- to handle the head item specially.
 | 
					
						
							|  |  |  | 		Fetch_Token; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		case Interp.Token.Kind is | 
					
						
							|  |  |  | 			when End_Token => | 
					
						
							|  |  |  | Ada.Text_IO.Put_Line ("ERROR: PREMATURE LIST END"); | 
					
						
							|  |  |  | 				raise Syntax_Error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Left_Parenthesis_Token => | 
					
						
							|  |  |  | 				Set_Frame_Opcode (Interp.Stack, Opcode_Read_List_End); | 
					
						
							|  |  |  | 				Push_Frame (Interp, Opcode_Read_List, Nil_Pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Single_Quote_Token => | 
					
						
							|  |  |  | Ada.Text_IO.Put_Line ("ERROR: CDR QUOT LIST END"); | 
					
						
							|  |  |  | 				Set_Frame_Opcode (Interp.Stack, Opcode_Read_List_End); | 
					
						
							| 
									
										
										
										
											2014-02-06 03:28:14 +00:00
										 |  |  | 				Push_Frame (Interp, Opcode_Close_Quote_In_List, Nil_Pointer); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				Push_Frame (Interp, Opcode_Read_Object, Nil_Pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when others => | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 				V := Token_To_Pointer (Interp.Self, Interp.Token); | 
					
						
							|  |  |  | 				if V = null then | 
					
						
							|  |  |  | 					-- TODO: set various error info
 | 
					
						
							|  |  |  | 					raise Syntax_Error; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					Chain_Frame_Intermediate (Interp, Interp.Stack, V); | 
					
						
							|  |  |  | 					Set_Frame_Opcode (Interp.Stack, Opcode_Read_List_End); | 
					
						
							|  |  |  | 				end if; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 		end case; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	end Read_List_Cdr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Read_List_End is | 
					
						
							|  |  |  | 		pragma Inline (Read_List_End); | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		V: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		Fetch_Token; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Interp.Token.Kind is | 
					
						
							|  |  |  | 			when Right_Parenthesis_Token => | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 				V := Get_Frame_Intermediate(Interp.Stack); | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 				pragma Assert (Is_Cons(V)); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				-- The first item in the chain is actually Cdr of the last cell.
 | 
					
						
							| 
									
										
										
										
											2014-01-17 13:03:05 +00:00
										 |  |  | 				V := Reverse_Cons(Get_Cdr(V), Get_Car(V));  | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				Pop_Frame (Interp);  | 
					
						
							| 
									
										
										
										
											2014-02-06 03:28:14 +00:00
										 |  |  | 				Chain_Frame_Intermediate (Interp, Interp.Stack, V); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 			when others => | 
					
						
							| 
									
										
										
										
											2014-01-21 05:08:46 +00:00
										 |  |  | Ada.Text_IO.Put_Line ("Right parenthesis expected"); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 				raise Syntax_Error; | 
					
						
							|  |  |  | 		end case; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	end Read_List_End; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Close_List is | 
					
						
							|  |  |  | 		pragma Inline (Close_List); | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		V: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		V := Get_Frame_Intermediate(Interp.Stack); | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		pragma Assert (Is_Cons(V)); | 
					
						
							|  |  |  | 		pragma Assert (Get_Cdr(V) = Nil_Pointer); -- only 1 item as it's used for the top-level list only
 | 
					
						
							|  |  |  | 		Return_Frame (Interp, Get_Car(V)); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	end Close_List; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 03:28:14 +00:00
										 |  |  | 	procedure Close_Quote_In_List is | 
					
						
							|  |  |  | 		pragma Inline (Close_Quote_In_List); | 
					
						
							|  |  |  | 		V: Object_Pointer; | 
					
						
							|  |  |  | 	begin | 
					
						
							|  |  |  | 		V := Get_Frame_Result(Interp.Stack); | 
					
						
							|  |  |  | 		V := Make_Cons(Interp.Self, V, Nil_Pointer); | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 		V := Make_Cons(Interp.Self, Interp.Quote_Symbol, V); | 
					
						
							| 
									
										
										
										
											2014-02-06 03:28:14 +00:00
										 |  |  | 		Pop_Frame (Interp);  | 
					
						
							|  |  |  | 		Chain_Frame_Intermediate (Interp, Interp.Stack, V); | 
					
						
							|  |  |  | 	end Close_Quote_In_List; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	procedure Close_Quote is | 
					
						
							|  |  |  | 		pragma Inline (Close_Quote); | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		V: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		V := Get_Frame_Result(Interp.Stack); | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		V := Make_Cons(Interp.Self, V, Nil_Pointer); | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 		V := Make_Cons(Interp.Self, Interp.Quote_Symbol, V); | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 		Return_Frame (Interp, V); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	end Close_Quote; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	procedure Read_Object is | 
					
						
							|  |  |  | 		pragma Inline (Read_Object); | 
					
						
							| 
									
										
										
										
											2014-02-05 15:08:59 +00:00
										 |  |  | 		V: Object_Pointer; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	begin | 
					
						
							|  |  |  | 		Fetch_Token; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case Interp.Token.Kind is | 
					
						
							|  |  |  | 			when End_Token => | 
					
						
							|  |  |  | Ada.Text_IO.Put_Line ("INFO: NO MORE TOKEN "); | 
					
						
							|  |  |  | 				raise Stream_End_Error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Left_Parenthesis_Token => | 
					
						
							|  |  |  | 				Set_Frame_Opcode (Interp.Stack, Opcode_Close_List); | 
					
						
							|  |  |  | 				Push_Frame (Interp, Opcode_Read_List, Nil_Pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Single_Quote_Token => | 
					
						
							|  |  |  | 				Set_Frame_Opcode (Interp.Stack, Opcode_Close_Quote); | 
					
						
							|  |  |  | 				Push_Frame (Interp, Opcode_Read_Object, Nil_Pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when others => | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 				V := Token_To_Pointer (Interp.Self, Interp.Token); | 
					
						
							|  |  |  | 				if V = null then | 
					
						
							|  |  |  | 					-- TODO: set various error info
 | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | Ada.Text_IO.Put_Line ("INFO: UNKNOWN TOKEN " & Token_Kind'Image(Interp.Token.Kind)); | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 					raise Syntax_Error; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					Return_Frame (Interp, V); | 
					
						
							|  |  |  | 				end if; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 		end case; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	end Read_Object; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 	-- --------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | begin | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 	-- TODO: This comment is out-dated. Update it with Intermediate.
 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 	-- Stack frames looks like this upon initialization
 | 
					
						
							|  |  |  | 	-- 
 | 
					
						
							|  |  |  | 	--               | Opcode                 | Operand    | Result
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Opcode_Evaluate_Object | Source     | Nil
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil        | Nil
 | 
					
						
							|  |  |  | 	--
 | 
					
						
							|  |  |  | 	-- For a source (+ 1 2), it should look like this.
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Opcode_Evaluate_Object | Source       | Nil
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil          | Nil
 | 
					
						
							|  |  |  | 	-- 
 | 
					
						
							|  |  |  | 	-- The operand changes to the cdr of the source.
 | 
					
						
							|  |  |  | 	-- The symbol '+' is pushed to the stack with Opcode_Evaluate_Object.
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Opcode_Evaluate_Object | +            | Nil
 | 
					
						
							|  |  |  | 	--               | Opcode_Evaluate_Object | (1 2)        | Nil
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil          | Nil
 | 
					
						
							|  |  |  | 	--
 | 
					
						
							|  |  |  | 	-- After the evaluation of the symbol, the pushed frame is removed
 | 
					
						
							|  |  |  | 	-- and the result is set to the return field.
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Opcode_Evaluate_Object | (1 2)        | (#Proc+)
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil          | Nil
 | 
					
						
							|  |  |  | 	--
 | 
					
						
							|  |  |  | 	-- The same action is taken to evaluate the literal 1.
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Opcode_Evaluate_Object | 1            | Nil
 | 
					
						
							|  |  |  | 	--               | Opcode_Evaluate_Object | (2)          | (#Proc+)
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil          | Nil
 | 
					
						
							|  |  |  | 	--
 | 
					
						
							|  |  |  | 	-- The result of the valuation is reverse-chained to the return field. 
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Opcode_Evaluate_Object | (2)          | (1 #Proc+)
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil          | Nil
 | 
					
						
							|  |  |  | 	--
 | 
					
						
							|  |  |  | 	-- The same action is taken to evaluate the literal 2.
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Opcode_Evaluate_Object | 2            | Nil
 | 
					
						
							|  |  |  | 	--               | Opcode_Evaluate_Object | Mark         | (1 #Proc+)
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil          | Nil
 | 
					
						
							|  |  |  | 	--
 | 
					
						
							|  |  |  | 	-- The result of the valuation is reverse-chained to the return field. 
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Opcode_Evaluate_Object | Mark         | (2 1 #Proc+)
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil          | Nil
 | 
					
						
							|  |  |  | 	--
 | 
					
						
							|  |  |  | 	-- Once evluation of each cons cell is complete, switch the top frame
 | 
					
						
							|  |  |  | 	-- to 'Apply' reversing the result field into the operand field and
 | 
					
						
							|  |  |  | 	-- nullifying the result field afterwards.
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top       | Apply                  | (#Proc+ 1 2) | Nil
 | 
					
						
							|  |  |  | 	--     bottom    | Opcode_Exit            | Nil          | Nil
 | 
					
						
							|  |  |  | 	--
 | 
					
						
							|  |  |  | 	-- The apply operation produces the final result and sets it to the 
 | 
					
						
							|  |  |  | 	-- parent frame while removing the apply frame.
 | 
					
						
							|  |  |  | 	--     -----------------------------------------------------------------
 | 
					
						
							|  |  |  | 	--     top/bottom| Opcode_Exit            | Nil          | (3)
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	-- The caller must push some frames before calling this procedure
 | 
					
						
							|  |  |  | 	pragma Assert (Interp.Stack /= Nil_Pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	loop | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | ada.text_io.put_line (Opcode_Type'Image(Get_Frame_Opcode(Interp.Stack))); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 		case Get_Frame_Opcode(Interp.Stack) is | 
					
						
							|  |  |  | 			when Opcode_Exit => | 
					
						
							|  |  |  | 				exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Evaluate_Result => | 
					
						
							|  |  |  | 				Evaluate_Result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Evaluate_Object => | 
					
						
							| 
									
										
										
										
											2014-01-19 15:47:45 +00:00
										 |  |  | 				Evaluate; | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 			when Opcode_And_Finish =>  | 
					
						
							|  |  |  | 				Do_And_Finish; | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  |   | 
					
						
							| 
									
										
										
										
											2014-02-14 15:47:10 +00:00
										 |  |  | 			when Opcode_Case_Finish => | 
					
						
							|  |  |  | 				Do_Case_Finish; | 
					
						
							|  |  |  | 				 | 
					
						
							| 
									
										
										
										
											2014-02-10 15:39:20 +00:00
										 |  |  | 			when Opcode_Cond_Finish =>  | 
					
						
							|  |  |  | 				Do_Cond_Finish; | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 			when Opcode_Define_Finish => | 
					
						
							|  |  |  | 				Do_Define_Finish; | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 15:11:00 +00:00
										 |  |  | 			when Opcode_Do_Binding => | 
					
						
							|  |  |  | 				Do_Do_Binding; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Do_Break => | 
					
						
							|  |  |  | 				Do_Do_Break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Do_Step => | 
					
						
							|  |  |  | 				Do_Do_Step; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Do_Test => | 
					
						
							|  |  |  | 				Do_Do_Test; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Do_Update => | 
					
						
							|  |  |  | 				Do_Do_Update; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 			when Opcode_Grouped_Call => | 
					
						
							|  |  |  | 				Do_Grouped_Call; | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:25:38 +00:00
										 |  |  | 			when Opcode_If_Finish => | 
					
						
							|  |  |  | 				Do_If_Finish; -- Conditional
 | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 			when Opcode_Let_Binding => | 
					
						
							|  |  |  | 				Do_Let_Binding;  | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-24 07:58:46 +00:00
										 |  |  | 			when Opcode_Letast_Binding => | 
					
						
							|  |  |  | 				Do_Letast_Binding;  | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 15:28:46 +00:00
										 |  |  | 			when Opcode_Letrec_Binding => | 
					
						
							|  |  |  | 				Do_Letrec_Binding;  | 
					
						
							| 
									
										
										
										
											2014-01-23 13:41:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 			when Opcode_Or_Finish =>  | 
					
						
							|  |  |  | 				Do_Or_Finish; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 			when Opcode_Procedure_Call => | 
					
						
							|  |  |  | 				Do_Procedure_Call; | 
					
						
							| 
									
										
										
										
											2014-02-08 03:53:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 13:29:08 +00:00
										 |  |  | 			when Opcode_Procedure_Call_Finish => | 
					
						
							|  |  |  | 				Do_Procedure_Call_Finish; | 
					
						
							| 
									
										
										
										
											2014-01-28 15:42:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Set_Finish => | 
					
						
							|  |  |  | 				Do_Set_Finish; -- Assignment
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-23 15:18:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 			when Opcode_Apply => | 
					
						
							|  |  |  | 				Apply; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Read_Object => | 
					
						
							|  |  |  | 				Read_Object; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Read_List => | 
					
						
							|  |  |  | 				Read_List; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Read_List_Cdr => | 
					
						
							|  |  |  | 				Read_List_Cdr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Read_List_End => | 
					
						
							|  |  |  | 				Read_List_End; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Close_List => | 
					
						
							|  |  |  | 				Close_List; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			when Opcode_Close_Quote => | 
					
						
							|  |  |  | 				Close_Quote; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-06 03:28:14 +00:00
										 |  |  | 			when Opcode_Close_Quote_In_List => | 
					
						
							|  |  |  | 				Close_Quote_In_List; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 		end case; | 
					
						
							|  |  |  | 	end loop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | exception | 
					
						
							|  |  |  | 	when Stream_End_Error => | 
					
						
							| 
									
										
										
										
											2014-01-19 06:40:23 +00:00
										 |  |  | Ada.Text_IO.Put_Line ("INFO: NO MORE TOKEN ............."); | 
					
						
							| 
									
										
										
										
											2014-01-16 16:52:18 +00:00
										 |  |  | 		raise; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	when others => | 
					
						
							|  |  |  | 		Ada.Text_IO.Put_Line ("EXCEPTION OCCURRED"); | 
					
						
							|  |  |  | 		-- TODO: restore stack frame???
 | 
					
						
							|  |  |  | 		-- TODO: restore envirronemtn frame???
 | 
					
						
							|  |  |  | 		raise; | 
					
						
							|  |  |  | end Execute; |