// #module_parameters(RUN_TESTS := false);

#load "parser.jai";
#load "interp.jai";

#scope_module;

// exported to the entire module since we want these everywhere

mem   :: #import "jc/memory";
array :: #import "jc/array";
kv    :: #import "jc/kv";

basic   :: #import "Basic"; // @future
strings :: #import "String"; // @future

#scope_file;

#run {
   parser: Parser;
   init(*parser, context.allocator);

   ok := parse_string(*parser, #string END
      fn add(l, r) do return l + r end
      fn sub(l, r) do return l - r end
      fn mul(l, r) do return l * r end
      fn div(l, r) do return l / r end

      var x = 21.0
      var y = 22.0
      var z = x + y

      x = x + 1.0 / 2.0
      print x

      x = add(x, div(1.0, 2.0))
      print x

      print x == x
      print x == y
      print x == z

      assert x == y
      assert x != z

      // def (
      //    Add = poly[T] proc(x T, y T) T do return x + y end
      //    Sub = poly[T] proc(x T, y T) T do return x - y end
      //    Mul = poly[T] proc(x T, y T) T do return x * y end
      //    Div = poly[T] proc(x T, y T) T do return x / y end
      // )

      // def (
      //    Addi = Add[int]
      //    Addf = Add[float]
      //    Subi = Sub[int]
      //    Subf = Sub[float]
      //    Muli = Mul[int]
      //    Mulf = Mul[float]
      //    Divi = Div[int]
      //    Divf = Div[float]
      // )

      // def Foo = struct {
      //    x int = 1
      //    y int = 2
      //    z int = 3
      // }

      // def Value = union {
      //    i int
      //    f float
      //    b bool
      // }

      // def Kind = enum {
      //    a
      //    b
      //    c
      //    d
      // }

      // var foo  = Foo{ x = 10, y = 20, z = 30 }
      // var val  = Value{ f = 3.14 }
      // var kind = Kind.a
   END);

   interp: Interp;
   interp.toplevel = parser.toplevel;
   init(*interp, context.allocator);

   interp_program(*interp);
}

// #if RUN_TESTS {
//    test :: #import "jc/test";
// }
