-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathenvironment.lisp
More file actions
89 lines (69 loc) · 3.6 KB
/
environment.lisp
File metadata and controls
89 lines (69 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
(defpackage :environment
(:use :common-lisp)
(:export #:define #:get-value #:assign #:environment #:create-env #:create-env-with-enclosing #:define-with-name #:environment-enclosing))
(in-package #:environment)
(defstruct environment table enclosing)
(defun create-env()
(make-environment :table (make-hash-table :test #'equal) :enclosing nil))
(defun create-env-with-enclosing (enclosing)
(make-environment :table (make-hash-table :test #'equal) :enclosing enclosing))
(defun define (env name-token value)
(make-environment
:table (add-to-hash-table (environment-table env) (lexer:token-lexeme name-token) value)
:enclosing (environment-enclosing env)))
(defun define-with-name (env name value)
(make-environment
:table (add-to-hash-table (environment-table env) name value)
:enclosing (environment-enclosing env)))
(defun get-value (env name-token)
(let* ((name (lexer:token-lexeme name-token))
(value (gethash name (environment-table env) :not-found)))
(if (eq value :not-found)
(if (not (null (environment-enclosing env)))
(get-value (environment-enclosing env) name-token)
(error "Undefined variable '~a'." name))
value)))
(defun assign-new (env name-token value)
(let* ((name (lexer:token-lexeme name-token))
(existing-value (gethash name (environment-table env) :not-found)))
(if (eq existing-value :not-found)
(if (not (null (environment-enclosing env)))
(make-environment :table (environment-table env) :enclosing (assign-new (environment-enclosing env) name-token value))
(error "Undefined variable '~a'." name))
(define-with-name env name value))))
#|(defparameter env (create-env))
(setf env (define-with-name env "key" 1))
(setf env (assign-new env (lexer:create-token 'identifier "key" nil 0) 2))
(get-value env (lexer:create-token 'identifer "key" nil 0))
(defparameter env-2 (create-env-with-enclosing env))
(print env-2)
(get-value env-2 (lexer:create-token 'identifer "key" nil 0))
(setf env-2 (assign-new env-2 (lexer:create-token 'identifier "key" nil 0) 6))|#
(defun assign (env name-token value)
(let* ((name (lexer:token-lexeme name-token))
(existing-value (gethash name (environment-table env) :not-found)))
(if (eq existing-value :not-found)
(if (not (null (environment-enclosing env)))
(assign (environment-enclosing env) name-token value)
(error "Undefined variable '~a'." name))
(setf (gethash name (environment-table env)) value))))
(defun add-to-hash-table (hash-table key value)
"Returns a new hash table with the key-value pair added to it."
(let ((new-hash-table (make-hash-table :test #'equal)))
(maphash (lambda (k v) (setf (gethash k new-hash-table) v)) hash-table)
(setf (gethash key new-hash-table) value)
new-hash-table))
(defun get-from-hash-table (hash-table key)
"Returns the value associated with the key in the hash table."
(gethash key hash-table))
(defun test ()
(let ((hash-table (make-hash-table :test #'equal)))
(setf (gethash "a" hash-table) 1)
(setf (gethash "b" hash-table) 2)
(setf (gethash "c" hash-table) 3)
(format t "Original hash table:~%~A~%" hash-table)
(let ((new-hash-table (add-to-hash-table hash-table "d" 4)))
(format t "New hash table:~%~A~%" new-hash-table)
(format t "Value of 'b' in original hash table: ~A~%" (get-from-hash-table hash-table "b"))
(format t "Value of 'b' in new hash table: ~A~%" (get-from-hash-table new-hash-table "b"))
(format t "Value of 'd' in new hash table: ~A~%" (get-from-hash-table new-hash-table "d")))))