/* fail-assign1.cp */

int main()
{
  int i;
  bool b;

  i = 42;
  i = 10;
  b = true;
  b = false;
  i = false; /* Fail: assigning a bool to an integer */
}
/* fail-assign2.cp */


int main()
{
  int i;
  bool b;

  b = 48; /* Fail: assigning an integer to a bool */
}
/* fail-assign3.cp */

void myvoid()
{
  return;
}

int main()
{
  int i;

  i = myvoid(); /* Fail: assigning a void to an integer */
}
/* fail-chainassigndecl.cp */

int main()
{
    int x = y = z = 1;
    return 0;
}
/* fail-dead1.cp */

int main()
{
  int i;  

  i = 15;
  return i;
  i = 32; /* Error: code after a return */
}
/* fail-dead2.cp */

int main()
{
  int i;  

  {
    i = 15;
    return i;
  }
  i = 32; /* Error: code after a return */
}
/* fail-expr1.cp */

int a;
bool b;

void foo(int c, bool d)    
{
  int dd;
  bool e;
  a + c;
  c - a;
  a * 3;
  c / 2;
  d + a; /* Error: bool + int */
}

int main()
{
  return 0;
}
/* fail-expr2.cp */

int a;
bool b;

void foo(int c, bool d)    
{
  int d;
  bool e;
  b + a; /* Error: bool + int */
}

int main()
{
  return 0;
}
/* fail-for1.cp */

int main()
{
  int i;
  for ( ; true ; ) {} /* OK: Forever */

  for (i = 0 ; i < 10 ; i = i + 1) {
    if (i == 3) return 42;
  }

  for (j = 0; i < 10 ; i = i + 1) {} /* j undefined */

  return 0;
}
/* fail-for2.cp */

int main()
{
  int i;

  for (i = 0; j < 10 ; i = i + 1) {} /* j undefined */

  return 0;
}
/* fail-for3.cp */

int main()
{
  int i;

  for (i = 0; i ; i = i + 1) {} /* i is an integer, not Boolean */

  return 0;
}
/* fail-for4.cp */

int main()
{
  int i;

  for (i = 0; i < 10 ; i = j + 1) {} /* j undefined */

  return 0;
}
/* fail-for5.cp */

int main()
{
  int i;

  for (i = 0; i < 10 ; i = i + 1) {
    foo(); /* Error: no function foo */
  }

  return 0;
}
/* fail-func1.cp */

int foo() {}

int bar() {}

int baz() {}

void bar() {} /* Error: duplicate function bar */

int main()
{
  return 0;
}
/* fail-func2.cp */

int foo(int a, bool b, int c) { }

void bar(int a, bool b, int a) {} /* Error: duplicate formal a in bar */

int main()
{
  return 0;
}
/* fail-func3.cp */

int foo(int a, bool b, int c) { }

void bar(int a, void b, int c) {} /* Error: illegal void formal b */

int main()
{
  return 0;
}
/* fail-func4.cp */

int foo() {}

void bar() {}

int print() {} /* Should not be able to define print */

void baz() {}

int main()
{
  return 0;
}
/* fail-func5.cp */

int foo() {}

int bar() {
  int a;
  void b; /* Error: illegal void local b */
  bool c;

  return 0;
}

int main()
{
  return 0;
}
/* fail-func6.cp */

void foo(int a, bool b)
{
}

int main()
{
  foo(42, true);
  foo(42); /* Wrong number of arguments */
}
/* fail-func7.cp */

void foo(int a, bool b)
{
}

int main()
{
  foo(42, true);
  foo(42, true, false); /* Wrong number of arguments */
}
/* fail-func8.cp */

void foo(int a, bool b)
{
}

void bar()
{
}

int main()
{
  foo(42, true);
  foo(42, bar()); /* int and void, not int and bool */
}
/* fail-func9.cp */

void foo(int a, bool b)
{
}

int main()
{
  foo(42, true);
  foo(42, 42); /* Fail: int, not bool */
}
/* fail-global1.cp */

