рд╢реБрджреНрдз C рдореЗрдВ LISP рджреБрднрд╛рд╖рд┐рдпрд╛

рдореБрдЭреЗ рдЗрд╕рдХреА рд╕рд╛рджрдЧреА рдФрд░ рдкреНрд░рднрд╛рд╡рд╢реАрд▓рддрд╛ рдХреЗ рд▓рд┐рдП C рд╕реЗ рдкреНрдпрд╛рд░ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕реЗ рд▓рдЪреАрд▓рд╛ рдФрд░ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЕрднреВрддрдкреВрд░реНрд╡ рд▓рдЪреАрд▓рд╛рдкрди рдФрд░ рддрдиреНрдордпрддрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рдФрд░ рд╕рд░рд▓ рднрд╛рд╖рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдВрд╕рд╛рдзрди рджрдХреНрд╖рддрд╛ рдореЗрдВ C рд╕реЗ рд╣рд╛рд░рдирд╛ред рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ LISPред рджреЛрдиреЛрдВ рднрд╛рд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рд┐рд╕реНрдЯрдо рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЗрд╕рдХрд╛ рдПрдХ рд▓рдВрдмрд╛ рдФрд░ рд╢рд╛рдирджрд╛рд░ рдЗрддрд┐рд╣рд╛рд╕ рд╣реИред

рдкрд┐рдЫрд▓реЗ рдХреБрдЫ рд╕рдордп рд╕реЗ рдореИрдВ рдЗрди рджреЛрдиреЛрдВ рднрд╛рд╖рд╛рдУрдВ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдПрдХрдЬреБрдЯ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдПрдХ рд╡рд┐рдЪрд╛рд░ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдЗрд╕рдХрд╛ рд╕рд╛рд░ рдПрд▓рдЖрдИрдПрд╕рдкреА рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИ рдЬреЛ рд╕реА рдХреЗ рд╕рдорд╛рди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ: рдЙрдкрдХрд░рдг рдкрд░ рдЙрдЪреНрдЪ рд╕реНрддрд░ рдХрд╛ рдирд┐рдпрдВрддреНрд░рдг рдкреНрд░рджрд╛рди рдХрд░рдирд╛ (рд╕реНрдореГрддрд┐ рдореЗрдВ рдирд┐рдореНрди-рд╕реНрддрд░реАрдп рдкрд╣реБрдВрдЪ рд╕рд╣рд┐рдд)ред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдпрд╣ LISP рдореИрдХреНрд░реЛ рдХреА рдПрдХ рдкреНрд░рдгрд╛рд▓реА рд╣реЛрдЧреА рдЬреЛ рдмрд╛рдЗрдирд░реА рдХреЛрдб рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП LISP рдХреНрд╖рдорддрд╛рдУрдВ, рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ, рднрд╛рд╖рд╛ рдХреА рдореВрд▓ рд╕рд╛рджрдЧреА рдХреЛ рдмрдирд╛рдП рд░рдЦрддреЗ рд╣реБрдП, C рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ рдпрд╛ C ++ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрднреВрддрдкреВрд░реНрд╡ рд▓рдЪреАрд▓рд╛рдкрди рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ред рдпрд╣ рдРрд╕реЗ рдбреАрдПрд╕рдПрд▓ рдирдП рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИ рдЬреЛ рд╡рд┐рдХрд╛рд╕ рдХреА рдЧрддрд┐ рдФрд░ рдЖрд╕рд╛рдиреА рдХреЛ рдмрдврд╝рд╛рддреЗ рд╣реИрдВред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдЗрд╕ рднрд╛рд╖рд╛ рдореЗрдВ LISP рдкреНрд░рдгрд╛рд▓реА рдХреЛ рд╣реА рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдХрдВрдкрд╛рдЗрд▓рд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рдФрд░ рдЕрдВрддрддрдГ рдПрдХ рдХреЛрдбрд╛рдВрддрд░рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЕрдиреБрд╕рдВрдзрд╛рди рдХреЛ рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди (рд▓рдХреНрд╖реНрдп рдкреНрд░реЛрд╕реЗрд╕рд░ рдХреЗ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд╕рдмрд╕реЗрдЯ рдХреЗ рд▓рд┐рдП) рд╕реЗ рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореБрдЭреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпреЛрдВ, рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдФрд░ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рдХрд┐рд╕реА рднреА рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдХрдо рдХрд░рдиреЗ рдореЗрдВ рд░реБрдЪрд┐ рдереАред рдЗрд╕рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕реА рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рд╕реА рдореЗрдВ рдПрдХ рдЗрдВрдкреНрд░реЛрдореЗрдкреНрдЯреВ рдПрд▓рдЖрдИрдПрд╕рдкреА рдмреЛрд▓реА рдХрд╛ рд╕рдмрд╕реЗ рд╕рд░рд▓ рд╡реНрдпрд╛рдЦреНрдпрд╛рдХрд╛рд░, рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдореИрдХреНрд░реЛ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╕рд┐рд╕реНрдЯрдо рднреА рд▓рд┐рдЦрд╛, рдЬреЛ рд╣рдореЗрдВ x86 рдЕрд╕реЗрдВрдмрд▓рд░ рдХреЗ рд╕рдмрд╕реЗрдЯ рдкрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рдХреЛрдб рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдореЗрд░реЗ рдкреНрд░рдпрд╛рд╕реЛрдВ рдХрд╛ рддрд╛рдЬ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдмреВрдЯ рдЫрд╡рд┐ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ "рд╣реИрд▓реЛ рд╡рд░реНрд▓реНрдб!" рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЛрдб рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред

рд╡рд░реНрддрдорд╛рди рдореЗрдВ, рдореИрдВрдиреЗ рдПрдХ рдХрд╛рд░реНрдпрд╢реАрд▓ рджреБрднрд╛рд╖рд┐рдпрд╛ (int.c рдлрд╝рд╛рдЗрд▓, C-рдХреЛрдб рдХреА рд▓рдЧрднрдЧ 900 рдкрдВрдХреНрддрд┐рдпрд╛рдБ) рд▓рд╛рдЧреВ рдХреА рд╣реИ, рд╕рд╛рде рд╣реА рд╕рд╛рде рдмреБрдирд┐рдпрд╛рджреА рдХрд╛рд░реНрдпреЛрдВ рдФрд░ macros (lib.l рдлрд╝рд╛рдЗрд▓, LISP рдХреЛрдб рдХреА рд▓рдЧрднрдЧ 100 рдкрдВрдХреНрддрд┐рдпреЛрдВ) рдХрд╛ рдПрдХ рд╕реЗрдЯ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИред рдХреМрди LISP рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрд░рд╡рд╛рд╣ рдХрд░рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рджреБрднрд╛рд╖рд┐рдпрд╛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╡рд┐рд╡рд░рдг, рдореИрдВ рдмрд┐рд▓реНрд▓реА рдХреЗ рд▓рд┐рдП рдкреВрдЫрддрд╛ рд╣реВрдВред

