#!/usr/bin/ruby

# Test for `const` declared in a module.
# https://github.com/trizen/sidef/issues/77

module F {
  const VALUE = "any value"
}

# works
assert_eq("works "+(nil || F::VALUE), "works any value")

class A {
  method f {
    # works
    assert_eq("works "+F::VALUE, "works any value")
    "ok "+(nil || F::VALUE)
  }
}

func x {
  assert_eq("works "+F::VALUE, "works any value")
  return ("ok "+(nil || F::VALUE))
}

var a = A()
assert_eq(a.f, "ok any value")
assert_eq(x(), "ok any value")


# Make sure `const` is initialized at declaration.
# https://github.com/trizen/sidef/issues/81

do {
    var n = 42

    func bar {
        ++n
    }

    func foo() {
        const t = bar()
        10.of { bar() }
        return t
    }

    assert_eq(foo(), 43)
}

do {
    const v = 42
    assert_eq(v, 42)

    func foo(n) {
        const _v = n
    }

    assert_eq(foo(3), 3)
    assert_eq(foo(4), 4)

    func bar(n) {
        const v = n
        return v
    }

    assert_eq(bar(5), 5)
    assert_eq(bar(6), 6)
}

do {
    const String foo = "hello"  # now works under -O2
    assert_eq(foo, "hello")
}

do {
    func factorial(n) {
        const f = (n <= 1 ? 1 : n*factorial(n-1))
        f
    }

    assert_eq(factorial(5), 120)
    assert_eq(factorial(6), 720)
}

do {
    func factorial(n) is cached {
        const f = (n <= 1 ? 1 : n*factorial(n-1))
        f
    }

    assert_eq(factorial(5), 120)
    assert_eq(factorial(6), 720)
}

do {
    class Example {
        method foo (n) {
            const t = 42
            { t + n }
        }
    }

    var obj = Example()

    assert_eq(obj.foo(2).run, 44)
    assert_eq(obj.foo(3).run, 45)
}

do {
    class Foo {
        const n = 42
        method foo(k) {
            n + k
        }
    }

    var obj = Foo()

    assert_eq(obj.foo(2), 44)
    assert_eq(obj.foo(3), 45)
}

do {
    const x = 42
    try { x += 2 }
    assert_eq(x, 42)
    try { x = 99 }
    assert_eq(x, 42)
    try { x.add!(9) }
    assert_eq(x, 42)
    try { ++x }
    assert_eq(x, 42)
    try { x++ }
    assert_eq(x, 42)
}

say "** Test passed!"