]> git.lizzy.rs Git - nothing.git/blob - src/ebisp/scope.c
Add TODO(#537)
[nothing.git] / src / ebisp / scope.c
1 #include <assert.h>
2 #include "./scope.h"
3
4 static struct Expr get_scope_value_impl(struct Expr scope, struct Expr name)
5 {
6     if (cons_p(scope)) {
7         struct Expr value = assoc(name, scope.cons->car);
8         return nil_p(value) ? get_scope_value_impl(scope.cons->cdr, name) : value;
9     }
10
11     return scope;
12 }
13
14 struct Expr get_scope_value(const struct Scope *scope, struct Expr name)
15 {
16     return get_scope_value_impl(scope->expr, name);
17 }
18
19 static struct Expr set_scope_value_impl(Gc *gc, struct Expr scope, struct Expr name, struct Expr value)
20 {
21     if (cons_p(scope)) {
22         if (!nil_p(assoc(name, scope.cons->car)) || nil_p(scope.cons->cdr)) {
23             return CONS(gc,
24                         CONS(gc, CONS(gc, name, value), scope.cons->car),
25                         scope.cons->cdr);
26         } else {
27             return CONS(gc,
28                         scope.cons->car,
29                         set_scope_value_impl(gc, scope.cons->cdr, name, value));
30         }
31     } else {
32         return CONS(gc,
33                     CONS(gc, CONS(gc, name, value), NIL(gc)),
34                     scope);
35     }
36 }
37
38 struct Scope create_scope(Gc *gc)
39 {
40     struct Scope scope = {
41         .expr = CONS(gc, NIL(gc), NIL(gc))
42     };
43     return scope;
44 }
45
46 void set_scope_value(Gc *gc, struct Scope *scope, struct Expr name, struct Expr value)
47 {
48     scope->expr = set_scope_value_impl(gc, scope->expr, name, value);
49 }
50
51 void push_scope_frame(Gc *gc, struct Scope *scope, struct Expr vars, struct Expr args)
52 {
53     assert(gc);
54     assert(scope);
55
56     struct Expr frame = NIL(gc);
57
58     while(!nil_p(vars) && !nil_p(args)) {
59         frame = CONS(gc,
60                      CONS(gc, vars.cons->car, args.cons->car),
61                      frame);
62         vars = vars.cons->cdr;
63         args = args.cons->cdr;
64     }
65
66     scope->expr = CONS(gc, frame, scope->expr);
67 }
68
69 void pop_scope_frame(Gc *gc, struct Scope *scope)
70 {
71     assert(gc);
72     assert(scope);
73
74     if (!nil_p(scope->expr)) {
75         scope->expr = scope->expr.cons->cdr;
76     }
77 }