LISP рдХрдВрдкреНрдпреВрдЯрд┐рдВрдЧ рдХреА рдореВрд▓ рдЗрдХрд╛рдИ рдПрдХ рдмрд┐рдВрджреАрджрд╛рд░ рдЬреЛрдбрд╝реА рд╣реИред рдХреНрд▓рд╛рд╕рд┐рдХ рдореЗрдХрд╛рд░реНрдереА рд▓рд┐рд╕реНрдк рдореЗрдВ, рдПрдХ рдмрд┐рдВрджреБ рдЬреЛрдбрд╝реА рдФрд░ рдПрдХ рдЪрд░рд┐рддреНрд░ рдХреЗрд╡рд▓ рджреЛ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИрдВред рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рдЗрд╕ рд╕реЗрдЯ рдХреЛ рдХрдо рд╕реЗ рдХрдо рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдФрд░ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЛ рдЖрдзрд╛рд░ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рднреА рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ (рдкреВрд░реНрд╡ рдмрд╛рдж рдХреЗ рдмрджрд▓рд╛рд╡ рд╣реИрдВ)ред рд╕рд░рд▓реАрдХрд░рдг рдХреА рдЪрд╛рд╣ рдореЗрдВ, рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд▓реЛрднрди рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЬрд╛рдирдмреВрдЭрдХрд░ рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдореЗрдВ рддреЗрдЬреА рд╕реЗ рд╕реАрдорд┐рдд рднрд╛рд╖рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рд╣реИред рдореИрдВрдиреЗ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдВрдЯреЗрдирд░ рдХреЗ рд░реВрдк рдореЗрдВ рдбрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред

рддреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдмреБрдирд┐рдпрд╛рджреА рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИрдВ: рдмрд┐рдВрджреБ рдЬреЛрдбрд╝реА, рдЪрд░рд┐рддреНрд░, рд╕рдВрдЦреНрдпрд╛, рд╕реНрдЯреНрд░рд┐рдВрдЧ (рдкрд╛рд╕реНрдХрд▓ рд╢реИрд▓реА, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рд╕реЗ рдордирдорд╛рдирд╛ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рдбреЗрдЯрд╛ рдХреЛ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛)ред рдЪреВрдВрдХрд┐ рдореИрдВ рдПрдХ рджреБрднрд╛рд╖рд┐рдпрд╛ (рдФрд░ рдПрдХ рд╕рдВрдХрд▓рдХ рдкрд░ рдирд╣реАрдВ) рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд╕реЗрдЯ (рдлрд╝рдВрдХреНрд╢рди рдФрд░ рдореИрдХреНрд░реЛрдЬрд╝ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдПрд╕-рдПрдХреНрд╕рдкреНрд░реЗрд╢рдВрд╕ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ) рддрдХ рдЦреБрдж рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рдерд╛, рд▓реЗрдХрд┐рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП 4 рдЕрддрд┐рд░рд┐рдХреНрдд рдкреНрд░рдХрд╛рд░ рдЬреЛрдбрд╝реЗ рдЧрдП: рдлрд╝рдВрдХреНрд╢рди, рдореИрдХреНрд░реЛ, рдмрд┐рд▓реНрдЯ-рдЗрди рдлрд╝рдВрдХреНрд╢рди рдФрд░ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдореИрдХреНрд░реЛред рддреЛ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрд╕-рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд░рдЪрдирд╛ рд╣реИ:

struct l_env; typedef struct s_expr *(*built_in) (struct s_expr*, struct l_env*, struct file_pos*); struct s_expr { enum { DOTTED_PAIR, STRING, SYMBOL, NUMBER, FUNCTION, MACRO, BUILT_IN_FUNCTION, BUILT_IN_MACRO } type; union { struct { struct s_expr *first, *rest; } pair; struct { char *ptr; size_t size; } string; struct { struct s_expr *expr; struct l_env *env; } function; char *symbol; double number; built_in built_in; } u; }; struct l_env { char *symbol; struct s_expr *expr; struct l_env *next; }; 

рдпрд╣ рд╕рдВрд░рдЪрдирд╛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдФрд░ рдЙрддреНрдкрд╛рджрдХрддрд╛ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╖реНрдЯрддрдо рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЦреБрдж рдХреЛ рдПрдХ рдкреНрд░рднрд╛рд╡реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рд▓рдХреНрд╖реНрдп рдирд╣реАрдВ рджрд┐рдпрд╛ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдХреЛрдб рдХреА рд╕рд╛рджрдЧреА рдФрд░ рд╕рдВрдХреНрд╖рд┐рдкреНрддрддрд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдереАред рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдореБрдЭреЗ рд╕реНрдореГрддрд┐ рдкреНрд░рдмрдВрдзрди рдХреЛ рднреА рдЫреЛрдбрд╝рдирд╛ рдкрдбрд╝рд╛: рд╕рднреА рдореЗрдореЛрд░реА рдХреЛ рдмрд┐рдирд╛ рд░рд┐рд▓реАрдЬрд╝ рдХреЗ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореЗрд░реЗ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдпрд╣ рд╕рдорд╛рдзрд╛рди рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реИ: рджреБрднрд╛рд╖рд┐рдпрд╛ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛: рдЗрд╕рдХрд╛ рдХрд╛рд░реНрдп рдХреЗрд╡рд▓ рдХреЛрдб рдХреЛ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рд░реВрдк рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░рдирд╛ рд╣реИред

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдлрд╝рдВрдХреНрд╢рди (рдФрд░ рдореИрдХреНрд░реЛ) l_env рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдПрдХ рд╕реВрдЪреА рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд, рд╢рд╛рдмреНрджрд┐рдХ рд╡рд╛рддрд╛рд╡рд░рдг рдХрд╛ рдПрдХ рдореВрд▓ рддрддреНрд╡ рд╣реИред рдмреЗрд╢рдХ, рдпрд╣ рдЕрдХреНрд╖рдо рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рд╡рд░реНрдгреЛрдВ рддрдХ рдЕрдиреБрдХреНрд░рдорд┐рдХ рдкрд╣реБрдВрдЪ рд╢рд╛рдорд┐рд▓ рд╣реИред рд▓реЗрдХрд┐рди рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рд░рд▓ рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╕рдВрд░рдЪрдирд╛ рд╣реИ: рдЙрдиреНрд╣реЗрдВ рд╕реВрдЪреА рдХреЗ рдкреНрд░рдореБрдЦ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рд╡реИрд╢реНрд╡рд┐рдХ рд▓реЛрдЧреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ, рдкреВрдВрдЫ рддрдХред рдХреЗрд╡рд▓ рдЗрд╕ рд╕реВрдЪреА рдХреЗ рд╕рд╛рдордиреЗ рдХреА рдЕрдирджреЗрдЦреА рдХрд░рдХреЗ рд╕реНрдерд╛рдиреАрдп рдЪрд░ (рдЬрдм рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдпрд╛ рдХрд┐рд╕реА рд▓реЗрдЯ рдмреНрд▓реЙрдХ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддреЗ рд╣реИрдВ) рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд╛рддрд╛рд╡рд░рдг рдЖрдкрдХреЛ рдХреНрд▓реЛрдЬрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдПрд╕-рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЙрдкрд░реЛрдХреНрдд рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдЗрд╕рдХреА рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ:

 struct s_expr *eval_s_expr (struct s_expr *expr, struct l_env *env, struct file_pos *pos) { struct s_expr *first, *in = expr; struct l_env *benv; trace_put("%s -> ...", in, NULL, env); if (expr) if (expr->type == SYMBOL) if (find_symbol(expr->u.symbol, &env)) expr = env->expr; else error(UNBOUND_SYMBOL_MSG, pos, expr->u.symbol); else if (expr->type == DOTTED_PAIR) { first = eval_s_expr(expr->u.pair.first, env, pos); if (!first || first->type == DOTTED_PAIR || first->type == SYMBOL || first->type == STRING || first->type == NUMBER) error(NON_FUNC_MACRO_MSG, pos, s_expr_string(first, env)); expr = first->type == FUNCTION || first->type == BUILT_IN_FUNCTION ? map_eval(expr->u.pair.rest, env, pos) : expr->u.pair.rest; if (first->type == FUNCTION || first->type == MACRO) { assert(first->u.function.expr->type == DOTTED_PAIR); benv = apply_args(first->u.function.expr->u.pair.first, expr, first->u.function.env, pos); expr = eval_list(first->u.function.expr->u.pair.rest, benv, pos); if (first->type == MACRO) { trace_put("%s ~> %s", in, expr, env); expr = eval_s_expr(expr, env, pos); } } else expr = first->u.built_in(expr, env, pos); } trace_put("%s -> %s", in, expr, env); return expr; } 

