Matt Coles il y a 8 ans
Parent
commit
592ccd454f

+ 140 - 80
cw/main.c

@@ -10,6 +10,8 @@
10 10
 TOKEN* lookup_token(char *s);
11 11
 int asprintf(char **strp, const char *fmt, ...);
12 12
 
13
+int debug = 0;
14
+
13 15
 /*
14 16
  * Existing problems/todo:
15 17
  * return from control block, need a "return address" to jump to -- call levels
@@ -102,7 +104,7 @@ void print_tree0(NODE *tree, int level) {
102 104
 }
103 105
 
104 106
 // forward declare because it is used in add_var_to_env
105
-int recursive_interpret(NODE*, ENV*);
107
+BIND* recursive_interpret(NODE*, ENV*);
106 108
 
107 109
 void print_tree(NODE *tree) {
108 110
     print_tree0(tree, 0);
@@ -121,27 +123,6 @@ int count_args(NODE *tree) {
121 123
   return a;
122 124
 }
123 125
 
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 126
 void populate_arg_list(NODE *tree, TOKEN** arr, int arr_len) {
146 127
   if (tree->type == '~') {
147 128
     for (int i = 0; i < arr_len; i++) {
@@ -169,106 +150,138 @@ void add_function_to_env(NODE *tree, ENV *env_ptr) {
169 150
   NODE* func_name = tree->left->right->left->left;
170 151
   TOKEN* name_token = (TOKEN*) func_name;
171 152
   if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
172
-    ENV* new_func_env = create_new_function_env(env_ptr);
173
-    if (tree->left->right->right != NULL) {
174
-      add_args_to_env(tree->left->right->right, new_func_env);
175
-    }
176 153
     if (env_ptr->bindings == NULL) {
177
-      env_ptr->bindings = create_list(create_binding(name_token, tree, new_func_env), NULL);
154
+      env_ptr->bindings = create_list(create_binding(name_token, tree, env_ptr), NULL);
178 155
     } else {
179
-      append_list(env_ptr->bindings, create_binding(name_token, tree, new_func_env));
156
+      append_list(env_ptr->bindings, create_binding(name_token, tree, env_ptr));
180 157
     }
181 158
   } else {
182 159
     printf("Error: redefinition of function with name %s\n", name_token->lexeme);
183 160
   }
184 161
 }
185 162
 
186
-void populate_val_list(NODE* tree, TOKEN** arr, int num_args) {
187
-  if (tree->type == LEAF) {
163
+void populate_val_list(NODE* tree, NODE** arr, int num_args, ENV* env_ptr) {
164
+  if (tree->type == ',') {
165
+    populate_val_list(tree->left, arr, num_args, env_ptr);
166
+    populate_val_list(tree->right, arr, num_args, env_ptr);
167
+  } else {
188 168
     for (int i = 0; i < num_args; i++) {
189 169
       if (arr[i] == NULL) {
190
-        TOKEN* tok = (TOKEN*) tree->left;
191
-        arr[i] = tok;
170
+        arr[i] = tree;
192 171
         break;
193 172
       }
194 173
     }
195
-  } else {
196
-    populate_val_list(tree->left, arr, num_args);
197
-    populate_val_list(tree->right, arr, num_args);
198 174
   }
199 175
 }
200 176
 
201
-TOKEN** get_val_list(NODE *tree) {
177
+NODE** get_val_list(NODE *tree, ENV* env_ptr) {
202 178
   int num_args = count_args(tree);
203
-  TOKEN** arr = (TOKEN**) malloc(sizeof(TOKEN*) * num_args);
204
-  populate_val_list(tree, arr, num_args);
179
+  NODE** arr = (NODE**) malloc(sizeof(NODE*) * num_args);
180
+  populate_val_list(tree, arr, num_args, env_ptr);
205 181
   return arr;
206 182
 }
207 183
 
208
-void bind_arg(TOKEN* val, TOKEN* arg_name, ENV *env_ptr) {
209
-  BIND* existing = find_name_in_list(arg_name, env_ptr->bindings);
210
-  if (existing == NULL) {
211
-    printf("Attempted to bind arg that doesn't exist, the compiler is broken\n");
212
-    exit(1);
184
+void bind_arg(NODE* val, TOKEN* arg_name, ENV *env_ptr, ENV* src_env) {
185
+  BIND* result = recursive_interpret(val, src_env);
186
+  if(debug)printf("Binding argument: %s\n", arg_name->lexeme);
187
+  if (env_ptr->bindings == NULL) {
188
+    env_ptr->bindings = create_list(create_binding(arg_name, result->tree, result->env), NULL);
189
+  } else {
190
+    BIND* existing = find_name_in_list(arg_name, env_ptr->bindings);
191
+    if (existing) {
192
+      existing->tree = result->tree;
193
+    } else {
194
+      append_list(env_ptr->bindings, create_binding(arg_name, result->tree, result->env));
195
+    }
213 196
   }
214
-  existing->tree = (NODE*) val;
215 197
 }
216 198
 
217 199
 void add_var_to_env(NODE *tree, ENV *env_ptr) {
218 200
   BIND* existing;
219 201
   NODE* var_name = tree->left->left;
220 202
   TOKEN* name_token = (TOKEN*) var_name;
221
-  TOKEN* tok = new_token(CONSTANT);
222
-  tok->value = recursive_interpret(tree->right, env_ptr);
223
-  asprintf(&tok->lexeme, "%d", tok->value);
203
+  if (debug) printf("assigning %s:\n", name_token->lexeme);
204
+  BIND* node = recursive_interpret(tree->right, env_ptr);
224 205
   if ((existing = find_name_in_env(name_token, env_ptr)) == NULL) {
225 206
     if (env_ptr->bindings == NULL) {
226
-      env_ptr->bindings = create_list(create_binding(name_token, (NODE*) tok, NULL), NULL);
207
+      env_ptr->bindings = create_list(create_binding(name_token, node->tree, node->env), NULL);
227 208
     } else {
228
-      append_list(env_ptr->bindings, create_binding(name_token, (NODE*) tok, NULL));
209
+      append_list(env_ptr->bindings, create_binding(name_token, node->tree, node->env));
229 210
     }
230 211
   } else {
231
-    existing->tree = (NODE *) tok;
212
+    existing->tree = node->tree;
232 213
   } 
233 214
 }
234 215
 
235
-int recursive_interpret(NODE *tree, ENV *env_ptr) {
236
-  if (tree==NULL) return 0;
216
+TOKEN* get_int_token(int value) {
217
+  TOKEN* res;
218
+  char buffer[20];
219
+  snprintf(buffer, 20, "%d", value);
220
+  res = lookup_token(buffer);
221
+  if (res->type != CONSTANT) res->type = CONSTANT;
222
+  if (res->value != value) res->value = value;
223
+  return res;
224
+}
225
+
226
+BIND* anon_binding(NODE *tree) {
227
+  return create_binding(NULL, tree, NULL);
228
+}
229
+
230
+BIND* ret_val;
231
+int returning;
232
+
233
+BIND* recursive_interpret(NODE *tree, ENV *env_ptr) {
234
+  if (returning == 1) return NULL;
235
+  if (tree==NULL) return NULL;
237 236
   if (tree->type==LEAF) {
238 237
     if (tree->left->type == CONSTANT) {
239
-      return ((TOKEN *) tree->left)->value;
238
+      return anon_binding(tree->left);
240 239
     } else if (tree->left->type == STRING_LITERAL) {
241 240
       printf("Not implemented\n");
242 241
       exit(1);
243 242
     } else if (tree->left->type == INT || tree->left->type == FUNCTION) {
244 243
       // do nothing we dont care about types for now
245
-      return 0;
244
+      return NULL;
246 245
     } else {
247 246
       // an identifier
248 247
       TOKEN* tok = (TOKEN *) tree->left;
249 248
       BIND* var_bind = find_name_in_env(tok, env_ptr);
249
+      if (debug) {
250
+        printf("looking up %s\n", tok->lexeme);
251
+      }
250 252
       if (var_bind == NULL) {
251 253
         printf("Could not find variable %s\n", tok->lexeme);
252 254
         exit(1);
253 255
       }
256
+      if(debug)printf("I got: ");
254 257
       if (var_bind->tree->type == CONSTANT) {
255
-        TOKEN* var_tok = (TOKEN *) var_bind->tree;
256
-        return var_tok->value;
258
+        if(debug){
259
+          printf("CONSTANT\n");
260
+          print_leaf(var_bind->tree, 0);
261
+        }
257 262
       } else {
258
-        printf("Maybe got a function?\n");
259
-        return 0;
263
+        if(debug)print_tree(var_bind->tree);
260 264
       }
265
+      return var_bind;
266
+      /* if (var_bind->tree->type == CONSTANT) { */
267
+      /*   return var_bind->tree; */
268
+      /* } else { */
269
+      /*   print_tree(var_bind->tree); */
270
+      /*   printf("I GOT A %d from %s\n", var_bind->tree->type, var_bind->name->lexeme); */
271
+      /*   printf("Maybe got a function?\n"); */
272
+      /*   return NULL; */
273
+      /* } */
261 274
     }
