Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/VDM/VDMSL/newspeakSL/   (Wiener Entwicklungsmethode ©)  Datei vom 13.4.2020 mit Größe 105 kB image not shown  

Quelle  newspeak.vdmsl

  Sprache: VDM
 

values

beta:nat1 = 2;
epsilon_r:real = 1;
epsilon_t:real = 1;
bytemax:int = 10000;
maxint:int = 100000;
Phi: Fl_elt = mk_Fl_elt(<phi>,1);

zerot:Time = mk_(0,0);
t_absreal:Time = mk_(1,1);
t_absint:Time = mk_(1,1);
t_realmonminus:Time = mk_(1,1);
t_intmonminus:Time = mk_(1,1);
t_not:Time = mk_(1,1);
t_discard:Time = mk_(1,1);
t_round:Time = mk_(1,1);
t_mantissa:Time = mk_(1,1);
t_exponent:Time = mk_(1,1);
t_odd:Time = mk_(1,1);
t_float:Time = mk_(1,1);
t_min:Time = mk_(1,1);
t_max:Time = mk_(1,1);
t_intbinop:Time = mk_(1,1);
t_realbinop:Time = mk_(1,1);
t_intcomp:Time = mk_(1,1);
t_realcomp:Time = mk_(1,1);
t_tr_eq:Time = mk_(1,1);
t_real_eq:Time = mk_(1,1);
t_int_eq:Time = mk_(1,1);
t_void_eq:Time = mk_(1,1);
t_and:Time = mk_(1,1);
t_skip:Time = mk_(1,1);
t_access:Time = mk_(1,1);
t_comp_extract:Time = mk_(1,1);
t_update:Time = mk_(1,1);
t_construct_ev:Time = mk_(1,1);
t_const_type:Time = mk_(1,1);
t_widen_type:Time = mk_(1,1);
t_if: Time = mk_(1,1)

types

Errvalue = <err>;

Id = token;

Flavdom = set of Fl_elt;

Fl_elt::label : token | <phi>
        dim : rat;

Tr:: val: bool
     type: TrType;

TrType:: range: set of bool
         fl: Flavdom;

EqOp = <EQ> | <NEQ>;

Int::val : int
     type : IntType;

IntType:: rep : <byte> | <word>
          range : set of int
          fl : Flavdom;

NumOp ::   <numplus> | <binaryminus> | <nummult> | <numdiv> | <nummod>
        | <nummax> | <nummin>;

CompOp = <numgt> | <numlt> | <numge> | <numle>;

Real::val:real
      type:Float;

Floatrng::lower:int
          upper:int;

Float::range:set of Floatrng
       abserr: real
       relerr: real
       fl:Flavdom;

Void::val:<nil>
      type: VoidType;

VoidType :: fl: Flavdom;

Structure:: val: StructValue
            type: StructureType;

StructValue = seq1 of Component;

Component = int | real | bool;

StructureType :: tps: seq1 of CompType
                 fl : Flavdom;

CompType = TrType | Float | IntType;

Vector::val: VectorValue
        type: VectorType;

VectorValue = seq1 of Tr | seq1 of Real | seq1 of Int | seq1 of Void |
              seq1 of Errvalue | seq1 of VectorValue | seq1 of StructValue;

VectorType :: lower: int
              upper: int
              type : Expressible_type
              fl : Flavdom;

Union:: val : UnionValue
        type : UnionType;

UnionValue = Int | Real | Tr | Void;

UnionType :: tps : set of (IntType | Float | TrType | VoidType)
             fl : Flavdom;

Expressible_type = TrType | Float | IntType | VoidType | VectorType |
                   StructureType | UnionType;

Location :: nat;

Expressible_value = Errvalue | Tr | Int | Real | Void | Structure |
                    Union | Vector;

Storable_value :: Tr | Real | Int | Void | Vector | Structure | Union;

Store = map Location to Storable_value;

Time = nat * nat;

PState:: sto : Store
          time : Time;

Denotable_value = Location | Storable_value | Errvalue |
                  Expressible_type | Proc;

Env = (map Id to Denotable_value) * Location;

EnvState = (Env * PState) | Errvalue;

EST_value:: val : Expressible_value
            sto : Store
            time : Time;

EST_Iterate :: expst : EST_value
               i : int;

Param = seq of Expressible_value;

Proc :: Param -> PState -> EST_value;

Formal_elt :: id : Id
              rep : Expressible_type
              fl : Flavdom;

Program :: Expression;

Expression :: Operation | InnerLoop | Assignment | Scope |
             GuardedScope | Assertion | TimedExpression;

Operation :: MonOperation | BinaryOperation;

MonOperation :: MonOpMonOperand | VectorOperation | Value;

MonOpMonOperand :: operator : MonOp
                   operand : MonOperation;

MonOp = <numabs> | <unaryminus> | <not> | CompileTimeOp | <odd> |
        <round> | <float> | <mantissa> | <exponent> | <discard>;

CompileTimeOp :: <inf> | <sup> | <relonly> | <absonly> | <relerr> |
                <abserr>;

VectorOperation :: vo : VectorOp
                   mo : MonOperation
                   mult : [Multiple];

VectorOp = <sum> | <product> | <all> | <some> | <vecmax> | <vecmin> |
           <flatten>;

Multiple :: op : Operation
            to_p : ToPart;

ToPart = Upto | Downto;

Upto =  Operation;

Downto = Operation;

BinaryOperation:: left : MonOperation
                  opr : BinaryOp
                  right : MonOperation;

BinaryOp :: NumOp | CompOp | EqOp | BoolOp | VecBinOp | <replaceflav>;

BoolOp = <and> | <or>;

VecBinOp = <concat>;

Value :: ConstantValue | NamedValue | VectorVal | Sequence | Call | 
        StructureValue | Widening | Conditional | OuterLoop;

ConstantValue :: IntegerDenotation | FloatingDenotation | Ascii_Char |
                BooleanDenotation | Ascii_string | Flavouring |
                <skip>;

IntegerDenotation :: int;

FloatingDenotation :: real;

BooleanDenotation :: bool;

Ascii_Char :: char;

Ascii_string :: seq1 of char;

NamedValue :: Id | FlavourExtract | FlavourStrip | VectorExtract |
             VectorTrimming; 

FlavourExtract :: nv : NamedValue
                  fl : Flavouring;

Flavouring :: seq of Flavour;

Flavour:: name : token
          index : [rat];

FlavourStrip :: nv:NamedValue
                fl : Flavouring;

VectorExtract :: named : NamedValue
                 index : Operation;

VectorTrimming :: named : NamedValue
                  to_p : <gtvalue> | <ltvalue> | <atvalue>
                  ctv : CompileTimeValue;

CompileTimeValue :: Operation;

VectorVal :: seq1 of Operation;

Sequence :: seq1 of Expression;

Call :: id : Id
        acts: seq of Operation;

StructureValue :: seq1 of Operation;

Widening :: expr : Expression
            tp : Type;

Type :: PrimitiveType | StrucType | VecType | FlavouredType | UnionTp |
       TypeName;

PrimitiveType :: Number | FloatType | VoidValType;

Number :: rep : <bit> | <byte> | <word>
          range : seq of Range;

Range::lower : [CompileTimeValue]
       upper : [CompileTimeValue];

FloatType :: range : seq of Range
            abserr : [CompileTimeValue]
            relerr : [CompileTimeValue];

VoidValType = Flavouring;

VecType :: range : Range
           tp : Type;

StrucType :: seq1 of Type;

FlavouredType::fl : Flavouring
               tp : Type;

UnionTp :: seq1 of Type;

TypeName :: Id;

Conditional :: IfThenOnly | IfThenElse | CaseExpr;

IfThenOnly :: prop : Expression
              action : Sequence;

IfThenElse :: prop : Expression
              thenaction : Sequence
              elseaction : Sequence;

CaseExpr :: expr : Expression
            limbs : seq1 of CaseLimb
            out : [Outlimb];

CaseLimb :: test : Tester
            sequ : Sequence;

Tester = SkeletonType | StrucTest | NonStrucTest;

SkeletonType :: Type | NumSkel | StrucSkel | FlavSkel | VecSkel |
               UnionSkel;

NumSkel :: ranges : [seq1 of Range]
           errors: [Errors];

Errors :: abserr : [CompileTimeValue]
          relerr : [CompileTimeValue];

StrucSkel :: seq1 of (SkeletonType | <nil>);

FlavSkel:: skel : SkeletonType
           fl : Flavouring;

VecSkel :: SkeletonType;

UnionSkel :: seq1 of (FlavouredType | VoidValType | FlavSkel);

StrucTest :: seq1 of (NonStrucTest | <nil>);

NonStrucTest :: id : [Id]
                fl : [Flavouring]
                tp : SkeletonType;

Outlimb = Sequence;

OuterLoop :: OuterIntLoop | OuterVecLoop;

OuterIntLoop :: ovr : OverRange
                actions : Sequence;

OverRange :: cnt : LoopId
             range : Range;

LoopId = Id;

OuterVecLoop :: ovs : OverVectors
                action : Sequence;

OverVectors :: cnt : [LoopId]
               ovv : seq1 of OverVector;

OverVector :: id : Id
              val : Operation;

InnerLoop :: IntLoop | VecLoop | TimeLoop;

IntLoop :: inc : InnerControl
           actions : Sequence;

InnerControl = OverRange | PartialRange;

PartialRange :: cnt : LoopId
                from_p : Operation
                to_p : ToPart
                inc : [Operation];

VecLoop :: ovs : OverVectors
           actions : Sequence;

TimeLoop :: time : TimeInterval
            actions : Sequence;

TimeInterval = Range;

Assignment :: NvAssignment | MultAssignment | StrAssignment;

NvAssignment :: dest : Id
                expr : Expression;

MultAssignment :: dest : Id
                  mult : Multiple
                  expr : Expression;

StrAssignment :: dest : seq1 of Id
                 expr : Expression;

Scope :: SimpleScope | PackageScope;

SimpleScope :: decls : seq1 of Declaration
               expr : Expression;

Declaration = ImportDecl | ExportDecl | LetDecl | VarDecl | ProcDec |
              TypeDec;

ImportDecl :: id : Id
              tp : Type;

ExportDecl :: id : Id
              expr : Expression;

LetDecl :: SimpleLetDecl | StrucLetDecl;

SimpleLetDecl :: id : Id
                 expr : Expression;

StrucLetDecl :: ids : seq1 of Id
                expr : Expression;

VarDecl :: id : Id
           expr : Expression;

ProcDec :: nls : [NonLocals]
           ph : ProcHeading
           expr : Expression;

NonLocals :: ids : [seq1 of Id]
             decls : [seq1 of Declaration];

ProcHeading :: id : Id
               formals : seq of Formal;

Formal :: id : Id
          rep : Representation
          fl : Flavouring;

Representation = PrimitiveRep | StrucRep | VecRep| UnionRep |
                 FlavouredRep | Type;

PrimitiveRep :: NumRep | FloatRep;

NumRep :: rep : <bit> | <byte> | <word>
          rnage : [seq1 of Range];

FloatRep :: range : [seq1 of Range]
            abserr : [CompileTimeValue]
            relerr : [CompileTimeValue];

StrucRep :: seq1 of Representation;

VecRep :: range : Range
          rep : Representation;

UnionRep :: seq1 of Representation;

FlavouredRep :: fl :Flavouring
                rep : Representation;

TypeDec :: id : Id
           tp : Type;

PackageScope :: ids : seq1 of Id
                decls : seq1 of Declaration
                expr : Expression;

GuardedScope :: decls : seq1 of GuardedDeclaration
                inseq : Sequence
                out : Sequence;

GuardedDeclaration = Declaration | WhereDecl;

WhereDecl :: type : SkeletonType
             expr : Expression
             id : [Id];

Assertion :: expr : Expression
             tp : SkeletonType;

TimedExpression :: TimeTakes | TimeAssertion;

TimeTakes :: expr : Expression
             time : TimeInterval;

TimeAssertion :: expr : Expression
                 time : TimeInterval

               





functions

