Browse Source

Add function argument functionality

Matt Coles 8 years ago
parent
commit
ea320f604c
5 changed files with 159 additions and 20 deletions
  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
         (ptr = find_name_in_list(name, env_ptr->bindings)) == NULL) env_ptr = env_ptr->parent;
64
         (ptr = find_name_in_list(name, env_ptr->bindings)) == NULL) env_ptr = env_ptr->parent;
65
   return ptr;
65
   return ptr;
66
 }
66
 }
67
-

+ 110 - 7
cw/main.c

108
     print_tree0(tree, 0);
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
 void add_function_to_env(NODE *tree, ENV *env_ptr) {
167
 void add_function_to_env(NODE *tree, ENV *env_ptr) {
112
   BIND* existing;
168
   BIND* existing;
113
   NODE* func_name = tree->left->right->left->left;
169
   NODE* func_name = tree->left->right->left->left;
114
   TOKEN* name_token = (TOKEN*) func_name;
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
   if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
171
   if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
119
     /* printf("Added function name %s to environment with value: \n", name_token->lexeme); */
172
     /* printf("Added function name %s to environment with value: \n", name_token->lexeme); */
120
     /* print_tree(tree); */
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
     if (env_ptr->bindings == NULL) {
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
     } else {
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
   } else {
183
   } else {
127
     printf("Error: redefinition of function with name %s\n", name_token->lexeme);
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
 void add_var_to_env(NODE *tree, ENV *env_ptr) {
219
 void add_var_to_env(NODE *tree, ENV *env_ptr) {
133
   BIND* existing;
220
   BIND* existing;
134
   NODE* var_name = tree->left->left;
221
   NODE* var_name = tree->left->left;
135
   TOKEN* name_token = (TOKEN*) var_name;
222
   TOKEN* name_token = (TOKEN*) var_name;
136
-  TOKEN* tok = new_token(INT);
223
+  TOKEN* tok = new_token(CONSTANT);
137
   tok->value = recursive_interpret(tree->right, env_ptr);
224
   tok->value = recursive_interpret(tree->right, env_ptr);
138
   asprintf(&tok->lexeme, "%d", tok->value);
225
   asprintf(&tok->lexeme, "%d", tok->value);
139
   if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
226
   if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
168
         printf("Could not find variable %s\n", tok->lexeme);
255
         printf("Could not find variable %s\n", tok->lexeme);
169
         exit(1);
256
         exit(1);
170
       }
257
       }
171
-      if (var_bind->tree->type == INT) {
258
+      if (var_bind->tree->type == CONSTANT) {
172
         TOKEN* var_tok = (TOKEN *) var_bind->tree;
259
         TOKEN* var_tok = (TOKEN *) var_bind->tree;
173
         return var_tok->value;
260
         return var_tok->value;
174
       } else {
261
       } else {
194
       printf("Could not find binding for function with name %s\n", func_name->lexeme);
281
       printf("Could not find binding for function with name %s\n", func_name->lexeme);
195
       exit(1);
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
     return recursive_interpret(func->tree->right, func->env);
300
     return recursive_interpret(func->tree->right, func->env);
198
   }
301
   }
199
   if (tree->type == IF) {
302
   if (tree->type == IF) {

+ 9 - 8
cw/simple.c

1
 int y = 0;
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
 int blah() {
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
   return y;
19
   return y;
19
 }
20
 }

+ 20 - 0
cw/tests/func_args.c

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
 #/bin/bash
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
 ret_ans='3'
10
 ret_ans='3'
8
 var_ans='11'
11
 var_ans='11'
9
 func_ans='8'
12
 func_ans='8'
13
+args_ans='14'
10
 cond_ans='17'
14
 cond_ans='17'
11
 
15
 
12
 overall='0'
16
 overall='0'
42
   echo " expected $cond_ans but got $cond_loop"
46
   echo " expected $cond_ans but got $cond_loop"
43
   overall='1'
47
   overall='1'
44
 fi
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
 exit $overall
62
 exit $overall