|
30 | 30 | ((assignment? exp) (eval-assignment exp env))
|
31 | 31 | ((definition? exp) (eval-definition exp env))
|
32 | 32 | ((if? exp) (eval-if exp env))
|
33 |
| - ((lambda? exp) |
| 33 | + ((lambda? exp) ; evaluated when define procedure |
34 | 34 | (make-procedure (lambda-params exp)
|
35 | 35 | (lambda-body exp)
|
36 | 36 | env))
|
|
43 | 43 | ((letstar? exp) (seck-eval (let*->nested-let exp) env))
|
44 | 44 | ((for? exp) (seck-eval (for->let exp) env))
|
45 | 45 | ((application? exp)
|
| 46 | + ; evaluated when call procedure |
46 | 47 | (seck-apply (seck-eval (operator exp) env)
|
47 | 48 | (list-of-values (operand exp) env)))
|
48 | 49 | (else
|
|
54 | 55 | (eq? (car exp) tag)
|
55 | 56 | #f))
|
56 | 57 |
|
| 58 | +(define (unassigned? value) |
| 59 | + (eq? value '*unassigned*)) |
| 60 | + |
57 | 61 | ; @(environment)
|
58 | 62 |
|
59 | 63 | (define (make-env base)
|
|
65 | 69 | (let ((ret (dict-lookup (cur-env-var-dict) var)))
|
66 | 70 | (let ((found (car ret))
|
67 | 71 | (value (cadr ret)))
|
68 |
| - (cond (found value) |
| 72 | + (cond ((and found |
| 73 | + (not (unassigned? value))) |
| 74 | + value) |
| 75 | + (found |
| 76 | + (error 'lookup "variabled looked up is unassigned")) |
69 | 77 | ((empty-env? (base-env))
|
70 | 78 | (error 'lookup "variable not defined" var))
|
71 | 79 | (else
|
|
249 | 257 | (seck-eval (first-exp exps) env)
|
250 | 258 | (eval-sequence (rest-exps exps) env))
|
251 | 259 | ))
|
| 260 | +; proc-body is a sequence of expressions to be evaluated |
| 261 | +(define (scan-out-defines proc-body) |
| 262 | + (let ((definitions (filter definition? proc-body)) |
| 263 | + (non-definitions (filter (compose not definition?) |
| 264 | + proc-body))) |
| 265 | + (make-let (map (lambda (exp) |
| 266 | + (list (definition-var exp) |
| 267 | + '*unassigned*)) |
| 268 | + definitions) |
| 269 | + (append (map (lambda (exp) |
| 270 | + (list 'set! |
| 271 | + (definition-var exp) |
| 272 | + (definition-value exp))) |
| 273 | + definitions) |
| 274 | + non-definitions)))) |
252 | 275 |
|
253 | 276 | ; @(assignment)
|
254 | 277 |
|
|
465 | 488 | (define (for-body exp) (cddddr exp))
|
466 | 489 |
|
467 | 490 |
|
| 491 | + |
468 | 492 | ; @(application)
|
469 | 493 | (define application? pair?)
|
470 | 494 | (define (operator exp) (car exp))
|
|
486 | 510 | (extend-environment
|
487 | 511 | (procedure-parameters procedure)
|
488 | 512 | arguments
|
| 513 | + ; Here, we eval the expression in |
| 514 | + ; a new env which extends procedure env(the |
| 515 | + ; env in which procedure is defined). This |
| 516 | + ; ensures lexical scoping. |
| 517 | + ; If we evaluate the procedure bodyin |
| 518 | + ; the env that seck-apply is called, then |
| 519 | + ; it will be dynamic scoping. |
489 | 520 | (procedure-env procedure))))
|
490 | 521 | (else
|
491 | 522 | (error
|
492 | 523 | 'seck-apply
|
493 | 524 | "Unknown procedure type" procedure))))
|
494 | 525 |
|
| 526 | + |
495 | 527 | ; @(global env)
|
496 | 528 | (define (setup-environment)
|
497 | 529 | (extend-environment (primitive-names)
|
|
563 | 595 | new-env)
|
564 | 596 | 55))
|
565 | 597 | )
|
566 |
| - (seck-eval '((lambda () |
567 |
| - (define (foo a) a) |
568 |
| - (foo 3) |
569 |
| - ) |
| 598 | + (seck-eval '((lambda () |
| 599 | + (define (foo a) a) |
| 600 | + (foo 3) |
570 | 601 | )
|
571 |
| - global-env) |
572 |
| - 'pass) |
573 |
| - |
574 |
| -(define (simple-test) |
575 |
| - (seck-eval '(define (foo x) |
576 |
| - x) |
| 602 | + ) |
577 | 603 | global-env)
|
578 |
| - (display (seck-eval '(map foo '(1 2 3)) |
579 |
| - global-env)) |
580 |
| - ) |
| 604 | + 'pass) |
| 605 | + |
| 606 | +(define proc (make-procedure '(c) |
| 607 | + '((define b (+ a x)) |
| 608 | + (define a 5) |
| 609 | + (+ a b c)) |
| 610 | + global-env)) |
| 611 | +(define (test-scan-out-definitons) |
| 612 | + (scan-out-defines (procedure-body proc))) |
| 613 | + |
| 614 | +(define (test-scoping) |
| 615 | + ; if it's lexical scoping, it will return 7 |
| 616 | + ; but if it's dynamic scoping, it will return 8 |
| 617 | + (let ((new-env (make-env global-env))) |
| 618 | + (seck-eval '(define a 4) |
| 619 | + new-env) |
| 620 | + (seck-eval '(define (foo) |
| 621 | + (+ a 3)) |
| 622 | + new-env) |
| 623 | + (seck-eval '(define (bar) |
| 624 | + (define a 5) |
| 625 | + (foo)) |
| 626 | + new-env) |
| 627 | + (println (seck-eval '(bar) |
| 628 | + new-env)) |
| 629 | + )) |
0 commit comments