implemented the define syntax of the form (define (f x y) ...)
This commit is contained in:
parent
9a426594a3
commit
21b0dd665f
@ -74,7 +74,79 @@ procedure Evaluate is
|
|||||||
|
|
||||||
procedure Evaluate_Case_Syntax is
|
procedure Evaluate_Case_Syntax is
|
||||||
pragma Inline (Evaluate_Case_Syntax);
|
pragma Inline (Evaluate_Case_Syntax);
|
||||||
|
Synlist: Object_Pointer;
|
||||||
|
Ptr1: Object_Pointer;
|
||||||
|
Ptr2: Object_Pointer;
|
||||||
|
Ptr3: Object_Pointer;
|
||||||
begin
|
begin
|
||||||
|
-- (case <key> <clause 1> <clause 2> ...)
|
||||||
|
-- <key> is an expression.
|
||||||
|
-- <clause> should be of the form:
|
||||||
|
-- ((<datum 1> ...) <expression 1> <expression 2> ...)
|
||||||
|
-- the last <clause> may be an else clause of the form:
|
||||||
|
-- (else <expression 1> <expression 2> ...)
|
||||||
|
--
|
||||||
|
-- (case (* 2 3)
|
||||||
|
-- ((2 3 5 7) 'prime)
|
||||||
|
-- ((1 4 6 8 9) 'composite))
|
||||||
|
--
|
||||||
|
-- (case (car '(c d))
|
||||||
|
-- ((a e i o u) 'vowel)
|
||||||
|
-- ((w y) 'semivowel)
|
||||||
|
-- (else 'consonant))
|
||||||
|
--
|
||||||
|
|
||||||
|
Synlist := Operand;
|
||||||
|
Operand := Get_Cdr(Operand); -- Skip "case"
|
||||||
|
|
||||||
|
if (Interp.State and Force_Syntax_Check) /= 0 or else
|
||||||
|
(Synlist.Flags and Syntax_Checked) = 0 then
|
||||||
|
|
||||||
|
if Not Is_Cons(Operand) then
|
||||||
|
-- e.g) (case)
|
||||||
|
-- (case . 10)
|
||||||
|
Ada.Text_IO.Put_LINE ("NO KEY FOR CASE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
--Key := Get_Car(Operand);
|
||||||
|
|
||||||
|
Ptr1 := Get_Cdr(Operand); -- <clause> list.
|
||||||
|
while Is_Cons(Ptr1) loop
|
||||||
|
Ptr2 := Get_Car(Ptr1); -- <clause>
|
||||||
|
if Get_Last_Cdr(Ptr2) /= Nil_Pointer then
|
||||||
|
Ada.Text_IO.Put_Line ("FUCKING CDR FOR CASE CLAUSE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Ptr3 := Get_Car(Ptr2); -- <datum>
|
||||||
|
if Is_Cons(Ptr3) then
|
||||||
|
if Get_Last_Cdr(Ptr3) /= Nil_Pointer then
|
||||||
|
Ada.Text_IO.Put_LINE ("FUCKING CDR FOR CASE DATUM");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
elsif Ptr3 = Interp.Else_Symbol then
|
||||||
|
-- check <test>. if it's else, it should be in the last clause.
|
||||||
|
if Is_Cons(Get_Cdr(Ptr1)) then
|
||||||
|
Ada.Text_IO.Put_Line ("ELSE NOT IN THE LAST CASE CLAUSE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
Ada.Text_IO.Put_LINE ("INVALID DATUM FOR CASE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Ptr1 := Get_Cdr(Ptr1); -- next <clause> list
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
if Ptr1 /= Nil_Pointer then
|
||||||
|
Ada.Text_IO.Put_Line ("FUCKING LAST CLAUSE FOR CASE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Synlist.Flags := Synlist.Flags or Syntax_Checked;
|
||||||
|
end if;
|
||||||
|
|
||||||
Ada.Text_IO.Put_LINE ("UNIMPLEMENTED");
|
Ada.Text_IO.Put_LINE ("UNIMPLEMENTED");
|
||||||
raise Evaluation_Error;
|
raise Evaluation_Error;
|
||||||
end Evaluate_Case_Syntax;
|
end Evaluate_Case_Syntax;
|
||||||
@ -123,6 +195,15 @@ procedure Evaluate is
|
|||||||
Ada.Text_IO.Put_Line ("FUCKING CDR FOR COND CLAUSE");
|
Ada.Text_IO.Put_Line ("FUCKING CDR FOR COND CLAUSE");
|
||||||
raise Syntax_Error;
|
raise Syntax_Error;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
if Get_Car(Ptr2) = Interp.Else_Symbol then
|
||||||
|
-- check <test>. if it's else, it should be in the last clause.
|
||||||
|
if Is_Cons(Get_Cdr(Ptr1)) then
|
||||||
|
Ada.Text_IO.Put_Line ("ELSE NOT IN THE LAST COND CLAUSE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
Ptr1 := Get_Cdr(Ptr1); -- next <clause> list
|
Ptr1 := Get_Cdr(Ptr1); -- next <clause> list
|
||||||
exit when not Is_Cons(Ptr1);
|
exit when not Is_Cons(Ptr1);
|
||||||
end loop;
|
end loop;
|
||||||
@ -144,17 +225,27 @@ procedure Evaluate is
|
|||||||
procedure Evaluate_Define_Syntax is
|
procedure Evaluate_Define_Syntax is
|
||||||
pragma Inline (Evaluate_Define_Syntax);
|
pragma Inline (Evaluate_Define_Syntax);
|
||||||
Synlist: Object_Pointer;
|
Synlist: Object_Pointer;
|
||||||
Ptr: Object_Pointer;
|
Ptr1: Object_Pointer;
|
||||||
|
Ptr2: Object_Pointer;
|
||||||
|
Ptr3: Object_Pointer;
|
||||||
|
Ptr4: Object_Pointer;
|
||||||
begin
|
begin
|
||||||
-- TODO: limit the context where define can be used.
|
-- TODO: limit the context where define can be used.
|
||||||
|
|
||||||
-- (define x 10)
|
-- (define <variable> <expression>)
|
||||||
-- (define (add x y) (+ x y)) -> (define add (lambda (x y) (+ x y)))
|
-- (define (<variable> <formals>) <body>)
|
||||||
|
-- (define (<variable> . <formal>) <body>)
|
||||||
|
--
|
||||||
|
-- e.g)
|
||||||
|
-- (define x 10)
|
||||||
|
-- (define (add x y) (+ x y)) -> (define add (lambda (x y) (+ x y)))
|
||||||
|
|
||||||
Synlist := Operand;
|
Synlist := Operand;
|
||||||
Operand := Get_Cdr(Operand); -- Skip "define"
|
Operand := Get_Cdr(Operand); -- Skip "define"
|
||||||
|
|
||||||
if (Interp.State and Force_Syntax_Check) /= 0 or else
|
if (Interp.State and Force_Syntax_Check) /= 0 or else
|
||||||
(Synlist.Flags and Syntax_Checked) = 0 then
|
(Synlist.Flags and Syntax_Checked) = 0 then
|
||||||
|
|
||||||
if not Is_Cons(Operand) or else not Is_Cons(Get_Cdr(Operand)) then
|
if not Is_Cons(Operand) or else not Is_Cons(Get_Cdr(Operand)) then
|
||||||
-- e.g) (define)
|
-- e.g) (define)
|
||||||
-- (define . 10)
|
-- (define . 10)
|
||||||
@ -163,12 +254,60 @@ procedure Evaluate is
|
|||||||
raise Syntax_Error;
|
raise Syntax_Error;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Ptr := Get_Car(Operand);
|
Ptr1 := Get_Car(Operand);
|
||||||
if Is_Cons(Ptr) then
|
if Is_Cons(Ptr1) then
|
||||||
ada.text_io.put_line ("NOT IMPLEMENTED YET");
|
-- (define (add x y) ...)
|
||||||
raise Syntax_Error;
|
|
||||||
|
|
||||||
elsif Is_Symbol(Ptr) then
|
Ptr2 := Get_Car(Ptr1); -- <variable> as a function name
|
||||||
|
if not Is_Symbol(Ptr2) then
|
||||||
|
Ada.Text_IO.Put_LINE ("WRONG NAME FOR DEFINE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Ptr1 := Get_Cdr(Ptr1); -- <formals>
|
||||||
|
Ptr2 := Ptr1;
|
||||||
|
|
||||||
|
while Is_Cons(Ptr2) loop
|
||||||
|
Ptr3 := Get_Car(Ptr2); -- <formal argument>
|
||||||
|
if not Is_Symbol(Ptr3) then
|
||||||
|
Ada.Text_IO.Put_Line ("WRONG FORMAL FOR LAMBDA");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Check for a duplication formal argument
|
||||||
|
-- TODO: make duplication check optional or change the implementation more efficient so that this check is not repeated
|
||||||
|
Ptr4 := Ptr1;
|
||||||
|
while Ptr4 /= Ptr2 loop
|
||||||
|
if Get_Car(Ptr4) = Ptr3 then
|
||||||
|
Ada.Text_IO.Put_Line ("DUPLICATE FORMAL FOR DEFINE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
Ptr4 := Get_Cdr(Ptr4);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
-- Move on to the next formal argument
|
||||||
|
Ptr2 := Get_Cdr(Ptr2);
|
||||||
|
exit when not Is_Cons(Ptr2);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
if Ptr2 /= Nil_Pointer and then not Is_Symbol(Ptr2) then
|
||||||
|
Ada.Text_IO.Put_Line ("FUCKING CDR IN FORMALS FOR DEFINE");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Ptr1 := Get_Cdr(Operand); -- <body>
|
||||||
|
if not Is_Cons(Ptr1) then
|
||||||
|
Ada.Text_IO.Put_Line ("NO BODY");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if Get_Last_Cdr(Ptr1) /= Nil_Pointer then
|
||||||
|
-- (lambda (x y) (+ x y) . 99)
|
||||||
|
Ada.Text_IO.Put_Line ("FUCKING CDR IN BODY FOR LAMBDA");
|
||||||
|
raise Syntax_Error;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
elsif Is_Symbol(Ptr1) then
|
||||||
if Get_Cdr(Get_Cdr(Operand)) /= Nil_Pointer then
|
if Get_Cdr(Get_Cdr(Operand)) /= Nil_Pointer then
|
||||||
Ada.Text_IO.Put_LINE ("TOO MANY ARGUMENTS FOR DEFINE");
|
Ada.Text_IO.Put_LINE ("TOO MANY ARGUMENTS FOR DEFINE");
|
||||||
raise Syntax_Error;
|
raise Syntax_Error;
|
||||||
@ -178,25 +317,34 @@ raise Syntax_Error;
|
|||||||
raise Syntax_Error;
|
raise Syntax_Error;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
|
||||||
Synlist.Flags := Synlist.Flags or Syntax_Checked;
|
Synlist.Flags := Synlist.Flags or Syntax_Checked;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Ptr := Get_Car(Operand);
|
Ptr1 := Get_Car(Operand);
|
||||||
if Is_Cons(Ptr) then
|
if Is_Cons(Ptr1) then
|
||||||
-- define a function: (define (add x y) ...)
|
-- define a function: (define (add x y) ...)
|
||||||
ada.text_io.put_line ("NOT IMPLEMENTED YET");
|
-- Get_Car(Ptr1) -- <variable>
|
||||||
raise Syntax_Error;
|
-- Get_Cdr(Ptr1) -- <formals>
|
||||||
|
-- Get_Cdr(Operand) -- <body>
|
||||||
|
|
||||||
|
-- It's ok to not reload but switch because no continuation
|
||||||
|
-- can be created in this form of 'define'.
|
||||||
|
Switch_Frame (Interp.Stack, Opcode_Define_Finish, Get_Car(Ptr1), Nil_Pointer);
|
||||||
|
|
||||||
|
-- Make closure and set it as a frame result. Note this is done
|
||||||
|
-- after switching in order to avoid GC problems withoug using
|
||||||
|
-- Push_Top/Pop_Tops.
|
||||||
|
Ptr2 := Make_Cons(Interp.Self, Get_Cdr(Ptr1), Get_Cdr(Operand));
|
||||||
|
Ptr2 := Make_Closure(Interp.Self, Ptr2, Get_Frame_Environment(Interp.Stack));
|
||||||
|
Set_Frame_Result (Interp.Stack, Ptr2);
|
||||||
else
|
else
|
||||||
-- define a symbol: (define x ...)
|
-- define a symbol: (define x ...)
|
||||||
pragma Assert (Is_Symbol(Ptr));
|
pragma Assert (Is_Symbol(Ptr1));
|
||||||
|
|
||||||
-- Arrange to finish defining after value evaluation
|
-- Arrange to finish defining after value evaluation
|
||||||
-- and to evaluate the value part.
|
-- and to evaluate the value part.
|
||||||
--Switch_Frame (Interp.Stack, Opccode_Define_Finish, Ptr);
|
|
||||||
--Push_Frame (Interp, Opcode_Evaluate_Object, Get_Car(Get_Cdr(Operand)));
|
|
||||||
Switch_Frame (Interp.Stack, Opcode_Evaluate_Object, Get_Car(Get_Cdr(Operand)), Nil_Pointer);
|
Switch_Frame (Interp.Stack, Opcode_Evaluate_Object, Get_Car(Get_Cdr(Operand)), Nil_Pointer);
|
||||||
Push_Subframe (Interp, Opcode_Define_Finish, Ptr);
|
Push_Subframe (Interp, Opcode_Define_Finish, Ptr1);
|
||||||
end if;
|
end if;
|
||||||
end Evaluate_Define_Syntax;
|
end Evaluate_Define_Syntax;
|
||||||
|
|
||||||
@ -204,7 +352,38 @@ raise Syntax_Error;
|
|||||||
|
|
||||||
procedure Evaluate_Do_Syntax is
|
procedure Evaluate_Do_Syntax is
|
||||||
pragma Inline (Evaluate_Do_Syntax);
|
pragma Inline (Evaluate_Do_Syntax);
|
||||||
|
Synlist: Object_Pointer;
|
||||||
begin
|
begin
|
||||||
|
-- (do <bindings> <clause> <body>)
|
||||||
|
-- <bindings> should be of the form: ((<variable 1> <init 1> <step 1>) ...)
|
||||||
|
-- <clause> should be of the form: (<test> <expression> ...)
|
||||||
|
-- <body> is zero or more expressions.
|
||||||
|
--
|
||||||
|
-- (let ((x '(1 3 5 7 9)))
|
||||||
|
-- (do ((x x (cdr x))
|
||||||
|
-- (sum 0 (+ sum (car x)))) ; <bindings>
|
||||||
|
-- ((null? x) sum) ; <clause>. if <test> is true, exit do with sum.
|
||||||
|
-- )
|
||||||
|
-- )
|
||||||
|
--
|
||||||
|
-- (do ((i 0 (+ i 1)))
|
||||||
|
-- ((= i 5) i)
|
||||||
|
-- (display i) ; <body> downwards
|
||||||
|
-- (newline)
|
||||||
|
-- )
|
||||||
|
|
||||||
|
Synlist := Operand;
|
||||||
|
Operand := Get_Cdr(Operand); -- Skip "do"
|
||||||
|
|
||||||
|
if (Interp.State and Force_Syntax_Check) /= 0 or else
|
||||||
|
(Synlist.Flags and Syntax_Checked) = 0 then
|
||||||
|
|
||||||
|
Ada.Text_IO.Put_LINE ("UNIMPLEMENTED");
|
||||||
|
raise Evaluation_Error;
|
||||||
|
|
||||||
|
Synlist.Flags := Synlist.Flags or Syntax_Checked;
|
||||||
|
end if;
|
||||||
|
|
||||||
Ada.Text_IO.Put_LINE ("UNIMPLEMENTED");
|
Ada.Text_IO.Put_LINE ("UNIMPLEMENTED");
|
||||||
raise Evaluation_Error;
|
raise Evaluation_Error;
|
||||||
end Evaluate_Do_Syntax;
|
end Evaluate_Do_Syntax;
|
||||||
@ -263,7 +442,6 @@ raise Syntax_Error;
|
|||||||
Synlist.Flags := Synlist.Flags or Syntax_Checked;
|
Synlist.Flags := Synlist.Flags or Syntax_Checked;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
|
||||||
-- Arrange to evaluate <consequent> or <alternate> after <test>
|
-- Arrange to evaluate <consequent> or <alternate> after <test>
|
||||||
-- evaluation and to evaluate <test>. Use Switch_Frame/Push_Subframe
|
-- evaluation and to evaluate <test>. Use Switch_Frame/Push_Subframe
|
||||||
-- instead of Switch_Frame/Push_Frame for continuation to work.
|
-- instead of Switch_Frame/Push_Frame for continuation to work.
|
||||||
|
Loading…
Reference in New Issue
Block a user