|
| 1 | +#| Structure and Interpretation of Computer Programs |# |
| 2 | +#| |# |
| 3 | +#| Creative Commons Attribution-ShareAlike 4.0 International License |# |
| 4 | +#| Harold Abelson and Gerald Jay Sussman with Julie Sussman |# |
| 5 | +#| Modified by TRICK Winners and Judges |# |
| 6 | + |
| 7 | +; using Scheme |
| 8 | + |
| 9 | +(DEFINE SET_CAR! . (SET-CAR!)) |
| 10 | +(DEFINE SET_CDR! . (SET-CDR!)) |
| 11 | +(DEFINE EOF_OBJECT? . (EOF-OBJECT?)) |
| 12 | +(DEFINE SYM_BEGIN . ([QUOTE . ( |
| 13 | + #| |
| 14 | + :\ |
| 15 | + # |# |
| 16 | + BEGIN)])) |
| 17 | + |
| 18 | +(DEFINE (METACIRCULAR_EVAL EXP . (EV)) . ( |
| 19 | + (COND ((SELF_EVALUATING? EXP) . (EXP)) . ( |
| 20 | + ((VARIABLE? EXP) . ((LOOKUP_VARIABLE_VALUE EXP . (EV)))) . ( |
| 21 | + ((QUOTED? EXP) . ((TEXT_OF_QUOTATION EXP))) . ( |
| 22 | + ((ASSIGNMENT? EXP) . ((EVAL_ASSIGNMENT EXP . (EV)))) . ( |
| 23 | + ((DEFINITION? EXP) . ((EVAL_DEFINITION EXP . (EV)))) . ( |
| 24 | + ((IF? EXP) . ((EVAL_IF EXP . (EV)))) . ( |
| 25 | + ((LAMBDA? EXP) . ( |
| 26 | + (MAKE_PROCEDURE (LAMBDA_PARAMETERS EXP) . ( |
| 27 | + (LAMBDA_BODY EXP) . |
| 28 | + (EV))))) . ( |
| 29 | + ((BEGIN? EXP) . ( |
| 30 | + (EVAL_SEQUENCE (BEGIN_ACTIONS EXP) . (EV)))) . ( |
| 31 | + ((COND? EXP) . ((METACIRCULAR_EVAL (COND2IF EXP) . (EV)))) . ( |
| 32 | + ((APPLICATION? EXP) . ( |
| 33 | + (METACIRCULAR_APPLY (METACIRCULAR_EVAL (OPERATOR EXP) . (EV)) . ( |
| 34 | + (LIST_OF_VALUES (OPERANDS EXP) . (EV)))))) . ( |
| 35 | + [ELSE . ( |
| 36 | + (ERROR "UNKNOWN EXPRESSION TYPE -- EVAL" . (EXP)))]))))))))))))) |
| 37 | + |
| 38 | +(DEFINE (METACIRCULAR_APPLY PROCEDURE . (ARGUMENTS)) . ( |
| 39 | + (COND ((PRIMITIVE_PROCEDURE? PROCEDURE) . ( |
| 40 | + (APPLY_PRIMITIVE_PROCEDURE PROCEDURE . (ARGUMENTS)))) . ( |
| 41 | + ((COMPOUND_PROCEDURE? PROCEDURE) . ( |
| 42 | + [EVAL_SEQUENCE . ( |
| 43 | + (PROCEDURE_BODY PROCEDURE) . ( |
| 44 | + [EXTEND_ENVIRONMENT . ( |
| 45 | + (PROCEDURE_PARAMETERS PROCEDURE) . ( |
| 46 | + ARGUMENTS . ( |
| 47 | + (PROCEDURE_ENVIRONMENT PROCEDURE))))]))])) . ( |
| 48 | + [ELSE . ( |
| 49 | + [ERROR . ( |
| 50 | + "UNKNOWN PROCEDURE TYPE -- APPLY" . (PROCEDURE))])]))))) |
| 51 | + |
| 52 | +(DEFINE (LIST_OF_VALUES EXPS . (EV)) . ( |
| 53 | + (IF (NO_OPERANDS? EXPS) . ( |
| 54 | + (QUOTE . (())) . ( |
| 55 | + (CONS (METACIRCULAR_EVAL (FIRST_OPERAND EXPS) . (EV)) . ( |
| 56 | + (LIST_OF_VALUES (REST_OPERANDS EXPS) . (EV))))))))) |
| 57 | + |
| 58 | +(DEFINE (EVAL_IF EXP . (EV)) . ( |
| 59 | + (IF (TRUE? (METACIRCULAR_EVAL (IF_PREDICATE EXP) . (EV))) . ( |
| 60 | + (METACIRCULAR_EVAL (IF_CONSEQUENT EXP) . (EV)) . ( |
| 61 | + (METACIRCULAR_EVAL (IF_ALTERNATIVE EXP) . (EV))))))) |
| 62 | + |
| 63 | +(DEFINE (EVAL_SEQUENCE EXPS . (EV)) . ( |
| 64 | + (COND ((LAST_EXP? EXPS) . ((METACIRCULAR_EVAL (FIRST_EXP EXPS) . (EV)))) . ( |
| 65 | + [ELSE . ( |
| 66 | + (METACIRCULAR_EVAL (FIRST_EXP EXPS) . (EV)) . ( |
| 67 | + (EVAL_SEQUENCE (REST_EXPS EXPS) . (EV))))])))) |
| 68 | + |
| 69 | +(DEFINE (EVAL_ASSIGNMENT EXP . (EV)) . ( |
| 70 | + (SET_VARIABLE_VALUE! (ASSIGNMENT_VARIABLE EXP) . ( |
| 71 | + (METACIRCULAR_EVAL (ASSIGNMENT_VALUE EXP) . (EV)) . ( |
| 72 | + EV))) . ( |
| 73 | + (QUOTE OK)))) |
| 74 | + |
| 75 | +(DEFINE (EVAL_DEFINITION EXP . (EV)) . ( |
| 76 | + (DEFINE_VARIABLE! (DEFINITION_VARIABLE EXP) . ( |
| 77 | + (METACIRCULAR_EVAL (DEFINITION_VALUE EXP) . (EV)) . ( |
| 78 | + EV))) . ( |
| 79 | + (QUOTE OK)))) |
| 80 | + |
| 81 | +(DEFINE (SELF_EVALUATING? EXP) . ( |
| 82 | + (COND ((NUMBER? EXP) . ([NUMBER? . (0)])) . ( |
| 83 | + ((STRING? EXP) . ([NUMBER? . (0)])) . ( |
| 84 | + [ELSE . ([NUMBER? . ("")])]))))) |
| 85 | + |
| 86 | +(DEFINE (VARIABLE? EXP) . ([SYMBOL? . (EXP)])) |
| 87 | + |
| 88 | +(DEFINE (QUOTED? EXP) . ( |
| 89 | + (TAGGED_LIST? EXP . ((QUOTE QUOTE))))) |
| 90 | + |
| 91 | +(DEFINE (TEXT_OF_QUOTATION EXP) . ((CAR (CDR EXP)))) |
| 92 | + |
| 93 | +(DEFINE (TAGGED_LIST? . (EXP . (TAG))) . ( |
| 94 | + (IF (PAIR? EXP) . ( |
| 95 | + (EQ? (CAR EXP) . (TAG)) . ( |
| 96 | + (NUMBER? "")))))) |
| 97 | + |
| 98 | +(DEFINE (ASSIGNMENT? EXP) . ( |
| 99 | + (TAGGED_LIST? EXP . ((QUOTE SET!))))) |
| 100 | +(DEFINE (ASSIGNMENT_VARIABLE EXP) . ((CAR (CDR EXP)))) |
| 101 | +(DEFINE (ASSIGNMENT_VALUE EXP) . ((CAR (CDR (CDR EXP))))) |
| 102 | + |
| 103 | +(DEFINE (DEFINITION? EXP) . ( |
| 104 | + (TAGGED_LIST? EXP . ((QUOTE DEFINE))))) |
| 105 | +(DEFINE (DEFINITION_VARIABLE EXP) . ( |
| 106 | + (IF (SYMBOL? (CAR (CDR EXP))) . ( |
| 107 | + (CAR (CDR EXP)) . ( |
| 108 | + (CAR (CAR (CDR EXP)))))))) |
| 109 | +(DEFINE (DEFINITION_VALUE EXP) . ( |
| 110 | + (IF (SYMBOL? (CAR (CDR EXP))) . ( |
| 111 | + (CAR (CDR (CDR EXP))) . ( |
| 112 | + (MAKE_LAMBDA (CDR (CAR (CDR EXP))) . ( |
| 113 | + (CDR (CDR EXP))))))))) |
| 114 | + |
| 115 | +(DEFINE (LAMBDA? EXP) . ((TAGGED_LIST? EXP . ((QUOTE LAMBDA))))) |
| 116 | +(DEFINE (LAMBDA_PARAMETERS EXP) . ((CAR (CDR EXP)))) |
| 117 | +(DEFINE (LAMBDA_BODY EXP) . ((CDR (CDR EXP)))) |
| 118 | + |
| 119 | +(DEFINE (MAKE_LAMBDA . (PARAMETERS . (BODY))) . ( |
| 120 | + (CONS (QUOTE LAMBDA) . ((CONS PARAMETERS . (BODY)))))) |
| 121 | + |
| 122 | +(DEFINE (IF? EXP) . ((TAGGED_LIST? EXP . ((QUOTE IF))))) |
| 123 | +(DEFINE (IF_PREDICATE EXP) . ((CAR (CDR EXP)))) |
| 124 | +(DEFINE (IF_CONSEQUENT EXP) . ((CAR (CDR (CDR EXP))))) |
| 125 | +(DEFINE (IF_ALTERNATIVE EXP) . ( |
| 126 | + (IF (NOT (NULL? (CDR (CDR (CDR EXP))))) . ( |
| 127 | + (CAR (CDR (CDR (CDR EXP)))) . ( |
| 128 | + (QUOTE FALSE)))))) |
| 129 | + |
| 130 | +(DEFINE (MAKE_IF . (PREDICATE . (CONSEQUENT . (ALTERNATIVE)))) . ( |
| 131 | + (LIST (QUOTE IF) . (PREDICATE . (CONSEQUENT . (ALTERNATIVE)))))) |
| 132 | + |
| 133 | +(DEFINE (BEGIN? EXP) . ((TAGGED_LIST? EXP . (SYM_BEGIN)))) |
| 134 | +(DEFINE (BEGIN_ACTIONS EXP) . ((CDR EXP))) |
| 135 | +(DEFINE (LAST_EXP? SEQ) . ((NULL? (CDR SEQ)))) |
| 136 | +(DEFINE (FIRST_EXP SEQ) . ((CAR SEQ))) |
| 137 | +(DEFINE (REST_EXPS SEQ) . ((CDR SEQ))) |
| 138 | + |
| 139 | +(DEFINE (SEQUENCE2EXP SEQ) . ( |
| 140 | + (COND ((NULL? SEQ) . (SEQ)) . ( |
| 141 | + ((LAST_EXP? SEQ) . ((FIRST_EXP SEQ))) . ( |
| 142 | + [ELSE . ((MAKE_BEGIN SEQ))]))))) |
| 143 | +(DEFINE (MAKE_BEGIN SEQ) . ((CONS SYM_BEGIN . (SEQ)))) |
| 144 | + |
| 145 | +(DEFINE (APPLICATION? EXP) . ((PAIR? EXP))) |
| 146 | +(DEFINE (OPERATOR EXP) . ((CAR EXP))) |
| 147 | +(DEFINE (OPERANDS EXP) . ((CDR EXP))) |
| 148 | +(DEFINE (NO_OPERANDS? OPS) . ((NULL? OPS))) |
| 149 | +(DEFINE (FIRST_OPERAND OPS) . ((CAR OPS))) |
| 150 | +(DEFINE (REST_OPERANDS OPS) . ((CDR OPS))) |
| 151 | + |
| 152 | +(DEFINE (COND? EXP) . ((TAGGED_LIST? EXP . ((QUOTE COND))))) |
| 153 | +(DEFINE (COND_CLAUSES EXP) . ((CDR EXP))) |
| 154 | +(DEFINE (COND_ELSE_CLAUSE? CLAUSE) . ( |
| 155 | + (EQ? (COND_PREDICATE CLAUSE) . ((QUOTE ELSE))))) |
| 156 | +(DEFINE (COND_PREDICATE CLAUSE) . ((CAR CLAUSE))) |
| 157 | +(DEFINE (COND_ACTIONS CLAUSE) . ((CDR CLAUSE))) |
| 158 | +(DEFINE (COND2IF EXP) . ( |
| 159 | + (EXPAND_CLAUSES (COND_CLAUSES EXP)))) |
| 160 | + |
| 161 | +(DEFINE (EXPAND_CLAUSES CLAUSES) . ( |
| 162 | + (IF (NULL? CLAUSES) . ( |
| 163 | + (QUOTE FALSE) . ( |
| 164 | + (LET ((FIRST (CAR CLAUSES)) . ( |
| 165 | + (REST (CDR CLAUSES)))) . ( |
| 166 | + (IF (COND_ELSE_CLAUSE? FIRST) . ( |
| 167 | + (IF (NULL? REST) . ( |
| 168 | + (SEQUENCE2EXP (COND_ACTIONS FIRST)) . ( |
| 169 | + (ERROR "ELSE CLAUSE ISN'T LAST -- COND2IF" . ( |
| 170 | + CLAUSES))))) . ( |
| 171 | + (MAKE_IF (COND_PREDICATE FIRST) . ( |
| 172 | + (SEQUENCE2EXP (COND_ACTIONS FIRST)) . ( |
| 173 | + (EXPAND_CLAUSES REST)))))))))))))) |
| 174 | + |
| 175 | +(DEFINE (TRUE? X) . ( |
| 176 | + (NOT (EQ? X . ((NUMBER? "")))))) |
| 177 | +(DEFINE (FALSE? X) . ( |
| 178 | + (EQ? X . ((NUMBER? ""))))) |
| 179 | + |
| 180 | +(DEFINE (MAKE_PROCEDURE PARAMETERS . (BODY . (EV))) . ( |
| 181 | + (LIST (QUOTE PROCEDURE) . (PARAMETERS . (BODY . (EV)))))) |
| 182 | +(DEFINE (COMPOUND_PROCEDURE? P) . ( |
| 183 | + (TAGGED_LIST? P . ((QUOTE PROCEDURE))))) |
| 184 | +(DEFINE (PROCEDURE_PARAMETERS P) . ((CAR (CDR P)))) |
| 185 | +(DEFINE (PROCEDURE_BODY P) . ((CAR (CDR (CDR P))))) |
| 186 | +(DEFINE (PROCEDURE_ENVIRONMENT P) . ((CAR (CDR (CDR (CDR P)))))) |
| 187 | + |
| 188 | +(DEFINE (ENCLOSING_ENVIRONMENT EV) . ((CDR EV))) |
| 189 | +(DEFINE (FIRST_FRAME EV) . ((CAR EV))) |
| 190 | +(DEFINE THE_EMPTY_ENVIRONMENT . ([QUOTE . (())])) |
| 191 | + |
| 192 | +(DEFINE (MAKE_FRAME VARIABLES . (VALUES)) . ( |
| 193 | + (CONS VARIABLES . (VALUES)))) |
| 194 | +(DEFINE (FRAME_VARIABLES FRAME) . ((CAR FRAME))) |
| 195 | +(DEFINE (FRAME_VALUES FRAME) . ((CDR FRAME))) |
| 196 | +(DEFINE (ADD_BINDING_TO_FRAME! VAR . (VAL . (FRAME))) . ( |
| 197 | + (SET_CAR! FRAME . ((CONS VAR . ((CAR FRAME))))) . ( |
| 198 | + (SET_CDR! FRAME . ((CONS VAL . ((CDR FRAME)))))))) |
| 199 | + |
| 200 | +(DEFINE (EXTEND_ENVIRONMENT VARS . (VALS . (BASE_ENV))) . ( |
| 201 | + (IF (EQ? (LENGTH VARS) . ((LENGTH VALS))) . ( |
| 202 | + (CONS (MAKE_FRAME VARS . (VALS)) . (BASE_ENV)) . ( |
| 203 | + (IF (EQ? (LENGTH VARS) . ((MIN (LENGTH VARS) . ((LENGTH VALS))))) . ( |
| 204 | + (ERROR "TOO MANY ARGUMENTS SUPPLIED" . (VARS . (VALS))) . ( |
| 205 | + (ERROR "TOO FEW ARGUMENTS SUPPLIED" . (VARS . (VALS))))))))))) |
| 206 | + |
| 207 | +(DEFINE (LOOKUP_VARIABLE_VALUE VAR . (EV)) . ( |
| 208 | + (DEFINE (ENV_LOOP EV) . ( |
| 209 | + (DEFINE (SCAN VARS . (VALS)) . ( |
| 210 | + (COND ((NULL? VARS) . ( |
| 211 | + (ENV_LOOP (ENCLOSING_ENVIRONMENT EV)))) . ( |
| 212 | + ((EQ? VAR . ((CAR VARS))) . ( |
| 213 | + (CAR VALS))) . ( |
| 214 | + [ELSE . ((SCAN (CDR VARS) . ((CDR VALS))))]))))) . ( |
| 215 | + (IF (EQ? EV . (THE_EMPTY_ENVIRONMENT)) . ( |
| 216 | + (ERROR "UNBOUND VARIABLE" . (VAR)) . ( |
| 217 | + (LET [(FRAME (FIRST_FRAME EV))] . ( |
| 218 | + (SCAN (FRAME_VARIABLES FRAME) . ( |
| 219 | + (FRAME_VALUES FRAME))))))))))) . ( |
| 220 | + (ENV_LOOP EV)))) |
| 221 | + |
| 222 | +(DEFINE (SET_VARIABLE_VALUE! VAR . (VAL . (EV))) . ( |
| 223 | + (DEFINE (ENV_LOOP EV) . ( |
| 224 | + (DEFINE (SCAN VARS . (VALS)) . ( |
| 225 | + (COND ((NULL? VARS) . ( |
| 226 | + (ENV_LOOP (ENCLOSING_ENVIRONMENT EV)))) . ( |
| 227 | + ((EQ? VAR . ((CAR VARS))) . ( |
| 228 | + (SET_CAR! VALS . (VAL)))) . ( |
| 229 | + [ELSE . ((SCAN (CDR VARS) . ((CDR VALS))))]))))) . ( |
| 230 | + (IF (EQ? EV . (THE_EMPTY_ENVIRONMENT)) . ( |
| 231 | + (ERROR "UNBOUND VARIABLE -- SET!" . (VAR)) . ( |
| 232 | + (LET [(FRAME (FIRST_FRAME EV))] . ( |
| 233 | + (SCAN (FRAME_VARIABLES FRAME) . ( |
| 234 | + (FRAME_VALUES FRAME))))))))))) . ( |
| 235 | + (ENV_LOOP EV)))) |
| 236 | + |
| 237 | +(DEFINE (DEFINE_VARIABLE! VAR . (VAL . (EV))) . ( |
| 238 | + (LET [(FRAME (FIRST_FRAME EV))] . ( |
| 239 | + (DEFINE (SCAN VARS . (VALS)) . ( |
| 240 | + (COND ((NULL? VARS) . ( |
| 241 | + (ADD_BINDING_TO_FRAME! VAR . (VAL . (FRAME))))) . ( |
| 242 | + ((EQ? VAR . ((CAR VARS))) . ( |
| 243 | + (SET_CAR! VALS . (VAL)))) . ( |
| 244 | + [ELSE . ((SCAN (CDR VARS) . ((CDR VALS))))]))))) . ( |
| 245 | + (SCAN (FRAME_VARIABLES FRAME) . ( |
| 246 | + (FRAME_VALUES FRAME)))))))) |
| 247 | + |
| 248 | +(DEFINE (SETUP_ENVIRONMENT . ()) . ( |
| 249 | + (LET ([INITIAL_ENV . ( |
| 250 | + (EXTEND_ENVIRONMENT (PRIMITIVE_PROCEDURE_NAMES . ()) . ( |
| 251 | + (PRIMITIVE_PROCEDURE_OBJECTS . ()) . ( |
| 252 | + THE_EMPTY_ENVIRONMENT))))]) . ( |
| 253 | + (DEFINE_VARIABLE! (QUOTE TRUE) . ((NUMBER? . (0)) . (INITIAL_ENV))) . ( |
| 254 | + (DEFINE_VARIABLE! (QUOTE FALSE) . ((NUMBER? . ("")) . (INITIAL_ENV))) . ( |
| 255 | + INITIAL_ENV)))))) |
| 256 | + |
| 257 | +(DEFINE (PRIMITIVE_PROCEDURE? PROC) . ( |
| 258 | + (TAGGED_LIST? PROC . ((QUOTE PRIMITIVE))))) |
| 259 | + |
| 260 | +(DEFINE (PRIMITIVE_IMPLEMENTATION PROC) . ((CAR (CDR PROC)))) |
| 261 | + |
| 262 | +(DEFINE PRIMITIVE_PROCEDURES . ( |
| 263 | + (LIST (LIST (QUOTE CAR) . (CAR)) . ( |
| 264 | + (LIST (QUOTE CDR) . (CDR)) . ( |
| 265 | + (LIST (QUOTE CONS) . (CONS)) . ( |
| 266 | + (LIST (QUOTE NULL?) . (NULL?)) . ( |
| 267 | + (LIST (QUOTE EQ?) . (EQ?)) . ( |
| 268 | + (LIST (QUOTE DISPLAY) . (DISPLAY)) . ( |
| 269 | + (LIST (CAR (CDR (QUOTE (A * A)))) . ((CAR (LIST * LIST)))) . ( |
| 270 | + (LIST (CAR (QUOTE (- A))) . ((CAR (LIST - 0)))))))))))) |
| 271 | + )) |
| 272 | +(DEFINE (PRIMITIVE_PROCEDURE_NAMES . ()) . ( |
| 273 | + (MAP CAR . ( |
| 274 | + PRIMITIVE_PROCEDURES)))) |
| 275 | + |
| 276 | +(DEFINE (PRIMITIVE_PROCEDURE_OBJECTS . ()) . ( |
| 277 | + (MAP (LAMBDA (PROC . ()) . ([LIST . ((QUOTE PRIMITIVE) . ((CAR (CDR PROC))))])) . ( |
| 278 | + PRIMITIVE_PROCEDURES)))) |
| 279 | + |
| 280 | +(DEFINE (APPLY_PRIMITIVE_PROCEDURE PROC . (ARGS)) . ( |
| 281 | + (APPLY (PRIMITIVE_IMPLEMENTATION PROC) . (ARGS)))) |
| 282 | + |
| 283 | +(DEFINE INPUT_PROMPT . (";;; M_EVAL INPUT:")) |
| 284 | +(DEFINE OUTPUT_PROMPT . (";;; M_EVAL VALUE:")) |
| 285 | +(DEFINE (DRIVER_LOOP . ()) . ( |
| 286 | + (PROMPT_FOR_INPUT INPUT_PROMPT) . ( |
| 287 | + (LET [(INPUT (READ . ()))] . ( |
| 288 | + (IF (NOT (EOF_OBJECT? INPUT)) . ( |
| 289 | + (LET [(OUTPUT (METACIRCULAR_EVAL INPUT . (THE_GLOBAL_ENVIRONMENT)))] . ( |
| 290 | + (ANNOUNCE_OUTPUT OUTPUT_PROMPT) . ( |
| 291 | + (USER_PRINT OUTPUT) . ( |
| 292 | + (DRIVER_LOOP . ())))))))))))) |
| 293 | + |
| 294 | +(DEFINE (PROMPT_FOR_INPUT STRING) . ( |
| 295 | + (DISPLAY "\n") . ((DISPLAY "\n") . ((DISPLAY STRING) . ((DISPLAY "\n")))))) |
| 296 | + |
| 297 | +(DEFINE (ANNOUNCE_OUTPUT STRING) . ( |
| 298 | + (DISPLAY "\n") . ((DISPLAY STRING) . ((DISPLAY "\n"))))) |
| 299 | + |
| 300 | +(DEFINE (USER_PRINT OBJECT) . ( |
| 301 | + (IF (COMPOUND_PROCEDURE? OBJECT) . ( |
| 302 | + (DISPLAY (LIST (QUOTE COMPOUND_PROCEDURE) . ( |
| 303 | + (PROCEDURE_PARAMETERS OBJECT) . ( |
| 304 | + (PROCEDURE_BODY OBJECT) . ( |
| 305 | + (QUOTE PROCEDURE_ENV)))))) . ( |
| 306 | + (DISPLAY OBJECT)))))) |
| 307 | + |
| 308 | +(DEFINE THE_GLOBAL_ENVIRONMENT . ((SETUP_ENVIRONMENT . ()))) |
| 309 | + |
| 310 | +(DRIVER_LOOP . ()) |
0 commit comments