|
1 | 1 | (load "./utils/dict.scm")
|
2 | 2 |
|
3 |
| -(define (assert v) |
4 |
| - (if (not v) |
5 |
| - (error 'assert "failed"))) |
| 3 | +(define (assert exp) |
| 4 | + (if (not exp) |
| 5 | + (error 'assert "expression is not true") |
| 6 | + exp)) |
| 7 | + |
| 8 | +(define (assert-eq a b eqproc) |
| 9 | + (if (not (eqproc a b)) |
| 10 | + (error 'assert-eq a " and " b " is not equal") |
| 11 | + #t)) |
6 | 12 |
|
7 | 13 | (define (typeof v)
|
8 | 14 | (cond ((boolean? v)
|
|
37 | 43 | ((and? exp) (seck-eval (and->if exp) env))
|
38 | 44 | ((or? exp) (seck-eval (or->if exp) env))
|
39 | 45 | ((let? exp) (seck-eval (let->combination exp) env))
|
| 46 | + ((letstar? exp) (seck-eval (let*->nested-let exp) env)) |
40 | 47 | ((application? exp)
|
41 | 48 | (seck-apply (seck-eval (operator exp) env)
|
42 | 49 | (list-of-values (operand exp) env)))
|
|
236 | 243 | (define (eval-sequence exps env)
|
237 | 244 | (if (last-exp? exps)
|
238 | 245 | (seck-eval (first-exp exps) env)
|
239 |
| - (eval-sequence (rest-exps) env))) |
| 246 | + (eval-sequence (rest-exps exps) env))) |
240 | 247 |
|
241 | 248 | ; @(assignment)
|
242 | 249 |
|
|
331 | 338 | (make-if 'true (sequence->exp (cond-match-actions first)))
|
332 | 339 | (error 'cond "else is not last match")))
|
333 | 340 | (else ; the other conditions
|
334 |
| - (make-if (cond-match-predicate first) |
335 |
| - (sequence->exp-2 (cond-match-predicate first) |
336 |
| - (cond-match-actions first)) |
337 |
| - (expand rest))))))) |
| 341 | + (make-if (cond-match-predicate first) |
| 342 | + (sequence->exp-2 (cond-match-predicate first) |
| 343 | + (cond-match-actions first)) |
| 344 | + (expand rest))))))) |
338 | 345 | (expand (cdr exp)))
|
339 | 346 |
|
340 | 347 | ; @(and/or)
|
|
380 | 387 | (define (let? exp)
|
381 | 388 | (tagged-list? exp 'let))
|
382 | 389 |
|
| 390 | +(define (let-bindings exp) (cadr exp)) |
| 391 | +(define (let-body exp) (cddr exp)) |
| 392 | +(define (let-vars exp) (map car (let-bindings exp))) |
| 393 | +; if you define let-values here, there will be |
| 394 | +(define (let-vals exp) (map cadr (let-bindings exp))) |
| 395 | + |
383 | 396 | (define (let->combination exp)
|
384 |
| - (let ((var-bindings (cadr exp)) |
385 |
| - (body (cddr exp))) |
386 |
| - (let ((vars (map car var-bindings)) |
387 |
| - (values (map cadr var-bindings))) |
388 |
| - (cons (cons 'lambda |
389 |
| - (cons vars body)) |
390 |
| - values)))) |
| 397 | + (make-let (let-vars exp) |
| 398 | + (let-vals exp) ; todo |
| 399 | + (let-body exp))) |
| 400 | + |
| 401 | +(define (make-let vars values body) |
| 402 | + (cons (cons 'lambda |
| 403 | + (cons vars body)) |
| 404 | + values)) |
| 405 | + |
| 406 | +(define (letstar? exp) |
| 407 | + (tagged-list? exp 'let*)) |
| 408 | + |
| 409 | +(define (let*->nested-let exp) |
| 410 | + (define (wrap-let-body vars values) |
| 411 | + (cond ((and (null? vars) |
| 412 | + (null? values)) |
| 413 | + (make-let vars values (let-body exp))) |
| 414 | + ((or (null? vars) |
| 415 | + (null? values)) |
| 416 | + (error 'wrap-let-body "let vars-values length not match")) |
| 417 | + (else |
| 418 | + (make-let (list (car vars)) |
| 419 | + (list (car values)) |
| 420 | + (wrap-let-body (cdr vars) |
| 421 | + (cdr values)))) |
| 422 | + )) |
| 423 | + (wrap-let-body (let-vars exp) |
| 424 | + (let-vals exp) ; todo |
| 425 | + )) |
391 | 426 |
|
392 | 427 | ; @(application)
|
393 | 428 | (define application? pair?)
|
|
424 | 459 |
|
425 | 460 | (define global-env (setup-environment))
|
426 | 461 |
|
427 |
| -(define (test-eval) |
428 |
| - (assert (= (seck-eval '(+ 1 2) global-env) 3)) |
429 |
| - (assert (equal? (seck-eval '(cons 1 2) global-env) (cons 1 2))) |
| 462 | +(define (init-test-env) |
430 | 463 | (let ((new-env (make-env global-env)))
|
431 | 464 | (seck-eval '(define a 3) new-env)
|
432 | 465 | (seck-eval '(set! a 4) new-env)
|
| 466 | + new-env)) |
| 467 | + |
| 468 | +(define (test-eval) |
| 469 | + (let ((new-env (init-test-env))) |
| 470 | + (assert (= (seck-eval '(+ 1 2) global-env) 3)) |
| 471 | + (assert (equal? (seck-eval '(cons 1 2) global-env) (cons 1 2))) |
433 | 472 | (assert (= (seck-eval 'a new-env) 4))
|
434 | 473 | (assert (seck-eval '(and (= a 4) (< a 5) (> a 2)) new-env))
|
435 | 474 | (assert (seck-eval '(or (= a 5) (> a 5) (> a 2)) new-env))
|
|
455 | 494 | (cons a b))
|
456 | 495 | new-env)
|
457 | 496 | (cons 3 4)))
|
| 497 | + (display (let*->nested-let '(let* ((x 1) |
| 498 | + (y (+ x 1)) |
| 499 | + (z (+ x a)) |
| 500 | + ) |
| 501 | + (+ x y z))))(newline) |
| 502 | + (assert-eq (seck-eval '(let* ((x 1) |
| 503 | + (y (+ x 1)) |
| 504 | + (z (+ x a)) |
| 505 | + ) |
| 506 | + (+ x y z)) |
| 507 | + new-env) |
| 508 | + 8 |
| 509 | + =) |
458 | 510 | ))
|
0 commit comments