int c;
bool b;
void a; /* global variables should not be void */


int main()
{
  return 0;
}
/* fail-global2.cp */

int b;
bool c;
int a;
int b; /* Duplicate global variable */

int main()
{
  return 0;
}
/* fail-if1.cp */

int main()
{
  if (true) {}
  if (false) {} else {}
  if (42) {} /* Error: non-bool predicate */
}

/* fail-if2.cp */

int main()
{
  if (true) {
    foo; /* Error: undeclared variable */
  }
}
/* fail-if3.cp */

int main()
{
  if (true) {
    42;
  } else {
    bar; /* Error: undeclared variable */
  }
}
/* fail-malloc.cp */

int main()
{
    malloc(3*3);
    return 0;
}
/* fail-mallocbool.cp */

int main()
{
    malloc(true*sizeof(int));
    return 0;
}
/* fail-nomain.cp */
/* fail-pointerassign.cp */

int main()
{
    int* i;
    bool* b;
    i = b; /* Error: illegal pointer assignment */
}
/* fail-return1.cp */

int main()
{
  return true; /* Should return int */
}
/* fail-return2.cp */

void foo()
{
  if (true) return 42; /* Should return void */
  else return;
}

int main()
{
  return 42;
}
/* fail-while1.cp */

int main()
{
  int i;

  while (true) {
    i = i + 1;
  }

  while (42) { /* Should be boolean */
    i = i + 1;
  }

}

/* fail-while2.cp */

int main()
{
  int i;

  while (true) {
    i = i + 1;
  }

  while (true) {
    foo(); /* foo undefined */
  }

}
/* test-add1.cp */

int add(int x, int y)
{
  return x + y;
}

int main()
{
  print( add(17, 25) );
  return 0;
}
/* test-addinit.cp */

int main()
{
    int x = 4 + 2;
    print(x);
    return 0;
}
/* test-app_insert.cp */

/* ============================= Data Structures  ================================== */

/* Stores a key-value property pair for a given node */
struct Prop {
  /* memory struct to retain properties */
  int prop_id;
  char* property;
  char* value;
};

/* Node data structure */
struct Node {
  /* node_id is hash int id, node_label is string id, prop are properties */
  int node_id;
  int prop_cnt;
  char* node_label;
  Prop *property[10];
};

int node_index_avail = 1000;

/* Edge data structure */
struct Edge {
  /* edge_id is has int id, edge_label is string id, prop are properties */
  int edge_id;
	int num_pairs;
	int prop_cnt;
  char* edge_label;
	Node *src;
	Node *trg;
  Prop *property;
};

int nodes = 0;
int edges = 0;
int properties = 0;
/* int node_index_avail = 1000; */
/* Node* nodeIndex[node_index_avail]; */
Node* dummyItem;
Node* item;
/* struct edge* edgeIndex[1000]; */
/* struct edge* dummyItemEdge; */
/* struct edge* itemEdge; */
Prop* propIndex[1000];
Prop* dummyItemProp;
Prop* itemProp;

/* ============================= Creation Functions ========================= */

/* Insert a Node into Hashable Index for Reference */
int insert_node(char* key) {

  /* have to declare all variables at the beginning */
  Node *item = (Node*) malloc(sizeof(Node));
  int hashIndex = 0, i = 0; /* have to declare are variables at the top of a function */

  /* FIXME this should be globals!!! */
  Node* nodeIndex[node_index_avail];

  /* make a tmp node to initialize the "global" nodeIndex array */
  Node* tmpNode = (Node*) malloc(sizeof(Node));
  tmpNode->node_label = "init";
  tmpNode->prop_cnt = 0;
  tmpNode->node_id = 0;


  /* FIXME: strdup is broken, might be returning null */
  /* item->node_label = strdup(key); */
  item->node_label = key;
  item->prop_cnt = 0;

  /* get the hash */
  /* printf is not that fancy yet */
  printf("Insert node: ");
  printf(key);
  printf("\n");

  for (i = 0; i < node_index_avail; i++){
    nodeIndex[i] = tmpNode;
  }

  /* move in array until an empty or deleted cell */
  while(hashIndex < node_index_avail && nodeIndex[hashIndex]->node_id != -1) {
     /* go to next cell */
     ++hashIndex;
  }
  node_index_avail--;

  item->node_id = hashIndex;
  nodeIndex[hashIndex] = item;
  printf("inserted at index: "); print(hashIndex); printf("\n");
  return hashIndex;

}