рдпрджрд┐ рдЧрдгрдирд╛ рдХреА рдЧрдИ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдПрдХ рдкреНрд░рддреАрдХ рд╣реИ, рддреЛ рд╣рдо рдмрд╕ рд╡рд░реНрддрдорд╛рди рд╢рд╛рдмреНрджрд┐рдХ рд╡рд╛рддрд╛рд╡рд░рдг (find_symbol) рдореЗрдВ рдЗрд╕рдХреЗ рдореВрд▓реНрдп рдХреА рддрд▓рд╛рд╢ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдлрд╝рдВрдХреНрд╢рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ: рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд╡рд░реНрддрдорд╛рди рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд╛рддрд╛рд╡рд░рдг (map_eval) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдФрдкрдЪрд╛рд░рд┐рдХ рдорд╛рдкрджрдВрдбреЛрдВ (apply_args) рдХреЗ рдкреНрд░рддреАрдХреЛрдВ рд╕реЗ рдмрд╛рдВрдзрддреЗ рд╣реИрдВред рдЕрдЧрд▓рд╛, рд╣рдо рдЕрдиреБрдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рд╢рд░реАрд░ рдХреЗ рддрддреНрд╡реЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд╛рддрд╛рд╡рд░рдг рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдЕрдВрддрд┐рдо рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ (eval_list) рдХреЗ рдореВрд▓реНрдп рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рдореИрдХреНрд░реЛ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЧрдгрдирд╛ рдХреНрд░рдо рдХреБрдЫ рдЕрд▓рдЧ рд╣реИред рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЧрдгрдирд╛ рдирд╣реАрдВ рдХреА рдЬрд╛рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╕рдВрдЪрд╛рд░рд┐рдд рд╣реЛрддреА рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдореИрдХреНрд░реЛ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ (рдореИрдХреНрд░реЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди) рдЕрддрд┐рд░рд┐рдХреНрдд рдЧрдгрдирд╛ рдХреЗ рдЕрдзреАрди рд╣реИред рд╕рдВрдЦреНрдпрд╛рдПрдБ, рддрд╛рд░, рдХрд╛рд░реНрдп рдФрд░ рдореИрдХреНрд░реЛрдЬрд╝ рдХреА рдЧрдгрдирд╛ рд╕реНрд╡рдпрдВ рджреНрд╡рд╛рд░рд╛ рдХреА рдЬрд╛рддреА рд╣реИред

