From 097dcd6a1f10760a6e457828e1bcae84e134a78b Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 19 Jan 2014 15:47:45 +0000 Subject: [PATCH] implemented symbol defining --- lib/h2-scheme-execute-apply.adb | 11 +- lib/h2-scheme-execute-evaluate.adb | 258 +++++++++++++++++++ lib/h2-scheme-execute.adb | 382 +++++++++++------------------ lib/h2-scheme.adb | 27 +- lib/h2-scheme.ads | 3 + lib/lib.gpr.in | 1 + 6 files changed, 420 insertions(+), 262 deletions(-) create mode 100644 lib/h2-scheme-execute-evaluate.adb diff --git a/lib/h2-scheme-execute-apply.adb b/lib/h2-scheme-execute-apply.adb index 45f5b1a..9a35187 100644 --- a/lib/h2-scheme-execute-apply.adb +++ b/lib/h2-scheme-execute-apply.adb @@ -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 diff --git a/lib/h2-scheme-execute-evaluate.adb b/lib/h2-scheme-execute-evaluate.adb new file mode 100644 index 0000000..6dcb180 --- /dev/null +++ b/lib/h2-scheme-execute-evaluate.adb @@ -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); + +<> + 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 <>. + 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; + +<> + Pop_Frame (Interp); -- done +Ada.Text_IO.Put ("Return => "); +Print (Interp, Operand); + Chain_Frame_Result (Interp, Interp.Stack, Operand); + goto Done; + +<> + Pop_Tops (Interp, 3); +end Evaluate; diff --git a/lib/h2-scheme-execute.adb b/lib/h2-scheme-execute.adb index baf7533..18a2e61 100644 --- a/lib/h2-scheme-execute.adb +++ b/lib/h2-scheme-execute.adb @@ -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); - <> - 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; - - <> - Pop_Frame (Interp); -- done -Ada.Text_IO.Put ("Return => "); -Print (Interp, Operand); - Chain_Frame_Result (Interp, Interp.Stack, Operand); - goto 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; diff --git a/lib/h2-scheme.adb b/lib/h2-scheme.adb index acbb5f3..cb1a513 100644 --- a/lib/h2-scheme.adb +++ b/lib/h2-scheme.adb @@ -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 diff --git a/lib/h2-scheme.ads b/lib/h2-scheme.ads index 68856fd..e6f65e0 100644 --- a/lib/h2-scheme.ads +++ b/lib/h2-scheme.ads @@ -451,6 +451,9 @@ private Right_Parenthesis_Token, Period_Token, Single_Quote_Token, + True_Token, + False_Token, + Character_Token, String_Token, Integer_Token ); diff --git a/lib/lib.gpr.in b/lib/lib.gpr.in index 043ab97..4cf0fbc 100644 --- a/lib/lib.gpr.in +++ b/lib/lib.gpr.in @@ -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",