-
Notifications
You must be signed in to change notification settings - Fork 0
/
talloc.c
115 lines (107 loc) · 2.83 KB
/
talloc.c
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* This code implements a garbage collector to manage memory
* usage throughout the interpreter project.
*
* Authors: Yitong Chen, Yingying Wang, Megan Zhao
*/
#include <assert.h>
#include <stdio.h>
#include "talloc.h"
#include <string.h>
#include "linkedlist.h"
// The global static variable
static Value *head;
static Value *usefulListHead;
/*
* Create an empty list (a new Value object of type NULL_TYPE).
*
* Returns a pointer to an empty list.
* If memory allocation fails, returns a null pointer.
*/
Value *talloc_makeNull() {
Value *nullList = malloc(sizeof(Value));
if (!nullList) {
printf("Out of memory!\n");
return nullList;
}
nullList->type = NULL_TYPE;
return nullList;
}
/*
* Create a nonempty list (a new Value object of type CONS_TYPE).
*
* Returns a pointer to a non-empty list.
* If memory allocation fails, returns a null pointer.
* Asserts that car is not a list (so no nested list)
*/
Value *talloc_cons(Value *car, Value *cdr) {
struct ConsCell cell;
cell.car = car;
cell.cdr = cdr;
Value *newValue = malloc(sizeof(Value));
if (!newValue) {
printf("Out of memory!\n");
return newValue;
}
newValue->type = CONS_TYPE;
newValue->c = cell;
return newValue;
}
/*
* A malloc-like function that allocates memory, tracking all allocated
* pointers in the "active list." (You can choose your implementation of the
* active list, but whatever it is, your talloc code should NOT call functions
* in linkedlist.h; instead, implement any list-like behavior directly here.
* Otherwise you'll end up with circular dependencies, since you're going to
* modify the linked list to use talloc instead of malloc.)
*/
void *talloc(size_t size){
if (head == NULL){
head = talloc_makeNull();
if (!head){
printf("Out of memory!\n");
return head;
}
}
Value *newHead = malloc(sizeof(Value));
if (!newHead){
printf("Out of memory!\n");
return newHead;
}
newHead->type = PTR_TYPE;
// newHead->useful = false;
newHead->p = malloc(size);
// newHead->useful = false;
if (!newHead->p){
printf("Out of memory!\n");
return newHead->p;
}
head = talloc_cons(newHead, head);
return newHead->p;
}
/*
* Free all pointers allocated by talloc, as well as whatever memory you
* malloc'ed to create/update the active list.
*/
void tfree(){
Value *cur = head;
Value *next;
while (cur->type != NULL_TYPE){
next = cur->c.cdr;
free(cur->c.car->p);
free(cur->c.car);
free(cur);
cur = next;
}
free(next);
head = NULL;
}
/*
* A simple two-line function to stand in the C function "exit", which calls
* tfree() and then exit(). (You'll use this later to allow a clean exit from
* your interpreter when you encounter an error: so memory can be automatically
* cleaned up when exiting.)
*/
void texit(int status){
tfree();
exit(status);
}