]> git.lizzy.rs Git - nothing.git/blob - src/script/scope.c
Support lambdas
[nothing.git] / src / script / 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 void set_scope_value(Gc *gc, struct Scope *scope, struct Expr name, struct Expr value)
39 {
40     scope->expr = set_scope_value_impl(gc, scope->expr, name, value);
41 }
42
43 void push_scope_frame(Gc *gc, struct Scope *scope, struct Expr vars, struct Expr args)
44 {
45     assert(gc);
46     assert(scope);
47
48     struct Expr frame = NIL(gc);
49
50     while(!nil_p(vars) && !nil_p(args)) {
51         frame = CONS(gc,
52                      CONS(gc, vars.cons->car, args.cons->car),
53                      frame);
54         vars = vars.cons->cdr;
55         args = args.cons->cdr;
56     }
57
58     scope->expr = CONS(gc, frame, scope->expr);
59 }
60
61 void pop_scope_frame(Gc *gc, struct Scope *scope)
62 {
63     assert(gc);
64     assert(scope);
65
66     if (!nil_p(scope->expr)) {
67         scope->expr = scope->expr.cons->cdr;
68     }
69 }