/* ============================== MAIN =========================== */
int main()
{
  int main_node_id = insert_node("main_node");
  printf("Main node id: "); print(main_node_id); printf("\n");
  return 0;
}
/* test-application.cp */

int size = 1000;

struct Record {
    char* name;
    int student_id;
    int grade;
};

int main()
{
    Record class[size];
    Record tmp;
    int i = 0;
    
    for (i = 0; i < size; i++){
        tmp.student_id = size % (2 * i + 3);
        class[i] = tmp;
    }

    tmp = class[7];
    print(tmp.student_id);

    return 0;
}
/* test-arith1.cp */

int main()
{
  print(39 + 3);
  return 0;
}
/* test-arith2.cp */

int main()
{
  print(1 + 2 * 3 + 4);
  return 0;
}
/* test-arith3.cp */

int foo(int a)
{
  return a;
}

int main()
{
  int a;
  a = 42;
  a = a + 5;
  print(a);
  return 0;
}
/* test-arrayaccess.cp */

int main()
{
    int a[10], i;
    for(i = 0; i < 9; i++){
       a[i] = i; 
    } 
    print(a[3]);
    print(a[4]);
    print(a[5]);
    print(a[6]);
    return 0;
}
/* test-arraydecl.cp */

int main()
{
    int a[10], i;
    a;
}
/*
 * test-castvoidptr_to_intptr.cp
 *
 * Test that the cast functionality works as an expression 
 *
 * Date 4-12-2017
 *
 */

int main()
{
   void* x;
   int* y;
   y = (int*) x;
   return 0;
}
/* test chain of assignment operators */

int main()
{
    int a, b, c, d;
    a = b = c = d;
    return 0;
}
/* test-charstar.cp */

int main()
{
    char* c = "this is a char star.\n";
    printf(c);
    return 0;
}
/* test initialization lists */

int main()
{
    int a = 1, b = 2, c = 3, d = 4;
    print(d);
    return 0;
}
/* test-fib.cp */

int fib(int x)
{
  if (x < 2) return 1;
  return fib(x-1) + fib(x-2);
}

int main()
{
  print(fib(0));
  print(fib(1));
  print(fib(2));
  print(fib(3));
  print(fib(4));
  print(fib(5));
  return 0;
}
/* test-for1.cp */

int main()
{
  int i;
  for (i = 0 ; i < 5 ; i = i + 1) {
    print(i);
  }
  print(42);
  return 0;
}
/* test-for2.cp */

int main()
{
  int i;
  i = 0;
  for ( ; i < 5; ) {
    print(i);
    i = i + 1;
  }
  print(42);
  return 0;
}
/* test-func1.cp */

int add(int a, int b)
{
  return a + b;
}

int main()
{
  int a;
  a = add(39, 3);
  print(a);
  return 0;
}
/* test-func2.cp */

/* Bug noticed by Pin-Chin Huang */

int fun(int x, int y)
{
  return 0;
}

int main()
{
  int i;
  i = 1;

  fun(i = 2, i = i+1);

  print(i);
  return 0;
}

/* test-func3.cp */

void printem(int a, int b, int c, int d)
{
  print(a);
  print(b);
  print(c);
  print(d);
}

int main()
{
  printem(42,17,192,8);
  return 0;
}
/* test-func4.cp */

int add(int a, int b)
{
  int c;
  c = a + b;
  return c;
}

int main()
{
  int d;
  d = add(52, 10);
  print(d);
  return 0;
}
/* test-func5.cp */

int foo(int a)
{
  return a;
}