Int.c рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдкреВрд░реНрдг рдкрд╛рда
 #include <assert.h> #include <ctype.h> #include <float.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define LINE_COMMENT_CHAR ';' #define BLOCK_COMMENT_CHAR1 ';' #define BLOCK_COMMENT_CHAR2 '|' #define LIST_OPEN_BRACE_CHAR '(' #define LIST_CLOSE_BRACE_CHAR ')' #define LIST_DOT_CHAR '.' #define STRING_DELIMITER_CHAR '"' #define STRING_ESCAPE_CHAR '\\' #define NUMBER_PREFIX_CHAR '$' #define NUMBER_FORMAT_HEX_CHAR 'h' #define NUMBER_FORMAT_OCT_CHAR 'o' #define NIL_SYMBOL_STR "_" #define TRUE_SYMBOL_STR "t" #define TRACE_SYMBOL_STR "trace" #define CAR_SYMBOL_STR "@" #define CDR_SYMBOL_STR "%" #define CONS_SYMBOL_STR "^" #define IF_SYMBOL_STR "?" #define LAMBDA_SYMBOL_STR "!" #define MACRO_SYMBOL_STR "#" #define SETQ_SYMBOL_STR "=" #define QUOTE_SYMBOL_STR "'" #define PLUS_SYMBOL_STR "+" #define GREATER_SYMBOL_STR ">" #define FUNCTION_STR_FORMAT "<!%s>" #define MACRO_STR_FORMAT "<#%s>" #define OUT_OF_MEMORY_MSG "out of memory" #define UNEXPECTED_EOF_MSG "unexpected end of file" #define BAD_SYNTAX_MSG "bad syntax" #define NON_FUNC_MACRO_MSG "expression %s is neither a function nor a macro" #define NON_NONEMPTY_LIST_MSG "expression %s is not a nonempty list" #define NON_LIST_MSG "expression %s is not a proper list" #define UNBOUND_SYMBOL_MSG "unbound symbol %s" #define BAD_FORMAL_ARGS_MSG "bad formal arguments %s" #define BAD_ACTUAL_ARGS_MSG "bad actual arguments %s" #define STRING_OVERFLOW_MSG "string size overflow" #define NUMBER_LENGTH_MAX 32 #define SYMBOL_LENGTH_MAX 32 #define STRING_LENGTH_MAX 256 #define S_EXPR_LENGTH_MAX 1024 struct file_pos { char *filename; int line, chr; }; struct l_env; typedef struct s_expr *(*built_in) (struct s_expr*, struct l_env*, struct file_pos*); struct s_expr { enum { DOTTED_PAIR, STRING, SYMBOL, NUMBER, FUNCTION, MACRO, BUILT_IN_FUNCTION, BUILT_IN_MACRO } type; union { struct { struct s_expr *first, *rest; } pair; struct { char *ptr; size_t size; } string; struct { struct s_expr *expr; struct l_env *env; } function; char *symbol; double number; built_in built_in; } u; }; void error(char *message, struct file_pos *pos, char *expr) { if (pos) printf("Error at %s:%d:%d: ", pos->filename, pos->line, pos->chr); else printf("Error: "); if (expr) printf(message, expr); else printf("%s", message); puts(""); exit(1); } void *alloc_mem(size_t size) { void *ptr = malloc(size); if (!ptr) error(OUT_OF_MEMORY_MSG, NULL, NULL); return ptr; } struct s_expr *true_ () { static struct s_expr *expr = NULL; if (!expr) { expr = alloc_mem(sizeof(*expr)); expr->type = SYMBOL; expr->u.symbol = TRUE_SYMBOL_STR; } return expr; } int get_char(FILE *file, struct file_pos *pos) { int chr = getc(file); if (chr == '\n') pos->line++, pos->chr = 1; else if (chr != EOF) pos->chr++; return chr; } int next_char(FILE *file) { int chr = getc(file); ungetc(chr, file); return chr; } int get_significant_char (FILE *file, struct file_pos *pos) { enum { NO_COMMENT, LINE_COMMENT, BLOCK_COMMENT } state = NO_COMMENT; int chr; while (1) { chr = get_char(file, pos); if (state == NO_COMMENT) { if (chr == BLOCK_COMMENT_CHAR1 && next_char(file) == BLOCK_COMMENT_CHAR2) { get_char(file, pos); state = BLOCK_COMMENT; continue; } if (chr == LINE_COMMENT_CHAR) state = LINE_COMMENT; else if (chr != ' ' && chr != '\t' && chr != '\r' && chr != '\n') return chr; } else if (state == BLOCK_COMMENT) { if (chr == BLOCK_COMMENT_CHAR2 && next_char(file) == BLOCK_COMMENT_CHAR1) { get_char(file, pos); state = NO_COMMENT; } else if (chr == EOF) error(UNEXPECTED_EOF_MSG, pos, NULL); } else if (state == LINE_COMMENT) { if (chr == '\n') state = NO_COMMENT; else if (chr == EOF) return EOF; } } } struct s_expr *parse_s_expr (FILE*, struct file_pos*); struct s_expr *parse_list (FILE *file, struct file_pos *pos) { struct s_expr *expr, *rest; int chr; chr = get_significant_char(file, pos); if (chr == LIST_CLOSE_BRACE_CHAR) return NULL; ungetc(chr, file); pos->chr--; expr = alloc_mem(sizeof(*expr)); expr->type = DOTTED_PAIR; expr->u.pair.first = parse_s_expr(file, pos); rest = expr; while (1) { chr = get_significant_char(file, pos); if (chr == LIST_DOT_CHAR) { rest->u.pair.rest = parse_s_expr(file, pos); if (get_significant_char(file, pos) != LIST_CLOSE_BRACE_CHAR) error(BAD_SYNTAX_MSG, pos, NULL); break; } else if (chr == LIST_CLOSE_BRACE_CHAR) { rest->u.pair.rest = NULL; break; } else if (chr == EOF) error(UNEXPECTED_EOF_MSG, pos, NULL); else { ungetc(chr, file); pos->chr--; rest->u.pair.rest = alloc_mem(sizeof(*expr)); rest->u.pair.rest->type = DOTTED_PAIR; rest->u.pair.rest->u.pair.first = parse_s_expr(file, pos); rest = rest->u.pair.rest; } } return expr; } void read_escape_seq (FILE *file, struct file_pos *pos, char *buf) { /* TODO: add support for escape sequences */ } struct s_expr *parse_string (FILE *file, struct file_pos *pos) { char buf[STRING_LENGTH_MAX]; struct s_expr *expr; int chr, i = 0; while (i < STRING_LENGTH_MAX) { chr = get_char(file, pos); if (chr == STRING_ESCAPE_CHAR) read_escape_seq(file, pos, buf); else if (chr == STRING_DELIMITER_CHAR) break; else if (chr == EOF) error(UNEXPECTED_EOF_MSG, pos, NULL); else buf[i++] = chr; } expr = alloc_mem(sizeof(*expr)); expr->type = STRING; expr->u.string.ptr = i ? alloc_mem(i) : NULL; memcpy(expr->u.string.ptr, buf, i); expr->u.string.size = i; return expr; } void read_double (FILE *file, struct file_pos *pos, char *buf) { int chr, i = 0, point = -1; chr = next_char(file); if (chr == '+' || chr == '-') { get_char(file, pos); buf[i++] = chr; } while (i < NUMBER_LENGTH_MAX && isdigit(next_char(file))) buf[i++] = get_char(file, pos); if (i < NUMBER_LENGTH_MAX && next_char(file) == '.') buf[point = i++] = get_char(file, pos); while (i < NUMBER_LENGTH_MAX && isdigit(next_char(file))) buf[i++] = get_char(file, pos); chr = next_char(file); if (i < NUMBER_LENGTH_MAX && (chr == 'e' || chr == 'E') && i > point + 1) { get_char(file, pos); buf[i++] = chr; chr = next_char(file); if (i < NUMBER_LENGTH_MAX && (chr == '+' || chr == '-')) { get_char(file, pos); buf[i++] = chr; } while (i < NUMBER_LENGTH_MAX && isdigit(next_char(file))) buf[i++] = get_char(file, pos); } if (i && i < NUMBER_LENGTH_MAX) buf[i] = 0; else error(BAD_SYNTAX_MSG, pos, NULL); } void read_int (FILE *file, struct file_pos *pos, int base, char *buf) { int chr, i = 0; assert(base == 8 || base == 16); for (; i < NUMBER_LENGTH_MAX; get_char(file, pos)) { chr = next_char(file); if ((base == 16 && isxdigit(chr)) || (chr >= '0' && chr <= '7')) buf[i++] = chr; else break; } if (i && i < NUMBER_LENGTH_MAX) buf[i] = 0; else error(BAD_SYNTAX_MSG, pos, NULL); } struct s_expr *parse_number (FILE *file, struct file_pos *pos) { char buf[NUMBER_LENGTH_MAX + 1]; struct s_expr *expr; int inum; expr = alloc_mem(sizeof(*expr)); expr->type = NUMBER; switch (next_char(file)) { case NUMBER_FORMAT_HEX_CHAR: get_char(file, pos); read_int(file, pos, 16, buf); sscanf(buf, "%x", &inum); expr->u.number = inum; break; case NUMBER_FORMAT_OCT_CHAR: get_char(file, pos); read_int(file, pos, 8, buf); sscanf(buf, "%o", &inum); expr->u.number = inum; break; default: read_double(file, pos, buf); sscanf(buf, "%lf", &expr->u.number); break; } return expr; } struct s_expr *parse_symbol (FILE *file, struct file_pos *pos) { char buf[NUMBER_LENGTH_MAX + 1]; struct s_expr *expr; int chr, chr2, i = 0; for (; i < NUMBER_LENGTH_MAX; get_char(file, pos)) { chr = next_char(file); if (chr == BLOCK_COMMENT_CHAR1) { get_char(file, pos); chr2 = next_char(file); ungetc(chr2, file); pos->chr--; if (chr2 == BLOCK_COMMENT_CHAR2) break; } if (chr >= '!' && chr <= '~' && chr != LINE_COMMENT_CHAR && chr != LIST_OPEN_BRACE_CHAR && chr != LIST_CLOSE_BRACE_CHAR && chr != LIST_DOT_CHAR && chr != STRING_DELIMITER_CHAR && chr != NUMBER_PREFIX_CHAR) buf[i++] = chr; else break; } if (i && i < SYMBOL_LENGTH_MAX) buf[i] = 0; else error(BAD_SYNTAX_MSG, pos, NULL); if(!strcmp(buf, NIL_SYMBOL_STR)) return NULL; if(!strcmp(buf, TRUE_SYMBOL_STR)) return true_(); expr = alloc_mem(sizeof(*expr)); expr->type = SYMBOL; expr->u.symbol = alloc_mem(i + 1); strcpy(expr->u.symbol, buf); return expr; } struct s_expr *parse_s_expr (FILE *file, struct file_pos *pos) { struct s_expr *expr; int chr; chr = get_significant_char(file, pos); switch (chr) { case EOF: return NULL; case LIST_OPEN_BRACE_CHAR: expr = parse_list(file, pos); break; case STRING_DELIMITER_CHAR: expr = parse_string(file, pos); break; case NUMBER_PREFIX_CHAR: expr = parse_number(file, pos); break; default: ungetc(chr, file); pos->chr--; expr = parse_symbol(file, pos); break; } return expr; } struct l_env { char *symbol; struct s_expr *expr; struct l_env *next; }; static int do_trace = 0; char *s_expr_string (struct s_expr*, struct l_env*); void trace_put (char *format, struct s_expr *expr1, struct s_expr *expr2, struct l_env *env) { if (do_trace) { printf("Trace: "); printf(format, s_expr_string(expr1, env), s_expr_string(expr2, env)); puts(""); } } struct l_env *add_symbol (char *symbol, struct s_expr *expr, struct l_env *env, int append) { struct l_env *new_env; new_env = alloc_mem(sizeof(*new_env)); new_env->symbol = symbol, new_env->expr = expr; if (append) env->next = new_env, new_env->next = NULL; else new_env->next = env; return new_env; } struct l_env * add_built_in (int macro, char *symbol, built_in bi, struct l_env *env) { struct s_expr *expr = alloc_mem(sizeof(*expr)); expr->type = macro ? BUILT_IN_MACRO : BUILT_IN_FUNCTION; expr->u.built_in = bi; return add_symbol(symbol, expr, env, 0); } int find_symbol (char *symbol, struct l_env **env) { struct l_env *next = *env; for (; next; *env = next, next = next->next) if (!strcmp(symbol, next->symbol)) { *env = next; return 1; } return 0; } char *str_cat (char *dest, size_t dest_size, char *src) { if (strlen(src) > dest_size - 1 - strlen(dest)) error(STRING_OVERFLOW_MSG, NULL, NULL); return strcat(dest, src); } char *list_string (struct s_expr *list, struct l_env *env) { char buf[S_EXPR_LENGTH_MAX + 1] = { LIST_OPEN_BRACE_CHAR, 0 }; char psep[] = { ' ', LIST_DOT_CHAR, ' ', 0 }; char cbrc[] = { LIST_CLOSE_BRACE_CHAR, 0 }; for (; list && list->type == DOTTED_PAIR; list = list->u.pair.rest) { if (buf[1]) str_cat(buf, S_EXPR_LENGTH_MAX + 1, " "); str_cat(buf, S_EXPR_LENGTH_MAX + 1, s_expr_string(list->u.pair.first, env)); } if (list) str_cat(str_cat(buf, S_EXPR_LENGTH_MAX + 1, psep), S_EXPR_LENGTH_MAX + 1, s_expr_string(list, env)); str_cat(buf, S_EXPR_LENGTH_MAX + 1, cbrc); return strcpy(alloc_mem(strlen(buf) + 1), buf); } char *string_string (char *ptr, size_t size) { char *str = alloc_mem(size + 3); str[0] = str[size + 1] = '"'; memcpy(str + 1, ptr, size); str[size + 2] = 0; return str; } char *number_string (double number) { char *str = alloc_mem(NUMBER_LENGTH_MAX + 2); str[0] = NUMBER_PREFIX_CHAR; sprintf(str + 1, "%g", number); return str; } char *function_string (struct s_expr *expr, int macro, struct l_env *env) { char *str; for (; env; env = env->next) if (env->expr == expr) break; str = alloc_mem((macro ? sizeof(MACRO_STR_FORMAT) : sizeof(FUNCTION_STR_FORMAT)) + (env ? strlen(env->symbol) : 0) - 1); sprintf(str, macro ? MACRO_STR_FORMAT : FUNCTION_STR_FORMAT, env ? env->symbol : ""); return str; } char *s_expr_string (struct s_expr *expr, struct l_env *env) { if (!expr) return NIL_SYMBOL_STR; switch (expr->type) { case DOTTED_PAIR: return list_string(expr, env); case STRING: return string_string(expr->u.string.ptr, expr->u.string.size); case SYMBOL: return expr->u.symbol; case NUMBER: return number_string(expr->u.number); case FUNCTION: case BUILT_IN_FUNCTION: return function_string(expr, 0, env); case MACRO: case BUILT_IN_MACRO: return function_string(expr, 1, env); default: assert(0); return NULL; } } int proper_listp (struct s_expr *expr) { while (expr && expr->type == DOTTED_PAIR) expr = expr->u.pair.rest; return expr == NULL; } struct s_expr *search_symbol(struct s_expr *list, char *symbol) { for (; list && list->type == DOTTED_PAIR; list = list->u.pair.rest) { assert(list->u.pair.first->type == SYMBOL); if (!strcmp(list->u.pair.first->u.symbol, symbol)) return list; } return NULL; } void check_fargs (struct s_expr *fargs, struct l_env *env, struct file_pos *pos) { struct s_expr *rest = fargs; if (rest && rest->type == DOTTED_PAIR && !rest->u.pair.first && rest->u.pair.rest->type == SYMBOL) return; for (; rest && rest->type == DOTTED_PAIR; rest = rest->u.pair.rest) if (!rest->u.pair.first || rest->u.pair.first->type != SYMBOL || search_symbol(fargs, rest->u.pair.first->u.symbol) != rest) error(BAD_FORMAL_ARGS_MSG, pos, s_expr_string(fargs, env)); if (rest && (rest->type != SYMBOL || search_symbol(fargs, rest->u.symbol))) error(BAD_FORMAL_ARGS_MSG, pos, s_expr_string(fargs, env)); } void check_aargs (struct s_expr *args, int count, int va, struct l_env *env, struct file_pos *pos) { struct s_expr *rest = args; for (; count && rest && rest->type == DOTTED_PAIR; count--) rest = rest->u.pair.rest; if (count || (!va && rest) || !proper_listp(rest)) error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(args, env)); } struct s_expr *eval_list (struct s_expr*, struct l_env*, struct file_pos*); struct s_expr *eval_s_expr (struct s_expr*, struct l_env*, struct file_pos*); #define ARG1(args) args->u.pair.first #define ARG2(args) args->u.pair.rest->u.pair.first #define ARG3(args) args->u.pair.rest->u.pair.rest->u.pair.first struct s_expr *trace (struct s_expr *args, struct l_env *env, struct file_pos *pos) { struct s_expr *expr; do_trace = 1; expr = eval_list(args, env, pos); do_trace = 0; return expr; } struct s_expr *quote (struct s_expr *args, struct l_env *env, struct file_pos *pos) { check_aargs(args, 1, 0, env, pos); return ARG1(args); } struct s_expr *car (struct s_expr *args, struct l_env *env, struct file_pos *pos) { check_aargs(args, 1, 0, env, pos); if (ARG1(args) && ARG1(args)->type != DOTTED_PAIR) error(NON_LIST_MSG, pos, s_expr_string(ARG1(args), env)); return ARG1(args) ? ARG1(args)->u.pair.first : NULL; } struct s_expr *cdr (struct s_expr *args, struct l_env *env, struct file_pos *pos) { check_aargs(args, 1, 0, env, pos); if (ARG1(args) && ARG1(args)->type != DOTTED_PAIR) error(NON_LIST_MSG, pos, s_expr_string(ARG1(args), env)); return ARG1(args) ? ARG1(args)->u.pair.rest : NULL; } struct s_expr *cons (struct s_expr *args, struct l_env *env, struct file_pos *pos) { struct s_expr *expr; check_aargs(args, 2, 0, env, pos); expr = alloc_mem(sizeof(*expr)); expr->type = DOTTED_PAIR; expr->u.pair.first = ARG1(args); expr->u.pair.rest = ARG2(args); return expr; } struct s_expr *if_ (struct s_expr *args, struct l_env *env, struct file_pos *pos) { check_aargs(args, 3, 0, env, pos); return eval_s_expr(ARG1(args), env, pos) ? eval_s_expr(ARG2(args), env, pos) : eval_s_expr(ARG3(args), env, pos); } struct s_expr *function (struct s_expr *args, struct l_env *env, struct file_pos *pos, int macro) { struct s_expr *expr; check_aargs(args, 1, 1, env, pos); check_fargs(ARG1(args), env, pos); expr = alloc_mem(sizeof(*expr)); expr->type = macro ? MACRO : FUNCTION; expr->u.function.expr = args; expr->u.function.env = env; return expr; } struct s_expr *lambda (struct s_expr *args, struct l_env *env, struct file_pos *pos) { return function(args, env, pos, 0); } struct s_expr *macro (struct s_expr *args, struct l_env *env, struct file_pos *pos) { return function(args, env, pos, 1); } struct s_expr *setq (struct s_expr *args, struct l_env *env, struct file_pos *pos) { struct s_expr *rest = args, *expr = NULL; struct l_env *senv; while (rest && rest->type == DOTTED_PAIR) { if (ARG1(rest) && ARG1(rest)->type == SYMBOL && rest->u.pair.rest && rest->u.pair.rest->type == DOTTED_PAIR) { expr = eval_s_expr(ARG2(rest), env, pos), senv = env; if (find_symbol(ARG1(rest)->u.symbol, &senv)) { trace_put("%s => %s [assign]", expr, ARG1(rest), env); senv->expr = expr; } else { trace_put("%s => %s [global]", expr, ARG1(rest), env); add_symbol(ARG1(rest)->u.symbol, expr, senv, 1); } } else error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(args, env)); rest = rest->u.pair.rest->u.pair.rest; } if (rest) error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(args, env)); return expr; } struct s_expr *plus (struct s_expr *args, struct l_env *env, struct file_pos *pos) { struct s_expr *rest = args; double sum = 0; while (rest && rest->type == DOTTED_PAIR && ARG1(rest)->type == NUMBER) sum += ARG1(rest)->u.number, rest = rest->u.pair.rest; if (rest) error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(args, env)); rest = alloc_mem(sizeof(*rest)); rest->type = NUMBER; rest->u.number = sum; return rest; } struct s_expr *greater (struct s_expr *args, struct l_env *env, struct file_pos *pos) { struct s_expr *rest = args, *num; double prev = DBL_MAX; while (rest && rest->type == DOTTED_PAIR) { num = eval_s_expr(ARG1(rest), env, pos); if (!num || num->type != NUMBER) error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(args, env)); if (prev - num->u.number < DBL_EPSILON) return NULL; prev = num->u.number, rest = rest->u.pair.rest; } if (rest) error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(args, env)); return true_(); } struct l_env *create_env () { struct l_env *env = NULL; env = add_built_in(1, TRACE_SYMBOL_STR, trace, env); env = add_built_in(1, QUOTE_SYMBOL_STR, quote, env); env = add_built_in(0, CAR_SYMBOL_STR, car, env); env = add_built_in(0, CDR_SYMBOL_STR, cdr, env); env = add_built_in(0, CONS_SYMBOL_STR, cons, env); env = add_built_in(1, IF_SYMBOL_STR, if_, env); env = add_built_in(1, LAMBDA_SYMBOL_STR, lambda, env); env = add_built_in(1, MACRO_SYMBOL_STR, macro, env); env = add_built_in(1, SETQ_SYMBOL_STR, setq, env); env = add_built_in(0, PLUS_SYMBOL_STR, plus, env); env = add_built_in(1, GREATER_SYMBOL_STR, greater, env); return env; } struct s_expr *map_eval (struct s_expr *list, struct l_env *env, struct file_pos *pos) { struct s_expr *expr = NULL, *rest; while (list) { if (list->type != DOTTED_PAIR) error(NON_LIST_MSG, pos, s_expr_string(list, env)); if (expr) { rest->u.pair.rest = alloc_mem(sizeof(*expr)); rest = rest->u.pair.rest; } else expr = rest = alloc_mem(sizeof(*expr)); rest->type = DOTTED_PAIR; rest->u.pair.first = eval_s_expr(list->u.pair.first, env, pos); list = list->u.pair.rest; } if (expr) rest->u.pair.rest = NULL; return expr; } struct l_env *apply_args (struct s_expr *fargs, struct s_expr *aargs, struct l_env *env, struct file_pos *pos) { struct s_expr *rest = aargs; if (!fargs || fargs->u.pair.first) while (fargs && fargs->type == DOTTED_PAIR) { if (!rest || rest->type != DOTTED_PAIR) error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(aargs, env)); assert(fargs->u.pair.first->type == SYMBOL); trace_put("%s => %s [local]", rest->u.pair.first, fargs->u.pair.first, env); env = add_symbol(fargs->u.pair.first->u.symbol, rest->u.pair.first, env, 0); fargs = fargs->u.pair.rest, rest = rest->u.pair.rest; } else fargs = fargs->u.pair.rest; if (fargs) { assert(fargs->type == SYMBOL); if (rest && !proper_listp(rest)) error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(aargs, env)); trace_put("%s => %s [local]", rest, fargs, env); env = add_symbol(fargs->u.symbol, rest, env, 0); } else if (rest) error(BAD_ACTUAL_ARGS_MSG, pos, s_expr_string(aargs, env)); return env; } struct s_expr *eval_list (struct s_expr *list, struct l_env *env, struct file_pos *pos) { struct s_expr *expr = NULL, *rest = list; for (; rest && rest->type == DOTTED_PAIR; rest = rest->u.pair.rest) expr = eval_s_expr(rest->u.pair.first, env, pos); if (rest) error(NON_LIST_MSG, pos, s_expr_string(list, env)); return expr; } struct s_expr *eval_s_expr (struct s_expr *expr, struct l_env *env, struct file_pos *pos) { struct s_expr *first, *in = expr; struct l_env *benv; trace_put("%s -> ...", in, NULL, env); if (expr) if (expr->type == SYMBOL) if (find_symbol(expr->u.symbol, &env)) expr = env->expr; else error(UNBOUND_SYMBOL_MSG, pos, expr->u.symbol); else if (expr->type == DOTTED_PAIR) { first = eval_s_expr(expr->u.pair.first, env, pos); if (!first || first->type == DOTTED_PAIR || first->type == SYMBOL || first->type == STRING || first->type == NUMBER) error(NON_FUNC_MACRO_MSG, pos, s_expr_string(first, env)); expr = first->type == FUNCTION || first->type == BUILT_IN_FUNCTION ? map_eval(expr->u.pair.rest, env, pos) : expr->u.pair.rest; if (first->type == FUNCTION || first->type == MACRO) { assert(first->u.function.expr->type == DOTTED_PAIR); benv = apply_args(first->u.function.expr->u.pair.first, expr, first->u.function.env, pos); expr = eval_list(first->u.function.expr->u.pair.rest, benv, pos); if (first->type == MACRO) { trace_put("%s ~> %s", in, expr, env); expr = eval_s_expr(expr, env, pos); } } else expr = first->u.built_in(expr, env, pos); } trace_put("%s -> %s", in, expr, env); return expr; } struct s_expr *eval_file (char *filename, struct l_env *env) { struct file_pos pos, prev_pos; struct s_expr *expr; FILE *file; int chr; file = fopen(filename, "r"); if (!file) { printf("Failed to open file '%s'\n", filename); exit(1); } pos.filename = filename, pos.line = pos.chr = 1; expr = NULL; while (1) { chr = get_significant_char(file, &pos); if (chr == EOF) break; ungetc(chr, file); pos.chr--, prev_pos = pos; expr = eval_s_expr(parse_s_expr(file, &pos), env, &prev_pos); } fclose(file); return expr; } int main (int argc, char *argv[]) { struct l_env *env; if (argc != 2) { puts("Usage: int source"); exit(1); } env = create_env(); puts(s_expr_string(eval_file(argv[1], env), env)); return 0; } 