262 275
   }
263 276
   if (tree->type=='D') {
264 277
     // this is a function definition
265 278
     add_function_to_env(tree, env_ptr);
266
-    return 0;
279
+    return NULL;
267 280
   }
268 281
   if (tree->type=='=') {
269 282
     // this is a variable definition
270 283
     add_var_to_env(tree, env_ptr);
271
-    return 0;
284
+    return NULL;
272 285
   }
273 286
   if (tree->type==APPLY) {
274 287
     TOKEN* func_name = ((TOKEN*) tree->left->left);
@@ -277,26 +290,35 @@ int recursive_interpret(NODE *tree, ENV *env_ptr) {
277 290
       printf("Could not find binding for function with name %s\n", func_name->lexeme);
278 291
       exit(1);
279 292
     }
293
+    ENV* new_func_env = create_new_function_env(func->env);
294
+    if (debug) printf("Calling function %s\n", func_name->lexeme);
280 295
     if (tree->right != NULL) {
281
-      TOKEN **arg_list, **val_list;
296
+      TOKEN **arg_list;
297
+      NODE **val_list;
282 298
       int exp_args, num_args;
283 299
       exp_args = count_args(func->tree->left->right->right);
284 300
       num_args = count_args(tree->right);
285 301
       arg_list = get_argument_list(func->tree);
286
-      val_list = get_val_list(tree->right);
302
+      val_list = get_val_list(tree->right, env_ptr);
287 303
       if (exp_args == num_args) {
288 304
         for (int i = 0; i < num_args; i++) {
289
-          bind_arg(val_list[i], arg_list[i], func->env);
305
+          bind_arg(val_list[i], arg_list[i], new_func_env, env_ptr);
290 306
         }
291 307
       } else {
292 308
         printf("Incorrect arguments passed to function %s, expected %d got %d\n", func_name->lexeme, exp_args, num_args);
293 309
         exit(1);
294 310
       }
295 311
     }
296
-    return recursive_interpret(func->tree->right, func->env);
312
+    recursive_interpret(func->tree->right, new_func_env);
313
+    if (returning == 1) {
314
+      returning = 0;
315
+      return ret_val;
316
+    } else {
317
+      printf("HELP called a function with no return!!\n");
318
+    }
297 319
   }