int main()
{
  return 0;
}
/* test-func6.cp */

void foo() {}

int bar(int a, bool b, int c) { return a + c; }

int main()
{
  print(bar(17, false, 25));
  return 0;
}
/* test-func7.cp */

int a;

void foo(int c)
{
  a = c + 42;
}

int main()
{
  foo(73);
  print(a);
  return 0;
}
/* test-func8.cp */

void foo(int a)
{
  print(a + 3);
}

int main()
{
  foo(40);
  return 0;
}
/* test-gcd.cp */

int gcd(int a, int b) {
  while (a != b) {
    if (a > b) a = a - b;
    else b = b - a;
  }
  return a;
}

int main()
{
  print(gcd(2,14));
  print(gcd(3,15));
  print(gcd(99,121));
  return 0;
}
/* test-gcd2.cp */

int gcd(int a, int b) {
  while (a != b)
    if (a > b) a = a - b;
    else b = b - a;
  return a;
}

int main()
{
  print(gcd(14,21));
  print(gcd(8,36));
  print(gcd(99,121));
  return 0;
}
/* test-gobainit.cp */

int size = 100;

int main()
{
    print(size);
    return 0;
}
/* test-global1.cp */

int a;
int b;

void print_a()
{
  print(a);
}

void print_b()
{
  print(b);
}

void incab()
{
  a = a + 1;
  b = b + 1;
}

int main()
{
  a = 42;
  b = 21;
  print_a();
  print_b();
  incab();
  print_a();
  print_b();
  return 0;
}
/* test-global2.cp */

bool i;

int main()
{
  int i; /* Should hide the global i */

  i = 42;
  print(i + i);
  return 0;
}
/* test-global3.cp */

int i;
bool b;
int j;

int main()
{
  i = 42;
  j = 10;
  print(i + j);
  return 0;
}
/* test-hello.cp */

int main()
{
  print(42);
  print(71);
  print(1);
  return 0;
}
/* test-if1.cp */

int main()
{
  if (true) print(42);
  print(17);
  return 0;
}
/* test-if2.cp */

int main()
{
  if (true) print(42); else print(8);
  print(17);
  return 0;
}
/* test-if3.cp */

int main()
{
  if (false) print(42);
  print(17);
  return 0;
}
/* test-if4.cp */

int main()
{
  if (false) print(42); else print(8);
  print(17);
  return 0;
}
/* test-if5.cp */

int cond(bool b)
{
  int x;
  if (b)
    x = 42;
  else
    x = 17;
  return x;
}

int main()
{
 print(cond(true));
 print(cond(false));
 return 0;
}
/* test-inlinefor.cp */

int main()
{
    int i;
    for (i=0;i < 10;i++){}
    return 0;
}
/* test-lazybooboo.cp */

int main()
{
    int x = 1;
    int y = x + 1;
    x = 5;
    print(x);
    print(y);
}
/* test-local1.cp */

void foo(bool i)
{
  int i; /* Should hide the formal i */

  i = 42;
  print(i + i);
}

int main()
{
  foo(true);
  return 0;
}
/* test-local2.cp */

int foo(int a, bool b)
{
  int c;
  bool d;

  c = a;

  return c + 10;
}

int main() {
 print(foo(37, false));
 return 0;
}
/* test-mallocassign.cp */

int main()
{
    int* array = (int*) malloc(sizeof(int));
    array;
    return 0;
}
/* test-mallocassign2.cp */

int main()
{
    int x;
    int* ptr = (int*) malloc(sizeof(int));
    *ptr = 5;
    print(*ptr); 
    return 0;
}
/* test-mallocexpr.cp */
/*
 * Test for assigning a value to a pointer, via the 
 * linked in C malloc function
 *
 * Date 4-11-2017
 *
 */

int main()
{
   malloc(sizeof(int));
   return 0;
}
/* test-modequals.cp */

int main()
{
    int i;
    i = 11;
    i %= 2;
    print(i);
    return 0;
}
/* test-multimalloc.cp */

/* test for allocating multiple entries */

