]> git.lizzy.rs Git - nothing.git/blob - src/script/scope.c
(#312) implement find_frame_with_name
[nothing.git] / src / script / scope.c
1 #include "./scope.h"
2
3 static struct Expr find_frame_with_name(struct Expr scope, struct Expr name)
4 {
5     struct Expr frame = scope;
6
7     while (cons_p(frame)) {
8         if (!nil_p(assoc(name, frame))) {
9             return frame;
10         }
11
12         frame = frame.cons->car;
13     }
14
15     if (cons_p(scope)) {
16         return scope.cons->car;
17     }
18
19     return scope;
20 }
21
22 struct Expr empty_scope(void)
23 {
24     return CONS(NIL, NIL);      /* '(()) */
25 }
26
27 struct Expr get_scope_value(struct Expr scope, struct Expr name)
28 {
29     switch (scope.type) {
30     case EXPR_CONS: {
31         struct Expr value = assoc(name, scope.cons->car);
32         return nil_p(value) ? get_scope_value(scope.cons->cdr, name) : value;
33     } break;
34
35     default:
36         return scope;
37     }
38 }
39
40 void set_scope_value(struct Expr scope, struct Expr name, struct Expr value)
41 {
42     struct Expr frame = find_frame_with_name(scope, name);
43     push(CONS(name, value), frame);
44 }
45
46 struct Expr push_scope_frame(struct Expr scope)
47 {
48     return CONS(empty_scope(), scope);
49 }
50
51 struct Expr pop_scope_frame(struct Expr scope)
52 {
53     if (scope.type == EXPR_CONS) {
54         return scope.cons->cdr;
55     } else {
56         return scope;
57     }
58 }