Преглед изворни кода

Add function argument functionality

Matt Coles пре 8 година
родитељ
комит
ea320f604c
5 измењених фајлова са 159 додато и 20 уклоњено
  1. 0 1
      cw/list.c
  2. 110 7
      cw/main.c
  3. 9 8
      cw/simple.c
  4. 20 0
      cw/tests/func_args.c
  5. 20 4
      cw/tests/test.sh

+ 0 - 1
cw/list.c

@@ -64,4 +64,3 @@ BIND* find_name_in_list(TOKEN* name, BLIST *head) {
64 64
         (ptr = find_name_in_list(name, env_ptr->bindings)) == NULL) env_ptr = env_ptr->parent;
65 65
   return ptr;
66 66
 }
67
-

+ 110 - 7
cw/main.c

@@ -108,32 +108,119 @@ void print_tree(NODE *tree) {
108 108
     print_tree0(tree, 0);
109 109
 }
110 110
 
111
+int count_args(NODE *tree) { 
112
+  NODE *tmp = tree;
113
+  int a = 1;
114
+  while (tmp != NULL) {
115
+    if (tmp->type != ',') {
116
+      break;
117
+    }
118
+    tmp = tmp->left;
119
+    a++;
120
+  }
121
+  return a;
122
+}
123
+
124
+void add_args_to_env(NODE *tree, ENV *env_ptr) {
125
+  if (tree->type == '~') {
126
+    BIND* arg;
127
+    TOKEN *tok, *name;
128
+    // we found an argument
129
+    name = (TOKEN*)tree->right->left;
130
+    tok = new_token(INT);
131
+    tok->value = 0;
132
+    asprintf(&tok->lexeme, "%d", tok->value);
133
+    arg = create_binding(name, (NODE*) tok, NULL);
134
+    if (env_ptr->bindings == NULL) {
135
+      env_ptr->bindings = create_list(arg, NULL);
136
+    } else {
137
+      append_list(env_ptr->bindings, arg);
138
+    }
139
+  } else {
140
+    add_args_to_env(tree->left, env_ptr);
141
+    add_args_to_env(tree->right, env_ptr);
142
+  }
143
+}
144
+
145
+void populate_arg_list(NODE *tree, TOKEN** arr, int arr_len) {
146
+  if (tree->type == '~') {
147
+    for (int i = 0; i < arr_len; i++) {
148
+      if (arr[i] == NULL) {
149
+        TOKEN* name = (TOKEN*)tree->right->left;
150
+        arr[i] = name;
151
+        break;
152
+      }
153
+    }
154
+  } else {
155
+    populate_arg_list(tree->left, arr, arr_len);
156
+    populate_arg_list(tree->right, arr, arr_len);
157
+  }
158
+}
159
+
160
+TOKEN** get_argument_list(NODE *tree) {
161
+  int num_args = count_args(tree->left->right->right);
162
+  TOKEN** arr = (TOKEN**) malloc(sizeof(TOKEN*) * num_args);
163
+  populate_arg_list(tree->left->right->right, arr, num_args);
164
+  return arr;
165
+}
166
+
111 167
 void add_function_to_env(NODE *tree, ENV *env_ptr) {
112 168
   BIND* existing;
113 169
   NODE* func_name = tree->left->right->left->left;
114 170
   TOKEN* name_token = (TOKEN*) func_name;
115
-  if (tree->left->right->right == NULL) {
116
-    printf("%s has no arguments\n", name_token->lexeme);
117
-  }
118 171
   if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
119 172
     /* printf("Added function name %s to environment with value: \n", name_token->lexeme); */
120 173
     /* print_tree(tree); */
174
+    ENV* new_func_env = create_new_function_env(env_ptr);
175
+    if (tree->left->right->right != NULL) {
176
+      add_args_to_env(tree->left->right->right, new_func_env);
177
+    }
121 178
     if (env_ptr->bindings == NULL) {
122
-      env_ptr->bindings = create_list(create_binding(name_token, tree, env_ptr), NULL);
179
+      env_ptr->bindings = create_list(create_binding(name_token, tree, new_func_env), NULL);
123 180
     } else {
124
-      append_list(env_ptr->bindings, create_binding(name_token, tree, env_ptr));
181
+      append_list(env_ptr->bindings, create_binding(name_token, tree, new_func_env));
125 182
     }
126 183
   } else {
127 184
     printf("Error: redefinition of function with name %s\n", name_token->lexeme);
128 185
   }
129 186
 }
130 187
 
188
+void populate_val_list(NODE* tree, TOKEN** arr, int num_args) {
189
+  if (tree->type == LEAF) {
190
+    for (int i = 0; i < num_args; i++) {
191
+      if (arr[i] == NULL) {
192
+        TOKEN* tok = (TOKEN*) tree->left;
193
+        arr[i] = tok;
194
+        break;
195
+      }
196
+    }
197
+  } else {
198
+    populate_val_list(tree->left, arr, num_args);
199
+    populate_val_list(tree->right, arr, num_args);
200
+  }
201
+}
202
+
203
+TOKEN** get_val_list(NODE *tree) {
204
+  int num_args = count_args(tree);
205
+  TOKEN** arr = (TOKEN**) malloc(sizeof(TOKEN*) * num_args);
206
+  populate_val_list(tree, arr, num_args);
207
+  return arr;
208
+}
209
+
210
+void bind_arg(TOKEN* val, TOKEN* arg_name, ENV *env_ptr) {
211
+  BIND* existing = find_name_in_list(arg_name, env_ptr->bindings);
212
+  if (existing == NULL) {
213
+    printf("fatal error\n");
214
+    exit(1);
215
+  }
216
+  existing->tree = (NODE*) val;
217
+}
131 218
 