int main()
{
    malloc(10*sizeof(int));
    malloc(sizeof(bool)*300);
    return 0;
}
/* test-multiptraddr.cp */

int main()
{
    int a;
    int *b = &a;
    int *c = &a;

    *b = 5;
    *c = 42;

    print(a);
    print(*b);
    print(*c); 

    return 0;
}
/* test-nestedcall.cp */

int a (int x)
{
    return x + 1;
}

int b (int y)
{
    return y + 2;
}

int main()
{
    int z = 5;
    print(b(a(z)));
    return 0;
}
/* test-nodeEdgeHash.cp */

/* Hashable Code for Node/Edge ID */
int hashCode(int key, int size) {
   return key % size;
}

/* Node data structure */
struct Node {
        /* node_id is hash int id, node_label is string id, prop are properties */
        int node_id;
        char* node_label;
        char* prop;
};

/* Edge data structure */
struct Edge {
        /* edge_id is has int id, edge_label is string id, prop are properties */
        int edge_id;
        int source_id;
        int sink_id;
        char* edge_label;
        char* prop;

};

int size = 100;
Node* hashArray[100];
Node* dummyItem;
Node* item;

int main()
{
    Node n1, n2, n3;
    Edge e1, e2, e3;
    int h = hashCode(1005, size);
    print(h);
    return 0;
}
/* test-ops1.cp */

int main()
{
  print(1 + 2);
  print(1 - 2);
  print(1 * 2);
  print(100 / 2);
  print(99);
  printb(1 == 2);
  printb(1 == 1);
  print(99);
  printb(1 != 2);
  printb(1 != 1);
  print(99);
  printb(1 < 2);
  printb(2 < 1);
  print(99);
  printb(1 <= 2);
  printb(1 <= 1);
  printb(2 <= 1);
  print(99);
  printb(1 > 2);
  printb(2 > 1);
  print(99);
  printb(1 >= 2);
  printb(1 >= 1);
  printb(2 >= 1); 
  return 0;
}
/* test-ops2.cp */

int main()
{
  printb(true);
  printb(false);
  printb(true && true);
  printb(true && false);
  printb(false && true);
  printb(false && false);
  printb(true || true);
  printb(true || false);
  printb(false || true);
  printb(false || false);
  printb(!false);
  printb(!true);
  print(-10);
  print(--42); /* WHY DOESNT THIS WORK */
}
/* test-pluspluspostfix.cp */

int main()
{
    int i = 1;
    i++;
    print(i);
    return 0;
}
/* test-plusplusprefix.cp */

int main()
{
    int i = 1;
    ++i;
    print(i);
    return 0;
}
/* test-pointeradd.cp */

/* test for enabling pointer addition */

int main()
{
    int* x;
    x = (int*) malloc(2*sizeof(int));
    *x = 5;
    x = x + 1;
    *x = 10;
    print(*x);
    return 0;
}
/* test-pointeraddress.cp */

/*
 * Test for getting the address of a pointer, via the 
 * via the '&' operator
 *
 * Date 4-11-2017
 *
 */

int main()
{
   int x;
   int * ptr;
   int ** ptr1;
   x = 5;
   ptr = &x;
   ptr1 = &ptr;
   return 0;
}
/* test-pointerassign.cp */

/*
 * Test for assigning a value to a pointer, via the 
 * linked in C malloc function
 *
 * Date 4-11-2017
 *
 */

int main()
{
   int * ptr1;
   int * ptr2;
   ptr1 = ptr2;
   return 0;
}
/* test-pointerdecl.cp */

/*
 * Test for declaring a "pointer variable"
 *
 * This simple test just needs not to fail when the variable is declared.
 * Does NOT test assignment to the pointer, which will be another test.
 *
 * Date: 4-11-2017
 *
 */

int main()
{
  int * ptr;
  return 0;
}
/* test-pointerderef.cp */

/* This test uses the pointer dereference operator
 * 
 * Date: 4-22-2017
 *
 */