рдореИрдВрдиреЗ рдмреБрдирд┐рдпрд╛рджреА рдФрд░ рдХрд╕реНрдЯрдо рдлрд╝рдВрдХреНрд╢рдВрд╕ рдФрд░ рдореИрдХреНрд░реЛрдЬрд╝ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдирд╛рдо рд╢реБрд░реВ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдХреНрд▓рд╛рд╕рд┐рдХ LISP рдореЗрдВ (рдФрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЖрдо рд▓рд┐рд╕реНрдк рдореЗрдВ), рдореВрд▓ рдЖрджрд┐рдо рдХреА рдХреНрд░рд┐рдпрд╛ рдореБрдЭреЗ рдереЛрдбрд╝рд╛ рдкрд░реЗрд╢рд╛рди рдХрд░рддреА рд╣реИред рдПрдХ рдУрд░, рдореИрдВ рдкрд╛рд░реНрд╕рд░ рдХреЛ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рдЙрджреНрдзрд░рдг рдФрд░ рдмреИрдХрдХреЙрдЗрди рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЙрдирдХреЗ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИ, рдХреЗрд╡рд▓ рдмреНрд░реИрдХреЗрдЯ рд╕рдВрдХреЗрддрдиред рджреВрд╕рд░реА рдУрд░, рдЙрдиреНрд╣реЛрдВрдиреЗ рд╕рдВрдХреНрд╖рд┐рдкреНрддрддрд╛ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рдкрд╛рддреНрд░реЛрдВ рдХреЗ рд╡реНрдпрд╛рдкрдХ рдЙрдкрдпреЛрдЧ рджреНрд╡рд╛рд░рд╛ рдЕрддреНрдпрдзрд┐рдХ рдмреНрд░реИрдХреЗрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдХреНрд╖рддрд┐рдкреВрд░реНрддрд┐ рдХрд░рдиреЗ рдХреА рдорд╛рдВрдЧ рдХреАред рдпрд╣ рдХреБрдЫ рдмрд╣реБрдд рд╡рд┐рд╡рд╛рджрд╛рд╕реНрдкрдж рдирд┐рд░реНрдгрдп рдкреНрд░рддреАрдд рд╣реЛрдЧрд╛ред

