This is a project to implement my own Scheme compiler.
Basically, I'll define term according to 'The Little Schemer'.
So we can just start from the beginning of this book.
- feat: implement lambda in lambda in lambda
- refactor implementation of function instantiate -- use stack/list instead of string/replace
- add automation test according to docs
- use smart pointer to refactor this codebase, since last 8 refactor commit introduce memory bugs when declare customized function
- refactor architecture
- refactor to basic structure
- extract function out of repl
- separate interpreter.cpp into several factories
- refactor code smell -- 40%
- use unique_ptr, shared_ptr and weak_ptr instead of all shared_ptr
passing function as param:
# you can define function like this:
(define rember-f
(lambda (test? a l)
(cond
((null? l) ())
((test? (car l) a) (cdr l))
(else (cons (car l) (rember-f test? a (cdr l))))
)
)
)
# 1. and then, pass a function into test? param
(rember-f = 5 (6 2 5 3))
# 2. or, you can do something like this
(rember-f (function = (lambda (n m) (cond ((and? (zero? n) (zero? m)) #t) ((or? (zero? n) (zero? m)) #f) (else (= (sub1 n) (sub1 m)))))) 5 (6 2 5 3))
customized function:
# I do not care about customized function's return type
(define atom
(lambda (atom)
(function)
)
)
function:
# function must be enclosed with (), they are the same
- math family:
- integer class:
- (zero? integer) -> bool(#t/#f)
- (add1 integer) -> integer
- (sub1 integer) -> integer
- nor logic family:
- or_logic class:
(or? s_expression s_expression) -> bool(#t/#f)
- and_logic class:
(and? s_expression s_expression) -> bool(#t/#f)
- s_expression family:
- is_atom class:
(atom? s_expression) -> bool(#t/#f)
- is_eq class:
(eq? s_expression s_expression) -> bool(#t/#f)
- is_number class:
(number? s_expression) -> bool(#t/#f)
- list family:
- car class:
(car list) -> s_expression
- cdr class:
(cdr list) -> list
- cons class:
(cons s_expression list) -> list
- is_null class:
(null? list) -> bool(#t/#f)
- add_tuple class:
(addtup tuple) -> integer
- condition family:
- cond class:
(lambda (s_expression)
(cond
(assertion s_expression)
(assertion s_expression)
(assertion s_expression)
...
(else s_expression)
)
)
- others:
- quote class:
(quote s_expression) -> atom
# function basic type
- assertion: every function return atom(#t/#f)
- (assertion s_expression) -> bool(#t/#f)
s_expression:
list
atom
bool
list:
# let's say these items can be in any order
(atom atom ...)
(list list ...)
(list atom ...)
- tuple
(integer integer ...)
atom:
- a string of characters
- bool:
- #t
- #f
- nonnegative integer
Now you can define any lambda like below:
(define lat? (lambda (l) (cond ((null? l) #t) ((atom? (car l)) (lat? (cdr l))) (else #f))))
And you'll get result like this:
---- func ----
-> name: lat?
-> var: ( l )
-> body: (cond ( ( null? l ) #t ) ( ( atom? ( car l ) ) ( lat? ( cdr l ) ) ) ( else #f ) )
Then you can call this lambda with parameters:
(lat? (Jack Sprat could eat no chicken fat))
And you'll get the process of calculation and result:
-> null? -> bool [#f]
-> car -> s_expression [Jack]
-> atom? -> bool [#t]
-> cdr -> list [( Sprat could eat no chicken fat )]
-> null? -> bool [#f]
-> car -> s_expression [Sprat]
-> atom? -> bool [#t]
-> cdr -> list [( could eat no chicken fat )]
-> null? -> bool [#f]
-> car -> s_expression [could]
-> atom? -> bool [#t]
-> cdr -> list [( eat no chicken fat )]
-> null? -> bool [#f]
-> car -> s_expression [eat]
-> atom? -> bool [#t]
-> cdr -> list [( no chicken fat )]
-> null? -> bool [#f]
-> car -> s_expression [no]
-> atom? -> bool [#t]
-> cdr -> list [( chicken fat )]
-> null? -> bool [#f]
-> car -> s_expression [chicken]
-> atom? -> bool [#t]
-> cdr -> list [( fat )]
-> null? -> bool [#f]
-> car -> s_expression [fat]
-> atom? -> bool [#t]
-> cdr -> list [( )]
-> null? -> bool [#t]
bool: #t