#!/usr/bin/julia

# Sidef concept expressed in Julia

import Base.sqrt
import Base./;

mutable struct S_Number
    value::Number;

    function S_Number(x::Number)
        this = new();
        this.value = x;
        return this;
    end
end

# S_number / S_Number
function /(x::S_Number, y::S_Number)
    S_Number(x.value / y.value);
end

# int(S_Number)
function int(x::S_Number)
    S_Number(round(Int, x.value));
end

# sqrt(S_Number)
function sqrt(x::S_Number)
    S_Number(sqrt(x.value));
end

n1 = S_Number(42);
n2 = S_Number(2);

println(n1);
println(n2);

println(n1 / n2);

method = Symbol("/");
println(eval(:($method(n1, n2))));

#########################################

d = Symbol("/");
x = S_Number(12);
y = S_Number(4);
println("$x / $y == ", eval(:($d(x, y))));

code = "25.3->int->sqrt";

if (m = match(r"\G(\d+(?:\.\d+)?)", code)) != nothing
    str = m.captures[1];
    n = S_Number(parse(Float64, str));
    pos = length(str);

    while (m = match(r"\G(->|\.)", code, pos)) != nothing
        pos += length(m.captures[1]);
        if (m = match(r"\G(\w+)", code, pos)) != nothing
            cap = m.captures[1];
            pos += length(cap);
            method = Symbol(cap);
            print(n, "->", cap);
            n = eval(:($method(n)));
            println(" == ", n);
        end
    end

end

abstract type Animal
end

struct Horse <: Animal
  name::String
end

run(::Animal) = println("Run, animal, run!")
sleep(a::Animal) = println("It's late; ", a.name, " is going to bed...")

function //(z::Horse)
    println("Run horsie, run!")
    println("Horsie's name is ", z.name, ".")
end

foo = Horse("Hashy");
//(foo);

sleep(Horse("Hashy"))