int main()
{
    int x;
    int * p;
    int y;
    x = 5;
    p = &x;
    y = *p;
    print(y);
    return 0;
}
/* test-pointerexpr.cp */

/*
 * Test for proving that a pointer is an acceptable statement
 *
 * Date 4-12-2017
 *
 */

int main()
{
   int * ptr;
   ptr;
   return 0;
}
/* test-pointerfree.cp */

/*
 * Test for freeing allocated memory with linked-in C free() function 
 *
 * Date 4-13-2017
 *
 */

int main()
{
   int * ptr;
   ptr = (int*) malloc(sizeof(int));
   free(ptr);
   return 0;
}
/* test-pointerlhs.cp */

/* Tests whether a pointer can be used on the LHS without a declaration */

int main()
{
    int * p;
    p = (int*) malloc(sizeof(int));
    *p = 5;
    print(*p);
    return 0;
}
/* test-pointermalloc.cp */

/*
 * Test for assigning a value to a pointer, via the 
 * linked in C malloc function
 *
 * Date 4-11-2017
 *
 */

int main()
{
   int * ptr;
   ptr = (int*) malloc(sizeof(int));
   return 0;
}
/* test-printbig.cp */

/*
 * Test for linking external C functions to LLVM-generated code
 *
 * printbig is defined as an external function, much like printf
 * The C compiler generates printbig.o
 * The LLVM compiler, llc, translates the .ll to an assembly .s file
 * The C compiler assembles the .s file and links the .o file to generate
 * an executable
 */

int main()
{
  printbig(72); /* H */
  printbig(69); /* E */
  printbig(76); /* L */
  printbig(76); /* L */
  printbig(79); /* O */
  printbig(32); /*   */
  printbig(87); /* W */
  printbig(79); /* O */
  printbig(82); /* R */
  printbig(76); /* L */
  printbig(68); /* D */
  return 0;
}
/* test-printf.cp */

/*
 * Test for linking "hello world" enablement in CPLUS
 *
 * printf is defined as an external function
 * The C compiler generates printbig.o, which includes the C standard IO library
 * which includes printf.
 * The LLVM compiler, llc, translates the .ll to an assembly .s file
 * The C compiler assembles the .s file and links the .o file to generate
 * an executable
 *
 * Date: 3-20-2017
 *
 */

int main()
{
  printf("Hello, My name is Alex\n");
  return 0;
}
/* test-sizeof.cp */

/*
 * test-sizeof.cp 
 * Test for using the sizeof operator
 *
 * Date 4-12-2017
 *
 */

int main()
{
   size_t x; 
   x = sizeof(int);
   return 0;
}
/* test-strlit.cp */

void accept(string s)
{
    return;
}

int main()
{
    string s;
    s = "hello world";
    accept(s);
    return 0;
}
/* test-structaccess.cp */

struct Test {
    int x;
    bool y;
    int a[10];
};

int main()
{
    Test t;
    t.x = 8;
    print(t.x);
    return 0;
}
/* test-structarrow.cp */

struct Test {
    int x;
    bool y;
    int a[10];
};

int main()
{
    Test* t = (Test*) malloc(sizeof(Test));
    t->x = 8;
    print(t->x);
    return 0;
}
/* test-structdecl.cp */

struct Test {
    int x;
    bool y;
    int a[10];
};

int main()
{
    Test t;
    return 0;
}
/* test-var2.cp */

int main()
{
  int a;
  a = 42;
  print(a);
  return 0;
}
/* test-var2.cp */

int a;

void foo(int c)
{
  a = c + 42;
}

int main()
{
  foo(73);
  print(a);
  return 0;
}
/* test-while1.cp */

int main()
{
  int i;
  i = 5;
  while (i > 0) {
    print(i);
    i = i - 1;
  }
  print(42);
  return 0;
}
/* test-while2.cp */

int foo(int a)
{
  int j;
  j = 0;
  while (a > 0) {
    j = j + 2;
    a = a - 1;
  }
  return j;
}

int main()
{
  print(foo(7));
  return 0;
}