298 320
   if (tree->type == IF) {
299
-    if (recursive_interpret(tree->left, env_ptr) == 1) {
321
+    if (((TOKEN*)recursive_interpret(tree->left, env_ptr)->tree)->value == 1) {
300 322
       ENV* scope_env = create_new_function_env(env_ptr);
301 323
       if (tree->right->type == ELSE) {
302 324
         return recursive_interpret(tree->right->left, scope_env);
@@ -312,37 +334,72 @@ int recursive_interpret(NODE *tree, ENV *env_ptr) {
312 334
     }
313 335
   }
314 336
   if (tree->type == LE_OP) {
315
-    return (int)recursive_interpret(tree->left, env_ptr) <= recursive_interpret(tree->right, env_ptr);
337
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
338
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
339
+    int result = lhs->value <= rhs->value;
340
+    return anon_binding((NODE*) get_int_token(result));
316 341
   }
317 342
   if (tree->type == GE_OP) {
318
-    return (int)recursive_interpret(tree->left, env_ptr) >= recursive_interpret(tree->right, env_ptr);
343
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
344
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
345
+    int result = lhs->value >= rhs->value;
346
+    return anon_binding((NODE*) get_int_token(result));
319 347
   }
320 348
   if (tree->type == EQ_OP) {
321
-    return (int)recursive_interpret(tree->left, env_ptr) == recursive_interpret(tree->right, env_ptr);
349
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
350
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
351
+    if (debug) printf("Comparing %d == %d\n", lhs->value, rhs->value);
352
+    int result = lhs->value == rhs->value;
353
+    return anon_binding((NODE*) get_int_token(result));
322 354
   }
323 355
   if (tree->type == NE_OP) {
324
-    return (int)recursive_interpret(tree->left, env_ptr) != recursive_interpret(tree->right, env_ptr);
356
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
357
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
358
+    int result = lhs->value != rhs->value;
359
+    return anon_binding((NODE*) get_int_token(result));
325 360
   }
326 361
   if (tree->type == '>') {
327
-    return (int)recursive_interpret(tree->left, env_ptr) > recursive_interpret(tree->right, env_ptr);
362
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
363
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
364
+    int result = lhs->value > rhs->value;
365
+    return anon_binding((NODE*) get_int_token(result));
328 366
   }
329 367
   if (tree->type == '<') {
330
-    return (int)recursive_interpret(tree->left, env_ptr) < recursive_interpret(tree->right, env_ptr);
368
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
369
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
370
+    int result = lhs->value < rhs->value;
371
+    return anon_binding((NODE*) get_int_token(result));
331 372
   }
332 373
   if (tree->type == '+') {
333
-    return recursive_interpret(tree->left, env_ptr) + recursive_interpret(tree->right, env_ptr);
374
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
375
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
376
+    if (debug) printf("Adding %d and %d\n", lhs->value, rhs->value);
377
+    int result = lhs->value + rhs->value;
378
+    return anon_binding((NODE*) get_int_token(result));
334 379
   }
335 380
   if (tree->type == '-') {
336
-    return recursive_interpret(tree->left, env_ptr) - recursive_interpret(tree->right, env_ptr);
381
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
382
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
383
+    int result = lhs->value - rhs->value;
384
+    return anon_binding((NODE*) get_int_token(result));
337 385
   }
338 386
   if (tree->type == '*') {
339
-    return recursive_interpret(tree->left, env_ptr) * recursive_interpret(tree->right, env_ptr);
387
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
388
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
389
+    int result = lhs->value * rhs->value;
390
+    return anon_binding((NODE*) get_int_token(result));
340 391
   }
341 392
   if (tree->type == '/') {
342
-    return recursive_interpret(tree->left, env_ptr) / recursive_interpret(tree->right, env_ptr);
393
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
394
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
395
+    int result = lhs->value / rhs->value;
396
+    return anon_binding((NODE*) get_int_token(result));
343 397
   }
344 398
   if (tree->type == '%') {
345
-    return recursive_interpret(tree->left, env_ptr) % recursive_interpret(tree->right, env_ptr);
399
+    TOKEN* lhs = (TOKEN*) recursive_interpret(tree->left, env_ptr)->tree;
400
+    TOKEN* rhs = (TOKEN*) recursive_interpret(tree->right, env_ptr)->tree;
401
+    int result = lhs->value % rhs->value;
402
+    return anon_binding((NODE*) get_int_token(result));
346 403
   }
347 404
   if (tree->type == '~') {
348 405
     if (tree->left->type == INT || tree->left->type == FUNCTION) {
@@ -353,11 +410,12 @@ int recursive_interpret(NODE *tree, ENV *env_ptr) {
353 410
     }
354 411
   }
355 412
   if (tree->type == RETURN) {
356
-    return recursive_interpret(tree->left, env_ptr);
413
+    ret_val = recursive_interpret(tree->left, env_ptr);
414
+    returning = 1;
357 415
   }
358 416
   if (tree->type == WHILE) {
359 417
     ENV* scope_env = create_new_function_env(env_ptr);
360
-    while (recursive_interpret(tree->left, env_ptr)) {
418
+    while(((TOKEN*)recursive_interpret(tree->left, env_ptr)->tree)->value == 1) {
361 419
       recursive_interpret(tree->right, scope_env);
362 420
     }
363 421
     return 0;
@@ -381,7 +439,9 @@ void interpret_tree(NODE *tree) {
381 439
   }
382 440
   // print ref_main to make sure we really got it
383 441
   printf("Located %s, ready to run!\n", ref_main->name->lexeme);
384
-  printf("%d\n", recursive_interpret(ref_main->tree->right, ref_main->env));
442
+  recursive_interpret(ref_main->tree->right, ref_main->env);
443
+  /* printf("%d\n", ((TOKEN*)recursive_interpret(ref_main->tree->right, ref_main->env))->value); */
444
+  printf("%d\n", ((TOKEN*)ret_val->tree)->value);
385 445
 }
386 446
 
387 447
 extern int yydebug;
@@ -392,7 +452,7 @@ extern void init_symbtable(void);
392 452
 int main(int argc, char** argv)
393 453
 {
394 454
     NODE* tree;
395
-    if (argc>1 && strcmp(argv[1],"-d")==0) yydebug = 1;
455
+    if (argc>1 && strcmp(argv[1],"-d")==0) debug = 1;
396 456
     init_symbtable();
397 457
     printf("--C COMPILER\n");
398 458
     yyparse();

+ 9 - 14
cw/simple.c

@@ -1,20 +1,15 @@
1
-int sum(int a, int b, int c) {
2
-  int y = 0;
3
-  if (a > 2) {
4
-    int x = 3;
5
-    y = x;
6
-  }
7
-  return y + b + c;
1
+int whammy(int a) {
2
+  return a + 5;
8 3
 }
9 4
 
10
-int fact(int n) {
11
-  int inner_fact(int n, int a) {
12
-    if (n == 0) return a;
13
-    return inner_fact(n-1, a*n);
14
-  }
15
-  return inner_fact(n, 1);
5
+function twice(function f) {
6
+  int g(int x) { return f(f(x)); }
7
+  return g;
16 8
 }
17 9
 
18 10
 int main() {
19
-  return fact(3);
11
+  x = twice(whammy);
12
+
13
+  return x(2);
20 14
 }
15
+

+ 3 - 0
cw/tests/cond_loop.c

@@ -1,11 +1,14 @@
1
+/* ##answer: 17*/
1 2
 int y = 0;
2 3
 
3 4
 int incr_one() {
4 5
   y = y + 1;
6
+  return 0;
5 7
 }
6 8
 
7 9
 int incr_two() {
8 10
   y = y + 2;
11
+  return 0;
9 12
 }
10 13
 
11 14
 int main() {

+ 17 - 0
cw/tests/cplus.c

@@ -0,0 +1,17 @@
1
+/* ##answer: 29 */
2
+function cplus(int a) {
3
+  int cplusa(int b) {
4
+    return a + b;
5
+  }
6
+
7
+  return cplusa;
8
+}
9
+
10
+int main() {
11
+  int x = cplus(5);
12
+  int y = x;
13
+  int f = cplus(2);
14
+  int z = y;
15
+
16
+  return x(2) + f(2) + y(5) + z(3);
17
+}

+ 1 - 4
cw/tests/func_args.c

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

+ 2 - 0
cw/tests/func_call.c

@@ -1,3 +1,5 @@
1
+/* ##answer: 8*/
2
+
1 3
 int foo() {
2 4
   return 5;
3 5
 }

+ 4 - 0
cw/tests/modulo.c

@@ -0,0 +1,4 @@
1
+/* ##answer: 1*/
2
+int main() {
3
+  return 5 % 2; 
4
+}

+ 37 - 0
cw/tests/new_test.sh

@@ -0,0 +1,37 @@
1
+#!/bin/bash
2
+uname=`uname`
3
+if [ "$uname" = "Darwin" ]; then
4
+  date="gdate"
5
+  readlink="greadlink"
6
+else
7
+  date="date"
8
+  readlink="readlink"
9
+fi
10
+start=$($date +%s.%N)
11
+absdir=$($readlink -f $(dirname $0))
12
+
13
+pass="\033[32mPASSED\033[0m"
14
+fail="\033[31mFAILED\033[0m"
15
+
16
+tests=0
17
+passes=0
18
+
19
+for i in $(ls $absdir | grep .\*.c | sort); do
20
+  answer=`$absdir/../mycc < $absdir/$i | tail -n 1`
21
+  exp_ans=`grep --color=none "##answer" $absdir/$i | sed 's/[^0-9]\+\([0-9]\+\).\+/\1/g'`
22
+  echo -n "${i%.*} ... "
23
+  if [ "$answer" -eq "$exp_ans" ]; then
24
+    echo -e "$pass"
25
+    passes=$((passes+1))
26
+  else
27
+    echo -e "$fail expected $exp_ans got $answer"
28
+  fi
29
+  tests=$((tests+1))
30
+done
31
+
32
+end=$($date +%s.%N)    
33
+runtime=$(python -c "print(${end} - ${start})")
34
+
35
+echo -e "\n$passes/$tests passed in $runtime""s"
36
+
37
+exit $((tests-passes))

+ 17 - 0
cw/tests/recursion.c

@@ -0,0 +1,17 @@
1
+/* ##answer: 5166*/
2
+
3
+int fact(int n) {
4
+  int inner_fact(int n, int a) {
5
+    if (n == 0) return a;
6
+    return inner_fact(n-1, a*n);
7
+  }
8
+  return inner_fact(n, 1);
9
+}
10
+
11
+int main() {
12
+  int x = fact(3);
13
+  int y = fact(5);
14
+  int z = fact(7);
15
+
16
+  return x+y+z;
17
+}

+ 1 - 0
cw/tests/return_only.c

@@ -1,3 +1,4 @@
1
+/* ##answer: 3*/
1 2
 int main() {
2 3
   return 1 + 2;
3 4
 }

+ 4 - 0
cw/tests/sub.c

@@ -0,0 +1,4 @@
1
+/* ##answer: 5 */
2
+int main() {
3
+  return 10 - 5;
4
+}

+ 24 - 51
cw/tests/test.sh

@@ -1,70 +1,43 @@
1
-#/bin/bash
1
+#!/bin/bash
2 2
 uname=`uname`
3 3
 if [ "$uname" = "Darwin" ]; then
4 4
   date="gdate"
5 5
   readlink="greadlink"
6
+  wc="gwc"
6 7
 else
7 8
   date="date"
8 9
   readlink="readlink"
10
+  wc="wc"
9 11
 fi
10 12
 start=$($date +%s.%N)
11 13
 absdir=$($readlink -f $(dirname $0))
12
-ret_only=`$absdir/../mycc < $absdir/return_only.c | tail -n 1`
13
-var_maths=`$absdir/../mycc < $absdir/var_maths.c | tail -n 1`
14
-func_call=`$absdir/../mycc < $absdir/func_call.c | tail -n 1`
15
-cond_loop=`$absdir/../mycc < $absdir/cond_loop.c | tail -n 1`
16
-func_args=`$absdir/../mycc < $absdir/func_args.c | tail -n 1`
17
-
18
-ret_ans='3'
19
-var_ans='11'
20
-func_ans='8'
21
-args_ans='14'
22
-cond_ans='17'
23
-
24
-overall='0'
25 14
 
26 15
 pass="\033[32mPASSED\033[0m"
27 16
 fail="\033[31mFAILED\033[0m"
28 17
 
29
-if [ "$ret_only" -eq $ret_ans ]; then
30
-  echo "return_only ... $pass"
31
-else
32
-  echo -n "return_only ... $fail"
33
-  echo " expected $ret_ans but got $ret_only"
34
-  overall='1'
35
-fi
36
-if [ "$var_maths" -eq $var_ans ]; then
37
-  echo "var_maths ..... $pass"
38
-else
39
-  echo "var_maths ..... $fail"
40
-  echo " expected $var_ans but got $var_maths"
41
-  overall='1'
42
-fi
43
-if [ "$func_call" -eq $func_ans ]; then
44
-  echo "func_call ..... $pass"
45
-else
46
-  echo -n "func_call ..... $fail"
47
-  echo " expected $func_ans but got $func_call"
48
-  overall='1'
49
-fi
50
-if [ "$cond_loop" -eq $cond_ans ]; then
51
-  echo "cond_loop ..... $pass"
52
-else
53
-  echo -n "cond_loop ..... $fail"
54
-  echo " expected $cond_ans but got $cond_loop"
55
-  overall='1'
56
-fi
57
-if [ "$func_args" -eq $args_ans ]; then
58
-  echo "func_args ..... $pass"
59
-else
60
-  echo -n "func_args ..... $fail"
61
-  echo " expected $args_ans but got $func_args"
62
-  overall='1'
63
-fi
18
+tests=0
19
+passes=0
20
+
21
+num=`ls $absdir | grep .\*.c | $wc -L`
22
+num=$((num-2))
23
+fmt=`echo "%-$num""s"`
24
+for i in $(ls $absdir | grep .\*.c | sort); do
25
+  answer=`$absdir/../mycc < $absdir/$i | tail -n 1`
26
+  exp_ans=`grep --color=none "##answer" $absdir/$i | sed 's/[^0-9]\+\([0-9]\+\).\+/\1/g'`
27
+  printf $fmt "${i%.*}"
28
+  echo -n " ... "
29
+  if [ "$answer" -eq "$exp_ans" ]; then
30
+    echo -e "$pass"
31
+    passes=$((passes+1))
32
+  else
33
+    echo -e "$fail expected $exp_ans got $answer"
34
+  fi
35
+  tests=$((tests+1))
36
+done
64 37
 
65 38
 end=$($date +%s.%N)    
66 39
 runtime=$(python -c "print(${end} - ${start})")
67 40
 
68
-echo "\nCompleted 5 tests in $runtime""s"
41
+echo -e "\n$passes/$tests passed in $runtime""s"
69 42
 
70
-exit $overall
43
+exit $((tests-passes))

+ 16 - 0
cw/tests/twice.c

@@ -0,0 +1,16 @@
1
+/* ##answer: 12*/
2
+int whammy(int a) {
3
+  return a + 5;
4
+}
5
+
6
+function twice(function f) {
7
+  int g(int x) { return f(f(x)); }
8
+  return g;
9
+}
10
+
11
+int main() {
12
+  x = twice(whammy);
13
+
14
+  return x(2);
15
+}
16
+

+ 1 - 0
cw/tests/var_maths.c

@@ -1,3 +1,4 @@
1
+/* ##answer: 11*/
1 2
 int main() {
2 3
   int x = 5;
3 4
 

+ 1 - 0
cw/types.h

@@ -15,6 +15,7 @@ typedef struct blist {
15 15
 
16 16
 typedef struct environ {
17 17
   BLIST *bindings;
18
+  NODE *ret_val;
18 19
   struct environ *parent;
19 20
 } ENV;
20 21