implemented symbol defining
This commit is contained in:
parent
f970a410fd
commit
097dcd6a1f
@ -16,7 +16,7 @@ procedure Apply is
|
||||
A: Object_Pointer;
|
||||
begin
|
||||
if Ptr = Nil_Pointer or else Get_Cdr(Ptr) /= Nil_Pointer then
|
||||
Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR CAR");
|
||||
Ada.Text_IO.Put_Line ("WRONG NUMBER OF ARGUMETNS FOR CAR");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
@ -31,7 +31,7 @@ Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR CAR");
|
||||
A: Object_Pointer;
|
||||
begin
|
||||
if Ptr = Nil_Pointer or else Get_Cdr(Ptr) /= Nil_Pointer then
|
||||
Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR CDR");
|
||||
Ada.Text_IO.Put_Line ("WRONG NUMBER OF ARGUMETNS FOR CDR");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
@ -47,7 +47,7 @@ Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR CDR");
|
||||
B: Object_Pointer;
|
||||
begin
|
||||
if Ptr = Nil_Pointer or else Get_Cdr(Ptr) = Nil_Pointer or else Get_Cdr(Get_Cdr(Ptr)) /= Nil_Pointer then
|
||||
Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR CONS");
|
||||
Ada.Text_IO.Put_Line ("WRONG NUMBER OF ARGUMETNS FOR CONS");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
@ -65,7 +65,7 @@ Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR CONS");
|
||||
B: Object_Pointer;
|
||||
begin
|
||||
if Ptr = Nil_Pointer or else Get_Cdr(Ptr) = Nil_Pointer or else Get_Cdr(Get_Cdr(Ptr)) /= Nil_Pointer then
|
||||
Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR SET-CAR!");
|
||||
Ada.Text_IO.Put_Line ("WRONG NUMBER OF ARGUMETNS FOR SET-CAR!");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
@ -83,7 +83,7 @@ Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR SET-CAR!");
|
||||
B: Object_Pointer;
|
||||
begin
|
||||
if Ptr = Nil_Pointer or else Get_Cdr(Ptr) = Nil_Pointer or else Get_Cdr(Get_Cdr(Ptr)) /= Nil_Pointer then
|
||||
Ada.Text_IO.Put ("WRONG NUMBER OF ARGUMETNS FOR SET-CDR!");
|
||||
Ada.Text_IO.Put_Line ("WRONG NUMBER OF ARGUMETNS FOR SET-CDR!");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
@ -259,6 +259,7 @@ begin
|
||||
Operand := Get_Frame_Operand(Interp.Stack);
|
||||
pragma Assert (Is_Cons(Operand));
|
||||
|
||||
ada.text_io.put ("OPERAND TO APPLY => ");
|
||||
Print (Interp, Operand);
|
||||
Func := Get_Car(Operand);
|
||||
if not Is_Normal_Pointer(Func) then
|
||||
|
258
lib/h2-scheme-execute-evaluate.adb
Normal file
258
lib/h2-scheme-execute-evaluate.adb
Normal file
@ -0,0 +1,258 @@
|
||||
separate (H2.Scheme.Execute)
|
||||
|
||||
procedure Evaluate is
|
||||
pragma Inline (Evaluate);
|
||||
|
||||
Operand: aliased Object_Pointer;
|
||||
Car: aliased Object_Pointer;
|
||||
Cdr: aliased Object_Pointer;
|
||||
|
||||
procedure Evaluate_Define_Syntax is
|
||||
pragma Inline (Evaluate_Define_Syntax);
|
||||
begin
|
||||
-- (define x 10)
|
||||
-- (define (add x y) (+ x y)) -> (define add (lambda (x y) (+ x y)))
|
||||
Operand := Cdr; -- Skip "define"
|
||||
|
||||
if not Is_Cons(Operand) or else not Is_Cons(Get_Cdr(Operand)) then
|
||||
-- e.g) (define)
|
||||
-- (define . 10)
|
||||
Ada.Text_IO.Put_LINE ("TOO FEW ARGUMENTS FOR DEFINE");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
Car := Get_Car(Operand);
|
||||
Cdr := Get_Cdr(Operand);
|
||||
if Is_Cons(Car) then
|
||||
-- define a function: (define (add x y) ...)
|
||||
null;
|
||||
elsif Is_Symbol(Car) then
|
||||
-- define a symbol: (define x ...)
|
||||
if Get_Cdr(Cdr) /= Nil_Pointer then
|
||||
Ada.Text_IO.Put_LINE ("TOO MANY ARGUMENTS FOR DEFINE");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
Cdr := Get_Car(Cdr); -- Value
|
||||
|
||||
-- Arrange to finish defining after value evaluation.
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Finish_Define_Symbol);
|
||||
Set_Frame_Operand (Interp.Stack, Car);
|
||||
|
||||
-- Arrange to evalaute the value part
|
||||
Push_Frame (Interp, Opcode_Evaluate_Object, Cdr);
|
||||
else
|
||||
Ada.Text_IO.Put_LINE ("NO SYMBOL NOR ARGUMENT LIST AFTER DEFINE");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
end Evaluate_Define_Syntax;
|
||||
|
||||
procedure Evaluate_Lambda_Syntax is
|
||||
pragma Inline (Evaluate_Lambda_Syntax);
|
||||
begin
|
||||
-- (lambda (x y) (+ x y));
|
||||
Operand := Cdr; -- Skip "lambda"
|
||||
if not Is_Cons(Operand) then
|
||||
-- e.g) (lambda)
|
||||
-- (lambda . 10)
|
||||
Ada.Text_IO.Put_LINE ("FUCKNING CDR FOR BEGIN");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
if not Is_Cons(Get_Car(Operand)) then
|
||||
Ada.Text_IO.Put_Line ("INVALID PARRAMETER LIST");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
--Print (Interp, Get_Cdr(Operand));
|
||||
if not Is_Cons(Get_Cdr(Operand)) then
|
||||
Ada.Text_IO.Put_Line ("NO BODY");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
declare
|
||||
Closure: Object_Pointer;
|
||||
begin
|
||||
Closure := Make_Closure (Interp.Self, Operand, Interp.Environment);
|
||||
Pop_Frame (Interp); -- Done
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Closure);
|
||||
end;
|
||||
end Evaluate_Lambda_Syntax;
|
||||
|
||||
procedure Evaluate_Quote_Syntax is
|
||||
pragma Inline (Evaluate_Quote_Syntax);
|
||||
begin
|
||||
Operand := Cdr; -- Skip "quote". Get the first argument.
|
||||
if not Is_Cons(Operand) then
|
||||
-- e.g) (quote)
|
||||
-- (quote . 10)
|
||||
Ada.Text_IO.Put_LINE ("FUCKNING CDR FOR QUOTE");
|
||||
raise Syntax_Error;
|
||||
elsif Get_Cdr(Operand) /= Nil_Pointer then
|
||||
Ada.Text_IO.Put_LINE ("WRONG NUMBER OF ARGUMENTS FOR QUOTE");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
Pop_Frame (Interp); -- Done
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Get_Car(Operand));
|
||||
end Evaluate_Quote_Syntax;
|
||||
|
||||
begin
|
||||
Push_Top (Interp, Operand'Unchecked_Access);
|
||||
Push_Top (Interp, Car'Unchecked_Access);
|
||||
Push_Top (Interp, Cdr'Unchecked_Access);
|
||||
|
||||
<<Start_Over>>
|
||||
Operand := Get_Frame_Operand(Interp.Stack);
|
||||
|
||||
if not Is_Normal_Pointer(Operand) then
|
||||
-- integer, character, specal pointers
|
||||
-- TODO: some normal pointers may point to literal objects. e.g.) bignum
|
||||
goto Literal;
|
||||
end if;
|
||||
|
||||
case Operand.Tag is
|
||||
when Symbol_Object => -- Is_Symbol(Operand)
|
||||
-- TODO: find it in the Environment hierarchy.. not in the current environemnt.
|
||||
Car := Get_Environment (Interp.Self, Operand);
|
||||
if Car = null then
|
||||
-- unbound
|
||||
Ada.Text_IO.Put_Line ("Unbound symbol....");
|
||||
Print (Interp, Operand);
|
||||
raise Evaluation_Error;
|
||||
else
|
||||
-- symbol found in the environment
|
||||
Operand := Car;
|
||||
goto Literal; -- In fact, this is not a literal, but can be handled in the same way
|
||||
end if;
|
||||
|
||||
when Cons_Object => -- Is_Cons(Operand)
|
||||
Car := Get_Car(Operand);
|
||||
Cdr := Get_Cdr(Operand);
|
||||
if Is_Syntax(Car) then
|
||||
-- special syntax symbol. normal evaluate rule doesn't
|
||||
-- apply for special syntax objects.
|
||||
|
||||
case Car.Scode is
|
||||
when Begin_Syntax =>
|
||||
|
||||
Operand := Cdr; -- Skip "begin"
|
||||
|
||||
if not Is_Cons(Operand) then
|
||||
-- e.g) (begin)
|
||||
-- (begin . 10)
|
||||
Ada.Text_IO.Put_LINE ("FUCKNING CDR FOR BEGIN");
|
||||
raise Syntax_Error;
|
||||
--Pop_Frame (Interp); -- Done
|
||||
|
||||
else
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Evaluate_Group);
|
||||
Set_Frame_Operand (Interp.Stack, Operand);
|
||||
|
||||
if (Interp.Trait.Trait_Bits and No_Optimization) = 0 then
|
||||
-- I call Evaluate_Group for optimization here.
|
||||
Evaluate_Group; -- for optimization only. not really needed.
|
||||
-- I can jump to Start_Over because Evaluate_Group called
|
||||
-- above pushes an Opcode_Evaluate_Object frame.
|
||||
pragma Assert (Get_Frame_Opcode(Interp.Stack) = Opcode_Evaluate_Object);
|
||||
goto Start_Over; -- for optimization only. not really needed.
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when Define_Syntax =>
|
||||
Evaluate_Define_Syntax;
|
||||
|
||||
when Lambda_Syntax =>
|
||||
Evaluate_Lambda_Syntax;
|
||||
|
||||
when Quote_Syntax =>
|
||||
Evaluate_Quote_Syntax;
|
||||
|
||||
when others =>
|
||||
Ada.Text_IO.Put_Line ("Unknown syntax");
|
||||
--Set_Frame_Opcode (Interp.Stack, Opcode_Evaluate_Syntax); -- Switch to syntax evaluation
|
||||
raise Internal_Error;
|
||||
end case;
|
||||
else
|
||||
if (Interp.Trait.Trait_Bits and No_Optimization) = 0 then
|
||||
while not Is_Normal_Pointer(Car) loop
|
||||
-- This while block is for optimization only. It's not really needed.
|
||||
-- If I know that the next object to evaluate is a literal object,
|
||||
-- I can simply reverse-chain it to the return field of the current
|
||||
-- frame without pushing another frame dedicated for it.
|
||||
|
||||
-- TODO: some normal pointers may point to a literal object. e.g.) bignum
|
||||
-- then it can goto <<Literal>>.
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Car);
|
||||
if Is_Cons(Cdr) then
|
||||
Operand := Cdr;
|
||||
Car := Get_Car(Operand);
|
||||
Cdr := Get_Cdr(Operand);
|
||||
else
|
||||
-- last cons
|
||||
Operand := Reverse_Cons(Get_Frame_Result(Interp.Stack));
|
||||
Clear_Frame_Result (Interp.Stack);
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Apply);
|
||||
Set_Frame_Operand (Interp.Stack, Operand);
|
||||
goto Done;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
if Is_Cons(Cdr) then
|
||||
-- Not the last cons cell yet
|
||||
Set_Frame_Operand (Interp.Stack, Cdr); -- change the operand for the next call
|
||||
else
|
||||
-- Reached the last cons cell
|
||||
if Cdr /= Nil_Pointer then
|
||||
-- The last CDR is not Nil.
|
||||
Ada.Text_IO.Put_Line ("WARNING: $$$$$$$$$$$$$$$$$$$$$..FUCKING CDR.....................$$$$");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
-- Change the operand to a mark object so that the call to this
|
||||
-- procedure after the evaluation of the last car goes to the
|
||||
-- Mark_Object case.
|
||||
Set_Frame_Operand (Interp.Stack, Interp.Mark);
|
||||
end if;
|
||||
|
||||
-- Arrange to evaluate the car object
|
||||
if (Interp.Trait.Trait_Bits and No_Optimization) = 0 then
|
||||
Push_Frame (Interp, Opcode_Evaluate_Object, Car);
|
||||
goto Start_Over; -- for optimization only. not really needed.
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when Mark_Object =>
|
||||
-- TODO: you can use the mark context to differentiate context
|
||||
|
||||
-- Get the evaluation result stored in the current stack frame by
|
||||
-- various sub-Opcode_Evaluate_Object frames. the return value
|
||||
-- chain must be reversed Chain_Frame_Result reverse-chains values.
|
||||
Operand := Reverse_Cons(Get_Frame_Result(Interp.Stack));
|
||||
|
||||
-- Refresh the current stack frame to Opcode_Apply.
|
||||
-- This should be faster than Popping the current frame and pushing
|
||||
-- a new frame.
|
||||
-- Envir := Get_Frame_Environment(Interp.Stack);
|
||||
-- Pop_Frame (Interp); -- done
|
||||
-- Push_Frame (Interp, Opcode_Apply, Operand, Envir);
|
||||
Clear_Frame_Result (Interp.Stack);
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Apply);
|
||||
Set_Frame_Operand (Interp.Stack, Operand);
|
||||
|
||||
when others =>
|
||||
-- normal literal object
|
||||
goto Literal;
|
||||
end case;
|
||||
goto Done;
|
||||
|
||||
<<Literal>>
|
||||
Pop_Frame (Interp); -- done
|
||||
Ada.Text_IO.Put ("Return => ");
|
||||
Print (Interp, Operand);
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Operand);
|
||||
goto Done;
|
||||
|
||||
<<Done>>
|
||||
Pop_Tops (Interp, 3);
|
||||
end Evaluate;
|
@ -77,236 +77,38 @@ procedure Execute (Interp: in out Interpreter_Record) is
|
||||
Pop_Tops (Interp, 3);
|
||||
end Evaluate_Group;
|
||||
|
||||
procedure Evaluate_Object is
|
||||
pragma Inline (Evaluate_Object);
|
||||
|
||||
Operand: aliased Object_Pointer;
|
||||
Car: aliased Object_Pointer;
|
||||
Cdr: aliased Object_Pointer;
|
||||
procedure Finish_Define_Symbol is
|
||||
pragma Inline (Finish_Define_Symbol);
|
||||
X: aliased Object_Pointer;
|
||||
Y: aliased Object_Pointer;
|
||||
begin
|
||||
Push_Top (Interp, Operand'Unchecked_Access);
|
||||
Push_Top (Interp, Car'Unchecked_Access);
|
||||
Push_Top (Interp, Cdr'Unchecked_Access);
|
||||
Ada.Text_IO.PUt_Line ("FINISH DEFINE SYMBOL");
|
||||
Push_Top (Interp, X'Unchecked_Access);
|
||||
Push_Top (Interp, Y'Unchecked_Access);
|
||||
|
||||
<<Start_Over>>
|
||||
Operand := Get_Frame_Operand(Interp.Stack);
|
||||
X := Get_Frame_Operand(Interp.Stack);
|
||||
Y := Get_Car(Get_Frame_Result(Interp.Stack));
|
||||
pragma Assert (Is_Symbol(X));
|
||||
pragma Assert (Get_Cdr(Get_Frame_Result(Interp.Stack)) = Nil_Pointer);
|
||||
|
||||
if not Is_Normal_Pointer(Operand) then
|
||||
-- integer, character, specal pointers
|
||||
-- TODO: some normal pointers may point to literal objects. e.g.) bignum
|
||||
goto Literal;
|
||||
end if;
|
||||
|
||||
case Operand.Tag is
|
||||
when Symbol_Object => -- Is_Symbol(Operand)
|
||||
-- TODO: find it in the Environment hierarchy.. not in the current environemnt.
|
||||
Car := Get_Environment (Interp.Self, Operand);
|
||||
if Car = null then
|
||||
-- unbound
|
||||
Ada.Text_IO.Put_Line ("Unbound symbol....");
|
||||
Print (Interp, Operand);
|
||||
raise Evaluation_Error;
|
||||
else
|
||||
-- symbol found in the environment
|
||||
Operand := Car;
|
||||
goto Literal; -- In fact, this is not a literal, but can be handled in the same way
|
||||
end if;
|
||||
Set_Environment (Interp, X, Y);
|
||||
|
||||
when Cons_Object => -- Is_Cons(Operand)
|
||||
Car := Get_Car(Operand);
|
||||
Cdr := Get_Cdr(Operand);
|
||||
if Is_Syntax(Car) then
|
||||
-- special syntax symbol. normal evaluate rule doesn't
|
||||
-- apply for special syntax objects.
|
||||
Pop_Frame (Interp); -- Done
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Y);
|
||||
|
||||
case Car.Scode is
|
||||
when Begin_Syntax =>
|
||||
|
||||
Operand := Cdr; -- Skip "begin"
|
||||
|
||||
if not Is_Cons(Operand) then
|
||||
-- e.g) (begin)
|
||||
-- (begin . 10)
|
||||
Ada.Text_IO.Put_LINE ("FUCKNING CDR FOR BEGIN");
|
||||
raise Syntax_Error;
|
||||
--Pop_Frame (Interp); -- Done
|
||||
|
||||
else
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Evaluate_Group);
|
||||
Set_Frame_Operand (Interp.Stack, Operand);
|
||||
|
||||
if (Interp.Trait.Trait_Bits and No_Optimization) = 0 then
|
||||
-- I call Evaluate_Group for optimization here.
|
||||
Evaluate_Group; -- for optimization only. not really needed.
|
||||
-- I can jump to Start_Over because Evaluate_Group called
|
||||
-- above pushes an Opcode_Evaluate_Object frame.
|
||||
pragma Assert (Get_Frame_Opcode(Interp.Stack) = Opcode_Evaluate_Object);
|
||||
goto Start_Over; -- for optimization only. not really needed.
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when Define_Syntax =>
|
||||
-- (define x 10)
|
||||
-- (define (add x y) (+ x y)) -> (define add (lambda (x y) (+ x y)))
|
||||
Operand := Cdr; -- Skip "define"
|
||||
|
||||
if not Is_Cons(Operand) then
|
||||
-- e.g) (define)
|
||||
-- (define . 10)
|
||||
Ada.Text_IO.Put_LINE ("FUCKNING CDR FOR DEFINE");
|
||||
raise Syntax_Error;
|
||||
elsif Get_Cdr(Operand) /= Nil_Pointer then
|
||||
-- TODO: IMPLEMENT OTHER CHECK
|
||||
null;
|
||||
end if;
|
||||
|
||||
--Pop_Frame (Interp); -- Done
|
||||
--Chain_Frame_Result (Interp, Interp.Stack, Get_Car(Operand));
|
||||
-- TODO: IMPLEMENT DEFINE.
|
||||
|
||||
when Lambda_Syntax =>
|
||||
-- (lambda (x y) (+ x y));
|
||||
Operand := Cdr; -- Skip "lambda"
|
||||
if not Is_Cons(Operand) then
|
||||
-- e.g) (lambda)
|
||||
-- (lambda . 10)
|
||||
Ada.Text_IO.Put_LINE ("FUCKNING CDR FOR BEGIN");
|
||||
raise Syntax_Error;
|
||||
--Pop_Frame (Interp); -- Done
|
||||
else
|
||||
if not Is_Cons(Get_Car(Operand)) then
|
||||
Ada.Text_IO.Put_Line ("INVALID PARRAMETER LIST");
|
||||
raise Syntax_Error;
|
||||
--Pop_Frame (Interp); -- Done
|
||||
end if;
|
||||
|
||||
--Print (Interp, Get_Cdr(Operand));
|
||||
if not Is_Cons(Get_Cdr(Operand)) then
|
||||
Ada.Text_IO.Put_Line ("NO BODY");
|
||||
raise Syntax_Error;
|
||||
--Pop_Frame (Interp); -- Done
|
||||
end if;
|
||||
|
||||
declare
|
||||
Closure: Object_Pointer;
|
||||
begin
|
||||
Closure := Make_Closure (Interp.Self, Operand, Interp.Environment);
|
||||
Pop_Frame (Interp); -- Done
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Closure);
|
||||
end;
|
||||
end if;
|
||||
|
||||
when Quote_Syntax =>
|
||||
Operand := Cdr; -- Skip "quote"
|
||||
if not Is_Cons(Operand) then
|
||||
-- e.g) (quote)
|
||||
-- (quote . 10)
|
||||
Ada.Text_IO.Put_LINE ("FUCKNING CDR FOR QUOTE");
|
||||
raise Syntax_Error;
|
||||
elsif Get_Cdr(Operand) /= Nil_Pointer then
|
||||
Ada.Text_IO.Put_LINE ("WRONG NUMBER OF ARGUMENTS FOR QUOTE");
|
||||
raise Syntax_Error;
|
||||
end if;
|
||||
Pop_Frame (Interp); -- Done
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Get_Car(Operand));
|
||||
|
||||
when others =>
|
||||
Ada.Text_IO.Put_Line ("Unknown syntax");
|
||||
--Set_Frame_Opcode (Interp.Stack, Opcode_Evaluate_Syntax); -- Switch to syntax evaluation
|
||||
raise Internal_Error;
|
||||
end case;
|
||||
else
|
||||
if (Interp.Trait.Trait_Bits and No_Optimization) = 0 then
|
||||
while not Is_Normal_Pointer(Car) loop
|
||||
-- This while block is for optimization only. It's not really needed.
|
||||
-- If I know that the next object to evaluate is a literal object,
|
||||
-- I can simply reverse-chain it to the return field of the current
|
||||
-- frame without pushing another frame dedicated for it.
|
||||
|
||||
-- TODO: some normal pointers may point to a literal object. e.g.) bignum
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Car);
|
||||
if Is_Cons(Cdr) then
|
||||
Operand := Cdr;
|
||||
Car := Get_Car(Operand);
|
||||
Cdr := Get_Cdr(Operand);
|
||||
else
|
||||
-- last cons
|
||||
Operand := Reverse_Cons(Get_Frame_Result(Interp.Stack));
|
||||
Clear_Frame_Result (Interp.Stack);
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Apply);
|
||||
Set_Frame_Operand (Interp.Stack, Operand);
|
||||
goto Done;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
if Is_Cons(Cdr) then
|
||||
-- Not the last cons cell yet
|
||||
Set_Frame_Operand (Interp.Stack, Cdr); -- change the operand for the next call
|
||||
else
|
||||
-- Reached the last cons cell
|
||||
if Cdr /= Nil_Pointer then
|
||||
-- The last CDR is not Nil.
|
||||
Ada.Text_IO.Put_Line ("$$$$..................FUCKING CDR.....................$$$$");
|
||||
-- raise Syntax_Error;
|
||||
end if;
|
||||
|
||||
-- Change the operand to a mark object so that the call to this
|
||||
-- procedure after the evaluation of the last car goes to the
|
||||
-- Mark_Object case.
|
||||
Set_Frame_Operand (Interp.Stack, Interp.Mark);
|
||||
end if;
|
||||
|
||||
-- Arrange to evaluate the car object
|
||||
if (Interp.Trait.Trait_Bits and No_Optimization) = 0 then
|
||||
Push_Frame (Interp, Opcode_Evaluate_Object, Car);
|
||||
goto Start_Over; -- for optimization only. not really needed.
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when Mark_Object =>
|
||||
-- TODO: you can use the mark context to differentiate context
|
||||
|
||||
-- Get the evaluation result stored in the current stack frame by
|
||||
-- various sub-Opcode_Evaluate_Object frames. the return value
|
||||
-- chain must be reversed Chain_Frame_Result reverse-chains values.
|
||||
Operand := Reverse_Cons(Get_Frame_Result(Interp.Stack));
|
||||
|
||||
-- Refresh the current stack frame to Opcode_Apply.
|
||||
-- This should be faster than Popping the current frame and pushing
|
||||
-- a new frame.
|
||||
-- Envir := Get_Frame_Environment(Interp.Stack);
|
||||
-- Pop_Frame (Interp); -- done
|
||||
-- Push_Frame (Interp, Opcode_Apply, Operand, Envir);
|
||||
Clear_Frame_Result (Interp.Stack);
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Apply);
|
||||
Set_Frame_Operand (Interp.Stack, Operand);
|
||||
|
||||
when others =>
|
||||
-- normal literal object
|
||||
goto Literal;
|
||||
end case;
|
||||
goto Done;
|
||||
|
||||
<<Literal>>
|
||||
Pop_Frame (Interp); -- done
|
||||
Ada.Text_IO.Put ("Return => ");
|
||||
Print (Interp, Operand);
|
||||
Chain_Frame_Result (Interp, Interp.Stack, Operand);
|
||||
goto Done;
|
||||
|
||||
<<Done>>
|
||||
Pop_Tops (Interp, 3);
|
||||
end Evaluate_Object;
|
||||
|
||||
procedure Evaluate_Procedure is
|
||||
pragma Inline (Evaluate_Procedure);
|
||||
begin
|
||||
null;
|
||||
end Evaluate_Procedure;
|
||||
Pop_Tops (Interp, 2);
|
||||
end Finish_Define_Symbol;
|
||||
|
||||
procedure Evaluate is separate;
|
||||
procedure Apply is separate;
|
||||
|
||||
procedure Unfetch_Character is
|
||||
pragma Inline (Unfetch_Character);
|
||||
pragma Assert (not Interp.LC_Unfetched);
|
||||
begin
|
||||
Interp.LC_Unfetched := Standard.True;
|
||||
end Unfetch_Character;
|
||||
|
||||
procedure Fetch_Character is
|
||||
begin
|
||||
-- TODO: calculate Interp.Input.Row, Interp.Input.Column
|
||||
@ -349,13 +151,12 @@ Print (Interp, Operand);
|
||||
X = Ch.CR or else X = Ch.LF or else X = Ch.FF;
|
||||
end Is_White_Space;
|
||||
|
||||
function Is_Identifier_Stopper (X: in Object_Character) return Standard.Boolean is
|
||||
function Is_Delimiter (X: in Object_Character) return Standard.Boolean is
|
||||
begin
|
||||
return X = Ch.Left_Parenthesis or else X = Ch.Right_Parenthesis or else
|
||||
X = Ch.Apostrophe or else LC.Value = Ch.Quotation or else
|
||||
X = Ch.Number_Sign or else LC.Value = Ch.Semicolon or else
|
||||
X = Ch.Quotation or else X = Ch.Semicolon or else
|
||||
Is_White_Space(X);
|
||||
end Is_Identifier_Stopper;
|
||||
end Is_Delimiter;
|
||||
|
||||
procedure Skip_Spaces_And_Comments is
|
||||
begin
|
||||
@ -416,6 +217,86 @@ Print (Interp, Operand);
|
||||
when Ch.Pos.Apostrophe =>
|
||||
Token.Set (Interp, Single_Quote_Token, LC.Value);
|
||||
|
||||
when Ch.Pos.Number_Sign =>
|
||||
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
|
||||
-- #( ) -- vector
|
||||
-- #[ ] -- list
|
||||
-- #{ } -- hash table
|
||||
-- #< > -- xxx
|
||||
|
||||
case Object_Character'Pos(LC.Value) is
|
||||
when Ch.Pos.LC_T => -- #t
|
||||
Token.Set (Interp, True_Token, Ch.Number_Sign);
|
||||
Token.Append_Character (Interp, LC.Value);
|
||||
|
||||
when Ch.Pos.LC_F => -- #f
|
||||
Token.Set (Interp, False_Token, Ch.Number_Sign);
|
||||
Token.Append_Character (Interp, LC.Value);
|
||||
|
||||
when Ch.Pos.Backslash => -- #\C, #\space, #\newline
|
||||
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
|
||||
if Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last) = Label_Newline then
|
||||
Token.Set (Interp, Character_Token, Ch.LF); -- reset the token to LF
|
||||
elsif Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last) = Label_Space then
|
||||
Token.Set (Interp, Character_Token, Ch.Space); -- reset the token to Space
|
||||
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;
|
||||
|
||||
--when Ch.Pos.Left_Parenthesis => -- #(
|
||||
-- Token.Set (Interp, Vector_Token, Ch.Number_Sign);
|
||||
-- Token.Append_Character (Interp, LC.Value);
|
||||
|
||||
--when Ch.Pos.Left_Bracket => -- $[
|
||||
-- Token.Set (Interp, List_Token, Ch.Number_Sign);
|
||||
-- Token.Append_Character (Interp, LC.Value);
|
||||
|
||||
--when Ch.Pos.Left_Bracket => -- ${
|
||||
-- Token.Set (Interp, Table_Token, Ch.Number_Sign);
|
||||
-- Token.Append_Character (Interp, LC.Value);
|
||||
|
||||
when others =>
|
||||
-- unknown #letter
|
||||
-- TODO: Set Error code, Error Number.... Error location
|
||||
raise Syntax_Error;
|
||||
|
||||
end case;
|
||||
|
||||
when Ch.Pos.Quotation =>
|
||||
Fetch_Character;
|
||||
Token.Set (Interp, String_Token);
|
||||
@ -443,9 +324,6 @@ Print (Interp, Operand);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
when Ch.Pos.Number_Sign =>
|
||||
Fetch_Character;
|
||||
-- TODO: t, false, etc
|
||||
|
||||
when Ch.Pos.Zero .. Ch.Pos.Nine =>
|
||||
-- TODO; negative number, floating-point number, bignum, hexdecimal, etc
|
||||
@ -456,7 +334,7 @@ Print (Interp, Operand);
|
||||
if LC.Kind /= Normal_Character or else
|
||||
LC.Value not in Ch.Zero .. Ch.Nine then
|
||||
-- Unfetch the last character
|
||||
Interp.LC_Unfetched := Standard.True;
|
||||
Unfetch_Character;
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
@ -474,8 +352,7 @@ Print (Interp, Operand);
|
||||
Fetch_Character;
|
||||
if LC.Kind /= Normal_Character or else
|
||||
LC.Value not in Ch.Zero .. Ch.Nine then
|
||||
-- Unfetch the last character
|
||||
Interp.LC_Unfetched := Standard.True;
|
||||
Unfetch_Character;
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
@ -483,10 +360,9 @@ Print (Interp, Operand);
|
||||
Token.Set (Interp, Identifier_Token, Tmp(1..1));
|
||||
loop
|
||||
-- TODO: more characters
|
||||
if LC.Kind /= Normal_Character or else
|
||||
Is_Identifier_Stopper(LC.Value) then
|
||||
-- Unfetch the last character
|
||||
Interp.LC_Unfetched := Standard.True;
|
||||
if LC.Kind /= Normal_Character or else
|
||||
Is_Delimiter(LC.Value) then
|
||||
Unfetch_Character;
|
||||
exit;
|
||||
end if;
|
||||
|
||||
@ -503,9 +379,8 @@ Print (Interp, Operand);
|
||||
--exit when not Is_Ident_Char(C.Value);
|
||||
-- TODO: more characters
|
||||
if LC.Kind /= Normal_Character or else
|
||||
Is_Identifier_Stopper(LC.Value) then
|
||||
-- Unfetch the last character
|
||||
Interp.LC_Unfetched := Standard.True;
|
||||
Is_Delimiter(LC.Value) then
|
||||
Unfetch_Character;
|
||||
exit;
|
||||
end if;
|
||||
end loop;
|
||||
@ -561,12 +436,17 @@ Ada.Text_IO.Put_Line ("ERROR: PREMATURE LIST END");
|
||||
V := String_To_Integer_Pointer(Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last));
|
||||
Chain_Frame_Result (Interp, Interp.Stack, V);
|
||||
|
||||
when Character_Token =>
|
||||
pragma Assert (Interp.Token.Value.Last = 1);
|
||||
V := Character_To_Pointer(Interp.Token.Value.Ptr.all(1));
|
||||
Chain_Frame_Result (Interp, Interp.Stack, V);
|
||||
|
||||
when String_Token =>
|
||||
V := Make_String (Interp.Self, Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last));
|
||||
V := Make_String(Interp.Self, Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last));
|
||||
Chain_Frame_Result (Interp, Interp.Stack, V);
|
||||
|
||||
when Identifier_Token =>
|
||||
V := Make_Symbol (Interp.Self, Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last));
|
||||
V := Make_Symbol(Interp.Self, Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last));
|
||||
Chain_Frame_Result (Interp, Interp.Stack, V);
|
||||
|
||||
when others =>
|
||||
@ -610,6 +490,12 @@ Ada.Text_IO.Put_Line ("ERROR: CDR QUOT LIST END");
|
||||
V := String_To_Integer_Pointer(Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last));
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Read_List_End);
|
||||
Chain_Frame_Result (Interp, Interp.Stack, V);
|
||||
|
||||
when Character_Token =>
|
||||
pragma Assert (Interp.Token.Value.Last = 1);
|
||||
V := Character_To_Pointer(Interp.Token.Value.Ptr.all(1));
|
||||
Set_Frame_Opcode (Interp.Stack, Opcode_Read_List_End);
|
||||
Chain_Frame_Result (Interp, Interp.Stack, V);
|
||||
|
||||
when String_Token =>
|
||||
V := Make_String (Interp.Self, Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last));
|
||||
@ -708,6 +594,12 @@ Ada.Text_IO.Put_Line ("INFO: NO MORE TOKEN ");
|
||||
Pop_Frame (Interp); -- Done with the current frame
|
||||
Chain_Frame_Result (Interp, Interp.Stack, V);
|
||||
|
||||
when Character_Token =>
|
||||
pragma Assert (Interp.Token.Value.Last = 1);
|
||||
V := Character_To_Pointer(Interp.Token.Value.Ptr.all(1));
|
||||
Pop_Frame (Interp); -- Done with the current frame
|
||||
Chain_Frame_Result (Interp, Interp.Stack, V);
|
||||
|
||||
when String_Token =>
|
||||
V := Make_String (Interp.Self, Interp.Token.Value.Ptr.all(1..Interp.Token.Value.Last));
|
||||
Pop_Frame (Interp); -- Done with the current frame
|
||||
@ -802,14 +694,14 @@ begin
|
||||
Evaluate_Result;
|
||||
|
||||
when Opcode_Evaluate_Object =>
|
||||
Evaluate_Object;
|
||||
Evaluate;
|
||||
|
||||
when Opcode_Evaluate_Group =>
|
||||
Evaluate_Group;
|
||||
|
||||
when Opcode_Evaluate_Procedure =>
|
||||
Evaluate_Procedure;
|
||||
|
||||
when Opcode_Finish_Define_Symbol =>
|
||||
Finish_Define_Symbol;
|
||||
|
||||
when Opcode_Apply =>
|
||||
Apply;
|
||||
|
||||
|
@ -51,6 +51,9 @@ package body H2.Scheme is
|
||||
Label_Minus: constant Object_Character_Array := (1 => Ch.Minus_Sign); -- "-"
|
||||
Label_Multiply: constant Object_Character_Array := (1 => Ch.Asterisk); -- "*"
|
||||
|
||||
|
||||
Label_Newline: constant Object_Character_Array := (Ch.LC_N, Ch.LC_E, Ch.LC_W, Ch.LC_L, Ch.LC_I, Ch.LC_N, Ch.LC_E); -- "newline"
|
||||
Label_Space: constant Object_Character_Array := (Ch.LC_S, Ch.LC_P, Ch.LC_A, Ch.LC_C, Ch.LC_E); -- "space"
|
||||
-----------------------------------------------------------------------------
|
||||
-- EXCEPTIONS
|
||||
-----------------------------------------------------------------------------
|
||||
@ -76,18 +79,18 @@ package body H2.Scheme is
|
||||
subtype Moved_Object_Record is Object_Record (Moved_Object, 0);
|
||||
|
||||
subtype Opcode_Type is Object_Integer range 0 .. 11;
|
||||
Opcode_Exit: constant Opcode_Type := Opcode_Type'(0);
|
||||
Opcode_Evaluate_Result: constant Opcode_Type := Opcode_Type'(1);
|
||||
Opcode_Evaluate_Object: constant Opcode_Type := Opcode_Type'(2);
|
||||
Opcode_Evaluate_Group: constant Opcode_Type := Opcode_Type'(3); -- (begin ...) and closure apply
|
||||
Opcode_Evaluate_Procedure: constant Opcode_Type := Opcode_Type'(4);
|
||||
Opcode_Apply: constant Opcode_Type := Opcode_Type'(5);
|
||||
Opcode_Read_Object: constant Opcode_Type := Opcode_Type'(6);
|
||||
Opcode_Read_List: constant Opcode_Type := Opcode_Type'(7);
|
||||
Opcode_Read_List_Cdr: constant Opcode_Type := Opcode_Type'(8);
|
||||
Opcode_Read_List_End: constant Opcode_Type := Opcode_Type'(9);
|
||||
Opcode_Close_List: constant Opcode_Type := Opcode_Type'(10);
|
||||
Opcode_Close_Quote: constant Opcode_Type := Opcode_Type'(11);
|
||||
Opcode_Exit: constant Opcode_Type := Opcode_Type'(0);
|
||||
Opcode_Evaluate_Result: constant Opcode_Type := Opcode_Type'(1);
|
||||
Opcode_Evaluate_Object: constant Opcode_Type := Opcode_Type'(2);
|
||||
Opcode_Evaluate_Group: constant Opcode_Type := Opcode_Type'(3); -- (begin ...) and closure apply
|
||||
Opcode_Finish_Define_Symbol: constant Opcode_Type := Opcode_Type'(4);
|
||||
Opcode_Apply: constant Opcode_Type := Opcode_Type'(5);
|
||||
Opcode_Read_Object: constant Opcode_Type := Opcode_Type'(6);
|
||||
Opcode_Read_List: constant Opcode_Type := Opcode_Type'(7);
|
||||
Opcode_Read_List_Cdr: constant Opcode_Type := Opcode_Type'(8);
|
||||
Opcode_Read_List_End: constant Opcode_Type := Opcode_Type'(9);
|
||||
Opcode_Close_List: constant Opcode_Type := Opcode_Type'(10);
|
||||
Opcode_Close_Quote: constant Opcode_Type := Opcode_Type'(11);
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- COMMON OBJECTS
|
||||
|
@ -451,6 +451,9 @@ private
|
||||
Right_Parenthesis_Token,
|
||||
Period_Token,
|
||||
Single_Quote_Token,
|
||||
True_Token,
|
||||
False_Token,
|
||||
Character_Token,
|
||||
String_Token,
|
||||
Integer_Token
|
||||
);
|
||||
|
@ -16,6 +16,7 @@ project Lib is
|
||||
"h2-scheme.ads",
|
||||
"h2-scheme-execute.adb",
|
||||
"h2-scheme-execute-apply.adb",
|
||||
"h2-scheme-execute-evaluate.adb",
|
||||
"h2-scheme-token.adb",
|
||||
"h2-utf8.adb",
|
||||
"h2-utf8.ads",
|
||||
|
Loading…
Reference in New Issue
Block a user