Specification := class Method (
    var dynamic pre;
    var dynamic post;
    var init:= method [args, precond, postcond] (
        (super.init) [args, quote (throw error "Imcomplete implemtation.")];
        pre := precond . coding [this];
        post := postcond. coding [this];
    );
    var implementing := method [b] (
        (att body) := b .coding [this];
    );
    var inclass invoke := method [x, v] {
        var prog;
        prog := att body;
        var r;
        r := x. (loc prog . eval[]);
        if (att post .eval[])  then (return r)
        else (throw error "Postcondition violated.");
    }
);

 permit 0 5 Value;
 permit 0 5 Array;
 permit 0 5 Base;
 permit 0 5 Class;
 permit 0 5 JClass;
 permit 0 5 Method;
 permit 0 5 JMethod;
 permit 0 5 Specification;

 var ownexp Char :=  ('a').getType[];
 var ownexp Int := (1).getType[];
 var ownexp Float :=  (1.2).getType[];
 var ownexp Long :=  (long(1)).getType[];
 var ownexp Double := (long(1.1)).getType[];
 var ownexp String := ("").getType[];
 var ownexp Boolean :=  (bool).getType[];
 var ownexp True :=  (true).getType[];
 var ownexp False := (false).getType[];
 var ownexp Null :=  (null).getType[];

 permit 0 5 Char;
 permit 0 5 Int;
 permit 0 5 Float;
 permit 0 5 String;
 permit 0 5 Long;
 permit 0 5 Double;
 permit 0 5 Boolean;
 permit 0 5 True;
 permit 0 5 False;
 permit 0 5 Null;
 permit 0 5 Reflection;

//---------------------------------------------------

 var ownexp Timer:= Jclass "MyTimer";
 var ownexp Memory :=  Jclass "MyMemory";
 var ownexp mserver :=  Jclass "MeshamServer";
 var ownexp mythread:=  Jclass "MyThread";
 var ownexp timer;
 var ownexp memory;

 permit 0 5 Timer;
 permit 0 5 Memory;
 permit 0 5 mserver;
 permit 0 5 mythread;
 permit 0 5 timer;
 permit 0 5 memory;

//---------------------------------------------------

 var ownexp project:=  class Value (
    var inclass specs:=6
 );
 permit 0 5 project;

 var ownexp Hashtable:= Jclass "java.util.Hashtable";
 var ownexp ht:= new Hashtable;

 permit 0 5 Hashtable;
 permit 0 5 ht;

 var gen home(ownexp (ht.get[(mserver.getIPAddress[])]),
              ownexp (method x { ht.put[(mserver.getIPAddress[]),wrap x]}));

 var stopping:=0;

// -------------------------- pre-defined types (binary ones) -------------------------

var ownexp BinaryType := class Value (
    var dynamic a;
    var dynamic b;
    var init := method [l,r] (a:= l; b:= r);
    var inclass invoke:= method [o,[l, r]] new thisclass[l,r];
    var add := method x   thisclass[a+x, b+x];
    var added := method x   thisclass[x+a, x+b];
    var subtract := method x   thisclass[a - x, b - x];
    var subtracted := method x   thisclass[x - a, x - b];
    var printing := method [] print [a,b];
);
 permit 0 5 BinaryType;

var ownexp Union := class BinaryType (
    var check := method [x]  ((a.check[x]) ||(b.check[x]));
    var lessThan := method x  (a< x) && (b<x);
    var greaterThan := method x  (a> x) || (b>x);
    var printing := method []   (
        print "Union"; (super.printing)[];
    );
);
 permit 0 5 Union;

var ownexp Intersect := class BinaryType (
    var inclass invoke := def BinaryType.invoke;
    var check := method [x]  ((a.check[x]) &&(b.check[x]));
    var lessThan := method x  (a< x) || (b<x);
    var greaterThan := method x  (a> x) && (b>x);
    var printing := method []   (
        print "Intersect"; (super.printing)[];
    );
);
 permit 0 5 Intersect;

// -------------------------- pre-defined types (binary ones) -------------------------