132 219
 void add_var_to_env(NODE *tree, ENV *env_ptr) {
133 220
   BIND* existing;
134 221
   NODE* var_name = tree->left->left;
135 222
   TOKEN* name_token = (TOKEN*) var_name;
136
-  TOKEN* tok = new_token(INT);
223
+  TOKEN* tok = new_token(CONSTANT);
137 224
   tok->value = recursive_interpret(tree->right, env_ptr);
138 225
   asprintf(&tok->lexeme, "%d", tok->value);
139 226
   if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
@@ -168,7 +255,7 @@ int recursive_interpret(NODE *tree, ENV *env_ptr) {
168 255
         printf("Could not find variable %s\n", tok->lexeme);
169 256
         exit(1);
170 257
       }
171
-      if (var_bind->tree->type == INT) {
258
+      if (var_bind->tree->type == CONSTANT) {
172 259
         TOKEN* var_tok = (TOKEN *) var_bind->tree;
173 260
         return var_tok->value;
174 261
       } else {
@@ -194,6 +281,22 @@ int recursive_interpret(NODE *tree, ENV *env_ptr) {
194 281
       printf("Could not find binding for function with name %s\n", func_name->lexeme);
195 282
       exit(1);
196 283
     }
284
+    if (tree->right != NULL) {
285
+      TOKEN** arg_list;
286
+      TOKEN** val_list;
287
+      int exp_args = count_args(func->tree->left->right->right);
288
+      int num_args = count_args(tree->right);
289
+      arg_list = get_argument_list(func->tree);
290
+      val_list = get_val_list(tree->right);
291
+      if (exp_args == num_args) {
292
+        for (int i = 0; i < num_args; i++) {
293
+          bind_arg(val_list[i], arg_list[i], func->env);
294
+        }
295
+      } else {
296
+        printf("Error! Arguments not right!!\n");
297
+        exit(1);
298
+      }
299
+    }
197 300
     return recursive_interpret(func->tree->right, func->env);
198 301
   }
199 302
   if (tree->type == IF) {

+ 9 - 8
cw/simple.c

@@ -1,19 +1,20 @@
1 1
 int y = 0;
2 2
 
3
-int incr_y(int a) {
4
-  y = y + 2;
3
+int incr_y(int a, int b) {
4
+  y = y + a + b;
5 5
 }
6 6
 
7 7
 int blah() {
8
+  y = 2;
8 9
 }
9 10
 
10
-int main() {
11
+/* int blah2(int a, int b, int c, int d) {} */
12
+
13
+/* int blah3(int a) {} */
11 14
 
12
-  int x = 0;
13
-  while (x < 10) {
14
-    incr_y();
15
-    x = x + 1;
16
-  }
15
+int main() {
16
+  incr_y(2,3);
17
+  incr_y(4, 5);
17 18
 
18 19
   return y;
19 20
 }

+ 20 - 0
cw/tests/func_args.c

@@ -0,0 +1,20 @@
1
+int y = 0;
2
+
3
+int incr_y(int a, int b) {
4
+  y = y + a + b;
5
+}
6
+
7
+int blah() {
8
+  y = 2;
9
+}
10
+
11
+/* int blah2(int a, int b, int c, int d) {} */
12
+
13
+/* int blah3(int a) {} */
14
+
15
+int main() {
16
+  incr_y(2,3);
17
+  incr_y(4, 5);
18
+
19
+  return y;
20
+}

+ 20 - 4
cw/tests/test.sh

@@ -1,12 +1,16 @@
1 1
 #/bin/bash
2
-ret_only=`../mycc < ./return_only.c | tail -n 1`
3
-var_maths=`../mycc < ./var_maths.c | tail -n 1`
4
-func_call=`../mycc < ./func_call.c | tail -n 1`
5
-cond_loop=`../mycc < ./cond_loop.c | tail -n 1`
2
+start=$(date +%s.%N)
3
+absdir=$(readlink -f $(dirname $0))
4
+ret_only=`$absdir/../mycc < $absdir/return_only.c | tail -n 1`
5
+var_maths=`$absdir/../mycc < $absdir/var_maths.c | tail -n 1`
6
+func_call=`$absdir/../mycc < $absdir/func_call.c | tail -n 1`
7
+cond_loop=`$absdir/../mycc < $absdir/cond_loop.c | tail -n 1`
8
+func_args=`$absdir/../mycc < $absdir/func_args.c | tail -n 1`
6 9
 
7 10
 ret_ans='3'
8 11
 var_ans='11'
9 12
 func_ans='8'
13
+args_ans='14'
10 14
 cond_ans='17'
11 15
 
12 16
 overall='0'
@@ -42,5 +46,17 @@ else
42 46
   echo " expected $cond_ans but got $cond_loop"
43 47
   overall='1'
44 48
 fi
49
+if [ "$func_args" -eq $args_ans ]; then
50
+  echo "func_args ..... $pass"
51
+else
52
+  echo -n "func_args ..... $fail"
53
+  echo " expected $args_ans but got $func_args"
54
+  overall='1'
55
+fi
56
+
57
+end=$(date +%s.%N)    
58
+runtime=$(python -c "print(${end} - ${start})")
59
+
60
+echo "\nCompleted 5 tests in $runtime""s"
45 61
 
46 62
 exit $overall