(define occurs-free?
(lambda (var exp)
(cond
((symbol? exp) (eqv? var exp)) ; Identifier
((eqv? (car exp) 'lambda) ; (lambda (Identifier) LcExp)
(and
(not (eqv? var (car (car (cdr exp)))))
(occurs-free? var (car (cdr (cdr exp))))))
(else ; (LcExp LcExp)
(or (occurs-free? var (car exp))
(occurs-free? var (car (cdr exp))))))))
(define occurs-free?
(lambda (var exp)
(cond
((symbol? exp) (eqv? var exp)) ; Identifier
((eqv? (car exp) 'lambda) ; (lambda (Identifier) LcExp)
(and
; (not (eqv? var (car (car (cdr exp)))))
(not (eqv? var (car (cadr exp))))
; (occurs-free? var (car (cdr (cdr exp))))))
(occurs-free? var (caddr exp))))
(else ; (LcExp LcExp)
(or (occurs-free? var (car exp))
; (occurs-free? var (car (cdr exp))))))))
(occurs-free? var (cadr exp)))))))
S-exp ::= Symbol | S-list
S-list ::= ({S-exp}*)
> (occurs-free? 'x '(lambda (x) (x y)))
#f
> (occurs-free? 'x '(lambda (y) (x y)))
#t
(define occurs-free?
(lambda (var exp)
(cond
((symbol? exp) (eqv? var exp)) ; Identifier
((eqv? (car exp) 'lambda) ; (lambda (Identifier) LcExp)
(and
(not (eqv? var (car (car (cdr exp)))))
(occurs-free? var (car (cdr (cdr exp))))))
(else ; (LcExp LcExp)
(or (occurs-free? var (car exp))
(occurs-free? var (car (cdr exp))))))))
Instead of
LcExp ::= Identifier
::= (lambda (Identifier) LcExp)
::= (LcExp LcExp)
use the following?
LcExp ::= Identifier
::= proc Identifier => LcExp
::= LcExp(LcExp)
How to implement occurs-free?
?
(define occurs-free?
(lambda (var exp)
...
Two concrete syntaxes
LcExp ::= Identifier
::= (lambda (Identifier) LcExp)
::= (LcExp LcExp)
LcExp ::= Identifier
::= proc Identifier => LcExp
::= LcExp(LcExp)
Abstract syntax
lc-exp ::= var-exp (var)
::= lambda-exp (bound-var body)
::= app-exp (rator rand)
lc-exp ::= var-exp (var)
::= lambda-exp (bound-var body)
::= app-exp (rator rand)
(define occurs-free?
(lambda (search-var exp)
(cases lc-exp exp
(var-exp (var) (eqv? search-var var))
(lambda-exp (bound-var body)
(and
(not (eqv? search-var bound-var))
(occurs-free? search-var body)))
(app-exp (rator rand)
(or
(occurs-free? search-var rator)
(occurs-free? search-var rand))))))
> (occurs-free? 'x (parse-expression '((lambda (x) x) (x y))))
(define occurs-free?
(lambda (search-var exp)
(cases lc-exp exp
(var-exp (var) (eqv? search-var var))
(lambda-exp (bound-var body)
(and
(not (eqv? search-var bound-var))
(occurs-free? search-var body)))
(app-exp (rator rand)
(or
(occurs-free? search-var rator)
(occurs-free? search-var rand))))))
> (occurs-free? 'x (parse-expression '((lambda (x) x) (x y))))
lc-exp ::= var-exp (var)
::= lambda-exp (bound-var body)
::= app-exp (rator rand)
app-exp
/ \
rator rand
/ \
lambda-exp app-exp
/ \ / \
bound-var body rator rand
| \ / \
x var-exp var-exp var-exp
| | |
var var var
| | |
x x y
app-exp
/ \
rator rand
/ \
lambda-exp app-exp
/ \ / \
bound-var body rator rand
| \ / \
x var-exp var-exp var-exp
| | |
var var var
| | |
x x y
(define occurs-free?
(lambda (search-var exp)
(cases lc-exp exp
(var-exp (var) (eqv? search-var var))
(lambda-exp (bound-var body)
(and
(not (eqv? search-var bound-var))
(occurs-free? search-var body)))
(app-exp (rator rand)
(or
(occurs-free? search-var rator)
(occurs-free? search-var rand))))))
app-exp
/ \
rator rand
/ \
lambda-exp app-exp
/ \ / \
((lambda (x) x) (x y)) → [ Parser ] → bound-var body rator rand
| \ / \
x var-exp var-exp var-exp
| | |
var var var
| | |
x x y
((lambda (x) x) (x y)) → [ Parser ] → ...
LcExp ::= Identifier
::= (lambda (Identifier) LcExp)
::= (LcExp LcExp)
lc-exp ::= var-exp (var)
::= lambda-exp (bound-var body)
::= app-exp (rator rand)
(define parse-expression
(lambda (datum)
(cond
((symbol? datum) (var-exp datum))
((pair? datum)
(if (eqv? (car datum) 'lambda)
(lambda-exp (car (cadr datum))
(parse-expression (caddr datum)))
(app-exp (parse-expression (car datum))
(parse-expression (cadr datum)))))
(else (report-invalid-expression datum)))))
(define parse-expression
(lambda (datum)
(cond
((symbol? datum) (var-exp datum))
((pair? datum)
(if (eqv? (car datum) 'lambda)
(lambda-exp (car (cadr datum))
(parse-expression (caddr datum)))
(app-exp (parse-expression (car datum))
(parse-expression (cadr datum)))))
(else (report-invalid-expression datum)))))
parse-expression
?(define parse-expression
(lambda (datum)
(cond
((symbol? datum) (var-exp datum))
((pair? datum)
(if (eqv? (car datum) 'lambda)
(lambda-exp (car (cadr datum))
(parse-expression (caddr datum)))
(app-exp (parse-expression (car datum))
(parse-expression (cadr datum)))))
(else (report-invalid-expression datum)))))
parse-expression
?
Instead of
LcExp ::= Identifier
::= (lambda (Identifier) LcExp)
::= (LcExp LcExp)
the following is used?
LcExp ::= Identifier
::= proc Identifier => LcExp
::= LcExp(LcExp)
How to change?
(define parse-expression
(lambda (datum)
(cond
((symbol? datum) (var-exp datum))
((pair? datum)
(if (eqv? (car datum) 'lambda)
(lambda-exp (car (cadr datum))
(parse-expression (caddr datum)))
(app-exp (parse-expression (car datum))
(parse-expression (cadr datum)))))
(else (report-invalid-expression datum)))))
You can learn more about parsing in CSE411, Introduction to Compilers.
(define occurs-free?
(lambda (search-var exp)
(cases lc-exp exp
(var-exp (var) (eqv? search-var var))
(lambda-exp (bound-var body)
(and
(not (eqv? search-var bound-var))
(occurs-free? search-var body)))
(app-exp (rator rand)
(or
(occurs-free? search-var rator)
(occurs-free? search-var rand))))))
lc-exp ::= var-exp (var)
::= lambda-exp (bound-var body)
::= app-exp (rator rand)
(cases <type-name> <expression>)
{(variant-name ({<field-name>}*)) <consequent>}*
(define occurs-free?
(lambda (search-var exp)
(cases lc-exp exp
(var-exp (var) (eqv? search-var var))
(lambda-exp (bound-var body)
(and
(not (eqv? search-var bound-var))
(occurs-free? search-var body)))
(app-exp (rator rand)
(or
(occurs-free? search-var rator)
(occurs-free? search-var rand))))))
(define occurs-free?
(lambda (search-var exp)
(cond
((var-exp? exp) (eqv? search-var (var-exp->var exp)))
((lambda-exp? exp)
(and
(not (eqv? search-var (lambda-exp->bound-var exp)))
(occurs-free? search-var (lambda-exp->body exp)))
(else
(or
(occurs-free? search-var (app-exp->rator exp))
(occurs-free? search-var (app-exp->rand exp))))))))
lc-exp
Expressions(define occurs-free?
(lambda (search-var exp)
(cond
((var-exp? exp) (eqv? search-var (var-exp->var exp)))
((lambda-exp? exp)
(and
(not (eqv? search-var (lambda-exp->bound-var exp)))
(occurs-free? search-var (lambda-exp->body exp)))
(else
(or
(occurs-free? search-var (app-exp->rator exp))
(occurs-free? search-var (app-exp->rand exp))))))))
var-exp?
, var-exp->var
, lambda-exp?
, lambda-exp->bound-var
, lambda-exp->body
, app-exp?
, app-exp->rator
, app-exp->rand
lc-exp
Expressions(define occurs-free?
(lambda (search-var exp)
(cond
((var-exp? exp) (eqv? search-var (var-exp->var exp)))
((lambda-exp? exp)
(and
(not (eqv? search-var (lambda-exp->bound-var exp)))
(occurs-free? search-var (lambda-exp->body exp)))
(else
(or
(occurs-free? search-var (app-exp->rator exp))
(occurs-free? search-var (app-exp->rand exp))))))))
var-exp?
, lambda-exp?
, app-exp?
var-exp->var
, lambda-exp->bound-var
, lambda-exp->body
, app-exp->rator
, app-exp->rand
lc-exp
Expressions(define parse-expression
(lambda (datum)
(cond
((symbol? datum) (var-exp datum))
((pair? datum)
(if (eqv? (car datum) 'lambda)
(lambda-exp (car (cadr datum))
(parse-expression (caddr datum)))
(app-exp (parse-expression (car datum))
(parse-expression (cadr datum)))))
(else (report-invalid-expression datum)))))
var-exp?
, lambda-exp?
, app-exp?
var-exp->var
, lambda-exp->bound-var
, lambda-exp->body
, app-exp->rator
, app-exp->rand
var-exp
, lambda-exp
, app-exp
lc-exp
Expressionsvar-exp?
: Lc-exp → Boollambda-exp?
: Lc-exp → Boolapp-exp?
: Lc-exp → Boolvar-exp->var
: Lc-exp → Varlambda-exp->bound-var
: Lc-exp → Varlambda-exp->body
: Lc-exp → Lc-expapp-exp->rator
: Lc-exp → Lc-expapp-exp->rand
: Lc-exp → Lc-explc-exp
Expressionsvar-exp
: Var → Lc-explambda-exp
: Var × Lc-exp → Lc-expapp-exp
: Lc-exp × Lc-exp → Lc-exp ;; var-exp : Var -> Lc-exp
(define var-exp
(lambda (var)
`(var-exp ,var)))
;; lambda-exp : Var * Lc-exp -> Lc-exp
(define lambda-exp
(lambda (var lc-exp)
`(lambda-exp ,var ,lc-exp)))
;; app-exp : Lc-exp * Lc-exp -> Lc-exp
(define app-exp
(lambda (lc-exp1 lc-exp2)
`(app-exp ,lc-exp1 ,lc-exp2)))
;; var-exp? : Lc-exp -> Bool
(define var-exp?
(lambda (x)
(and (pair? x) (eqv? (car x) 'var-exp))))
;; lambda-exp? : Lc-exp -> Bool
(define lambda-exp?
(lambda (x)
(and (pair? x) (eqv? (car x) 'lambda-exp))))
;; app-exp? : Lc-exp -> Bool
(define app-exp?
(lambda (x)
(and (pair? x) (eqv? (car x) 'app-exp))))
;; var-exp->var : Lc-exp -> Var
(define var-exp->var
(lambda (x)
(cadr x)))
;; lambda-exp->bound-var : Lc-exp -> Var
(define lambda-exp->bound-var
(lambda (x)
(cadr x)))
;; lambda-exp->body : Lc-exp -> Lc-exp
(define lambda-exp->body
(lambda (x)
(caddr x)))
;; app-exp->rator : Lc-exp -> Lc-exp
(define app-exp->rator
(lambda (x)
(cadr x)))
;; app-exp->rand : Lc-exp -> Lc-exp
(define app-exp->rand
(lambda (x)
(caddr x)))
Instead of
LcExp ::= Identifier
::= (lambda (Identifier) LcExp)
::= (LcExp LcExp)
the following is used?
LcExp ::= Identifier
::= proc Identifier => LcExp
::= LcExp(LcExp)
What to change?
(define occurs-free?
(lambda (search-var exp)
(cond
((var-exp? exp) (eqv? search-var (var-exp->var exp)))
((lambda-exp? exp)
(and
(not (eqv? search-var (lambda-exp->bound-var exp)))
(occurs-free? search-var (lambda-exp->body exp)))
(else
(or
(occurs-free? search-var (app-exp->rator exp))
(occurs-free? search-var (app-exp->rand exp))))))))
[Concrete syntax] [Abstract syntax]
LcExp ::= Identifier lc-exp ::= var-exp (var)
::= (lambda (Identifier) LcExp) ::= lambda-exp (bound-var body)
::= (LcExp LcExp) ::= app-exp (rator rand)
[Interface]
var-exp : Var -> Lc-exp
[Implementation]
(define var-exp
(lambda (var)
`(var-exp ,var)))
``` lc-exp ::= var-exp (var) ::= lambda-exp (bound-var body) ::= app-exp (rator rand) ```