var ownexp UnaryType := class Value (
    var dynamic t;
    var init := method [type] (t := type; this);
    var inclass invoke := method [o, a] (new thisclass).(att init # a);
    var invoke:= method [o, a] (new t).(att init # a);
    var create:= method [] (new t);
    var initValue:= method [] (t.initValue[]);

    var getT := method [] t;
    var setT := method [newt] t:=newt;
    var check := method [x]  ((t>=<x) || (this >=< x));
    var getFlexiboType := method x t;
    var add := method x (
        if (this >>= x) then this
        else (
        if (this << x) then x
        else (throw error "Type incompitable!")
        )
    );
    var anded := method x add#x;
    var added := method x add#x;
    var subtract := method x add#x;
    var subtracted := method x add#x;
    var multiply := method x add#x;
    var multiplied := method x add#x;
    var divide := method x add#x;
    var divided := method x add#x;
    var equalTo := method x (
        if (x::thisclass)
            then (t = (x.t))
            else False
    );
    var lessThan := method x (t< x);
    var greaterThan := method x (t> x);
    var typeEqualTo := method x (
        (x >=< t) ||
        if (x::thisclass) then x.t >=< t else false
    );
    var lessLessThan := method x ((!(this>=<x)) && t<<x);
    var greaterGreaterThan := method x (x<<= t);
    var printing := method [] (print "UnaryType"; print [t]);
);
 permit 0 5 UnaryType;

var ownexp Closure := class UnaryType (
    var check := method [x]  (this>>= x);
    var printing := method [] (print "Closure"; print [t]);
);
 permit 0 5 Closure;

var ownexp Java := class Closure (
    var inclass initValue:= method [] null;
    var greaterGreaterThan := method x (x <<= t)||(x >=< Null);
    var printing := method []   (
        print "Java"; print [t];
    );
    var typeEqualTo := method x   (
        if (x::thisclass) then (t>=<(x.t)) else false
    );
);
 permit 0 5 Java;

// -------------------------- pre-defined primitive types -------------------------

var ownexp Range := class Value (
    var dynamic a: Int;
    var dynamic b: Int;
    var init := method [l: Int,r:Int] (a:= l; b:= r);
    var initValue:= method [] a;
    var inclass invoke := method [o, [l,r]] (
        assertion (l<= r);
        new Range[l,r];
    );
    var union := method x   (
        if (x::thisclass)
            then Range[min[a,x.a], max[b,x.b]]
            else throw error "A range is expected here!"
    );
    var add := method x   (
        if  (Int <<= x)
        then x
        else (
            assertion (x::thisclass);
            thisclass[(a + (x.a)), (b + (x.b))];
        )
    );
    var added := add;
    var subtract := method x   (
        if  (Int <<= x)
        then x
        else (
            assertion (x::thisclass);
            thisclass[(a - (x.b)), (b - (x.a))]
        )
    );
    var subtracted := method x   (
        if  (Int <<= x)
        then x
        else (assertion (x::thisclass);
            thisclass[((x.a) - b), ((x.b) - a)]
        )
    );
    var multiply := method x   (
        if  (Int <<= x)
        then x
        else (
            assertion (x::thisclass); {
            var p:= a * (x.a);
            var q:= a * (x.b);
            var r:= b * (x.a);
            var s:= b * (x.b);
            thisclass[min[min[p,q],min[r,s]], max[max[p,q],max[r,s]]]
            }
        )
    );
    var multiplied := add;
    var printing := method []  (
        if (this::Class)
            then print "Range";
            else (print "Range"; print [a,b])
    );
    var equalTo := method x   (
        if (x>>= Int) then return Boolean else skip;
        if !(x::thisclass) then return False else skip;
        if ((a=x.b) && (b=x.a)) then return True else skip;
        if (b < x.a) then return False else skip;
        if (a > x.b) then return False else Boolean;
        );
    var lessThan := method x   (
        if (x>>= Int) then return Boolean else skip;
        if !(x::thisclass) then return False else skip;
        if (b < x.a) then return True else skip;
        if (a < x.b) then return Boolean else skip;
        if (a < x.b) then return Boolean else False;
        );
    var greaterThan := method x   (
        if (x>>= Int) then return Boolean else skip;
        if !(x::thisclass) then return False else skip;
        if (a > x.b) then return True else skip;
        if (b > x.a) then return Boolean else skip;
        if (b > x.a) then return Boolean else False;
        );
    var typeEqualTo := method x   (
        if (x::thisclass)
        then (((x.a) = a) && ((x.b) = b))
        else false
    );
    var lessLessThan := method x   (
        if (x::thisclass)
        then (((x.a) <=a) && ((x.b) >= b) && !((a = x.a)&&(b = x.b)))
        else (Int <<= x)
        );
    var greaterGreaterThan := method x (
        if (x::thisclass)
        then (((x.a) >=a) && ((x.b) <= b) && !((a = x.a)&&(b = x.b)))
        else false
    );
    var overlap := method [x]   (
        (x::thisclass) &&
        ((a <= (x.a) && (x.a)<= b) ||
         ((x.a) <= a && a<= (x.b)))
    );
);
 permit 0 5 Range;

//--------------- Global methods -----------------
var ownexp min := method [x,y]   (
    if (x<= y) then x
    else (
        if (y<= x) then y
        else throw error "Cannot calculate minimum!"
    )
);
 permit 0 5 min;

var ownexp max := method [x,y]   (
    if (x<= y) then y
    else (
        if (y<= x) then x
        else throw error "Cannot calculate maximum!"
    )
);
 permit 0 5 max;

var ownexp union := method [x,y]   (
    if (x<<= y) then y
    else (
        if (x>>y) then x
        else x.union#y
    )
);
 permit 0 5 union;

var ownexp mod := method [x,y]   (
    x - (x % y)*y
);
 permit 0 5 mod;





//
