#!/usr/bin/ruby

# In Sidef, the modules are global namespaces which can incorporate one or more statements, such as functions,
# which can be accessed later by using the module's name followed by a pair of colons and the name of the function.

#
## Module + func
#
module Fibonacci {
    func nth(n) {
        n > 1 ? (nth(n-2) + nth(n-1)) : n;
    }
}

Fibonacci::nth(5) == 5 || "Fib error!".die;


#
## Module + static var + func
#
module Google::Chrome {
    static version = 41;
    func info {
        return "Developed by Google inc.";
    }
}

Google::Chrome::version += 1;
Google::Chrome::version == 42 || "Version error!".die;

Google::Chrome::info().contains("Google") || "Info error!".die;


#
## Module + (class + method)
#
module Foo {
    class Bar {
        method Zoe {
            return "All good!";
        }
    }
}

Foo::Bar().Zoe == "All good!" || "module+class error!".die;


#
## Class + (module + func + func) + method
## (declaring modules inside a class/function/method is not really supported)
#

class Test {

    module Foo {            # module redeclaration
        func Bingo {
            return "Bingo!";
        }
        func Yay {
            return "Yay!";
        }
    }

    method Bar {
        assert_eq(Foo::Yay(), "Yay!")
        assert_eq(Foo::Bingo(), "Bingo!")
        assert_eq(Foo::Bar().Zoe, "All good!")
    }
}

Test().Bar;
assert_eq(Foo::Bar().Zoe, "All good!")

## No longer supported as of Sidef > 3.70
## "Bingo" and "Yay" functions are lexical to class "Test".
#~ assert_eq(Foo::Bingo(), "Bingo!")
#~ assert_eq(Foo::Yay(), "Yay!")

#
## Module + (module + func) + func
#
module Hi {
    module Hello {
        func hello {
            "Hello";
        }
    };
    func hi {
        Hello::hello() == "Hello" || "Inner hello error!".die;
        "Hi";
    };
}

Hi::hi()       == "Hi"    || "Hi error!".die;
Hello::hello() == "Hello" || "Hello error!".die;

###################
say "** Test passed!";
###################