рдореИрдВрдиреЗ рдЙрдирдХреА рд╕рд╛рд╣рдЪрд░реНрдп рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдирд╛рдореЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА:

рддрджрдиреБрд╕рд╛рд░, рд╡реНрдпреБрддреНрдкрдиреНрди рдлрд╝рдВрдХреНрд╢рдВрд╕ рдФрд░ рдореИрдХреНрд░реЛрдЬрд╝ рдХреЗ рдирд╛рдо рдореЛрдЯреЗ рддреМрд░ рдкрд░ рдореВрд▓ рд▓реЛрдЧреЛрдВ рдХреЗ рдирд╛рдореЛрдВ рд╕реЗ рдмрдиреЗ рд╣реИрдВ:

рдЕрдм рд╡реНрдпреБрддреНрдкрдиреНрди рдкрд░рд┐рднрд╛рд╖рд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдмреБрдирд┐рдпрд╛рджреА рд╕рдВрдХреНрд╖рд┐рдкреНрддрд╛рдХреНрд╖рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:

 (= @% (! (list) (@ (% list)))) ; cadr (= %% (! (list) (% (% list)))) ; cddr (= ^^ (! (_ . elts) elts)) ; list (= ## (# (name fargs . body) ; defmacro (^^ = name (^ # (^ fargs body))))) (## !! (name fargs . body) ; defun (^^ = name (^ ! (^ fargs body)))) 

рдФрдкрдЪрд╛рд░рд┐рдХ рддрд░реНрдХреЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рдбреЙрдЯ рдиреЛрдЯреЗрд╢рди рдкрд░ рдзреНрдпрд╛рди рджреЗрдВред рдбреЙрдЯ рдХреЗ рдмрд╛рдж рдХрд╛ рдкреНрд░рддреАрдХ рд╢реЗрд╖ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдХреИрдкреНрдЪрд░ рдХрд░рддрд╛ рд╣реИред рдорд╛рдорд▓рд╛ рдЬрдм рд╕рднреА рддрд░реНрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣реЛрддреЗ рд╣реИрдВ, рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕рдВрдХреЗрддрди рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: (_ред рдмрд╛рдХреА-рдЖрд░реНрдЧ)ред рдЕрдЧрд▓рд╛, рдПрдХ рдХреНрд▓рд╛рд╕рд┐рдХ рдорд╛рдирдЪрд┐рддреНрд░ рдФрд░ рджреЛ рдпреБрдЧреНрдорд┐рдд рд╕реВрдЪреА рд╡рд┐рднрд╛рдЬрди рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:

 (!! map (func list) (? list (^ (func (@ list)) (map func (% list))) _)) (!! pairs1 (list) ; (abcd) -> ((ab) (bc) (cd)) (? (% list) (^ (^^ (@ list) (@% list)) (pairs1 (% list))) _)) (!! pairs2 (list) ; (abcd) -> ((ab) (cd)) (? list (^ (^^ (@ list) (@% list)) (pairs2 (%% list))) _)) 

рд╣рдо рджреЛ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:

 (## : (name value . body) ; simplified let (^^ (^ ! (^ (^^ name) body)) value)) (## :: (vars . body) ; let without redundant braces (= vars (pairs2 vars)) (^ (^ ! (^ (map @ vars) body)) (map @% vars))) 

рдХреНрд▓рд╛рд╕рд┐рдХ рд░рд┐рд╡рд░реНрд╕ рдФрд░ рдмрд╛рдПрдВ рдХрдирд╡рд▓реНрд╢рдирд╢рди:
 (!! reverse (list) (: reverse+ _ (!! reverse+ (list rlist) (? list (reverse+ (% list) (^ (@ list) rlist)) rlist)) (reverse+ list _))) (!! fold (list func last) ; (fold (' (ab)) fl) <=> (fa (fbl)) (? list (func (@ list) (fold (% list) func last)) last)) 

рдЕрдм рдЕрдЧрд░ рдЖрдзрд╛рд░рд┐рдд рддрд╛рд░реНрдХрд┐рдХ рдСрдкрд░реЗрдЯрд░реЛрдВ:
 (= t (' t)) ; true constant (!! ~ (bool) (? bool _ t)) ; not (## & (_ . bools) ; and (: and (! (bool1 bool2) (^^ ? bool1 (^^ ? bool2 t _) _)) (fold bools and t))) (## | (_ . bools) ; or (: or (! (bool1 bool2) (^^ ? bool1 t (^^ ? bool2 t _))) (fold bools or _))) 

рдФрд░ рдЕрдВрдд рдореЗрдВ, рдмрд┐рд▓реНрдЯ-рдЗрди> (рдЕрдзрд┐рдХ рд╕реЗ рдЕрдзрд┐рдХ) рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рддреБрд▓рдирд╛ рдСрдкрд░реЗрдЯрд░реЛрдВ:
 (: defcmp (! (cmp) (# (_ . nums) (: cmp+ (! (pair bool) (^^ & (cmp (@ pair) (@% pair)) bool)) (fold (pairs1 nums) cmp+ t)))) (= == (defcmp (! (num1 num2) (^^ & (^^ ~ (^^ > num1 num2)) (^^ ~ (^^ > num2 num1)))))) (= >= (defcmp (! (num1 num2) (^^ ~ (^^ > num2 num1)))))) (## < (_ . nums) (^ > (reverse nums))) (## <= (_ . nums) (^ >= (reverse nums))) 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХрд╛ рдЕрдВрддрд┐рдо рдЦрдВрдб рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдПрдХ рдмрдВрдж рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред

рдкреВрд░реНрдг lib.l рдкрд░реАрдХреНрд╖рдг
 ;| Formal argument list notation: ([{arg1 [arg2 [arg3 ...]] | _} [. args]]) Number notation: ${double | ooctal | hhex} ; $4 $-2.2e3 $o376 $h7EF Built-in symbols: _ ; nil Built-in functions: @ (list) ; car % (list) ; cdr ^ (first rest) ; cons + (_ . nums) Built-in macros: trace (_ . body) ' (expr) ? (cond texpr fexpr) ; if with mandatory fexpr ! (args . body) ; lambda # (args . body) ; creates anonymous macro > (_ . nums) |; (= @% (! (list) (@ (% list)))) ; cadr (= %% (! (list) (% (% list)))) ; cddr (= ^^ (! (_ . elts) elts)) ; list (= ## (# (name fargs . body) ; defmacro (^^ = name (^ # (^ fargs body))))) (## !! (name fargs . body) ; defun (^^ = name (^ ! (^ fargs body)))) (!! map (func list) (? list (^ (func (@ list)) (map func (% list))) _)) (!! pairs1 (list) ; (abcd) -> ((ab) (bc) (cd)) (? (% list) (^ (^^ (@ list) (@% list)) (pairs1 (% list))) _)) (!! pairs2 (list) ; (abcd) -> ((ab) (cd)) (? list (^ (^^ (@ list) (@% list)) (pairs2 (%% list))) _)) (## : (name value . body) ; simplified let (^^ (^ ! (^ (^^ name) body)) value)) (## :: (vars . body) ; let without redundant braces (= vars (pairs2 vars)) (^ (^ ! (^ (map @ vars) body)) (map @% vars))) (!! reverse (list) (: reverse+ _ (!! reverse+ (list rlist) (? list (reverse+ (% list) (^ (@ list) rlist)) rlist)) (reverse+ list _))) (!! fold (list func last) ; (fold (' (ab)) fl) <=> (fa (fbl)) (? list (func (@ list) (fold (% list) func last)) last)) (= t (' t)) ; true constant (!! ~ (bool) (? bool _ t)) ; not (## & (_ . bools) ; and (: and (! (bool1 bool2) (^^ ? bool1 (^^ ? bool2 t _) _)) (fold bools and t))) (## | (_ . bools) ; or (: or (! (bool1 bool2) (^^ ? bool1 t (^^ ? bool2 t _))) (fold bools or _))) (: defcmp (! (cmp) (# (_ . nums) (: cmp+ (! (pair bool) (^^ & (cmp (@ pair) (@% pair)) bool)) (fold (pairs1 nums) cmp+ t)))) (= == (defcmp (! (num1 num2) (^^ & (^^ ~ (^^ > num1 num2)) (^^ ~ (^^ > num2 num1)))))) (= >= (defcmp (! (num1 num2) (^^ ~ (^^ > num2 num1)))))) (## < (_ . nums) (^ > (reverse nums))) (## <= (_ . nums) (^ >= (reverse nums))) 


рддреЛ, рдЗрдВрдЯрд░рдкреНрд░реЗрдЯрд░ рдФрд░ рдЕрдзрд┐рдХрд╛рдВрд╢ рдкреНрд░рд╛рдЗрдореЗрдЯрд░реАрдЬ рдбреАрдПрд╕рдПрд▓ рдЕрд╕реЗрдВрдмрд▓рд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВред рдореИрдВ рдХреЛрд╢рд┐рд╢ рдХрд░реВрдБрдЧрд╛ ...

Source: https://habr.com/ru/post/In150805/


All Articles