fl_mult: Flavdom * Flavdom -> Flavdom
fl_mult(f1,f2) ==
  if Phi in set f1 union f2 
  then {Phi}
  else {mk_Fl_elt(f.label,f.dim + f'.dim) | f in set f1, f' in set f2
           & f.label = f'.label} union
       { f | f in set f1 & forall f' in set f2 & f'.label <> f.label} union
       { f | f in set f2 & forall f' in set f1 & f'.label <> f.label};

fl_div: Flavdom * Flavdom -> Flavdom
fl_div(f1,f2) ==
  if Phi in set f1 union f2 
  then {Phi}
  else {mk_Fl_elt(f.label,f.dim - f'.dim) | f in set f1, f' in set f2
           & f.label = f'.label} union
       { f | f in set f1 & forall f' in set f2 & f'.label <> f.label} union
       { mk_Fl_elt(f.label,-f.dim) | 
             f in set f2 & forall f' in set f1 & f'.label <> f.label};

phi_remove: Expressible_type -> Expressible_type
phi_remove(tp) ==
  cases tp:
    mk_VoidType(t) -> mk_VoidType(t\ {Phi}),
    mk_TrType(range,fl) -> mk_TrType(range,fl \ {Phi}),
    mk_IntType(rep,range,fl) -> mk_IntType(rep,range, fl \ {Phi}),
    mk_Float(range,abse,rele,fl) -> mk_Float(range,abse,rele,fl\{Phi}),
    mk_VectorType(lower,upper,tp,fl) ->
                      mk_VectorType(lower,upper,tp, fl\{Phi}),
    mk_StructureType(tps,fl) -> mk_StructureType(tps,fl\{Phi}),
    mk_UnionType(tps,fl) -> mk_UnionType(tps,fl\{Phi})
  end;

tr_eq: Tr * Tr * EqOp -> Expressible_value
tr_eq(t1,t2,op) ==
  if t1.type.fl <> t2.type.fl
  then <err>
  elseif op = <EQ>
  then mk_Tr(t1.val = t2.val, mk_TrType({b1 = b2 | b1 in set
                 t1.type.range, b2 in set t2.type.range},{}))
  else mk_Tr(t1.val <> t2.val, mk_TrType({b1 <> b2 | b1 in set
                 t1.type.range, b2 in set t2.type.range},{}));

tr_and: Tr * Tr -> Expressible_value
tr_and(t1,t2) ==
  if t1.type.fl <> t2.type.fl
  then <err>
  else mk_Tr(t1.val and t2.val,
             mk_TrType({b1 and b2 | b1 in set t1.type.range, b2 in set
                                t2.type.range },t1.type.fl));

tr_or: Tr * Tr -> Expressible_value
tr_or(t1,t2) ==
  if t1.type.fl <> t2.type.fl
  then <err>
  else mk_Tr(t1.val or t2.val,
             mk_TrType({b1 or b2 | b1 in set t1.type.range, b2 in set
                                t2.type.range },t1.type.fl));

tr_not: Tr -> Expressible_value
tr_not(t) ==
  mk_Tr(not t.val, mk_TrType({ not b | b in set t.type.range},t.type.fl));


int_eq: Int * Int * EqOp -> Expressible_value
int_eq(z1,z2,op) ==
  if z1.type.fl <> z2.type.fl
  then <err>
  elseif op = <EQ>
  then mk_Tr(z1.val = z2.val, mk_TrType({i = j | i in set
     z1.type.range, j in set z2.type.range},{}))
  else mk_Tr(z1.val <> z2.val, mk_TrType({i <> j | i in set
     z1.type.range, j in set z2.type.range},{}));


min: set1 of real -> real
min(s) ==
  let m in set s in
  if card s = 1 then m 
  else let sm = min(s\{m}) in
    if m < sm then m else sm;

max: set1 of real -> real
max(s) ==
  let m in set s in
  if card s = 1 then m 
  else let sm = max(s\{m}) in
    if m > sm then m else sm;

intbinop: Int * Int * NumOp -> Expressible_value
intbinop(x,y,mk_NumOp(op)) ==
  cases op:
    (<numplus>) -> intplus(x,y),
    (<binaryminus>) -> intbinminus(x,y),
    (<nummult>) -> intmult(x,y),
    (<numdiv>) -> intdiv(x,y),
    (<nummod>) -> intmod(x,y),
    (<nummax>) -> intmax(x,y),
    (<nummin>) -> intmin(x,y)
  end;

intplus: Int * Int -> Expressible_value
intplus(x,y) ==
  if x.type.fl <> y.type.fl 
  then <err>
  else let range = { i + j | i in set x.type.range, j in set
                                          y.type.range} in
       if max({abs min(range), abs max(range)}) >= maxint
       then <err>
       else let rep = if min({abs min(range),abs max(range)}) >= bytemax
                         or x.type.rep = <word> or y.type.rep = <word>
                      then <word>
                      else <byte> in
            mk_Int(x.val + y.val, mk_IntType(rep,range,x.type.fl));

intbinminus: Int * Int -> Expressible_value
intbinminus(x,y) ==
  if x.type.fl <> y.type.fl 
  then <err>
  else let range = { i - j | i in set x.type.range, j in set
                                          y.type.range} in
       if max({abs min(range), abs max(range)}) >= maxint
       then <err>
       else let rep = if min({abs min(range),abs max(range)}) >= bytemax
                         or x.type.rep = <word> or y.type.rep = <word>
                      then <word>
                      else <byte> in
            mk_Int(x.val - y.val, mk_IntType(rep,range,x.type.fl));

intmult: Int * Int -> Expressible_value
intmult(x,y) ==
  let fl = fl_mult(x.type.fl,y.type.fl),
      range = { i * j | i in set x.type.range, j in set y.type.range} in
  if max({abs min(range), abs max(range)}) >= maxint 
  then <err>
  else let rep = if min({abs min(range),abs max(range)}) >= bytemax
                   or x.type.rep = <word> or y.type.rep = <word>
                 then <word>
                 else <byte> in
    mk_Int(x.val * y.val, mk_IntType(rep,range,fl));

intdiv: Int * Int -> Expressible_value
intdiv(x,y) ==
  if 0 in set y.type.range
  then <err>
  else let fl = fl_div(x.type.fl,y.type.fl),
           range = { i div j | i in set x.type.range, j in set
                                     y.type.range} in
       if max({abs min(range), abs max(range)}) >= maxint
       then <err>
       else let rep = if exists r in set range & abs r >= bytemax
                      then <word> else <byte> in
            mk_Int(x.val div y.val, mk_IntType(rep,range,fl));

intmod: Int * Int -> Expressible_value
intmod(x,y) ==
  if 0 in set y.type.range
  then <err>
  else let range = { i mod j | i in set x.type.range, j in set
                                            y.type.range} in
       mk_Int(x.val mod y.val,mk_IntType(y.type.rep,range,x.type.fl));


intmax: Int * Int -> Expressible_value
intmax(x,y) ==
  if x.type.fl <> y.type.fl
  then <err>
  else let rep = if (x.type.rep = <word>) or (y.type.rep = <word>)
                 then <word> else <byte>,
           range = {max({i,j}) | i in set x.type.range, j in set
                                               y.type.range} in
       mk_Int(max({x.val,y.val}),mk_IntType(rep,range,x.type.fl));

intmin: Int * Int -> Expressible_value
intmin(x,y) ==
  if x.type.fl <> y.type.fl
  then <err>
  else let rep = if (x.type.rep = <word>) or (y.type.rep = <word>)
                 then <word> else <byte>,
           range = {min({i,j}) | i in set x.type.range, j in set
                                               y.type.range} in
       mk_Int(min({x.val,y.val}),mk_IntType(rep,range,x.type.fl));


absint: Int -> Int
absint(z) ==
  mk_Int(abs z.val, mk_IntType(z.type.rep, { abs i | i in set
                        z.type.range}, z.type.fl));

intmonminus: Int -> Int
intmonminus(z) ==
  mk_Int(-z.val, mk_IntType(z.type.rep, {-i | i in set z.type.range},
              z.type.fl)) ;

odd: Int -> Tr
odd(z) ==
 let range = { x mod 2 = 0 | x in set z.type.range} in
 mk_Tr(z.val mod 2 = 0, mk_TrType(range,{}));

intcomp: Int * Int * CompOp -> Expressible_value
intcomp(x,y,op) ==
  if x.type.fl <> y.type.fl 
  then <err>
  else let p = lambda mk_(i,j): int * int & 
             cases op:
               <numgt> -> i > j,
               <numlt> -> i < j,
               <numge> -> i >= j,
               <numle> -> i <= j
             end in
       let val = p(mk_(x.val,y.val)),
           range = {p(mk_(i,j)) | i in set x.type.range, j in set
                                 y.type.range} in
           mk_Tr(val,mk_TrType(range,{}));

ascii : char -> int
ascii(c) == 1;

float: Int -> Real
float(z) ==
  mk_Real(z.val,mk_Float({mk_Floatrng(min(z.type.range),max(z.type.range))}, 
      maxint,maxint,{}));

real_eq: Real * Real * EqOp -> Expressible_value
real_eq(r,s,op) ==
  if r.type.fl <> s.type.fl 
  then <err>
  else let r1 = 
               dunion {{floor((1-r.type.relerr) * range.lower - 
                  r.type.abserr),..., floor(0.5 + (1+r.type.relerr) *
                  range.upper + r.type.abserr)} | range in set r.type.range},
           r2 =
               dunion {{floor((1-s.type.relerr) * range.lower - 
                  s.type.abserr),..., floor(0.5 + (1+s.type.relerr) *
                  range.upper + s.type.abserr)} | range in set s.type.range} in
       let range = if r1 inter r2 = {} then {falseelse {true,falsein
       if op = <EQ>
       then mk_Tr(r.val = s.val, mk_TrType(range,{}))
       else mk_Tr(r.val <> s.val, mk_TrType({ not t | t in set range},{}));


absreal: Real -> Real
absreal(r) ==
  let new_range = 
      { mk_Floatrng(min({abs range.lower, abs range.upper}),
                    max({abs range.lower, abs range.upper})) 
                            | range in set r.type.range} in
  mk_Real(abs r.val, mu (r.type, range |-> new_range));

realmonminus: Real -> Real
realmonminus(r) ==
  mk_Real(-r.val,mu (r.type, range |->
    { mk_Floatrng(- range.upper, -range.lower) | range in set r.type.range}));

realbinop: Real * Real * NumOp -> Expressible_value
realbinop(x,y,mk_NumOp(op)) ==
  cases op:
    <numplus> -> realplus(x,y),
    <binaryminus> -> realbinminus(x,y),
    <nummult> -> realmult(x,y),
    <numdiv> -> realdiv(x,y),
    <nummax> -> realmax(x,y),
    others -> <err>
  end;

realplus:Real * Real -> Expressible_value
realplus(x,y) ==
  if x.type.fl <> y.type.fl
  then <err>
  else let range = {mk_Floatrng(xrange.lower + yrange.lower,
                      xrange.upper + yrange.upper) | xrange in set
                        x.type.range, yrange in set y.type.range},
           Xmax = max(dunion {{abs range.lower,abs range.upper} | 
                                range in set x.type.range}),
           Ymax = max(dunion {{abs range.lower,abs range.upper} | 
                                range in set y.type.range}),
           XYmax = max({Xmax,Ymax}) in
       if max({max({abs r.lower, abs r.upper}) | r in set range})  >= maxint
       then <err>
       else let As = x.type.relerr + y.type.abserr + x.type.relerr *
                     Xmax + y.type.relerr * Ymax + epsilon_t*XYmax in
            let val = x.val + y.val,
                type = mk_Float(range,As,epsilon_r,x.type.fl) in
            mk_Real(val,type);

realbinminus: Real * Real -> Expressible_value
realbinminus(x,y) ==
  if x.type.fl <> y.type.fl
  then <err>
  else let range = {mk_Floatrng(xrange.lower - yrange.upper,
                      xrange.upper - yrange.lower) | xrange in set
                        x.type.range, yrange in set y.type.range},
           Xmax = max(dunion {{abs range.lower,abs range.upper} | 
                                range in set x.type.range}),
           Ymax = max(dunion {{abs range.lower,abs range.upper} | 
                                range in set y.type.range}),
           XYmax = max({Xmax,Ymax}) in
       if max({max({abs r.lower, abs r.upper}) | r in set range})  >= maxint
       then <err>
       else let As = x.type.relerr + y.type.abserr + x.type.relerr *
                     Xmax + y.type.relerr * Ymax + epsilon_t*XYmax in
            let val = x.val - y.val,
                type = mk_Float(range,As,epsilon_r,x.type.fl) in
            mk_Real(val,type);

realmult: Real * Real -> Expressible_value
realmult(x,y) ==
  let range = {mk_Floatrng(xrange.lower * yrange.lower,
                      xrange.upper * yrange.upper) | xrange in set
                        x.type.range, yrange in set y.type.range},
      Xmax = max(dunion {{abs range.lower,abs range.upper} | 
                                range in set x.type.range}),
      Ymax = max(dunion {{abs range.lower,abs range.upper} | 
                                range in set y.type.range}),
      XYmax = max({Xmax,Ymax}) in
      if max({max({abs r.lower, abs r.upper}) | r in set range})  
           >= maxint
      then <err>
      else let As = Xmax * Ymax * (x.type.relerr + y.type.relerr) +
                    x.type.abserr * Ymax * (1+y.type.relerr) +
                    y.type.abserr * Xmax * (1+x.type.relerr) +
                    x.type.abserr * y.type.abserr + epsilon_t *XYmax,
               fl = fl_mult(x.type.fl, y.type.fl) in
          mk_Real(x.val * y.val, mk_Float(range,As,epsilon_r,fl));

realdiv: Real * Real -> Expressible_value
realdiv(x,y) ==
  if (((1-y.type.relerr) * min({range.lower | range in set y.type.range}) 
           - y.type.abserr) <=0 ) and
     (((1+y.type.relerr) * max({range.upper | range in set y.type.range})
           + y.type.abserr) >=0 )
  then <err>
  else let range = {mk_Floatrng(floor (xrange.lower / yrange.upper),
                      floor(0.5+ xrange.upper / yrange.lower)) | 
                        xrange in set x.type.range, 
                        yrange in set y.type.range},
      Xmax = max(dunion {{abs range.lower,abs range.upper} | 
                                range in set x.type.range}),
      Ymax = max(dunion {{abs range.lower,abs range.upper} | 
                                range in set y.type.range}),
      XYmax = max({Xmax,Ymax}),
      Ymin = min(dunion {{abs range.lower,abs range.upper}
                           | range in set y.type.range}) in
       if max({max({abs r.lower, abs r.upper}) | r in set range}) 
              >= maxint
       then <err>
       else let As = ((Xmax * Ymax * max({x.type.relerr, y.type.relerr}) +
                       Ymax * x.type.abserr + Xmax * y.type.abserr)
                      /Ymin ** 2) + epsilon_t * XYmax,
                fl = fl_div(x.type.fl,y.type.fl) in
           mk_Real(x.val/y.val, mk_Float(range,As,epsilon_r,fl));


realmax: Real * Real -> Expressible_value
realmax(x,y) ==
  if x.type.fl <> y.type.fl
  then <err>
  else let val = max({x.val,y.val}),
           abserr = max({x.type.abserr,y.type.abserr}),
           relerr = max({x.type.relerr,y.type.relerr}),
           range = { mk_Floatrng(max({xr.lower,yr.lower}),
                      max({xr.upper,yr.upper})) | 
                       xr in set x.type.range,
                       yr in set y.type.range} in
       mk_Real(val,mk_Float(range,abserr,relerr,x.type.fl));
           

realmin: Real * Real -> Expressible_value
realmin(x,y) ==
  if x.type.fl <> y.type.fl
  then <err>
  else let val = min({x.val,y.val}),
           abserr = max({x.type.abserr,y.type.abserr}),
           relerr = max({x.type.relerr,y.type.relerr}),
           range = { mk_Floatrng(min({xr.lower,yr.lower}),
                      min({xr.upper,yr.upper})) | 
                       xr in set x.type.range,
                       yr in set y.type.range} in
       mk_Real(val,mk_Float(range,abserr,relerr,x.type.fl));

discard: Real -> Int
discard(r) ==
  mk_Int(floor (r.val + 0.5),
          mk_IntType(<word>,dunion {{range.lower,...,range.upper} |
             range in set r.type.range}, {}));

round: Real -> Int
round(r) ==
  if is_int(r.val)
  then mk_Int(r.val,mk_IntType(<word>, dunion {{range.lower,...,range.upper} |
             range in set r.type.range},{}))
  else mk_Int(floor (r.val + 0.5),mk_IntType(<word>,
             dunion {{range.lower,...,range.upper} |range in set r.type.range},
             {}));

realcomp: Real * Real * CompOp -> Expressible_value
realcomp(x,y,op) ==
  if x.type.fl <> y.type.fl 
  then <err>
  else let p = lambda mk_(i,j): real * real &
          cases op:
            <numgt> -> i > j,
            <numlt> -> i < j,
            <numle> -> i <= j,
            <numge> -> i >= j
          end,
           xrange = dunion {{(1-x.type.relerr)*range.lower - x.type.abserr,...,
                     (1+x.type.relerr)*range.upper + x.type.abserr} 
                      | range in set x.type.range},
           yrange = dunion {{(1-y.type.relerr)*range.lower - y.type.abserr,...,
                     (1+y.type.relerr)*range.upper + y.type.abserr} 
                      | range in set y.type.range} in
        let val = p(mk_(x.val,y.val)),
            range = if max(xrange) < min(yrange)
                    then {p(mk_(max(xrange),min(yrange)))}
                    elseif min(xrange) > max(yrange)
                    then {p(mk_(max(yrange),min(xrange)))}
                    else {true,falsein
        mk_Tr(val,mk_TrType(range,{}));

inf: Real -> Real
inf(r) ==
  let m = min({range.lower | range in set r.type.range}) * 
                   (1- r.type.relerr) - r.type.abserr in
  mk_Real(m,mk_Float({mk_Floatrng(m,m)},0,0,{Phi}));

sup: Real -> Real
sup(r) ==
  let m = max({range.upper | range in set r.type.range}) * 
                   (1+ r.type.relerr) + r.type.abserr in
  mk_Real(m,mk_Float({mk_Floatrng(m,m)},0,0,{Phi}));

absonly: Real -> Real
absonly(mk_Real(r,f)) ==
  let abse = f.abserr + (r * f.relerr) in
  mk_Real(r, mu(f, abserr |-> abse, relerr |-> 0));

relonly: Real -> Real
relonly(mk_Real(r,f)) ==
  if r = 0 then mk_Real(r,mu(f,relerr |-> 0, abserr |-> 0))
  else let rel = f.relerr + f.abserr/r in
    mk_Real(r,mu(f,relerr |-> rel, abserr |-> 0));

abserr: Real -> Real
abserr(r) ==
  mk_Real(r.type.abserr,
      mk_Float({mk_Floatrng(r.type.abserr,r.type.abserr)}, 0,0,{Phi}));

relerr: Real -> Real
relerr(r) ==
  mk_Real(r.type.relerr,
      mk_Float({mk_Floatrng(r.type.relerr,r.type.relerr)}, 0,0,{Phi}));


void_eq: Void * Void * EqOp -> Expressible_value
void_eq(v1,v2,op) ==
  if (v1.type = v2.type) and op = <EQ>
  then mk_Tr(true,mk_TrType({true},{}))
  elseif (v1.type <> v2.type) and op = <NEQ>
  then mk_Tr(true,mk_TrType({true},{}))
  else mk_Tr(false,mk_TrType({false},{}));

construct_ev: Component * CompType -> Expressible_value
construct_ev(v,t) ==
  if  is_real(v) then mk_Real(v,t)
  elseif is_bool(v) then mk_Tr(v,t)
  else mk_Int(v,t);

comp_extract: Structure * Flavdom -> Expressible_value
comp_extract(s,fl) ==
  let matches = { i | i in set inds s.val & s.type.tps(i).fl = fl} in
  if card matches <> 1 
  then <err>
  else let {i} = matches in
    construct_ev(s.val(i),s.type.tps(i));

struc_length:StructureType -> nat
struc_length(s) ==
  len s.tps;

vector_extract: Vector * int -> Expressible_value
vector_extract(v,i) ==
  v.val(i - v.type.lower + 1);

vector_subv: VectorValue * int * int -> VectorValue
vector_subv(v,l,u) ==
  v(l,...,u);

vector_length: VectorType -> nat
vector_length(v) ==
  v.type.upper - v.type.lower + 1;

vector_flatten:VectorValue -> VectorValue
vector_flatten(vs) ==
  conc vs;

vector_sum: VectorValue -> Expressible_value
vector_sum(v) ==
  if len v = 1 
  then hd v
  else let s = vector_sum(tl v) in
    if s = <err>
    then <err>
    elseif is_Real(hd v) 
    then realplus(hd v,s)
    else intplus(hd v,s);

vector_product: VectorValue -> Expressible_value
vector_product(v) ==
  if len v = 1 
  then hd v
  else let s = vector_product(tl v) in
    if s = <err>
    then <err>
    elseif is_Real(hd v) 
    then realmult(hd v,s)
    else intmult(hd v,s);
       

vector_all: VectorValue -> Expressible_value
vector_all(v) ==
  if len v = 1
  then hd v
  else let b = vector_all(tl v) in
       if b = <err>
       then <err>
       else tr_and(hd v,b);

vector_some: VectorValue -> Expressible_value
vector_some(v) ==
  if len v = 1
  then hd v
  else let b = vector_some(tl v) in
       if b = <err>
       then <err>
       else tr_or(hd v,b);

vector_max: VectorValue -> Expressible_value
vector_max(v) ==
  if len v = 1 
  then hd v
  else let s = vector_max(tl v) in
       if s = <err>
       then <err>
       elseif is_Real(hd v)
       then realmax(hd v,s)
       else intmax(hd v,s);

vector_min: VectorValue -> Expressible_value
vector_min(v) ==
  if len v = 1 
  then hd v
  else let s = vector_min(tl v) in
       if s = <err>
       then <err>
       elseif is_Real(hd v)
       then realmin(hd v,s)
       else intmin(hd v,s);

vector_concat: Vector * Vector -> Vector
vector_concat(v1,v2) ==
  let type = if tleq(v1.type.type,v2.type.type)
             then v2.type.type
             else v1.type.type,
      lower = v1.type.lower,
      upper = v1.type.upper + v2.type.upper - v2.type.lower + 1,
      fl = v1.type.fl,
      vec = v1.val^v2.val in
      let new_type = mk_VectorType(lower,upper,type,fl) in
      mk_Vector(vec,new_type);




widen_type: Expressible_value * Expressible_type -> Expressible_value
widen_type(x,type) ==
  if x = <err> or is_Void(x) 
  then <err>
  else mu(x,type |-> type);

const_type: Expressible_value -> (Expressible_type | Errvalue)
const_type(v) ==
  if is_Void(v) 
    then v.type
  elseif is_Vector(v) 
    then mk_VectorType(v.type.lower,v.type.upper,
              seqlub([const_type(i) | i in seq v.val]),v.type.fl)
  elseif is_Structure(v) 
    then mk_StructureType([const_type(construct_ev(v.val(i),v.type.tps(i)))
                            | i in set inds v.val],v.type.fl)
  elseif is_Union(v) 
    then const_type(v.val)
  elseif v = <err>
    then <err>
  elseif is_Real(v)
    then mk_Float({mk_Floatrng(floor v.val, if
                  is_int(v.val) then v.val else floor(v.val + 0.5))},
                  v.type.abserr,v.type.relerr,v.type.fl)
  elseif is_Int(v)
    then mk_IntType(v.type.rep,{v.val},v.type.fl)
  else mk_TrType({v.val},v.type.fl);

fleq: Expressible_type * Expressible_type -> bool
fleq(t1,t2) ==
  if (is_VoidType(t1) and is_VoidType(t2)) then  t1 = t2
  elseif not (is_VoidType(t1) and is_VoidType(t2)) then t1.fl = t2.fl
  else false;


replace_flavour: Expressible_type * Flavdom -> (Expressible_type|Errvalue)
replace_flavour(type,flav) ==
  cases type:
   mk_VoidType(fl) -> mk_VoidType(flav),
   mk_TrType(r,f) -> mk_TrType(r,flav),
   mk_Float(r,a,re,f) -> mk_Float(r,a,re,flav),
   mk_IntType(rep,r,f) -> mk_IntType(rep,r,flav),
   mk_VectorType(l,u,t,f) -> mk_VectorType(l,u,t,flav),
   mk_UnionType(tps,fl) -> mk_UnionType(tps, flav),
   mk_StructureType(tps,fl) -> mk_StructureType(tps, flav)
  end;


lub: Expressible_type * Expressible_type -> (Expressible_type | Errvalue)
lub(t1,t2) ==
  if is_TrType(t1) and is_TrType(t2) and fleq(t1,t2)
    then trlub(t1,t2)
  elseif is_Float(t1) and is_Float(t2) and fleq(t1,t2)
    then floatlub(t1,t2)
  elseif is_IntType(t1) and is_IntType(t2) and fleq(t1,t2)
    then intlub(t1,t2)
  elseif is_VectorType(t1) and is_VectorType(t2) and fleq(t1,t2)
    then vectorlub(t1,t2)
  elseif is_StructureType(t1) and is_StructureType(t2) and fleq(t1,t2)
    then struclub(t1,t2)
  elseif is_UnionType(t1) and is_UnionType(t2) and fleq(t1,t2)
    then unionlub(t1,t2)
  elseif is_VoidType(t1) and is_VoidType(t2) and fleq(t1,t2)
    then t1
  else <err>;

  
trlub : TrType * TrType -> TrType
trlub(t1,t2) ==
  mk_TrType(t1.range union t2.range,t1.fl);

floatlub: Float * Float -> Float
floatlub(t1,t2) ==
  mk_Float(t1.range union t2.range, max({t1.abserr,t2.abserr}), 
           max({t1.relerr,t2.relerr}),t1.fl);

intlub: IntType * IntType -> (IntType | Errvalue)
intlub(t1,t2) ==
  if t1.rep = <byte> and t2.rep = <byte>
    then mk_IntType(<byte>,t1.range union t2.range, t1.fl)
  elseif t1.rep = <word> and t2.rep = <word>
    then mk_IntType(<word>,t1.range union t2.range, t1.fl)
  else <err>;

vectorlub : VectorType * VectorType -> (VectorType | Errvalue)
vectorlub(t1,t2) ==
  if (t1.lower <> t2.lower) or (t1.upper <> t2.upper) or
     (lub(t1.type,t2.type) = <err>)
  then <err>
  else mk_VectorType(t1.lower,t1.upper,lub(t1.type,t2.type),t1.fl);

struclub: StructureType * StructureType -> (StructureType | Errvalue)
struclub(t1,t2) ==
  if len t1.tps <> len t2.tps
  then <err>
  elseif exists i in set inds t1.tps & lub(t1.tps(i),t2.tps(i)) = <err>
  then <err>
  else mk_StructureType([lub(t1.tps(i),t2.tps(i)) | i in set inds t1.tps],
                        t1.fl);

unionlub: UnionType * UnionType -> (UnionType | Errvalue)
unionlub(t1,t2) ==
  if card t1.tps <> card t2.tps
  then <err>
  else let lub = setlub(t1.tps union t2.tps) in 
       if lub = <err>
       then <err>
       elseif is_UnionType(lub)
       then mk_UnionType(lub.tps,t1.fl)
       else mk_UnionType({lub},t1.fl);

seqlub: seq1 of Expressible_type -> (Expressible_type | Errvalue)
seqlub(tps) ==
  if len tps = 1 
  then hd tps
  elseif lub(tps(1),tps(2)) = <err>
  then <err>
  else lub(lub(tps(1),tps(2)),seqlub(tl tps));

setlub : set of Expressible_type -> (Expressible_type | Errvalue)
setlub(s) ==
  if exists t1,t2 in set s & lub(t1,t2) = <err>
  then if forall t in set s & is_TrType(t) or is_IntType(t) or
                              is_Float(t) or is_VoidType(t)
       then let t1 = { setlub({ t' | t' in set s & is_TrType(t') and
                          t.fl = t'.fl}) | t in set s & is_TrType(t)},
                t2 = { setlub({ t' | t' in set s & is_IntType(t') and
                          t.fl = t'.fl}) | t in set s & is_IntType(t)},
                t3 = { setlub({ t' | t' in set s & is_Float(t') and
                          t.fl = t'.fl}) | t in set s & is_Float(t)},
                t4 = { setlub({ t' | t' in set s & is_VoidType(t') and
                          t.fl = t'.fl}) | t in set s & is_VoidType(t)} in
            if (exists t,t' in set dunion {t1,t2,t3,t4} & t.fl = t'.fl)
               or exists t in set dunion {t1,t2,t3}, 
                         mk_VoidType(f) in set t4 &
                    t.fl = f
            then <err>
            else mk_UnionType(t1 union t2 union t3 union t4,{})
       else <err>
  else let t in set s in
       if s = {t} 
       then t
       else lub(t,setlub(s \ {t}));


gt : Expressible_type * Expressible_type -> bool
gt(t1,t2) ==
  lub(t1,t2) = t1 or
  (fleq(t1,t2) and
    ( (is_TrType(t2) and let z in set power {0,1} be st
                           true in set t2.range => 1 in set z and
                           false in set t2.range => 0 in set z in
          (is_Float(t1) and z subset dunion {{lower,...,upper} | 
                            mk_Floatrng(lower,upper) in set t1.range}) or
          (is_IntType(t1) and z subset t1.range))
      or
      (is_IntType(t2) and t2.rep = <byte> and
          (is_Float(t1) and t2.range subset 
                   dunion {{lower,...,upper} | mk_Floatrng(lower,upper) 
                                      in set t1.range}) or
          (is_IntType(t1) and t1.rep = <word> and t2.range subset t1.range))
      or
      (is_IntType(t2) and t2.rep = <word> and is_Float(t1) and
           t2.range subset dunion {{lower,...,upper} | 
                        mk_Floatrng(lower,upper) in set t1.range})
      or
      (is_Float(t2) and is_Float(t1) and 
           dunion { {lower,...,upper} | mk_Floatrng(lower,upper) in set 
                   t2.range} subset
           dunion { {lower,...,upper} | mk_Floatrng(lower,upper) in set 
                   t1.range} and
           t2.abserr + t2.relerr * max({ abs max({lower,upper}) | 
                mk_Floatrng(lower,upper) in set t2.range}) <= t1.abserr + 
             t1.relerr * max({ abs max({lower,upper}) | 
                mk_Floatrng(lower,upper) in set t1.range}))
      or
      (is_UnionType(t1) and is_UnionType(t2) and
           forall t in set t1.tps & exists t' in set t2.tps &
                lub(t,t') = t))
   or
   (is_UnionType(t2) and exists t in set t2.tps & gt(t1,t)));     



tleq: Expressible_type * Expressible_type -> bool
tleq(t1,t2) ==
  lub(t1,t2) = t2;

next_locn: Location -> Location
next_locn(mk_Location(l)) ==
  mk_Location(l+1);

access: Location -> Store -> Storable_value
access(l)(s) ==
   s(l);

update : Location -> Storable_value -> Store -> Store
update(l)(v)(s) ==
  s ++ {l |-> v};

multi_update: seq of Location -> seq of Storable_value -> Store -> Store
multi_update(ls)(vs)(s) ==
  if ls = []
  then s
  else multi_update(tl ls)(tl vs)(s ++ { hd ls |-> hd vs})
pre len ls = len vs;

timeleq : Time * Time -> bool
timeleq(mk_(lt1,ut1),mk_(lt2,ut2)) ==
  lt2 <= lt1 and lt1 <= ut1 and ut1 <= ut2;

access_env : Id -> Env -> Denotable_value
access_env(i)(mk_(m,l)) ==
  m(i);

update_env : Id -> Denotable_value -> Env -> Env
update_env(i)(d)(mk_(m,l)) ==
  mk_(m ++ { i |-> d },l);

empty_env: Location -> Env
empty_env(l) ==
  mk_({|->},l);

multi_update_env : seq of (Id * Denotable_value) -> Env -> Env
multi_update_env(s)(e) ==
  if s = []
  then e
  else let mk_(id,v) = hd s in
    multi_update_env (tl s)(update_env(id)(v)(e));

reserve_locn : Env -> (Location * Env)
reserve_locn(mk_(m,l)) ==
  mk_(l,mk_(m,next_locn(l)));

instantiate_formals : (seq of Formal_elt) -> Param -> Env -> 
                      (Env | Errvalue)
instantiate_formals(formals)(params)(e) ==
  if len formals <> len params 
  then <err>
  else let lubs_eq = [ lub(formals(i).rep, (params(i)).type) =
                 formals(i).rep | i in set inds formals] in
       if false in set elems lubs_eq
       then <err>
       else let vals = [ if formals(i).fl = {}
                         then params(i)
                         else widen_type(params(i).val,
                                replace_flavour(params(i).type,
                                formals(i).fl)) | i in set inds params] in
            multi_update_env([mk_(formals(i).id,vals(i)) | i in set
                                 inds vals])(e);

mantissa : Real -> Real
mantissa(r) == r;

exponent : Real -> Real
exponent(r) == r;

tplus : Time * Time -> Time
tplus(mk_(l1,u1),mk_(l2,u2)) ==
  mk_(l1 + l2, u1 + u2);

dtplus : seq of Time -> Time
dtplus(ts) ==
  if ts = []
  then zerot
  else tplus(hd ts, dtplus(tl ts));

t_trimming_op:int -> Time 
t_trimming_op(l) == mk_(1,1);

t_vector_extract: int -> Time
t_vector_extract(l) == mk_(1,1);

t_vector_concat: int * int -> Time
t_vector_concat(l,m) == mk_(1,1);

t_vectorsum: int -> Time
t_vectorsum(l) == mk_(1,1);

t_vectorproduct: int -> Time
t_vectorproduct(l) == mk_(1,1);

t_vector_all: int -> Time
t_vector_all(l) == mk_(1,1);

t_vector_some: int -> Time
t_vector_some(l) == mk_(1,1);

t_vector_max: int -> Time
t_vector_max(l) == mk_(1,1);

t_vector_min: int -> Time
t_vector_min(l) == mk_(1,1);

t_vector_flatten: int -> Time
t_vector_flatten(l) == mk_(1,1);

t_vector_subv: int -> Time
t_vector_subv(l) == mk_(1,1);

t_multi_update : int -> Time
t_multi_update(l) == mk_(1,1);

choose : Expressible_type -> Expressible_value
choose(tp) ==
  let val: Expressible_value be st
    lub(const_type(val),tp) = tp in
  widen_type(const_type(val),tp);


eval_Program : Program -> Location -> Store -> EST_value
eval_Program(mk_Program(expr))(l)(sto) ==
  eval_Expression(expr)(empty_env(l))(mk_PState(sto,zerot)) ;

eval_Expression : Expression -> Env -> PState -> EST_value
eval_Expression(mk_Expression(expr))(env)(ps) ==
  cases expr:
   mk_Operation(op) -> eval_Operation(expr)(env)(ps),
   mk_InnerLoop(l) -> eval_InnerLoop(expr)(env)(ps),
   mk_Assignment(a) -> eval_Assignment(expr)(env)(ps),
   mk_Scope(s) -> eval_Scope(expr)(env)(ps),
   mk_GuardedScope(d,i,o) -> eval_GuardedScope(expr)(env)(ps),
   mk_Assertion(exp,tp) -> eval_Assertion(expr)(env)(ps),
   mk_TimedExpression(t) -> eval_TimedExpression(expr)(env)(ps)
  end;

eval_Operation : Operation -> Env -> PState -> EST_value
eval_Operation(mk_Operation(op))(e)(ps) ==
  cases op:
    mk_MonOperation(mo) -> eval_MonOperation(op)(e)(ps),
    mk_BinaryOperation(l,bo,r) -> eval_BinaryOperation(op)(e)(ps)
  end;

eval_MonOperation : MonOperation -> Env -> PState -> EST_value
eval_MonOperation(mk_MonOperation(mo))(e)(ps) ==
  cases mo:
    mk_MonOpMonOperand(opr,opnd) ->
           eval_MonOpMonOperand(mk_MonOpMonOperand(opr,opnd))(e)(ps),
    mk_VectorOperation(v,m,op) ->
           eval_VectorOperation(mk_VectorOperation(v,m,op))(e)(ps),
    mk_Value(v) -> eval_Value(mk_Value(v))(e)(ps)
  end;

eval_MonOpMonOperand: MonOpMonOperand -> Env -> PState -> EST_value
eval_MonOpMonOperand(mk_MonOpMonOperand(opr,opnd))(e)(ps) ==
  let x = eval_MonOperation(opnd)(e)(ps) in
  if x.val = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else cases opr:
        <numabs> -> eval_Abs(x),
        <unaryminus> -> eval_MonMinus(x),
        <not> -> eval_Not(x),
        mk_CompileTimeOp(o) -> eval_CompileTimeOp(opr)(x),
        <discard> -> eval_Discard(x),
        <round> -> eval_Round(x),
        <odd> -> eval_Odd(x),
        <float> -> eval_Float(x),
        <mantissa> -> eval_Mantissa(x),
        <exponent> -> eval_Exponent(x)
       end;

eval_Abs : EST_value -> EST_value
eval_Abs(mk_EST_value(val,sto,time)) ==
  if is_Real(val) 
  then mk_EST_value(absreal(val),sto,tplus(time,t_absreal))
  elseif is_Int(val)
  then mk_EST_value(absint(val),sto,tplus(time,t_absint))  
  else mk_EST_value(<err>,sto,zerot);

eval_MonMinus : EST_value -> EST_value
eval_MonMinus(mk_EST_value(val,sto,time)) ==
  if is_Real(val) 
  then mk_EST_value(realmonminus(val),sto,tplus(time,t_realmonminus))
  elseif is_Int(val)
  then mk_EST_value(intmonminus(val),sto,tplus(time,t_intmonminus))  
  else mk_EST_value(<err>,sto,zerot);

eval_Not : EST_value -> EST_value
eval_Not(mk_EST_value(val,sto,time)) ==
  if not is_Tr(val)
  then mk_EST_value(<err>, sto, zerot)
  else mk_EST_value(tr_not(val),sto, tplus(time,t_not));

eval_CompileTimeOp : CompileTimeOp -> EST_value -> EST_value
eval_CompileTimeOp(mk_CompileTimeOp(op))(mk_EST_value(val,sto,time)) ==
  if not is_Real(val)
  then mk_EST_value(<err>,sto,zerot)
  else cases op:
        <inf> -> mk_EST_value(inf(val),sto,time),
        <sup> -> mk_EST_value(sup(val),sto,time),
        <absonly> -> mk_EST_value(absonly(val),sto,time),
        <relonly> -> mk_EST_value(relonly(val),sto,time),
        <abserr> -> mk_EST_value(abserr(val),sto,time),
        <relerr> -> mk_EST_value(relerr(val),sto,time)
       end;

eval_Discard : EST_value -> EST_value
eval_Discard(mk_EST_value(val,sto,time)) ==
  if not is_Real(val)
  then mk_EST_value(<err>,sto, zerot)
  else mk_EST_value(discard(val),sto,tplus(time,t_discard));

eval_Round : EST_value -> EST_value
eval_Round(mk_EST_value(val,sto,time)) ==
  if not is_Real(val)
  then mk_EST_value(<err>,sto, zerot)
  else mk_EST_value(round(val),sto,tplus(time,t_round));

eval_Mantissa : EST_value -> EST_value
eval_Mantissa(mk_EST_value(val,sto,time)) ==
  if not is_Real(val)
  then mk_EST_value(<err>,sto, zerot)
  else mk_EST_value(mantissa(val),sto,tplus(time,t_mantissa));

eval_Exponent : EST_value -> EST_value
eval_Exponent(mk_EST_value(val,sto,time)) ==
  if not is_Real(val)
  then mk_EST_value(<err>,sto, zerot)
  else mk_EST_value(exponent(val),sto,tplus(time,t_exponent));

eval_Odd : EST_value -> EST_value
eval_Odd(mk_EST_value(val,sto,time)) ==
  if not is_Real(val)
  then mk_EST_value(<err>,sto, zerot)
  else mk_EST_value(odd(val),sto,tplus(time,t_odd));

eval_Float : EST_value -> EST_value
eval_Float(mk_EST_value(val,sto,time)) ==
  if not is_Real(val)
  then mk_EST_value(<err>,sto, zerot)
  else mk_EST_value(float(val),sto,tplus(time,t_float));

eval_VectorOperation : VectorOperation -> Env -> PState -> EST_value
eval_VectorOperation(mk_VectorOperation(vo,mo,mult))(e)(ps) ==
  let x = eval_MonOperation(mo)(e)(ps) in
  if not is_Vector(x.val)
  then mk_EST_value(<err>,ps.sto,zerot)
  else let v = if mult = nil then x
               else eval_VectorMult(mu(x,sto |-> ps.sto))(mult)(e) in
       if v.val = <err>
       then mk_EST_value(<err>,ps.sto,zerot)
       else cases vo:
             <sum> -> eval_VectorSum(v),
             <product> -> eval_VectorProduct(v),
             <vecmax> -> eval_VectorMax(v),
             <vecmin> -> eval_VectorMin(v),
             <all> -> eval_VectorAll(v),
             <some> -> eval_VectorSome(v),
             <flatten> -> eval_VectorFlatten(v)
            end;


eval_VectorMult : EST_value -> Multiple -> Env -> EST_value
eval_VectorMult(mk_EST_value(est_val,sto,time))(mk_Multiple(op,to_p))(e)
      ==
  let mk_Vector(val,type) = est_val in
  let b1 = eval_Operation(op)(e)(mk_PState(sto,time)) in
  let b2 = eval_Operation(to_p)(e)(mk_PState(sto,b1.time)) in
  if not (is_Int(b1.val) and is_Int(b2.val))
  then mk_EST_value(<err>,sto,zerot)
  elseif card(b1.val.type.range) <> 1 or card(b2.val.type.range) <> 1
  then mk_EST_value(<err>,sto,zerot)
  else let lower = min({b1.val.val,b2.val.val}),
           upper = max({b1.val.val,b2.val.val}) in
       if (lower < type.lower) or (type.upper < upper)
       then mk_EST_value(<err>,sto,zerot)
       else let new_val = vector_subv(val,lower,upper),
                new_type = mk_VectorType(lower,upper,type.type,type.fl) in
            let new_v = mk_Vector(new_val,new_type),
                new_t = tplus(tplus(b2.time,t_vector_subv(upper - lower)), 
                        tplus(t_min,t_max)) in
            mk_EST_value(new_v,sto,new_t);


eval_VectorSum : EST_value -> EST_value
eval_VectorSum(mk_EST_value(mk_Vector(val,type),sto,time)) ==
  if is_Float(type.type) or is_IntType(type.type)
  then mk_EST_value(vector_sum(val),sto,
                 tplus(time,t_vectorsum(type.upper - type.lower)))
  else mk_EST_value(<err>,sto,zerot);

eval_VectorProduct : EST_value -> EST_value
eval_VectorProduct(mk_EST_value(mk_Vector(val,type),sto,time)) ==
  if is_Float(type.type) or is_IntType(type.type)
  then mk_EST_value(vector_product(val),sto,
                 tplus(time,t_vectorproduct(type.upper - type.lower)))
  else mk_EST_value(<err>,sto,zerot);

eval_VectorMax : EST_value -> EST_value
eval_VectorMax(mk_EST_value(mk_Vector(val,type),sto,time)) ==
  if is_Float(type.type) or is_IntType(type.type)
  then mk_EST_value(vector_max(val),sto,
                 tplus(time,t_vector_max(type.upper - type.lower)))
  else mk_EST_value(<err>,sto,zerot);

eval_VectorMin : EST_value -> EST_value
eval_VectorMin(mk_EST_value(mk_Vector(val,type),sto,time)) ==
  if is_Float(type.type) or is_IntType(type.type)
  then mk_EST_value(vector_min(val),sto,
                 tplus(time,t_vector_min(type.upper - type.lower)))
  else mk_EST_value(<err>,sto,zerot);

eval_VectorAll : EST_value -> EST_value
eval_VectorAll(mk_EST_value(mk_Vector(val,type),sto,time)) ==
  if not is_TrType(type.type) 
  then mk_EST_value(<err>,sto,zerot)
  else mk_EST_value(vector_all(val),sto,
                 tplus(time,t_vector_all(type.upper - type.lower)));

eval_VectorSome : EST_value -> EST_value
eval_VectorSome(mk_EST_value(mk_Vector(val,type),sto,time)) ==
  if not is_TrType(type.type) 
  then mk_EST_value(<err>,sto,zerot)
  else mk_EST_value(vector_some(val),sto,
                 tplus(time,t_vector_some(type.upper - type.lower)));

eval_VectorFlatten : EST_value -> EST_value
eval_VectorFlatten(mk_EST_value(mk_Vector(val,type),sto,time)) ==
  if not is_VectorType(type.type)
  then mk_EST_value(<err>,sto,zerot)
  else let new_val = vector_flatten(val) in
       let new_upper = len new_val + type.lower - 1 in
       let new_time = tplus(time,t_vector_flatten(type.upper -
                      type.lower)),
           new_type = mk_VectorType(type.lower,
                          new_upper,type.type,type.fl) in
       mk_EST_value(mk_Vector(new_val,new_type),sto,new_time);



eval_BinaryOperation: BinaryOperation -> Env -> PState -> EST_value
eval_BinaryOperation(bo)(e)(ps) ==
 let mk_BinaryOp(op) = bo.opr in
  cases op:
    mk_NumOp(opr) -> eval_NumOp(bo)(e)(ps),
    <numgt>,<numlt>,<numge>,<numle> -> eval_CompOp(bo)(e)(ps),
    <and>,<or> -> eval_BoolOp(bo)(e)(ps),
    <EQ>,<NEQ> -> eval_EqOp(bo)(e)(ps),
    <concat> -> eval_Concat(bo)(e)(ps)
  end;

eval_NumOp : BinaryOperation -> Env -> PState -> EST_value
eval_NumOp(mk_BinaryOperation(left,mk_BinaryOp(opr),right))(e)(ps) ==
  let a1 = eval_MonOperation(left)(e)(ps) in
  let a2 = eval_MonOperation(right)(e)(mu(ps, time |-> a1.time)) in
  cases opr:
    mk_NumOp(op) -> 
      cases mk_(a1.val,a2.val):
        mk_(mk_Int(v1,t1),mk_Int(v2,t2)) ->
          if op <> <numdiv>
          then let val = intbinop(mk_Int(v1,t1),mk_Int(v2,t2),mk_NumOp(op)) in
               if val = <err>
               then mk_EST_value(<err>, ps.sto, zerot)
               else mk_EST_value(val,ps.sto, tplus(a2.time,t_intbinop))
          else mk_EST_value(<err>,ps.sto,zerot),
        mk_(mk_Real(v1,t1),mk_Real(v2,t2)) -> 
          if op not in set {<numdiv>,<nummod>} 
          then let val = realbinop(mk_Real(v1,t1),mk_Real(v2,t2),mk_NumOp(op)) 
                          in
               if val = <err>
               then mk_EST_value(<err>,ps.sto,zerot)
               else mk_EST_value(val,ps.sto, tplus(a2.time,t_realbinop))
          else mk_EST_value(<err>,ps.sto,zerot),
        others -> mk_EST_value(<err>,ps.sto,zerot)
      end,
    <replaceflav> -> if a2.val <> <err> and is_Void(a2.val)
                     then let mk_VoidType(f) = a2.val.type in
                          mk_EST_value(mu(a1.val,type |-> 
                              replace_flavour(a1.val.type,f)),
                              ps.sto,a2.time)
                     else mk_EST_value(<err>,ps.sto, zerot),
    others -> mk_EST_value(<err>,ps.sto,zerot)
  end;

eval_CompOp : BinaryOperation -> Env -> PState -> EST_value
eval_CompOp(mk_BinaryOperation(left,mk_BinaryOp(opr),right))(e)(ps) ==
  let a1 = eval_MonOperation(left)(e)(ps) in
  let a2 = eval_MonOperation(right)(e)(mu(ps, time |-> a1.time)) in
  if (is_Int(a1.val) and is_Int(a2.val))
  then mk_EST_value(intcomp(a1.val,a2.val,opr),
                                ps.sto,tplus(a2.time,t_intcomp))
  elseif is_Real(a1.val) and is_Real(a2.val)
  then mk_EST_value(realcomp(a1.val,a2.val,opr),
                                ps.sto,tplus(a2.time,t_realcomp))
  else mk_EST_value(<err>, ps.sto, zerot);

eval_EqOp : BinaryOperation -> Env -> PState -> EST_value
eval_EqOp(mk_BinaryOperation(left,mk_BinaryOp(op),right))(e)(ps)==
    let a1 = eval_MonOperation(left)(e)(ps) in
    let a2 = eval_MonOperation(right)(e)(mu(ps, time |-> a1.time)) in
    if is_Tr(a1.val) and is_Tr(a2.val)
    then mk_EST_value(tr_eq(a1.val,a2.val,op),
                                   ps.sto,tplus(a2.time,t_tr_eq)) 
    elseif is_Real(a1.val) and is_Real(a2.val)
    then mk_EST_value(real_eq(a1.val,a2.val,op),
                                   ps.sto,tplus(a2.time,t_real_eq)) 
    elseif is_Int(a1.val) and is_Int(a2.val)
    then mk_EST_value(int_eq(a1.val,a2.val,op),
                                   ps.sto,tplus(a2.time,t_int_eq)) 
    elseif is_Void(a1.val) and is_Void(a2.val)
    then mk_EST_value(void_eq(a1.val,a2.val,op),
                                   ps.sto,tplus(a2.time,t_void_eq)) 
    else mk_EST_value(<err>,ps.sto,zerot);

eval_BoolOp : BinaryOperation -> Env -> PState -> EST_value
eval_BoolOp(mk_BinaryOperation(left,mk_BinaryOp(op),right))(e)(ps) ==
    let a1 = eval_MonOperation(left)(e)(ps) in
    let a2 = eval_MonOperation(right)(e)(mu(ps, time |-> a1.time)) in
    if not (is_Tr(a2.val) and is_Tr(a2.val))
    then mk_EST_value(<err>,ps.sto,zerot)
    else cases op:
           <and> -> mk_EST_value(tr_and(a1.val,a2.val),ps.sto, 
                                       tplus(a2.time,t_and)),
           <or> -> mk_EST_value(tr_or(a1.val,a2.val),ps.sto,
                                     tplus(a2.time,t_and))
         end;

eval_Concat : BinaryOperation -> Env -> PState -> EST_value
eval_Concat(mk_BinaryOperation(left,op,right))(e)(ps)==
    let a1 = eval_MonOperation(left)(e)(ps) in
    let a2 = eval_MonOperation(right)(e)(mu(ps, time |-> a1.time)) in
    if not (is_Vector(a1.val) and is_Vector(a2.val))
    then mk_EST_value(<err>,ps.sto,zerot)
    elseif not (tleq(a1.val.type.type,a2.val.type.type) or
                tleq(a2.val.type.type,a1.val.type.type))
    then mk_EST_value(<err>, ps.sto,zerot)
    else let new_vec = vector_concat(a1.val,a2.val),
             new_time = tplus(a2.time
                   t_vector_concat(vector_length(a1.val.type),
                                   vector_length(a2.val.type))) in
         mk_EST_value(new_vec,ps.sto,new_time);

eval_Value: Value -> Env -> PState -> EST_value
eval_Value(mk_Value(val))(e)(ps) ==
  cases val:
    mk_ConstantValue(c) -> eval_ConstantValue(mk_ConstantValue(c))(ps),
    mk_NamedValue(n) -> eval_NamedValue(mk_NamedValue(n))(e)(ps),
    mk_VectorVal(v) -> eval_VectorVal(mk_VectorVal(v))(e)(ps),
    mk_StructureValue(s) -> eval_StructureValue(mk_StructureValue(s))(e)(ps),
    mk_Sequence(s) -> eval_Sequence(mk_Sequence(s))(e)(ps),
    mk_Call(id,acts) -> eval_Call(mk_Call(id,acts))(e)(ps),
    mk_Conditional(c) -> eval_Conditional(val)(e)(ps),
    mk_Widening(exp,t) -> eval_Widening(val)(e)(ps),
    mk_OuterLoop(l) -> eval_OuterLoop(val)(e)(ps)
  end;

eval_ConstantValue : ConstantValue -> PState -> EST_value
eval_ConstantValue(mk_ConstantValue(cv))(ps) ==
  cases cv:
    mk_IntegerDenotation(z) ->
        let rep = if abs z >= bytemax then <word> else <byte> in
        mk_EST_value(mk_Int(z,mk_IntType(rep,{z},{})),ps.sto,ps.time),
    mk_FloatingDenotation(r) ->
        mk_EST_value(mk_Real(r,mk_Float({mk_Floatrng(floor r, if
                          is_int(r) then r else floor (r +
                          0.5))},0,0,{})),ps.sto,ps.time),
    mk_BooleanDenotation(b) ->
        mk_EST_value(mk_Tr(b,mk_TrType({b},{})),ps.sto,ps.time),
    mk_Ascii_Char(c) ->
        mk_EST_value(mk_Int(ascii(c),mk_IntType(<byte>,{ascii(c)},{})), 
                ps.sto, ps.time),
    mk_Ascii_string(s) ->
        mk_EST_value(mk_Vector([mk_Int(ascii(a),
                                       mk_IntType(<byte>,{ascii(a)}, {})) 
                             |  a in seq s],
                     mk_VectorType(1,len s, seqlub([mk_IntType(<byte>,
                    {ascii(a)},{}) | a in seq s]),{})),ps.sto,ps.time),
    mk_Flavouring(fl) ->
  mk_EST_value(mk_Void(<nil>, mk_VoidType(eval_Flavouring(cv))), ps.sto, ps.time),
    <skip> -> mk_EST_value(mk_Void(<nil>,mk_VoidType({})), ps.sto,
                       tplus(ps.time, t_skip)) 
    end;

eval_NamedValue : NamedValue -> Env -> PState -> EST_value
eval_NamedValue(mk_NamedValue(nv))(e)(ps) ==
  cases nv :
    mk_FlavourExtract(n,fl) -> eval_FlavourExtract(nv)(e)(ps),
    mk_FlavourStrip(n,fl) -> eval_FlavourStrip(nv)(e)(ps),
    mk_VectorExtract(n,i) -> eval_VectorExtract(nv)(e)(ps),
    mk_VectorTrimming(n,t,i) -> eval_VectorTrimming(nv)(e)(ps),
    others -> eval_Identifier(nv)(e)(ps)
  end;


eval_Identifier : Id -> Env -> PState -> EST_value
eval_Identifier(id)(mk_(m,l))(mk_PState(sto,time)) ==
  if id in set dom m
  then cases access_env(id)(mk_(m,l)):
        mk_Location(l) -> let mk_Storable_value(v) = 
                               access (mk_Location(l))(sto) in
                   mk_EST_value(v,sto,tplus(time,t_access)),
        mk_Storable_value(v) -> mk_EST_value(v,sto,time)
       end
  else mk_EST_value(<err>,sto,time);

eval_FlavourExtract : FlavourExtract -> Env -> PState -> EST_value
eval_FlavourExtract(mk_FlavourExtract(nv,fl))(e)(ps) ==
  let n = eval_NamedValue(nv)(e)(ps),
      f = eval_Flavouring(fl) in
  if not is_Structure(n.val)
  then mk_EST_value(<err>,ps.sto,ps.time)
  else mk_EST_value(comp_extract(n.val,f),ps.sto,tplus(n.time,t_comp_extract));


eval_Flavouring : Flavouring -> Flavdom
eval_Flavouring(mk_Flavouring(fls)) ==
  if fls = []
  then {}
  else {eval_Flavour(hd fls)} union eval_Flavouring(mk_Flavouring(tl fls));

eval_Flavour : Flavour -> Fl_elt
eval_Flavour(mk_Flavour(name,index)) ==
  mk_Fl_elt(name,index);

eval_FlavourStrip : FlavourStrip -> Env -> PState -> EST_value
eval_FlavourStrip(mk_FlavourStrip(nv,fl))(e)(ps) ==
  let n = eval_NamedValue(nv)(e)(ps),
      f = eval_Flavouring(fl) in
  if not is_Structure(n.val)
  then mk_EST_value(<err>,ps.sto,ps.time)
  else let n' = comp_extract(n.val,f) in
       let n'' = mk_Structure(n'.val,mk_StructureType(n'.type.tps,{})) in
       mk_EST_value(n'',ps.sto,tplus(n.time,t_comp_extract));

eval_VectorExtract : VectorExtract -> Env -> PState -> EST_value
eval_VectorExtract(mk_VectorExtract(n,i))(e)(ps) ==
  let x = eval_NamedValue(n)(e)(ps) in
  if not is_Vector(x.val)
  then mk_EST_value(<err>,ps.sto,ps.time)
  else let index = eval_Operation(i)(e)(mu(ps, time |-> x.time)),
           length = x.val.type.upper - x.val.type.lower + 1 in
       if not is_Int(index.val)
       then mk_EST_value(<err>,ps.sto,ps.time)
       elseif not (index.val.type.range subset
                    {x.val.type.lower,...,x.val.type.upper}) 
       then mk_EST_value(<err>,ps.sto,ps.time)
       else mk_EST_value(vector_extract(x.val,index.val.val),
                          ps.sto,tplus(index.time,t_vector_extract(length)));



eval_VectorTrimming : VectorTrimming -> Env -> PState -> EST_value
eval_VectorTrimming(mk_VectorTrimming(name,to_p,ctv))(e)(ps)==
  let vec = eval_NamedValue(name)(e)(ps) in
  if not is_Vector(vec.val) or (is_Vector(vec.val) and
      not (is_Float(vec.val.type.type) or is_IntType(vec.val.type.type)))
  then mk_EST_value(<err>,ps.sto,zerot)
  else let v = eval_CompileTimeValue(ctv)(e) in
       if not (is_Real(v.val) or is_Int(v.val))
       then mk_EST_value(<err>,ps.sto,zerot)
       else let new_v = cases to_p:
                          <gtvalue> -> 
                             [i | i in seq vec.val.val & i >= v.val.val],
                          <ltvalue> -> 
                             [i | i in seq vec.val.val & i <= v.val.val],
                          <atvalue> -> 
                             [i | i in seq vec.val.val & i = v.val.val]
                        end in
            if new_v = []
            then mk_EST_value(<err>,ps.sto,zerot)
            else let new_l = vec.val.type.lower,
                     new_u = vec.val.type.lower + len new_v - 1,
                new_t = seqlub([const_type(v) | v in seq new_v]),
                     new_fl = vec.val.type.fl in
                 let new_vec = mk_Vector(new_v,mk_VectorType(new_l,new_u,new_t,
                                                   new_fl)),
                     new_time = tplus(vec.time,
                                         t_trimming_op(new_u-new_l)) in
                 mk_EST_value(new_vec,ps.sto,new_time);

eval_CompileTimeValue : CompileTimeValue -> Env -> EST_value
eval_CompileTimeValue(mk_CompileTimeValue(op))(mk_(m,l)) ==
  let locs = {id | id in set dom m & is_Location(m(id))} in
  let new_m = locs <-: m in
  let new_env = mk_(new_m,l) in
      eval_Operation(op)(new_env)(mk_PState({|->},zerot));

eval_VectorVal : VectorVal -> Env -> PState -> EST_value
eval_VectorVal(mk_VectorVal(ops))(e)(ps) ==
  let vals = [ eval_Operation(o)(e)(mk_PState(ps.sto,zerot)) | o in seq ops] in
  let val = [ v.val | v in seq vals],
      time = dtplus([v.time | v in seq vals]) in
  if <err> in set elems val
  then mk_EST_value(<err>,ps.sto,zerot)
  else let type = seqlub([v.type | v in seq val]) in
       if type = <err> 
       then mk_EST_value(<err>,ps.sto,zerot)
       else let tp = mk_VectorType(1,len val, type, {}) in
            let x = mk_Vector(val,tp) in
            mk_EST_value(x,ps.sto,time);

eval_StructureValue: StructureValue -> Env -> PState -> EST_value
eval_StructureValue(mk_StructureValue(ops))(e)(ps) ==
  let vals = [ eval_Operation(o)(e)(mk_PState(ps.sto,zerot)) | o in seq ops] in
  if (exists val in seq vals & 
        not (is_Tr(val.val) or is_Int(val.val) or is_Real(val.val)))
  then mk_EST_value(<err>,ps.sto,zerot)
  elseif exists v1,v2 in seq vals & fleq(v1.val.type,v2.val.type)
  then mk_EST_value(<err>,ps.sto, zerot)
  else let tps = [v.val.type | v in seq vals],
           time = dtplus([v.time | v in seq vals]),
           comps = [v.val.val | v in seq vals] in
       let type = mk_StructureType(tps,{}) in
       let val = mk_Structure(comps,type) in
       mk_EST_value(val,ps.sto,time);

eval_Sequence : Sequence -> Env -> PState -> EST_value
eval_Sequence(mk_Sequence(exprs))(e)(ps) ==
  let x = eval_Expression(hd exprs)(e)(ps) in
  if len exprs = 1 
  then x
  elseif is_Void(x.val)
  then eval_Sequence(mk_Sequence(tl exprs))(e)(mk_PState(x.sto,x.time))
  else mk_EST_value(<err>,ps.sto,zerot);

eval_Call : Call -> Env -> PState -> EST_value
eval_Call(mk_Call(id,acts))(mk_(m,l))(mk_PState(sto,time)) ==
  if id not in set dom m
  then mk_EST_value(<err>,sto,zerot)
  else let pp = access_env(id)(mk_(m,l)) in
       if not is_Proc(pp)
       then mk_EST_value(<err>,sto,zerot)
       else let mk_Proc(p) = pp in
            let params =  eval_Acts(acts)(mk_(m,l))(
                          mk_PState(sto,time)) in
              if <err> in set {x.val | x in seq params}
              then mk_EST_value(<err>,sto,zerot)
              else p([m.val | m in seq params]) 
                    (mk_PState(sto, params(len params).time));

eval_Acts: seq of Operation -> Env -> PState -> seq of EST_value
eval_Acts(ops)(e)(ps) ==
  if ops = []
  then []
  else let x = eval_Operation(hd ops)(e)(ps) in
       [x]^eval_Acts(tl ops)(e)(mk_PState(ps.sto,x.time));

eval_Widening : Widening -> Env -> PState -> EST_value
eval_Widening(mk_Widening(expr,dest_type))(e)(ps) ==
  let x = eval_Expression(expr)(e)(ps) in
  if x.val = <err>
  then mk_EST_value(<err>, ps.sto, zerot)
  else let xt = x.val.type,
           dt = eval_Type(dest_type)(e) in
       if dt=<err> 
       then mk_EST_value(<err>, ps.sto, zerot)
       else let dt' = phi_remove(dt) in
            if gt(dt',xt)
            then mk_EST_value(widen_type(x.val,dt'), ps.sto, x.time)
            else mk_EST_value(<err>, ps.sto, zerot);

eval_Type : Type -> Env -> (Expressible_type | Errvalue)
eval_Type(mk_Type(tp))(e) ==
  cases tp:
    mk_PrimitiveType(p) -> eval_PrimitiveType(tp)(e),
    mk_VecType(range,tpe) -> eval_VecType(tp)(e),
    mk_StrucType(tps) -> eval_StrucType(tp)(e),
    mk_FlavouredType(fl,tpe) -> eval_FlavouredType(tp)(e),
    mk_UnionTp(tps) -> eval_UnionTp(tp)(e),
    mk_TypeName(id) -> eval_TypeName(tp)(e)
  end;

eval_PrimitiveType : PrimitiveType -> Env -> (Expressible_type | Errvalue)
eval_PrimitiveType(mk_PrimitiveType(pt))(e) ==
  if is_Number(pt)
  then eval_Number(pt)(e)
  elseif is_FloatType(pt)
  then eval_FloatType(pt)(e)
  else eval_VoidValType(pt)(e);

eval_Number : Number -> Env -> (Expressible_type | Errvalue)
eval_Number(mk_Number(rep,range))(e) ==
  let ranges = { eval_Range(r)(e) | r in seq range} in
  if <err> in set ranges
  then <err>
  elseif rep = <bit>
  then if exists v in set dunion ranges & v not in set {0,1}
       then <err>
       else let m = { 0 |-> false, 1 |-> truein
            mk_TrType({m(v) | v in set dunion ranges},{})
  elseif rep = <byte>
  then if exists v in set dunion ranges & abs v > bytemax
       then <err>
       else mk_IntType(rep,dunion ranges, {})
  elseif exists v in set dunion ranges & abs v > maxint
  then <err>
  else mk_IntType(rep,dunion ranges, {});

eval_Range : Range -> Env -> (set of int | Errvalue)
eval_Range(mk_Range(lower,upper))(e) ==
  if (lower = nil and upper = nilor
     (lower <> nil and not is_Int((eval_CompileTimeValue(lower)(e)).val)) or
     (upper <> nil and not is_Int((eval_CompileTimeValue(upper)(e)).val))
  then <err>
  elseif lower=nil
  then { x | x: int & 0 <= x and x <= (eval_CompileTimeValue(upper)(e)).val.val}
  elseif upper = nil
  then { x | x: int & (eval_CompileTimeValue(lower)(e)).val.val <= x and
                      x <= maxint}
  else { x | x: int & (eval_CompileTimeValue(lower)(e)).val.val <= x and
                      x <= (eval_CompileTimeValue(upper)(e)).val.val};

eval_FloatType : FloatType -> Env -> (Expressible_type | Errvalue)
eval_FloatType(mk_FloatType(ranges,abserr,relerr))(e) ==
  if (abserr = nil and relerr = nilor
     (exists range in seq ranges & (eval_Range(range)(e)) = <err>)
  then <err>
  else let abse = if abserr = nil
                  then mk_Real(0,mk_Float({mk_Floatrng(0,0)},0,0,{}))
                  else (eval_CompileTimeValue(abserr)(e)).val,
           rele = if relerr = nil
                  then mk_Real(0,mk_Float({mk_Floatrng(0,0)},0,0,{}))
                  else (eval_CompileTimeValue(relerr)(e)).val in
       if not(is_Real(abse) and is_Real(rele))
       then <err>
       else mk_Float({mk_Floatrng(min(eval_Range(range)(e)),
                                  max(eval_Range(range)(e))) | range
                        in seq ranges}, abse.val,rele.val,{});

eval_VoidValType : VoidValType -> (Env -> (Expressible_type | Errvalue))
eval_VoidValType(fl) == 
  lambda e: Env & mk_VoidType(eval_Flavouring(fl));

eval_StrucType : StrucType -> Env -> (Expressible_type | Errvalue)
eval_StrucType(mk_StrucType(tps))(e) ==
  let typs = [ eval_Type(t)(e) | t in seq tps] in
  if exists tp in seq typs & 
         not (is_TrType(tp) or is_Float(tp) or is_IntType(tp))
  then <err>
  elseif exists tp1,tp2 in seq typs & 
         tp1 <> tp2 and tp1.fl = tp2.fl
  then <err>
  else mk_StructureType(typs,{});

eval_VecType : VecType -> (Env -> (Expressible_type | Errvalue))
eval_VecType(mk_VecType(range,tp)) == lambda e : Env & 
  let typ = eval_Type(tp)(e),
      nrange = eval_Range(range)(e) in
  if typ = <err> or nrange = <err>
  then <err>
  else mk_VectorType(min(nrange),max(nrange),typ,{});

eval_FlavouredType : FlavouredType -> Env -> (Expressible_type | Errvalue)
eval_FlavouredType(mk_FlavouredType(fl,tp))(e) ==
  let flavour = eval_Flavouring(fl),
      typ = eval_Type(tp)(e) in
  if typ = <err>
  then <err>
  else   cases typ:
    mk_VoidType(t) -> mk_VoidType(t union flavour),
    mk_TrType(range,fl) -> mk_TrType(range,fl union flavour),
    mk_IntType(rep,range,fl) -> mk_IntType(rep,range, fl union flavour),
    mk_Float(range,abse,rele,fl) -> mk_Float(range,abse,rele,fl union flavour),
    mk_VectorType(lower,upper,tp,fl) ->
                      mk_VectorType(lower,upper,tp, fl union flavour),
    mk_StructureType(tps,fl) -> mk_StructureType(tps,fl union flavour),
    mk_UnionType(tps,fl) -> mk_UnionType(tps,fl union flavour)
  end;

eval_UnionTp : UnionTp -> Env -> (Expressible_type | Errvalue)
eval_UnionTp(mk_UnionTp(tps))(e) ==
  let typs = {eval_Type(t)(e) | t in seq tps} in
  if exists tp in set typs &  not (is_IntType(tp) or is_Float(tp) or 
                        is_TrType(tp) or is_VoidType(tp))
  then <err>
  elseif exists t1,t2 in set typs & fleq(t1,t2)
  then <err>
  else mk_UnionType(typs,{});

eval_TypeName : TypeName -> Env -> (Expressible_type | Errvalue)
eval_TypeName(mk_TypeName(id))(mk_(m,l)) ==
  if id in set dom m
  then cases access_env(id)(mk_(m,l)):
         mk_Location(l),mk_Storable_value(v),
              mk_Proc(p),<err> -> <err>,
         t -> t
       end
  else <err>;


eval_Scope : Scope -> Env -> PState -> EST_value
eval_Scope(mk_Scope(s))(e)(ps) ==
  if is_SimpleScope(s)
  then eval_SimpleScope(s)(e)(ps)
  else eval_PackageScope(s)(e)(ps);

eval_SimpleScope : SimpleScope -> Env -> PState -> EST_value
eval_SimpleScope(mk_SimpleScope(decls,expr))(e)(ps) ==
  let old_env_st = mk_(e,ps) in
  let new_env_st = eval_Decls(decls)(old_env_st) in
  if new_env_st = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let mk_(new_env,new_sto) = new_env_st in
       eval_Expression(expr)(new_env)(new_sto);

eval_Decls: seq of Declaration -> EnvState -> EnvState 
eval_Decls(decls)(env_st) ==
  if env_st = <err>
  then <err>
  elseif decls = []
  then env_st
  else eval_Decls(tl decls)(eval_Declaration(hd decls)(env_st));

eval_Declaration : Declaration -> EnvState -> EnvState
eval_Declaration(decl)(env_st) ==
  cases decl :
    mk_ImportDecl(id,tp) -> eval_ImportDecl(decl)(env_st),
    mk_ExportDecl(id,expr) -> eval_ExportDecl(decl)(env_st),
    mk_LetDecl(l) -> eval_LetDecl(decl)(env_st),
    mk_VarDecl(id,expr) -> eval_VarDecl(decl)(env_st),
    mk_ProcDec(nls,ph,expr) -> eval_ProcDec(decl)(env_st),
    mk_TypeDec(id,type) -> eval_TypeDec(decl)(env_st)
  end;

eval_ImportDecl : ImportDecl -> EnvState -> EnvState
eval_ImportDecl(mk_ImportDecl(id,tp))(mk_(e,ps)) ==
  let type = eval_Type(tp)(e) in
  if type = <err>
  then <err>
  else let val = choose(type),
           mk_(l,n_e) = reserve_locn(e) in
       let nn_e = update_env(id)(l)(n_e),
           sto = update(l)(mk_Storable_value(val))(ps.sto),
           t = tplus(ps.time,t_update) in
       mk_(nn_e,mk_PState(sto,t));

eval_ExportDecl : ExportDecl -> EnvState -> EnvState
eval_ExportDecl(mk_ExportDecl(id,expr))(mk_(e,ps)) ==
  let x = eval_Expression(expr)(e)(ps) in
  if x.val = <err>
  then <err>
  else let mk_(l,n_e) = reserve_locn(e) in
       let nn_e = update_env(id)(l)(n_e),
           sto = update(l)(mk_Storable_value(x.val))(ps.sto),
           t = tplus(ps.time,t_update) in
       mk_(nn_e,mk_PState(sto,t));

eval_LetDecl : LetDecl -> EnvState -> EnvState
eval_LetDecl(mk_LetDecl(decl))(es) ==
  if is_SimpleLetDecl(decl)
  then eval_SimpleLetDecl(decl)(es)
  else eval_StrucLetDecl(decl)(es);

eval_SimpleLetDecl : SimpleLetDecl -> EnvState -> EnvState
eval_SimpleLetDecl(mk_SimpleLetDecl(id,expr))(mk_(e,ps)) ==
  let x = eval_Expression(expr)(e)(ps) in
  if x.val = <err>
  then <err>
  else mk_((update_env(id)(x.val)(e)),
                   mk_PState(ps.sto, x.time));

eval_StrucLetDecl : StrucLetDecl -> EnvState -> EnvState
eval_StrucLetDecl(mk_StrucLetDecl(ids,expr))(mk_(e,ps)) ==
  let x = eval_Expression(expr)(e)(ps) in
  if not is_Structure(x.val)
  then <err>
  elseif len ids <> struc_length(x.val.type)
  then <err>
  else let id_vals = [ mk_(ids(i),
                          construct_ev(x.val.val(i),x.val.type.tps(i))) | 
                             i in set inds ids] in
       let new_env = multi_update_env(id_vals)(e) in
       mk_(new_env,mk_PState(ps.sto,x.time));

eval_VarDecl : VarDecl -> EnvState -> EnvState
eval_VarDecl(mk_VarDecl(id,expr))(mk_(e,ps)) ==
  let x = eval_Expression(expr)(e)(ps) in
  if x.val = <err>
  then <err>
  else let mk_(l,n_e) = reserve_locn(e) in
       let nn_e = update_env(id)(l)(n_e),
           sto = update(l)(mk_Storable_value(x.val))(ps.sto),
           t = tplus(ps.time,t_update) in
       mk_(nn_e,mk_PState(sto,t));

eval_ProcDec : ProcDec -> EnvState -> EnvState
eval_ProcDec(mk_ProcDec(nls,ph,expr))(mk_(e,ps)) ==
  let env_st = eval_NonLocals(nls)(e)(ps) in
  if env_st = <err>
  then <err>
  else let mk_ProcHeading(id,formals) = ph,
           mk_(ne,ns) = env_st in
       let fls = eval_Formals(formals)(e) in
       let pr = 
           mk_Proc(lambda a:Param & 
                     let nn_e = instantiate_formals(fls)(a)(ne) in
                     lambda nps: PState &
                       if nn_e = <err>
                       then mk_EST_value(<err>,nps.sto,zerot)
                       else let x = eval_Expression(expr)(nn_e)(nps) in
                            if x.val <> <err> and 
                               ((is_Void(x.val) and x.val.type = mk_VoidType({Phi}))
                                 or
                                 (not is_Void(x.val) and x.val.type.fl = {Phi}))
                            then mk_EST_value(<err>,nps.sto,zerot)
                            else x) in
       mk_(update_env(id)(pr)(e),mk_PState(ps.sto, ns.time));

eval_NonLocals : NonLocals -> Env -> PState -> EnvState
eval_NonLocals(mk_NonLocals(ids,decls))(mk_(m,l))(ps) ==
  let ids_map = if ids = nil then {|->} else (elems ids) <: m in
  if decls = nil
  then mk_(mk_(ids_map,l),ps)
  else eval_Decls(decls)(mk_(mk_(ids_map,l),ps));

eval_Formals : seq of Formal -> Env -> seq of Formal_elt
eval_Formals(fls)(e) ==
  [eval_Formal(f)(e) | f in seq fls];

eval_Formal : Formal -> Env -> Formal_elt
eval_Formal(mk_Formal(id,rep,fl))(e) ==
  let n_rep = eval_Representation(rep)(e),
      n_fl = eval_Flavouring(fl) in
  mk_Formal_elt(id,n_rep,n_fl);

eval_Representation : Representation -> Env -> (Expressible_type | Errvalue)
eval_Representation(rep)(e) ==
  cases rep:
    mk_PrimitiveRep(p) -> eval_PrimitiveRep(rep)(e),
    mk_StrucRep(rs) -> eval_StrucRep(rep)(e),
    mk_VecRep(range,r) -> eval_VecRep(rep)(e),
    mk_UnionRep(rs) -> eval_UnionRep(rep)(e),
    mk_FlavouredRep(f,r) -> eval_FlavouredRep(rep)(e),
    mk_Type(t) -> eval_Type(rep)(e)
  end;

eval_PrimitiveRep : PrimitiveRep -> Env -> (Expressible_type | Errvalue)
eval_PrimitiveRep(mk_PrimitiveRep(rep))(e) ==
  if is_NumRep(rep)
  then eval_NumRep(rep)(e)
  else eval_FloatRep(rep)(e);

eval_NumRep : NumRep -> Env -> (Expressible_type | Errvalue)
eval_NumRep(mk_NumRep(rep,range))(e) ==
  let ranges = if range = nil then {}
               else {eval_Range(r)(e) | r in seq range} in
  if <err> in set ranges
  then <err>
  elseif rep = <bit>
  then if exists v in set dunion ranges & v not in set {0,1}
       then <err>
       else let rngs = if range = nil then {true,false}
                       else {{0 |-> false, 1 |-> true}(r) | r in set
                            dunion ranges} in
            mk_TrType(rngs,{})
   elseif rep = <byte>
   then if exists v in set dunion ranges & abs v > bytemax
        then <err>
        else let rngs = if range = nil then {-bytemax,...,bytemax}
                        else dunion ranges in
             mk_IntType(rep,rngs,{})
   elseif exists v in set dunion ranges & abs v > maxint
   then <err>
   else let rngs = if range = nil then {-maxint,...,maxint}
                   else dunion ranges in
        mk_IntType(rep,rngs,{});

eval_FloatRep : FloatRep -> Env -> (Expressible_type | Errvalue)
eval_FloatRep(mk_FloatRep(range,abserr,relerr))(e) ==
  let ranges = if range = nil then {} 
               else {eval_Range(r)(e) | r in seq range},
      abse   = if abserr = nil 
               then mk_Real(maxint,
                            mk_Float({mk_Floatrng(maxint,maxint)},0,0,{}))
               else eval_CompileTimeValue(abserr)(e),
      rele   = if relerr = nil 
               then mk_Real(maxint,
                            mk_Float({mk_Floatrng(maxint,maxint)},0,0,{}))
               else eval_CompileTimeValue(relerr)(e) in
  if not (is_Real(abse.val) and is_Real(rele.val)) or <err> in set ranges 
  then <err>
  else let rngs = if range = nil
                  then {mk_Floatrng(-(beta ** maxint),beta ** maxint)}
                  else {mk_Floatrng(min(r),max(r)) | r in set ranges} in
       mk_Float(rngs, abse.val.val,rele.val.val,{});

eval_StrucRep : StrucRep -> Env -> (Expressible_type | Errvalue)
eval_StrucRep(mk_StrucRep(reps))(e) ==
  let tps = [ eval_Representation(r)(e) | r in seq reps] in
  if exists tp in seq tps & not(is_TrType(tp) or is_Float(tp) or
                                      is_IntType(tp))
  then <err>
  elseif exists tp1,tp2 in seq tps & fleq(tp1,tp2)
  then <err>
  else mk_StructureType(tps,{});

eval_VecRep : VecRep -> Env -> (Expressible_type | Errvalue)
eval_VecRep(mk_VecRep(range,rep))(e) ==
  let nrange = eval_Range(range)(e),
      type = eval_Representation(rep)(e) in
  if type = <err> or nrange = <err>
  then <err>
  else mk_VectorType(min(nrange),max(nrange),type,{});

eval_UnionRep : UnionRep -> Env -> (Expressible_type | Errvalue)
eval_UnionRep(mk_UnionRep(reps))(e) ==
  let tps = {eval_Representation(rep)(e) | rep in seq reps} in
  if exists tp in set tps & not (is_IntType(tp) or is_Float(tp) or
                                   is_TrType(tp) or is_VoidType(tp))
  then <err>
  elseif exists tp1,tp2 in set tps & fleq(tp1,tp2)
  then <err>
  else mk_UnionType(tps,{});

eval_FlavouredRep : FlavouredRep -> Env -> (Expressible_type | Errvalue)
eval_FlavouredRep(mk_FlavouredRep(fl,rep))(e) ==
  let type = eval_Representation(rep)(e),
      flav = eval_Flavouring(fl) in
  if type = <err> 
  then <err>
  else replace_flavour(type,flav); 

eval_TypeDec : TypeDec -> EnvState -> EnvState
eval_TypeDec(mk_TypeDec(id,tp))(mk_(e,ps)) ==
  let type = eval_Type(tp)(e) in
  if type = <err>
  then <err>
  else mk_(update_env(id)(type)(e),ps);

eval_PackageScope : PackageScope -> Env -> PState -> EST_value
eval_PackageScope(mk_PackageScope(ids,decls,expr))(mk_(m,l))(ps) ==
  let env_st = mk_(mk_(m,l),ps) in
  let new_env_st = eval_Decls(decls)(env_st) in
  if new_env_st = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let mk_(mk_(nm,nl),nps) = new_env_st in
       if not (elems ids subset (dom nm \ dom m))
       then mk_EST_value(<err>,ps.sto,zerot)
       else let ne = mk_(((elems ids) union dom m) <: nm, nl) in
            eval_Expression(expr)(ne)(nps);

eval_GuardedScope : GuardedScope -> Env -> PState -> EST_value
eval_GuardedScope(mk_GuardedScope(decls,incl,outcl))(e)(ps) ==
  let g_decl = eval_GuardedDeclarations(decls)(true)(e)(ps) in
  if g_decl = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let mk_(ne,nps,val) = g_decl in
       let in_val = eval_Sequence(incl)(ne)(nps),
           out_val = eval_Sequence(outcl)(ne)(nps) in
       if in_val.val = <err> or out_val.val = <err>
       then mk_EST_value(<err>,ps.sto, zerot)
       else let type = setlub({in_val.val.type,out_val.val.type}) in
            if type = <err>
            then mk_EST_value(<err>,ps.sto, zerot)
            else if val
                 then mk_EST_value(widen_type(in_val.val,type),in_val.sto,
                                   tplus(in_val.time,t_if))
                 else mk_EST_value(widen_type(out_val.val,type),out_val.sto,
                                   tplus(out_val.time,t_if));

eval_GuardedDeclarations : seq1 of GuardedDeclaration -> bool -> Env
                     -> PState -> ((Env * PState * bool) | Errvalue)
eval_GuardedDeclarations(decls)(b)(e)(ps) ==
  let gdcl = eval_GuardedDecl(hd decls)(e)(ps) in
  if len decls = 1
  then gdcl
  elseif gdcl = <err>
  then <err>
  else let mk_(ne,nps,tr) = gdcl in
       eval_GuardedDeclarations(tl decls)(b and tr)(ne)(nps);

eval_GuardedDecl : GuardedDeclaration -> Env -> PState -> ((Env *
                    PState * bool) | Errvalue) 
eval_GuardedDecl(decl)(e)(ps) ==
  if is_WhereDecl(decl)
  then eval_WhereDecl(decl)(e)(ps)
  else let d = eval_Declaration(decl)(mk_(e,ps)) in
       if d = <err> 
       then <err>
       else let mk_(ne,nps) = d in
            mk_(ne,nps,true);

eval_WhereDecl : WhereDecl -> Env -> PState -> ((Env * PState * bool) | Errvalue)
eval_WhereDecl(mk_WhereDecl(type,expr,id))(e)(ps) ==
  let x = eval_Expression(expr)(e)(ps) in
  if x.val = <err>
  then <err>
  else let t = eval_SkeletonType(type)(x.val.type)(e) in
       cases t: 
       <err> ->  <err>,
       others ->  let env = if id = nil
                            then e
                            else update_env(id)(x.val)(e) in
                  let xt = const_type(x.val) in
                  cases xt:
                     <err> -> <err>,
                     others -> let val = gt(t,xt) in
                               mk_(env, mk_PState(ps.sto,x.time),val)
                  end
       end;

eval_Assertion : Assertion -> Env -> PState -> EST_value
eval_Assertion(mk_Assertion(expr,tp))(e)(ps) ==
  let x = eval_Expression(expr)(e)(ps) in
  if x.val = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let type = eval_SkeletonType(tp)(x.val.type)(e) in
       if type = <err>
       then mk_EST_value(<err>,ps.sto,zerot)
       else let xt = const_type(x.val) in
            cases xt:
              <err> -> mk_EST_value(<err>,ps.sto,zerot),
              others -> 
                if not (tleq(type,x.val.type) and tleq(xt,type))
                then mk_EST_value(<err>,ps.sto,zerot)
                else let val = widen_type(x.val, phi_remove(type)) in
                     mk_EST_value(val,x.sto,tplus(x.time,t_widen_type))
            end;


eval_Conditional: Conditional -> Env -> PState -> EST_value
eval_Conditional(mk_Conditional(cond))(e)(ps) ==
  if is_IfThenOnly(cond)
  then eval_IfThenOnly(cond)(e)(ps)
  elseif is_IfThenElse(cond)
  then eval_IfThenElse(cond)(e)(ps)
  else eval_CaseExpr(cond)(e)(ps);

eval_IfThenOnly : IfThenOnly -> Env -> PState -> EST_value
eval_IfThenOnly(mk_IfThenOnly(prop,action))(e)(ps) ==
  let cond = eval_Expression(prop)(e)(ps),
      aseq = eval_Sequence(action)(e)(mu(ps,time |-> tplus(cond.time,t_if)))
                 in
  if not is_Tr(cond.val) or not is_Void(aseq.val)
  then mk_EST_value(<err>,ps.sto,zerot)
  elseif cond.val.val
  then aseq
  else mk_EST_value(mk_Void(<nil>,mk_VoidType({})),ps.sto,
                        tplus(ps.time,tplus(cond.time,t_if)));

eval_IfThenElse : IfThenElse -> Env -> PState -> EST_value
eval_IfThenElse(mk_IfThenElse(prop,thenaction,elseaction))(e)(ps) ==
  let cond = eval_Expression(prop)(e)(ps) in
  if not is_Tr(cond.val)
  then mk_EST_value(<err>,ps.sto,zerot)
  else let then_x = eval_Sequence(thenaction)(e)(ps),
           else_x = eval_Sequence(elseaction)(e)(ps) in
       let type = lub(then_x.val.type,else_x.val.type) in
       if type = <err>
       then mk_EST_value(<err>,ps.sto,zerot)
       elseif cond.val.val
       then mu(then_x, val |-> widen_type(then_x.val,type),
                       time |-> tplus(then_x.time,cond.time))
       else mu(else_x, val |-> widen_type(else_x.val,type),
                       time |-> tplus(else_x.time,cond.time));

eval_CaseExpr : CaseExpr -> Env -> PState -> EST_value
eval_CaseExpr(mk_CaseExpr(expr,limbs,outlimb))(e)(ps) ==
  let x = eval_Expression(expr)(e)(ps) in
  if x.val = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let type_x = x.val.type in
       let ls = eval_Limbs(limbs)(x.val)(e)(mu(ps,time |-> x.time)) in
       let os = if outlimb = nil
                then []
                else let mk_(t,v) = ls(len ls) in
                     [mk_(type_x,eval_Sequence(outlimb)(e)(mu(ps,time
                           |-> v.time)))] in
       let pats = ls^os in
       if exists mk_(t,v) in seq pats & v.val = <err>
       then mk_EST_value(<err>,ps.sto,zerot)
       else let patlub = setlub({t | mk_(t,v) in seq pats}) in
            if patlub = <err>
            then mk_EST_value(<err>,ps.sto,zerot)
            elseif lub(type_x,patlub) <> patlub
            then mk_EST_value(<err>,ps.sto,zerot)
            else let type = setlub({v.val.type | mk_(t,v) in seq pats}) in
                 if type = <err>
                 then mk_EST_value(<err>,ps.sto,zerot)
                 else let x_type = const_type(x.val) in
                      let matches = [p | p in seq pats &
                                      let mk_(t,v) = p in
                                      lub(x_type,t) = t] in
                      let mk_(mt,mv) = hd matches in
                      let time = 
                           dtplus([mv.time,t_const_type,t_widen_type]) in
                      mk_EST_value(widen_type(mv.val,type),mv.sto,time);

eval_Limbs : seq1 of CaseLimb -> Expressible_value -> Env -> PState ->
             seq1 of (Expressible_type * EST_value)
eval_Limbs(limbs)(x)(e)(ps) ==
  let mk_(t,v) = eval_Limb(hd limbs)(x)(e)(ps) in
  if len limbs = 1
  then [mk_(t,v)]
  else [mk_(t,v)]^(eval_Limbs(tl limbs)(x)(e)(mu(ps,time |-> v.time)));

eval_Limb : CaseLimb -> Expressible_value -> Env -> PState ->
            (Expressible_type * EST_value) 
eval_Limb(mk_CaseLimb(test,sequ))(x)(e)(ps) ==
  let t = eval_Tester(test)(x)(e)(ps) in
  if t = <err>
  then   mk_(mk_VoidType({}),mk_EST_value(<err>,ps.sto,zerot))
  else let mk_(type,env,tm) = t in
       let val = eval_Sequence(sequ)(env)(mu(ps,time |-> tm)) in
       if val.val = <err>
       then   mk_(mk_VoidType({}),mk_EST_value(<err>,ps.sto,zerot))
       else mk_(type,val);




eval_Tester : Tester -> Expressible_value -> Env -> PState -> 
              ((Expressible_type * Env * Time) | Errvalue)
eval_Tester(tester)(x)(e)(ps) ==
  cases tester:
    mk_SkeletonType(t) -> 
          let nt = eval_SkeletonType(tester)(x.type)(e) in
          if nt = <err> 
          then <err>
          else mk_(nt,e,ps.time),
    mk_StrucTest(s) -> eval_StrucTest(tester)(x)(e)(ps),
    mk_NonStrucTest(id,tp,fl) -> eval_NonStrucTest(tester)(x)(e)(ps)
  end;


eval_SkeletonType : SkeletonType -> Expressible_type -> Env ->
                     (Expressible_type | Errvalue)
eval_SkeletonType(mk_SkeletonType(skel))(t)(e) == 
  cases skel:
    mk_Type(t) -> eval_Type(skel)(e),
    mk_NumSkel(r,er) -> eval_NumSkel(skel)(t)(e),
    mk_StrucSkel(s) -> eval_StrucSkel(skel)(t)(e),
    mk_FlavSkel(s,fl) -> eval_FlavSkel(skel)(t)(e),
    mk_VecSkel(s) -> eval_VecSkel(skel)(t)(e),
    mk_UnionSkel(s) -> eval_UnionSkel(skel)(t)(e)
  end;

eval_NumSkel : NumSkel -> Expressible_type -> Env -> 
               (Expressible_type | Errvalue)
eval_NumSkel(mk_NumSkel(ranges,errors))(x_type)(e) ==
  if not (is_TrType(x_type) or is_IntType(x_type) or is_Float(x_type))
  then <err>
  else let rngs = if ranges = nil
                  then if is_Float(x_type) 
                       then {{l,...,u} | mk_Floatrng(l,u) in set x_type.range} 
                       else {x_type.range}
                  else {eval_Range(r)(e) | r in seq ranges} in
       if <err> in set rngs
       then <err>
       else cases x_type:
              mk_TrType(range,fl) -> 
                     if not (dunion rngs subset {0,1})
                     then <err>
                     else mk_TrType({{0 |->false, 1 |->
                          true}(v) | v in set dunion rngs},fl),
              mk_IntType(rep,range,fl) ->
                     if (rep = <byte> and exists v in set dunion rngs &
                                         abs v >= bytemax) or
                        (exists v in set dunion rngs & abs v >= maxint)
                     then <err>
                     else mk_IntType(rep,dunion rngs,fl),
              mk_Float(rs,abse,rele,fl) ->
                     if exists v in set dunion rngs & abs v >= maxint
                     then <err>
                     else
                       let abserr 
                         = if errors.abserr = nil 
                           then abse
                           else 
                            let v1 = 
                              (eval_CompileTimeValue(errors.abserr)(e)).val in
                            if v1 = <err>
                            then <err>
                            else v1.val,
                           relerr 
                         = if errors.relerr = nil 
                           then rele
                           else 
                            let v1 = 
                              (eval_CompileTimeValue(errors.relerr)(e)).val in
                            if v1 = <err>
                            then <err>
                            else v1.val in
                        if not (is_real(abserr) and is_real(relerr))
                        then <err>
                        else mk_Float({mk_Floatrng(min(r),max(r))
                              | r in set rngs},abserr,relerr,fl)
              end;

eval_StrucSkel : StrucSkel -> Expressible_type -> Env ->
                 (Expressible_type | Errvalue)
eval_StrucSkel(mk_StrucSkel(comps))(x_type)(e) ==
  if not is_StructureType(x_type)
  then <err>
  elseif struc_length(x_type) <> len comps
  then <err>
  else let t = [if comps(i) = <nil>
                then x_type.tps(i)
                else eval_SkeletonType(comps(i))(x_type.tps(i))(e) |
                      i in set inds comps] in
       if exists tp in seq t & not (is_TrType(tp) or
                   is_IntType(tp) or is_Float(tp))
       then <err>
       else mk_StructureType(t,x_type.fl);

eval_FlavSkel : FlavSkel -> Expressible_type -> Env ->
                (Expressible_type | Errvalue)
eval_FlavSkel(mk_FlavSkel(skel,fl))(x_type)(e) ==
  let t = eval_SkeletonType(skel)(x_type)(e),
      f = eval_Flavouring(fl) in
  if t = <err>
  then <err>
  else replace_flavour(t,f);

eval_VecSkel : VecSkel -> Expressible_type -> Env -> 
               (Expressible_type | Errvalue)
eval_VecSkel(mk_VecSkel(skel))(x_type)(e) ==
  let t = eval_SkeletonType(skel)(x_type)(e) in
  if t = <err> 
  then <err>
  else  cases x_type:
         mk_VectorType(l,u,tp,fl) -> mk_VectorType(l,u,t,fl),
         others -> <err>
        end;

eval_UnionSkel : UnionSkel -> Expressible_type -> Env ->
                 (Expressible_type | Errvalue)
eval_UnionSkel(mk_UnionSkel(skels))(x_type)(e) ==
  let fls = { skel |-> fl | skel in seq skels, fl : Flavdom & 
                   fl = cases skel:
                          mk_FlavSkel(skel,f) -> eval_Flavouring(f),
                          mk_FlavouredType(f,t) -> eval_Flavouring(f),
                          others -> eval_Flavouring(skel)
                        endin
  if card dom fls <> card rng fls
  then <err>
  elseif is_UnionType(x_type)
  then let x_fls = merge{
                { mk_VoidType(f) |-> f | mk_VoidType(f) in set x_type.tps},
                { mk_IntType(rep,range,fl) |-> fl | 
                            mk_IntType(rep,range,fl) in set x_type.tps },
                { mk_TrType(range,fl) |-> fl | 
                            mk_TrType(range,fl) in set x_type.tps },
                { mk_Float(rs,a,r,fl) |-> fl | 
                            mk_Float(rs,a,r,fl) in set x_type.tps }}
                in
       if not (rng fls subset rng x_fls)
       then <err>
       else let tps = 
              { cases skel:
                  mk_FlavSkel(s,f)      ->  eval_FlavSkel(skel)(tp)(e),
                  mk_FlavouredType(f,t) -> eval_FlavouredType(skel)(e),
                  others                -> eval_VoidValType(skel)(e)
                end | skel in seq skels, tp in set x_type.tps &
                          fls(skel) = x_fls(tp)} in
            if exists tp in set tps & not (is_TrType(tp) or is_IntType(tp)
                   or is_Float(tp) or is_VoidType(tp))
            then <err>
            else mk_UnionType(tps,x_type.fl)
  else let fl = if is_VoidType(x_type)
                then x_type
                else x_type.fl in
       if fl not in set rng fls
       then <err>
       else let skel = iota s in set elems skels & fls(s) = fl in
            cases skel:
                  mk_FlavSkel(s,f)      -> eval_FlavSkel(skel)(x_type)(e),
                  mk_FlavouredType(f,t) -> eval_FlavouredType(skel)(e),
                  others                -> eval_VoidValType(skel)(e)
            end;

eval_NonStrucTest : NonStrucTest -> Expressible_value -> Env -> PState
                    -> ((Expressible_type * Env * Time) | Errvalue)
eval_NonStrucTest(mk_NonStrucTest(id,fl,skel))(x)(e)(ps) ==
  let t = eval_SkeletonType(skel)(x.type)(e) in
  if t = <err>
  then <err>
  else let t' = if fl = nil
                then t
                else replace_flavour(t,eval_Flavouring(fl)) in
       if id = nil
       then mk_(t',e,ps.time)
       else mk_(t',update_env(id)(x)(e), ps.time);

eval_StrucTest : StrucTest -> Expressible_value -> Env -> PState ->
                 ((Expressible_type * Env * Time) | Errvalue)
eval_StrucTest(mk_StrucTest(tests))(x)(e)(ps) ==
  if not is_Structure(x)
  then <err>
  elseif struc_length(x.type) <> len tests
  then <err>
  else let xs = [ construct_ev(x.val(i),x.type.tps(i)) | i in set inds
                                x.val] in
       let ts = eval_Testseq(tests)(xs)(e)(ps) in
       if ts = <err>
       then <err>
       else let mk_(tps,env,time) = ts in
            mk_(mk_StructureType(tps,x.type.fl),env,time);

eval_Testseq : seq of (NonStrucTest | <nil>) -> seq of Expressible_value 
               -> Env -> PState -> ((seq of Expressible_type * Env
               * Time) | Errvalue)
eval_Testseq(tests)(xs)(e)(ps) ==
  if tests = []
  then mk_([],e,ps.time)
  else let t = if hd tests = <nil>
               then mk_((hd xs).type, e, ps.time)
               else eval_NonStrucTest(hd tests)(hd xs)(e)(ps) in
       if t = <err>
       then <err>
       else let mk_(tp,env,time) = t in
            let ts = eval_Testseq(tl tests)(tl xs) (env) (mu(ps,time |-> time))
                    in
            if ts = <err>
            then <err>
            else let mk_(tps,n_env,n_time) = ts in
                 mk_([tp]^tps,n_env,n_time);

eval_OuterLoop : OuterLoop -> Env -> PState -> EST_value
eval_OuterLoop(mk_OuterLoop(oul))(e)(ps) ==
  if is_OuterIntLoop(oul)
  then eval_OuterIntLoop(oul)(e)(ps)
  else eval_OuterVecLoop(oul)(e)(ps);

eval_OuterIntLoop : OuterIntLoop -> Env -> PState -> EST_value
eval_OuterIntLoop(mk_OuterIntLoop(mk_OverRange(id,range),actns))(e)(ps) ==
  let nrange = eval_Range(range)(e) in
  if nrange = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let vec_elems = [eval_Sequence(actns)(update_env(id)
            (mk_Storable_value(mk_Int(i,mk_IntType(<word>,{i},{}))))(e))
                            (mu(ps,time |-> zerot)) | i in set nrange] in
       if <err> in set {x.val | x in seq vec_elems}
       then mk_EST_value(<err>,ps.sto,zerot)
       else let type = seqlub([i.val.type | i in seq vec_elems]),
                time = dtplus([i.time | i in seq vec_elems]) in
            if type = <err>
            then mk_EST_value(<err>,ps.sto,zerot)
            else let vec_val = if is_StructureType(type) or
                                  is_VectorType(type) 
                               then [ v.val.val | v in seq vec_elems]
                               else [ v.val | v in seq vec_elems]  in
                    mk_EST_value(mk_Vector(vec_val,mk_VectorType(1,len
                    vec_val,type,{})),ps.sto, tplus(ps.time,time));

eval_OuterVecLoop : OuterVecLoop -> Env -> PState -> EST_value
eval_OuterVecLoop(mk_OuterVecLoop(ovs,actions))(e)(ps) ==
  let idvs = eval_OverVectors(ovs)(e)(ps) in
  if idvs = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let time1 = dtplus([ let mk_(id,v,t) = i in t | i in seq idvs]),
           new_env = lambda i:nat &
                      (multi_update_env([ let mk_(id,v,t) = j in
                                        mk_(id,vector_extract(v,i)) |
                                            j in seq idvs]^(
                                        if ovs.cnt = nil then []
                                        else [mk_(ovs.cnt,i)]))(e)) in
       let vec_elems = [eval_Sequence(actions)(new_env(i))(mu(ps,time
                        |-> zerot)) | i in set let mk_(i1,v,t) =
                                 idvs(1) in inds (v.val)] in
       if <err> in set {x.val | x in seq vec_elems}
       then mk_EST_value(<err>,ps.sto,zerot)
       else let type = seqlub([i.val.type | i in seq vec_elems]),
                time = dtplus([i.time | i in seq vec_elems]^[time1]) in
            if type = <err>
            then mk_EST_value(<err>,ps.sto,zerot)
            else let new_tp = mk_VectorType(1,len vec_elems,type,{}) in
                 let vec_val = if is_StructureType(type) or
                                  is_VectorType(type) 
                               then [i.val.val | i in seq vec_elems]
                               else [i.val | i in seq vec_elems] in
                 let new_vec = mk_Vector(vec_val,new_tp) in
                 mk_EST_value(new_vec,ps.sto,tplus(ps.time,time));

eval_OverVectors : OverVectors -> Env -> PState -> (seq1 of (Id * Vector *
                   Time) | Errvalue)
eval_OverVectors(ovs)(e)(ps) ==
  let indices = [ let mk_OverVector(id,val) = o in
                  let x = eval_Operation(val)(e)(mu(ps,time |-> zerot)) in
                  mk_(id,x.val,x.time) | o in seq ovs.ovv] in
  if exists i in set inds indices & let mk_(id,v,t) = indices(i) in
                                    not is_Vector(v)
  then <err>
  else indices;

eval_InnerLoop : InnerLoop -> Env -> PState -> EST_value
eval_InnerLoop(mk_InnerLoop(innerl))(e)(ps) ==
  cases innerl:
    mk_IntLoop(inc,actions) -> eval_IntLoop(innerl)(e)(ps),
    mk_VecLoop(ovs,actions) -> eval_VecLoop(innerl)(e)(ps),
    mk_TimeLoop(time,actions) -> eval_TimeLoop(innerl)(e)(ps)
  end;

eval_IntLoop : IntLoop -> Env -> PState -> EST_value
eval_IntLoop(mk_IntLoop(inc,actions))(e)(ps) ==
  let idrng = eval_InnerControl(inc)(e)(ps) in
  if idrng = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let mk_(id,range) = idrng in
       let f: EST_Iterate -> EST_Iterate 
           = lambda x: EST_Iterate &
              let new_env = update_env(id)(
                              mk_Storable_value(mk_Int(range(x.i),
                                     mk_IntType(<word>,elems range,{}))))(e) in
              eval_SeqIterate(actions)(new_env)(x)         in
       let exi = (NIterate(f,(len range)))(mk_EST_Iterate(
                      mk_EST_value(mk_Void(<nil>,mk_VoidType({})),                              ps.sto,ps.time),1)) in
       exi.expst;

eval_InnerControl : InnerControl -> Env -> PState -> ((Id * seq of
                    int) | Errvalue)
eval_InnerControl(inc)(e)(ps) ==
  cases inc:
    mk_OverRange(cnt,range) ->
        let r = eval_Range(range)(e) in
        if r = <err> then <err> else mk_(cnt,[x | x in set r]),
    mk_PartialRange(cnt,from_b,to_b,inc) ->
        let b1 = eval_Operation(from_b)(e)(ps),
            b2 = eval_Operation(to_b)(e)(ps) in
        if not (is_Int(b1.val) and is_Int(b2.val))
        then <err>
        else let b3 = if inc = nil
                      then if b1.val.val <= b2.val.val
                           then mk_Int(1,mk_IntType(<byte>,{1,-1},{}))
                           else mk_Int(-1,mk_IntType(<byte>,{1,-1},{}))
                      else (eval_Operation(inc)(e)(ps)).val in
             if not (is_Int(b3.val)) or
                (is_Int(b3.val) and 
                   exists v1 in set b1.val.type.range, 
                          v2 in set b2.val.type.range, 
                          v3 in set b3.val.type.range & (v2-v1)*v3 < 0)
             then <err>
             else let r = [ b1.val.val + alpha * b3.val | alpha in set 
                         {0,...,floor(1+(b2.val.val-b1.val.val)/b3.val)} & 
                      abs (alpha * b3.val) <= abs (b2.val.val - b1.val.val)] in
                  mk_(cnt,r)
  end;

eval_SeqIterate : Sequence -> Env -> EST_Iterate -> EST_Iterate
eval_SeqIterate(sequ)(e)(exi) ==
  if exi.expst.val = <err>
  then mu(exi, i |-> exi.i + 1)
  else let new_expst = eval_Sequence(sequ)(e)(mk_PState(exi.expst.sto,exi.expst.time)) in
       mk_EST_Iterate(new_expst,exi.i + 1);

eval_VecLoop : VecLoop -> Env -> PState -> EST_value
eval_VecLoop(mk_VecLoop(ovs,actions))(e)(ps) ==
  let indices = eval_OverVectors(ovs)(e)(ps) in
  if indices = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  else let time = dtplus([let mk_(id,v,t) = i in t | i in seq indices]) in
       let f:EST_Iterate -> EST_Iterate
            = lambda x:EST_Iterate &
             let env = multi_update_env(
                   [let mk_(id,v,t) = indices(i) in
                   mk_(id,vector_extract(v,x.i)) |i in set inds indices])(e),
                 new_expst = mu(x.expst, time |-> x.expst.time)
                              in
             let new_env = if ovs.cnt = nil then env
                     else update_env(ovs.cnt)
        (mk_Storable_value(mk_Int(x.i,mk_IntType(<word>,{x.i},{}))))(env) in
             eval_SeqIterate(actions)(new_env)(mu(x,expst |-> new_expst)) in
       let mk_(-,v,-) = indices(1) in
       let exi = (NIterate(f,len v.val))(mk_EST_Iterate(mk_EST_value(
                     mk_Void(<nil>,mk_VoidType({})),
                         ps.sto,tplus(ps.time,time)),1))
                   in
       exi.expst;

eval_TimeLoop : TimeLoop -> Env -> PState -> EST_value
eval_TimeLoop(mk_TimeLoop(time,actions))(e)(ps) ==
  let t = eval_TimeInterval(time)(e),
      x = eval_Sequence(actions)(e)(mu(ps,time |-> zerot)) in
  if t = <err> or x.val = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  elseif exists n:nat & timeleq(dtplus([x.time | i in set {1,...,n}]),t)
  then let its = iota n:nat &
                  timeleq(dtplus([x.time | i in set {1,...,n}]),t) and
                  not (timeleq(dtplus([x.time | i in set {1,...,n+1}]),t)),
           f:EST_value ->EST_value = lambda exs:EST_value &
             eval_Sequence(actions)(e)(mk_PState(exs.sto,exs.time)) in
           (Iterate(f,its))(mk_EST_value(mk_Void(<nil>,mk_VoidType({})),
                                  ps.sto,ps.time))
  else mk_EST_value(<err>,ps.sto,zerot);

eval_Assignment : Assignment -> Env -> PState -> EST_value
eval_Assignment(mk_Assignment(ass))(env)(ps) ==
  cases ass:
    mk_NvAssignment(d,e) -> eval_NvAssignment(ass)(env)(ps),
    mk_MultAssignment(d,m,e) -> eval_MultAssignment(ass)(env)(ps),
    mk_StrAssignment(d,e) -> eval_StrAssignment(ass)(env)(ps)
  end;

eval_NvAssignment : NvAssignment -> Env -> PState -> EST_value
eval_NvAssignment(mk_NvAssignment(dest,expr))(e)(ps) ==
  let l = access_env(dest)(e) in
  if not is_Location(l)
  then mk_EST_value(<err>,ps.sto,zerot)
  else let x = eval_Expression(expr)(e)(ps) in
       if x.val = <err>
       then mk_EST_value(<err>,ps.sto,zerot)
       elseif cases x.val.type:
                mk_VoidType(t) -> t = {Phi},
                others -> x.val.type.fl = {Phi}
              end
       then mk_EST_value(<err>,ps.sto,zerot)
       else let mk_Storable_value(dest_val) = access(l)(ps.sto) in
            if gt(dest_val.type,x.val.type)
            then let new_sto =
       update(l)(mk_Storable_value(widen_type(x.val,dest_val.type)))(ps.sto) in
                 mk_EST_value(mk_Void(<nil>,mk_VoidType({})),new_sto,
                   tplus(tplus(ps.time,t_update),t_access))
            else mk_EST_value(<err>,ps.sto,zerot);

eval_MultAssignment : MultAssignment -> Env -> PState -> EST_value
eval_MultAssignment(mk_MultAssignment(dest,mult,expr))(e)(ps) ==
  let l = access_env(dest)(e) in
  if not is_Location(l)
  then mk_EST_value(<err>,ps.sto,zerot)
  else let mk_Storable_value(v) = access(l)(ps.sto) in
       if not is_Vector(v)
       then mk_EST_value(<err>,ps.sto,zerot)
       else let mk_Vector(val,type) = v in
            let v' = 
               eval_VectorMult(mk_EST_value(v,ps.sto,ps.time))(mult)(e) in
            let x = eval_Expression(expr)(e)(mk_PState(v'.sto,v'.time)) in
            if v'.val = <err> or not is_Vector(x.val)
            then mk_EST_value(<err>,ps.sto,zerot)
            elseif (x.val.type.upper - x.val.type.lower) <>
                     (v'.val.type.upper - v'.val.type.lower) or
                   not gt(v.type.type,x.val.type.type) or
              cases x.val.type.type:
                mk_VoidType(t) -> t = {Phi},
                others -> x.val.type.fl = {Phi}
              end
            then mk_EST_value(<err>,ps.sto,zerot)
            else let vleft = mk_Vector(vector_subv(val,type.lower,
                         v'.val.type.lower-1),mk_VectorType(type.lower,
                         v'.val.type.lower-1,type.type,type.fl)),
                     vmid = x.val,
                     vright = mk_Vector(vector_subv(val,v'.val.type.upper+1,
                         type.upper),mk_VectorType(v'.val.type.upper+1,
                         type.upper,type.type, type.fl)) in
                let new_vec = vector_concat(vector_concat(vleft,vmid),vright),
                    new_time = dtplus([x.time,t_vector_concat,
                              t_vector_concat, vector_subv,vector_subv]) in
                 mk_EST_value(mk_Void(<nil>,mk_VoidType({})), 
                                update(l)(mk_Storable_value(new_vec))(ps.sto),
                                 new_time);

eval_StrAssignment : StrAssignment -> Env -> PState -> EST_value
eval_StrAssignment(mk_StrAssignment(dest,expr))(e)(ps) ==
  let ls = [access_env(d)(e) | d in seq dest] in
  if exists l in seq ls & not is_Location(l)
  then mk_EST_value(<err>,ps.sto,zerot)
  else let x = eval_Expression(expr)(e)(ps) in
       if not is_Structure(x.val)
       then mk_EST_value(<err>,ps.sto,zerot)
       elseif len ls <> struc_length(x.val.type)
       then mk_EST_value(<err>,ps.sto,zerot)
       else let nvals = [ access(l)(ps.sto) | l in seq ls] in
            let vals = [ let mk_Storable_value(v) = i in v | i in seq nvals] in
            let dest_tps = [v.type | v in seq vals],
                x_tps = [i | i in seq x.val.type.tps] in
            if exists i in set inds dest_tps & not gt(dest_tps(i),x_tps(i))
            then mk_EST_value(<err>,ps.sto,zerot)
            else let ys = [mk_Storable_value(construct_ev(x.val.val(i),
                                x.val.type.tps(i))) | i in set inds x.val.val],
                     new_t = dtplus([x.time,t_access,t_construct_ev,
                                        t_multi_update(len ys)]) in
                 mk_EST_value(mk_Void(<nil>,mk_VoidType({})),
                    multi_update(ls)(ys)(ps.sto), new_t);


eval_TimedExpression : TimedExpression -> Env -> PState -> EST_value
eval_TimedExpression(mk_TimedExpression(texpr))(e)(ps) ==
  if is_TimeTakes(texpr)
  then eval_TimeTakes(texpr)(e)(ps)
  else eval_TimeAssertion(texpr)(e)(ps);

eval_TimeTakes : TimeTakes -> Env -> PState -> EST_value
eval_TimeTakes(mk_TimeTakes(expr,time))(e)(ps) ==
  let x = eval_Expression(expr)(e)(mu(ps, time |-> zerot)),
      t = eval_TimeInterval(time)(e) in
  if x.val = <err> or t = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  elseif timeleq(x.time,t)
  then mu(x,time |-> tplus(ps.time,x.time))
  else mk_EST_value(<err>,ps.sto,zerot);

eval_TimeInterval : TimeInterval -> Env -> (Time | Errvalue)
eval_TimeInterval(time)(e) ==
  let range = eval_Range(time)(e) in
  if range = <err> or min(range) < 0
  then <err>
  else mk_(min(range),max(range));

eval_TimeAssertion:TimeAssertion -> Env -> PState -> EST_value
eval_TimeAssertion(mk_TimeAssertion(expr,time))(e)(ps) ==
  let x = eval_Expression(expr)(e)(mu(ps, time |-> zerot)),
      t = eval_TimeInterval(time)(e) in
  if x.val = <err> or t = <err>
  then mk_EST_value(<err>,ps.sto,zerot)
  elseif timeleq(t,x.time)
  then mu(x,time |-> tplus(ps.time,t))
  else mk_EST_value(<err>,ps.sto,zerot);

Iterate: (EST_value -> EST_value) * nat -> (EST_value ->
           EST_value) 
Iterate(f,n) ==
  if n = 0 
  then lambda x:EST_value & x
  elseif n = 1
  then f
  else f comp (Iterate( f, n-1));

NIterate: (EST_Iterate -> EST_Iterate) * nat -> (EST_Iterate ->
           EST_Iterate) 
NIterate(f,n) ==
  if n = 0 
  then lambda x:EST_Iterate & x
  elseif n = 1
  then f
  else f comp (NIterate( f, n-1))





       

Messung V0.5 in Prozent
C=100 H=97 G=98

¤ Dauer der Verarbeitung: 0.47 Sekunden  (vorverarbeitet am  2026-04-30) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.