+#include <assert.h>
#include "./scope.h"
-struct Expr empty_scope(void)
+static struct Expr get_scope_value_impl(struct Expr scope, struct Expr name)
{
- return CONS(NIL, NIL);
+ if (cons_p(scope)) {
+ struct Expr value = assoc(name, scope.cons->car);
+ return nil_p(value) ? get_scope_value_impl(scope.cons->cdr, name) : value;
+ }
+
+ return scope;
}
-struct Expr get_scope_value(struct Expr scope, struct Expr name)
+struct Expr get_scope_value(const struct Scope *scope, struct Expr name)
{
- switch (scope.type) {
- case EXPR_CONS: {
- struct Expr value = assoc(name, scope.cons->car);
- return nil_p(value) ? get_scope_value(scope.cons->cdr, name) : value;
- } break;
+ return get_scope_value_impl(scope->expr, name);
+}
- default:
- return scope;
+static struct Expr set_scope_value_impl(Gc *gc, struct Expr scope, struct Expr name, struct Expr value)
+{
+ if (cons_p(scope)) {
+ if (!nil_p(assoc(name, scope.cons->car)) || nil_p(scope.cons->cdr)) {
+ return CONS(gc,
+ CONS(gc, CONS(gc, name, value), scope.cons->car),
+ scope.cons->cdr);
+ } else {
+ return CONS(gc,
+ scope.cons->car,
+ set_scope_value_impl(gc, scope.cons->cdr, name, value));
+ }
+ } else {
+ return CONS(gc,
+ CONS(gc, CONS(gc, name, value), NIL(gc)),
+ scope);
}
}
-struct Expr set_scope_value(struct Expr scope, struct Expr name, struct Expr value)
+void set_scope_value(Gc *gc, struct Scope *scope, struct Expr name, struct Expr value)
{
- (void) name;
- (void) value;
-
- /* TODO(#312): set_scope_value is not implemented */
-
- return scope;
+ scope->expr = set_scope_value_impl(gc, scope->expr, name, value);
}
-struct Expr push_scope_frame(struct Expr scope)
+void push_scope_frame(Gc *gc, struct Scope *scope, struct Expr vars, struct Expr args)
{
- return CONS(empty_scope(), scope);
+ assert(gc);
+ assert(scope);
+
+ struct Expr frame = NIL(gc);
+
+ while(!nil_p(vars) && !nil_p(args)) {
+ frame = CONS(gc,
+ CONS(gc, vars.cons->car, args.cons->car),
+ frame);
+ vars = vars.cons->cdr;
+ args = args.cons->cdr;
+ }
+
+ scope->expr = CONS(gc, frame, scope->expr);
}
-struct Expr pop_scope_frame(struct Expr scope)
+void pop_scope_frame(Gc *gc, struct Scope *scope)
{
- if (scope.type == EXPR_CONS) {
- return scope.cons->cdr;
- } else {
- return scope;
+ assert(gc);
+ assert(scope);
+
+ if (!nil_p(scope->expr)) {
+ scope->expr = scope->expr.cons->cdr;
}
}