end of line
[scilab.git] / scilab / modules / scicos / src / translator / instantiation / instantiation.ml
index 038645b..c07ec2c 100644 (file)
-(*\r
- *  Translator from Modelica 2.x to flat Modelica\r
- *\r
- *  Copyright (C) 2005 - 2007 Imagine S.A.\r
- *  For more information or commercial use please contact us at www.amesim.com\r
- *\r
- *  This program is free software; you can redistribute it and/or\r
- *  modify it under the terms of the GNU General Public License\r
- *  as published by the Free Software Foundation; either version 2\r
- *  of the License, or (at your option) any later version.\r
- *\r
- *  This program is distributed in the hope that it will be useful,\r
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- *  GNU General Public License for more details.\r
- *\r
- *  You should have received a copy of the GNU General Public License\r
- *  along with this program; if not, write to the Free Software\r
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
- *\r
- *)\r
-\r
-type ('a, 'b) node =\r
-  {\r
-    nature: 'a;\r
-    info: 'b\r
-  }\r
-\r
-type instance =\r
-  {\r
-    enclosing_instance: instance option;\r
-    kind: Types.kind;\r
-    elements: instance_elements Lazy.t\r
-  }\r
-\r
-and instance_elements =\r
-  {\r
-    named_elements: (string * element_description) list;\r
-    unnamed_elements: equation_or_algorithm_clause list\r
-  }\r
-\r
-and element_description =\r
-  {\r
-    redeclare: bool;\r
-    element_nature: element_nature Lazy.t\r
-  }\r
-\r
-and element_nature =\r
-  | Class of class_definition\r
-  | Component of component_description\r
-\r
-and class_definition =\r
-  {\r
-    class_type: Types.class_specifier;\r
-    class_path: path;\r
-    class_flow: bool option;\r
-    class_variability: Types.variability option;\r
-    class_causality: Types.causality option;\r
-    description: description;\r
-    modification: modification_argument list;\r
-    class_location: Parser.location\r
-  }\r
-\r
-and path = path_element list\r
-\r
-and path_element =\r
-  | Name of string\r
-  | Index of int\r
-\r
-and description =\r
-  | ClassDescription of context * class_description\r
-  | PredefinedType of predefined_type\r
-\r
-and class_description =\r
-  {\r
-    class_kind: Types.kind;\r
-    class_annotations: (annotation list) Lazy.t;\r
-    long_description: NameResolve.long_description\r
-  }\r
-\r
-and annotation =\r
-  | InverseFunction of inverse_function Lazy.t\r
-  | UnknownAnnotation of Parser.location Syntax.class_modification Lazy.t\r
-\r
-and inverse_function =\r
-  {\r
-    function_class: class_definition;\r
-    arguments: (string * string) list\r
-  }\r
-\r
-and class_modification = (string * modification_argument) list\r
-\r
-and modification_argument =\r
-  {\r
-    each: bool;\r
-    action: modification_action\r
-  }\r
-\r
-and modification_action =\r
-  | ElementModification of modification\r
-  | ElementRedeclaration of element_description\r
-\r
-and modification =\r
-  | Modification of class_modification * expression Lazy.t option\r
-  | Assignment of expression Lazy.t\r
-  | Equality of expression Lazy.t\r
-\r
-and component_description =\r
-  {\r
-    component_path: path;\r
-    flow: bool;\r
-    variability: Types.variability;\r
-    causality: Types.causality;\r
-    component_nature: component_nature Lazy.t;\r
-    declaration_equation: expression Lazy.t option;\r
-    comment: string;\r
-    component_location: Parser.location;\r
-    class_name: string\r
-  }\r
-\r
-and component_nature =\r
-  | DynamicArray of component_description\r
-      (* one representative member of the collection *)\r
-  | Instance of instance\r
-  | PredefinedTypeInstance of predefined_type_instance\r
-  | StaticArray of component_description array\r
-\r
-and predefined_type_instance =\r
-  {\r
-    predefined_type: predefined_type;\r
-    attributes: (string * expression Lazy.t) list\r
-  }\r
-\r
-and predefined_type =\r
-  | BooleanType\r
-  | IntegerType\r
-  | RealType\r
-  | StringType\r
-  | EnumerationType\r
-\r
-and equation_or_algorithm_clause =\r
-  | EquationClause of NameResolve.validity * equation list Lazy.t\r
-  | AlgorithmClause of NameResolve.validity * algorithm list Lazy.t\r
-\r
-and validity = Initial | Permanent\r
-\r
-and equation = (equation_desc list, NameResolve.equation) node\r
-\r
-and equation_desc =\r
-  | Equal of expression * expression\r
-  | ConditionalEquationE of (expression * equation list) list *\r
-      equation list\r
-  | ConnectFlows of NameResolve.sign * expression *\r
-      NameResolve.sign * expression\r
-  | WhenClauseE of (expression * equation list) list\r
-\r
-and algorithm = (algorithm_desc list, NameResolve.algorithm) node\r
-\r
-and algorithm_desc =\r
-  | Assign of expression * expression\r
-  | FunctionCallA of expression * expression list\r
-  | MultipleAssign of expression list * expression * expression list\r
-  | Break\r
-  | Return\r
-  | ConditionalEquationA of (expression * algorithm list) list *\r
-      algorithm list\r
-  | ForClauseA of expression (* range *) * algorithm list\r
-  | WhileClause of expression * algorithm list\r
-  | WhenClauseA of (expression * algorithm list) list\r
-\r
-and expression =\r
-  | BinaryOperation of binary_operator_kind * expression * expression\r
-  | ClassReference of class_definition\r
-  | ComponentReference of component_description\r
-  | EnumerationElement of string\r
-  | False\r
-  | FieldAccess of expression * string\r
-  | FunctionCall of expression * expression list\r
-  | If of (expression (* condition *) * expression) list *\r
-      expression (* default *)\r
-  | IndexedAccess of expression * expression list (* subscripts *)\r
-  | Integer of int32\r
-  | LoopVariable of int (* number of nested for loops to skip *)\r
-  | NoEvent of expression\r
-  | PredefinedIdentifier of string\r
-  | Range of expression * expression * expression\r
-  | Real of float\r
-  | Record of (string * expression) list\r
-  | String of string\r
-  | True\r
-  | Tuple of expression list\r
-  | UnaryOperation of unary_operator_kind * expression\r
-  | Vector of expression array\r
-  | VectorReduction of expression list (* ranges *) * expression\r
-\r
-and unary_operator_kind =\r
-  | Not\r
-  | UnaryMinus\r
-\r
-and binary_operator_kind =\r
-  | And\r
-  | Divide\r
-  | EqualEqual\r
-  | GreaterEqual\r
-  | Greater\r
-  | LessEqual\r
-  | Less\r
-  | Times\r
-  | NotEqual\r
-  | Or\r
-  | Plus\r
-  | Power\r
-  | Minus\r
-\r
-and context =\r
-  {\r
-    toplevel: (string * element_description) list Lazy.t;\r
-    path: path;\r
-    context_flow: bool option;\r
-    context_variability: Types.variability option;\r
-    context_causality: Types.causality option;\r
-    parent_context: context option; (* for normal parent scope lookup *)\r
-    class_context: context_nature; (* for normal (class-based) lookup *)\r
-    instance_context: instance option; (* for dynamically scoped identifiers *)\r
-    location: Parser.location;\r
-    instance_nature: instance_nature\r
-  }\r
-\r
-and context_nature =\r
-  | ToplevelContext\r
-  | InstanceContext of instance\r
-  | ForContext of context *\r
-      expression option (* current value of the loop variable, if available *)\r
-  | FunctionEvaluationContext of context * expression * expression list\r
-\r
-(* Error description *)\r
-and error_description =\r
-  {\r
-    err_msg: string list;\r
-    err_info: (string * string) list;\r
-    err_ctx: context\r
-  }\r
-\r
-and instance_nature =\r
-  | ClassElement\r
-  | ComponentElement of string\r
-\r
-exception InstantError of error_description\r
-\r
-\r
-(* Utilities *)\r
-\r
-let levels = ref 0\r
-\r
-let spaces () = for i = 1 to !levels do Printf.printf "  " done\r
-\r
-let nest i =\r
-  spaces (); Printf.printf "ForContext %ld\n" i;\r
-  incr levels\r
-\r
-let nest2 i =\r
-  spaces (); Printf.printf "ReductionContext %ld\n" i;\r
-  incr levels\r
-\r
-let unnest () =\r
-  decr levels;\r
-  spaces (); Printf.printf "Leaving ForContext\n"\r
-\r
-let evaluate x = Lazy.force x\r
-\r
-module ArrayExt =\r
-  struct\r
-    let map2 f a a' =\r
-      let l = Array.length a\r
-      and l' = Array.length a' in\r
-      if l <> l' then invalid_arg "ArrayExt.map2"\r
-      else begin\r
-        let create_array i = f a.(i) a'.(i) in\r
-        Array.init l create_array\r
-      end\r
-    let for_all2 f a a' =\r
-      let l = Array.length a\r
-      and l' = Array.length a' in\r
-      if l <> l' then invalid_arg "ArrayExt.for_all2"\r
-      else begin\r
-        let rec for_all2' i =\r
-          i = l || (f a.(i) a'.(i) && for_all2' (i + 1)) in\r
-        for_all2' 0\r
-      end\r
-    let exists2 f a a' =\r
-      let l = Array.length a\r
-      and l' = Array.length a' in\r
-      if l <> l' then invalid_arg "ArrayExt.exists2"\r
-      else begin\r
-        let rec exists2' i =\r
-          i < l && (f a.(i) a'.(i) || exists2' (i + 1)) in\r
-        exists2' 0\r
-      end\r
-  end\r
-\r
-\r
-(* Instantiation functions *)\r
-\r
-let rec evaluate_toplevel_definitions dic defs =\r
-  let rec ctx =\r
-    {\r
-      toplevel = lazy (dic @ evaluate defs');\r
-      path = [];\r
-      context_flow = None;\r
-      context_variability = None;\r
-      context_causality = None;\r
-      parent_context = None;\r
-      class_context = ToplevelContext;\r
-      instance_context = None;\r
-      location = {Parser.start = 0; Parser.enddd = 0; filename = Parser.CommandLine};\r
-      instance_nature = ClassElement\r
-    }\r
-  and defs' = lazy (List.map (evaluate_toplevel_definition ctx) defs) in\r
-  evaluate defs'\r
-\r
-and evaluate_toplevel_definition ctx (id, elt_desc) =\r
-  let elt_loc = [Name id] in\r
-  let ctx = {ctx with\r
-               path = elt_loc;\r
-               location = elt_desc.NameResolve.element_location;\r
-               instance_nature = instance_nature_of_element elt_desc} in\r
-  let elt_nat = elt_desc.NameResolve.element_nature in\r
-  let elt_desc' =\r
-    {\r
-      redeclare = false;\r
-      element_nature = lazy (evaluate_toplevel_element ctx elt_loc elt_nat)\r
-    } in\r
-  id, elt_desc'\r
-\r
-and evaluate_toplevel_element ctx elt_loc = function\r
-  | NameResolve.Component cpnt_desc ->\r
-      let cpnt_desc' =\r
-        instantiate_component_description ctx [] None elt_loc cpnt_desc in\r
-      Component cpnt_desc'\r
-  | NameResolve.Class cl_def ->\r
-      let cl_def' = evaluate_class_definition ctx [] elt_loc cl_def in\r
-      Class cl_def'\r
-  | NameResolve.ComponentType _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_NotYetImplemented"; "_ComponentTypeElemInstant"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | NameResolve.PredefinedType _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_NotYetImplemented"; "_PredefinedTypeElemInstant"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-\r
-and instantiate_class_description ctx modifs rhs elt_loc cl_desc =\r
-  let elements inst =\r
-    let ctx' =\r
-      { ctx with\r
-        toplevel = lazy (evaluate ctx.toplevel);\r
-        path = elt_loc;\r
-        parent_context = Some ctx;\r
-        class_context = InstanceContext inst;\r
-        instance_context = None\r
-      } in\r
-    instantiate_class_elements ctx' modifs rhs cl_desc.long_description in\r
-  let rec inst =\r
-    {\r
-      enclosing_instance = enclosing_instance ctx;\r
-      kind = cl_desc.class_kind;\r
-      elements = lazy (elements inst)\r
-    } in\r
-  inst\r
-\r
-and enclosing_instance ctx = match ctx.class_context with\r
-  | ToplevelContext -> None\r
-  | InstanceContext inst -> Some inst\r
-  | ForContext (ctx', _) | FunctionEvaluationContext (ctx', _, _) ->\r
-      enclosing_instance ctx'\r
-\r
-and instantiate_class_elements ctx modifs rhs long_desc =\r
-  let rec merge_elements named_elts unnamed_elts = function\r
-    | [] ->\r
-        {\r
-          named_elements = named_elts;\r
-          unnamed_elements = unnamed_elts\r
-        }\r
-    | inherited_elts :: inherited_eltss ->\r
-        let named_elts' = named_elts @ inherited_elts.named_elements\r
-        and unnamed_elts' = unnamed_elts @ inherited_elts.unnamed_elements in\r
-        merge_elements named_elts' unnamed_elts' inherited_eltss in\r
-  let named_elts = long_desc.NameResolve.named_elements\r
-  and unnamed_elts = long_desc.NameResolve.unnamed_elements\r
-  and exts = long_desc.NameResolve.extensions in\r
-  let named_elts' = instantiate_local_named_elements ctx modifs rhs named_elts\r
-  and unnamed_elts' = instantiate_local_unnamed_elements ctx unnamed_elts\r
-  and inherited_eltss = instantiate_inherited_elements ctx modifs rhs exts in\r
-  merge_elements named_elts' unnamed_elts' inherited_eltss\r
-\r
-and instantiate_local_named_elements ctx modifs rhs named_elts =\r
-  List.fold_right (instantiate_local_named_element ctx modifs rhs) named_elts []\r
-\r
-and instantiate_local_named_element ctx modifs rhs (id, elt_desc) named_elts =\r
-  let rec filter_current_element_modifications = function\r
-    | [] -> []\r
-    | (id', arg) :: modifs when id' = id ->\r
-        arg :: filter_current_element_modifications modifs\r
-    | _ :: modifs -> filter_current_element_modifications modifs\r
-  and select_current_element_value = function\r
-    | None -> None\r
-    | Some expr -> Some (lazy (field_access ctx (evaluate expr) id)) in\r
-  let modifs' = filter_current_element_modifications modifs\r
-  and rhs' = select_current_element_value rhs\r
-  and elt_loc = ctx.path @ [Name id] in\r
-  let ctx = {ctx with\r
-               path = elt_loc;\r
-               location = elt_desc.NameResolve.element_location;\r
-               instance_nature = instance_nature_of_element elt_desc} in\r
-  let elt_nat =\r
-    lazy (instantiate_local_element_nature ctx modifs' rhs' elt_loc elt_desc) in\r
-  let named_elt =\r
-    id,\r
-    {\r
-      redeclare = elt_desc.NameResolve.redeclare;\r
-      element_nature = elt_nat\r
-    } in\r
-  named_elt :: named_elts\r
-\r
-and instantiate_local_element_nature ctx modifs rhs elt_loc elt_desc =\r
-  match elt_desc.NameResolve.element_nature with\r
-    | NameResolve.Component cpnt_desc ->\r
-        let cpnt_desc' =\r
-          instantiate_component_description ctx modifs rhs elt_loc cpnt_desc in\r
-       Component cpnt_desc'\r
-    | NameResolve.Class cl_def ->\r
-        let cl_def' = evaluate_class_definition ctx modifs elt_loc cl_def in\r
-        Class cl_def'\r
-    | NameResolve.ComponentType _ ->\r
-        raise (InstantError\r
-          { err_msg = ["_NotYetImplemented"; "_ComponentTypeElemInstant"];\r
-            err_info = [];\r
-            err_ctx = ctx })\r
-    | NameResolve.PredefinedType _ ->\r
-        raise (InstantError\r
-          { err_msg = ["_NotYetImplemented"; "_PredefinedTypeElemInstant"];\r
-            err_info = [];\r
-            err_ctx = ctx })\r
-\r
-and instantiate_component_description ctx modifs rhs elt_loc cpnt_desc =\r
-  let cpnt_type = evaluate cpnt_desc.NameResolve.component_type in\r
-  let flow = evaluate cpnt_type.Types.flow\r
-  and var = evaluate cpnt_type.Types.variability\r
-  and inout = evaluate cpnt_type.Types.causality\r
-  and type_spec = evaluate cpnt_desc.NameResolve.type_specifier\r
-  and dims = evaluate cpnt_desc.NameResolve.dimensions\r
-  and modifs' = match evaluate cpnt_desc.NameResolve.modification with\r
-    | None -> modifs\r
-    | Some modif ->\r
-        let modif' = evaluate_modification ctx modif in\r
-        modifs @ [{ each = false; action = ElementModification modif' }]\r
-  and cmt = cpnt_desc.NameResolve.comment in\r
-  component_nature ctx modifs' rhs elt_loc flow var inout type_spec dims cmt\r
-\r
-and component_nature ctx modifs rhs elt_loc flow var inout type_spec dims cmt =\r
-  let type_spec' = evaluate_expression ctx type_spec in\r
-  let ctx = {ctx with location = expression_location ctx type_spec} in\r
-  expand_array ctx modifs rhs elt_loc flow var inout type_spec' dims cmt\r
-\r
-and expand_array ctx modifs rhs elt_loc flow var inout type_spec dims cmt =\r
-  let rec expand_along_dimension dim dims = match dim with\r
-    | NameResolve.Colon -> expand_dynamic_array dims\r
-    | NameResolve.Expression expr ->\r
-        let expr' = evaluate_expression ctx expr in\r
-        expand_static_array dims expr' expr\r
-  and expand_dynamic_array dims =\r
-    (* No need to select modifications since all of them have 'each' set *)\r
-    let elt_loc' = elt_loc @ [Index 0] in\r
-    let ctx = { ctx with path = elt_loc' } in\r
-    let expr =\r
-      expand_array ctx modifs rhs elt_loc' flow var inout type_spec dims cmt in\r
-    DynamicArray expr\r
-  and expand_static_array dims expr' expr =\r
-    let ctx = {ctx with location = expression_location ctx expr} in\r
-    let expand_element i =\r
-      let rec select_subargument arg = match arg.each with\r
-        | true -> arg\r
-        | false -> { arg with action = select_subarray arg.action }\r
-      and select_subarray arg = match arg with\r
-       | ElementModification modif ->\r
-            ElementModification (select_submodification modif)\r
-        | ElementRedeclaration _ -> arg\r
-      and select_sub_class_modification_element (id, arg) =\r
-        id, select_subargument arg\r
-      and select_submodification = function\r
-        | Modification (modifs, rhs) ->\r
-            let modifs' = List.map select_sub_class_modification_element modifs\r
-            and rhs' = select_rhs_subarray rhs in\r
-            Modification (modifs', rhs')\r
-        | Assignment expr ->\r
-            let expr' = lazy (select_row i (evaluate expr)) in\r
-            Assignment expr'\r
-        | Equality expr ->\r
-            let expr' = lazy (select_row i (evaluate expr)) in\r
-            Equality expr'\r
-      and select_rhs_subarray = function\r
-        | None -> None\r
-        | Some expr -> Some (lazy (select_row i (evaluate expr)))\r
-      and select_row i = function\r
-             | Vector exprs ->\r
-            begin\r
-              try\r
-                exprs.(i)\r
-              with\r
-              | _ -> raise (InstantError\r
-                  { err_msg = ["_IndexOutOfBound"];\r
-                    err_info = [];\r
-                    err_ctx = ctx}) (*error*)\r
-            end\r
-        | expr ->\r
-            let subs = [Integer (Int32.succ (Int32.of_int i))] in\r
-            evaluate_indexed_access ctx expr subs in\r
-      let modifs = List.map select_subargument modifs\r
-      and rhs = select_rhs_subarray rhs\r
-      and elt_loc = elt_loc @ [Index i] in\r
-      expand_array ctx modifs rhs elt_loc flow var inout type_spec dims cmt in\r
-    match expr' with\r
-      | Integer i ->\r
-          let a = Array.init (Int32.to_int i) expand_element in\r
-          StaticArray a\r
-      | _ ->\r
-          raise (InstantError\r
-          { err_msg = ["_NonIntegerArrayDim"];\r
-            err_info = [];\r
-            err_ctx = ctx }) (*error*) in\r
-  match dims with\r
-    | [] ->\r
-        let cl_def = class_definition_of_type_specification ctx type_spec in\r
-        create_instance ctx modifs rhs elt_loc flow var inout cl_def cmt\r
-    | dim :: dims ->\r
-        {\r
-          component_path = elt_loc;\r
-          flow = flow;\r
-          variability = var;\r
-          causality = inout;\r
-          component_nature = lazy (expand_along_dimension dim dims);\r
-          declaration_equation = rhs;\r
-          comment = cmt;\r
-          component_location = ctx.location;\r
-          class_name = instance_class_name ctx.instance_nature\r
-        }\r
-\r
-and create_instance ctx modifs rhs elt_loc flow var inout cl_def cmt =\r
-  let merge_class_modifications arg modifs = match arg.action with\r
-    | ElementModification (Modification (modifs', _)) -> modifs' @ modifs\r
-    | ElementModification (Assignment _ | Equality _) -> modifs\r
-    | ElementRedeclaration _ -> modifs in\r
-  let rec declaration_equation modifs rhs =\r
-    let rec declaration_equation' = function\r
-      | [] -> None\r
-      | {\r
-          action =\r
-            ElementModification (\r
-              Modification (_, Some expr) | Assignment expr | Equality expr)\r
-        } :: _ -> Some expr\r
-      | _ :: args -> declaration_equation' args in\r
-    match rhs with\r
-      | None -> declaration_equation' modifs\r
-      | Some _ -> rhs in\r
-  let flow' = match cl_def.class_flow, ctx.context_flow with\r
-    | None, None -> flow\r
-    | Some flow', None | None, Some flow' -> flow || flow'\r
-    | Some flow', Some flow'' -> flow || flow' || flow''\r
-  and var' = match cl_def.class_variability, ctx.context_variability with\r
-    | None, None -> var\r
-    | Some var', None | None, Some var' -> Types.min_variability var var'\r
-    | Some var', Some var'' ->\r
-        Types.min_variability var (Types.min_variability var' var'')\r
-  and inout' = match inout, cl_def.class_causality with\r
-    | Types.Input, _ | _, Some Types.Input -> Types.Input\r
-    | Types.Output, _ | _, Some Types.Output -> Types.Output\r
-    | _ -> Types.Acausal in\r
-  let modifs' =\r
-    List.fold_right\r
-      merge_class_modifications\r
-      (modifs @ cl_def.modification)\r
-      []\r
-  and rhs' = declaration_equation modifs rhs in\r
-  match cl_def.description with\r
-    | ClassDescription (ctx', cl_desc) ->\r
-        let class_name = instance_class_name ctx.instance_nature in\r
-        let ctx' =\r
-          { ctx' with\r
-            context_flow = Some flow';\r
-            context_variability = Some var';\r
-            context_causality = Some inout';\r
-            instance_context = enclosing_instance ctx;\r
-            instance_nature = ComponentElement class_name\r
-          } in\r
-        {\r
-          component_path = elt_loc;\r
-          flow = flow';\r
-          variability = var';\r
-          causality = inout';\r
-          component_nature =\r
-            lazy (create_class_instance ctx' modifs' rhs' elt_loc cl_desc);\r
-          declaration_equation = rhs';\r
-          comment = cmt;\r
-          component_location = ctx'.location;\r
-          class_name = class_name\r
-        }\r
-    | PredefinedType predef ->\r
-        let class_name = instance_class_name ctx.instance_nature in\r
-        let ctx' =\r
-          { ctx with\r
-            context_flow = Some flow';\r
-            context_variability = Some var';\r
-            context_causality = Some inout';\r
-            instance_nature = ComponentElement class_name\r
-          } in\r
-        {\r
-          component_path = elt_loc;\r
-          flow = flow';\r
-          variability = var';\r
-          causality = inout';\r
-          component_nature =\r
-            lazy (create_predefined_type_instance ctx' modifs' predef);\r
-          declaration_equation = rhs';\r
-          comment = cmt;\r
-          component_location = ctx'.location;\r
-          class_name = class_name\r
-        }\r
-\r
-and create_temporary_instance ctx cl_def =\r
-  match cl_def.description with\r
-    | ClassDescription (ctx', cl_desc) ->\r
-        {\r
-          component_path = [];\r
-          flow = false;\r
-          variability = Types.Continuous;\r
-          causality = Types.Acausal;\r
-          component_nature =\r
-            lazy (create_class_instance ctx' [] None [] cl_desc);\r
-          declaration_equation = None;\r
-          comment = "";\r
-          component_location = ctx'.location;\r
-          class_name = instance_class_name ctx.instance_nature\r
-        }\r
-    | PredefinedType predef -> assert false (*error*)\r
-\r
-and class_definition_of_type_specification ctx type_spec =\r
-  let predefined_class_specifier = function\r
-    | "Boolean" -> Types.boolean_class_type\r
-    | "Integer" -> Types.integer_class_type\r
-    | "Real" -> Types.real_class_type\r
-    | "String" -> Types.string_class_type\r
-    | s ->\r
-        raise (InstantError\r
-          { err_msg = ["_UnknownIdentifier"; s];\r
-            err_info = [];\r
-            err_ctx = ctx }) (*error*)\r
-  and predefined_class_description = function\r
-    | "Boolean" -> PredefinedType BooleanType\r
-    | "Integer" -> PredefinedType IntegerType\r
-    | "Real" -> PredefinedType RealType\r
-    | "String" -> PredefinedType StringType\r
-    | s ->\r
-        raise (InstantError\r
-          { err_msg = ["_UnknownIdentifier"; s];\r
-            err_info = [];\r
-            err_ctx = ctx }) (*error*) in\r
-  match type_spec with\r
-    | ClassReference cl_def -> cl_def\r
-    | PredefinedIdentifier id ->\r
-        {\r
-          class_type = predefined_class_specifier id;\r
-          class_path = [Name id];\r
-          class_flow = None;\r
-          class_variability = None;\r
-          class_causality = None;\r
-          description = predefined_class_description id;\r
-          modification = [];\r
-          class_location = ctx.location\r
-        }\r
-    | _ -> assert false (*error*)\r
-\r
-and create_class_instance ctx modifs rhs elt_loc cl_desc =\r
-  let inst = instantiate_class_description ctx modifs rhs elt_loc cl_desc in\r
-  Instance inst\r
-\r
-and create_predefined_type_instance ctx modifs predef =\r
-  let inst =\r
-    {\r
-      predefined_type = predef;\r
-      attributes = predefined_type_attributes ctx modifs\r
-    } in\r
-  PredefinedTypeInstance inst\r
-\r
-and predefined_type_attributes ctx modifs =\r
-  let rec predefined_type_attributes attrs = function\r
-    | [] -> attrs\r
-    | (id, { action = ElementModification (Equality expr) }) :: modifs\r
-      when not (List.mem_assoc id attrs) ->\r
-        let attrs' = (id, expr) :: attrs in\r
-        predefined_type_attributes attrs' modifs\r
-    | _ :: modifs -> predefined_type_attributes attrs modifs in\r
-  predefined_type_attributes [] modifs\r
-\r
-and instantiate_inherited_elements ctx modifs rhs exts =\r
-  List.fold_right (instantiate_inherited_element ctx modifs rhs) exts []\r
-\r
-and instantiate_inherited_element ctx modifs rhs (_, modif_cl) inherited_elts =\r
-  let instantiate_inherited_element' modifs cl_def =\r
-    match cl_def.description with\r
-      | ClassDescription (ctx', cl_desc) ->\r
-          let ctx' = { ctx with parent_context = Some ctx' } in\r
-          let long_desc = cl_desc.long_description in\r
-          instantiate_class_elements ctx' modifs rhs long_desc\r
-      | PredefinedType _ -> assert false (*error*) in\r
-  let type_spec = evaluate modif_cl.NameResolve.base_class\r
-  and modifs' = evaluate modif_cl.NameResolve.class_modification in\r
-  let type_spec' = evaluate_expression ctx type_spec\r
-  and ctx = {ctx with location = expression_location ctx type_spec} in\r
-  let modifs = modifs @ evaluate_class_modification ctx modifs' in\r
-  match type_spec' with\r
-    | ClassReference cl_def ->\r
-        instantiate_inherited_element' modifs cl_def :: inherited_elts\r
-    | _ -> assert false (*error*)\r
\r
-and evaluate_class_definition ctx modifs elt_loc cl_def =\r
-  match evaluate cl_def.NameResolve.description with\r
-    | NameResolve.LongDescription long_desc ->\r
-        let cl_anns = long_desc.NameResolve.class_annotations in\r
-        let cl_def' =\r
-          {\r
-            class_kind = Types.Class;\r
-            class_annotations = lazy (evaluate_class_annotations ctx cl_anns);\r
-            long_description = long_desc\r
-          } in\r
-        {\r
-          class_type = evaluate cl_def.NameResolve.class_type;\r
-          class_path = elt_loc;\r
-          class_flow = None;\r
-          class_variability = None;\r
-          class_causality = None;\r
-          description = ClassDescription (ctx, cl_def');\r
-          modification = modifs;\r
-          class_location = ctx.location\r
-        }\r
-    | NameResolve.ShortDescription short_desc ->\r
-        raise (InstantError\r
-          {err_msg = ["_NotYetImplemented"; "_ShortClassDef"];\r
-           err_info = [];\r
-           err_ctx = {ctx with path = elt_loc;\r
-                      instance_nature = ClassElement}})\r
-\r
-and evaluate_class_annotations ctx cl_anns =\r
-  let evaluate_inverse_function inv_func =\r
-    let inv_func = evaluate inv_func in\r
-    let expr =\r
-      evaluate_expression ctx inv_func.NameResolve.function_class in\r
-    match expr with\r
-    | ClassReference cl_def ->\r
-        {\r
-          function_class = cl_def;\r
-          arguments = inv_func.NameResolve.arguments\r
-        }\r
-    | _ -> assert false (*error*) in\r
-  let evaluate_class_annotation cl_ann = match cl_ann with\r
-    | NameResolve.InverseFunction inv_func ->\r
-        InverseFunction (lazy (evaluate_inverse_function inv_func))\r
-    | NameResolve.UnknownAnnotation cl_ann ->\r
-        UnknownAnnotation cl_ann in\r
-  List.map evaluate_class_annotation (evaluate cl_anns)\r
-\r
-and evaluate_class_modification ctx cl_modif =\r
-  let add_modification_argument arg cl_modif' =\r
-    match arg.NameResolve.action with\r
-      | None -> cl_modif'\r
-      | Some modif ->\r
-          let arg' =\r
-            arg.NameResolve.target,\r
-            {\r
-              each = arg.NameResolve.each;\r
-              action = evaluate_modification_action ctx modif\r
-            } in\r
-          arg' :: cl_modif' in\r
-  List.fold_right add_modification_argument cl_modif []\r
-\r
-and evaluate_modification_action ctx = function\r
-  | NameResolve.ElementModification modif ->\r
-      let modif' = evaluate_modification ctx modif in\r
-      ElementModification modif'\r
-  | NameResolve.ElementRedeclaration elt_desc ->\r
-      raise (InstantError\r
-        { err_msg = ["_NotYetImplemented"; "_ElementRedeclaration"];\r
-          err_info = [];\r
-          err_ctx = ctx })\r
-\r
-and evaluate_modification ctx = function\r
-  | NameResolve.Modification (modifs, rhs) ->\r
-      let modifs' = evaluate_class_modification ctx modifs\r
-      and rhs' = evaluate_modification_expression ctx rhs in\r
-      Modification (modifs', rhs')\r
-  | NameResolve.Assignment expr ->\r
-      let expr = evaluate expr in\r
-      let ctx = {ctx with location = expression_location ctx expr} in\r
-      raise (InstantError\r
-        { err_msg = ["_NotYetImplemented"; "_AssignExprInElemModif"];\r
-          err_info = [];\r
-          err_ctx = ctx })\r
-  | NameResolve.Equality expr ->\r
-      let expr' = lazy (evaluate_expression ctx (evaluate expr)) in\r
-      Equality expr'\r
-\r
-and evaluate_modification_expression ctx = function\r
-  | None -> None\r
-  | Some expr ->\r
-      let expr' = lazy (evaluate_expression ctx (evaluate expr)) in\r
-      Some expr'\r
-\r
-and instantiate_local_unnamed_elements ctx unnamed_elts =\r
-  List.map (instantiate_local_unnamed_element ctx) (evaluate unnamed_elts)\r
-\r
-and instantiate_local_unnamed_element ctx unnamed_elt =\r
-  match unnamed_elt with\r
-    | NameResolve.EquationClause (validity, equs) ->\r
-        EquationClause (validity, lazy (instantiate_equations ctx equs))\r
-    | NameResolve.AlgorithmClause (validity, algs) ->\r
-        raise (InstantError\r
-          { err_msg = ["_NotYetImplemented"; "_AlgoClause"];\r
-            err_info = [];\r
-            err_ctx = ctx })\r
-\r
-and instantiate_equations ctx equs =\r
-  let instantiate_equations' equ equs =\r
-    let equs' =  instantiate_equation ctx equ in\r
-    { nature = equs'; info = equ } :: equs in\r
-  List.fold_right instantiate_equations' equs []\r
-\r
-and instantiate_equation ctx equ = match equ.NameResolve.nature with\r
-  | NameResolve.Equal (expr, expr') -> instantiate_equal ctx expr expr'\r
-  | NameResolve.ConditionalEquationE (alts, default) ->\r
-      instantiate_conditional_equation ctx alts default\r
-  | NameResolve.ForClauseE (ranges, equs) ->\r
-      instantiate_for_clause_e ctx ranges equs\r
-  | NameResolve.ConnectFlows (sign, expr, sign', expr') ->\r
-      instantiate_connection ctx sign expr sign' expr'\r
-  | NameResolve.WhenClauseE alts ->\r
-      instantiate_when_clause_e ctx alts\r
-\r
-and instantiate_equal ctx expr expr' =\r
-  let rec equal_expr expr expr' =\r
-    match expr, expr' with\r
-    | BinaryOperation (bin_oper_kind, expr1, expr2),\r
-      BinaryOperation (bin_oper_kind', expr1', expr2') ->\r
-        (bin_oper_kind = bin_oper_kind') &&\r
-        (equal_expr expr1 expr1') &&\r
-        (equal_expr expr2 expr2')\r
-    | ClassReference cl_def, ClassReference cl_def' ->\r
-        cl_def.class_path = cl_def'.class_path\r
-    | ComponentReference cpnt_desc, ComponentReference cpnt_desc' ->\r
-        cpnt_desc.component_path = cpnt_desc'.component_path\r
-    | EnumerationElement s, EnumerationElement s' -> s = s'\r
-    | False, False -> true\r
-    | FieldAccess (expr, s), FieldAccess (expr', s') ->\r
-        (equal_expr expr expr') && (s = s')\r
-    | FunctionCall (expr, exprs), FunctionCall (expr', exprs') ->\r
-        (equal_expr expr expr') &&\r
-        (List.length exprs = List.length exprs') &&\r
-        (List.for_all2 (=) exprs exprs')\r
-    | If (alts, default), If (alts', default') ->\r
-        let f (cond, expr) (cond', expr') =\r
-          (equal_expr cond cond') && (equal_expr expr expr') in\r
-        (List.length alts = List.length alts') &&\r
-        (List.for_all2 f alts alts') &&\r
-        (equal_expr default default')\r
-    | IndexedAccess (expr, exprs), IndexedAccess (expr', exprs') ->\r
-        (equal_expr expr expr') &&\r
-        (List.length exprs = List.length exprs') &&\r
-        (List.for_all2 (=) exprs exprs')\r
-    | Integer i, Integer i' -> Int32.compare i i' = 0\r
-    | LoopVariable i, LoopVariable i' -> i = i'\r
-    | NoEvent expr, NoEvent expr' -> equal_expr expr expr'\r
-    | PredefinedIdentifier s, PredefinedIdentifier s' -> s = s'\r
-    | Range (start, step, stop), Range (start', step', stop') ->\r
-        (equal_expr start start') &&\r
-        (equal_expr step step') &&\r
-        (equal_expr stop stop')\r
-    | Real f, Real f' -> f = f'\r
-    | Record elts, Record elts' ->\r
-        let f (s, expr) (s', expr') =\r
-          (s = s') && (equal_expr expr expr') in\r
-        (List.length elts = List.length elts') &&\r
-        (List.for_all2 f elts elts')\r
-    | String s, String s' -> s = s'\r
-    | True, True -> true\r
-    | Tuple exprs, Tuple exprs' ->\r
-        (List.length exprs = List.length exprs') &&\r
-        (List.for_all2 equal_expr exprs exprs')\r
-    | UnaryOperation (un_oper_kind, expr),\r
-      UnaryOperation (un_oper_kind', expr') ->\r
-        (un_oper_kind = un_oper_kind') &&\r
-        (equal_expr expr expr')\r
-    | Vector exprs, Vector exprs' ->\r
-        (Array.length exprs = Array.length exprs') &&\r
-        (ArrayExt.for_all2 equal_expr exprs exprs')\r
-    | VectorReduction (exprs, expr), VectorReduction (exprs', expr') ->\r
-        (List.length exprs = List.length exprs') &&\r
-        (List.for_all2 equal_expr exprs exprs') &&\r
-        (equal_expr expr expr')\r
-    | _ -> false in\r
-  let expr = evaluate_expression ctx expr\r
-  and expr' = evaluate_expression ctx expr' in\r
-  match equal_expr expr expr' with\r
-  | true -> []\r
-  | false -> [ Equal (expr, expr') ]\r
-\r
-and instantiate_conditional_equation ctx alts default =\r
-  let rec instantiate_alternatives acc = function\r
-    | [] -> instantiate_default acc default\r
-    | (cond, equs) :: alts -> instantiate_alternative acc cond equs alts\r
-  and instantiate_alternative acc cond equs alts =\r
-    let cond' = evaluate_expression ctx cond in\r
-    match cond' with\r
-      | False -> instantiate_alternatives acc alts\r
-      | True -> instantiate_default acc equs\r
-      | _ ->\r
-          let equs' = instantiate_equations ctx equs in\r
-          instantiate_alternatives ((cond', equs') :: acc) alts\r
-  and instantiate_default acc equs =\r
-    let equs' = instantiate_equations ctx equs in\r
-    [ConditionalEquationE (List.rev acc, equs')] in\r
-  let alts' = instantiate_alternatives [] alts in\r
-  List.flatten (List.map (expand_equation ctx) alts')\r
-\r
-and expand_equation ctx equ =\r
-  let rec expand_equation' equ =\r
-    let expand_conditional_equation alts default =\r
-      let add_alternative (b, equs) altss =\r
-        let g equ = List.flatten (List.map expand_equation' equ.nature) in\r
-        let equs' = List.flatten (List.map g equs) in\r
-        let f (expr1, expr2) (expr1', expr2') = match expr1, expr2 with\r
-          | If (alts1, default1), If (alts2, default2) ->\r
-              If ((b, expr1') :: alts1, default1),\r
-              If ((b, expr2') :: alts2, default2)\r
-          | _ -> assert false in\r
-        try\r
-          List.map2 f altss equs'\r
-        with\r
-        | _ ->\r
-            raise (InstantError\r
-              {err_msg = ["_InvalidCondEquation"];\r
-               err_info = [];\r
-               err_ctx = ctx}) in\r
-      let g equ = List.flatten (List.map expand_equation' equ.nature) in\r
-      let default' = List.flatten (List.map g default) in\r
-      let f = function (expr1, expr2) -> If ([], expr1), If ([], expr2) in\r
-      List.fold_right add_alternative alts (List.map f default') in\r
-    match equ with\r
-    | ConditionalEquationE (alts, default) ->\r
-        expand_conditional_equation alts default\r
-    | Equal (expr, expr') -> [ expr, expr' ]\r
-    | _ ->\r
-        raise (InstantError\r
-          {err_msg = ["_InvalidCondEquation"];\r
-           err_info = [];\r
-           err_ctx = ctx}) in\r
-  let f (expr, expr') = Equal (expr, expr') in\r
-  List.map f (expand_equation' equ)\r
-\r
-and instantiate_when_clause_e ctx alts =\r
-  let instantiate_alternative (cond, equs) =\r
-    let cond' = evaluate_expression ctx cond in\r
-    let equs' = instantiate_equations ctx equs in\r
-    cond', equs' in\r
-  [WhenClauseE (List.map instantiate_alternative alts)]\r
-\r
-and instantiate_connection ctx sign expr sign' expr' =\r
-  let expr = evaluate_expression ctx expr\r
-  and expr' = evaluate_expression ctx expr' in\r
-  [ConnectFlows (sign, expr, sign', expr')]\r
-\r
-and instantiate_for_clause_e ctx ranges equs =\r
-  let rec instantiate_for_clause_e' ctx = function\r
-    | [] -> List.flatten (List.map (instantiate_equation ctx) equs)\r
-    | ranges -> equations_of_reduction ctx ranges\r
-  and equations_of_reduction ctx ranges = match ranges with\r
-    | (Vector exprs) :: ranges ->\r
-        let f expr =\r
-          let ctx' =\r
-            { ctx with\r
-              class_context = ForContext (ctx, Some expr)\r
-            } in\r
-          instantiate_for_clause_e' ctx' ranges in\r
-        List.flatten (List.map f (Array.to_list exprs))\r
-    | _ ->\r
-        raise (InstantError\r
-          {err_msg = ["_InvalidForClauseRange"];\r
-           err_info = [];\r
-           err_ctx = ctx}) in\r
-  let ranges = List.map (evaluate_expression ctx) ranges in\r
-  instantiate_for_clause_e' ctx ranges\r
-\r
-and evaluate_expression ctx expr =\r
-  let ctx = {ctx with location = expression_location ctx expr} in\r
-  match expr.NameResolve.nature with\r
-    | NameResolve.BinaryOperation (binop, expr, expr') ->\r
-        evaluate_binary_operation ctx binop expr expr'\r
-    | NameResolve.DynamicIdentifier (level, id) ->\r
-        evaluate_dynamic_identifier ctx level id\r
-    | NameResolve.False -> False\r
-    | NameResolve.FieldAccess (expr, id) ->\r
-        evaluate_field_access ctx expr id\r
-    | NameResolve.FunctionArgument pos -> evaluate_function_argument ctx pos\r
-    | NameResolve.FunctionCall (expr, exprs, expr') ->\r
-        evaluate_function_call ctx expr exprs expr'\r
-    | NameResolve.FunctionInvocation exprs ->\r
-        evaluate_function_invocation ctx exprs\r
-    | NameResolve.If (alts, default) -> evaluate_if ctx alts default\r
-    | NameResolve.IndexedAccess (expr, exprs) ->\r
-        let expr = evaluate_expression ctx expr\r
-        and exprs = List.map (evaluate_expression ctx) exprs in\r
-        evaluate_indexed_access ctx expr exprs\r
-    | NameResolve.Integer i -> Integer i\r
-    | NameResolve.LocalIdentifier (level, id) ->\r
-        evaluate_local_identifier ctx level id\r
-    | NameResolve.LoopVariable level -> evaluate_loop_variable ctx level\r
-    | NameResolve.NoEvent expr -> evaluate_no_event ctx expr\r
-    | NameResolve.PredefinedIdentifier id -> PredefinedIdentifier id\r
-    | NameResolve.Range (start, step, stop) ->\r
-        evaluate_range ctx start step stop\r
-    | NameResolve.Real f -> Real f\r
-    | NameResolve.String s -> String s\r
-    | NameResolve.ToplevelIdentifier id ->\r
-        evaluate_toplevel_identifier ctx id\r
-    | NameResolve.True -> True\r
-    | NameResolve.Tuple exprs -> evaluate_tuple ctx exprs\r
-    | NameResolve.UnaryOperation (unop, expr) ->\r
-        evaluate_unary_operation ctx unop expr\r
-    | NameResolve.VectorReduction (ranges, expr) ->\r
-        evaluate_vector_reduction ctx ranges expr\r
-    | NameResolve.Vector exprs -> evaluate_vector ctx exprs\r
-    | NameResolve.Coercion (coer, expr) ->\r
-        evaluate_coercion ctx coer expr\r
-\r
-and evaluate_binary_operation ctx binop expr expr' =\r
-  let expr = evaluate_expression ctx expr\r
-  and expr' = evaluate_expression ctx expr' in\r
-  let expr = flatten_expression expr\r
-  and expr' = flatten_expression expr' in\r
-  match binop with\r
-    | NameResolve.And -> evaluate_and expr expr'\r
-    | NameResolve.Divide -> evaluate_divide ctx expr expr'\r
-    | NameResolve.EqualEqual -> evaluate_equalequal expr expr'\r
-    | NameResolve.GreaterEqual -> evaluate_greater_equal expr expr'\r
-    | NameResolve.Greater -> evaluate_greater expr expr'\r
-    | NameResolve.LessEqual -> evaluate_less_equal expr expr'\r
-    | NameResolve.Less -> evaluate_less expr expr'\r
-    | NameResolve.Times -> evaluate_times expr expr'\r
-    | NameResolve.NotEqual -> evaluate_not_equal expr expr'\r
-    | NameResolve.Or -> evaluate_or expr expr'\r
-    | NameResolve.Plus -> evaluate_plus expr expr'\r
-    | NameResolve.Power -> evaluate_power ctx expr expr'\r
-    | NameResolve.Minus -> evaluate_minus expr expr'\r
-\r
-and evaluate_dynamic_identifier ctx level id =\r
-  let rec evaluate_dynamic_identifier' inst level =\r
-    match level, inst.enclosing_instance with\r
-    | 0, _ -> instance_field_access ctx inst id\r
-    | _, Some inst -> evaluate_dynamic_identifier' inst (level - 1)\r
-    | _, None -> assert false (*error*) in\r
-  match ctx.instance_context with\r
-    | Some inst -> evaluate_dynamic_identifier' inst level\r
-    | None -> assert false (*error*)\r
-\r
-and evaluate_field_access ctx expr id =\r
-  let expr = evaluate_expression ctx expr in\r
-  field_access ctx expr id\r
-\r
-and evaluate_function_argument ctx pos = match ctx.class_context with\r
-  | FunctionEvaluationContext (_, expr, _) when pos = 0 -> expr\r
-  | FunctionEvaluationContext (_, _, exprs) -> List.nth exprs (pos - 1)\r
-  | ForContext (ctx', _) -> evaluate_function_argument ctx' pos\r
-  | InstanceContext _ | ToplevelContext -> assert false (*error*)\r
-\r
-and evaluate_function_call ctx expr exprs expr' =\r
-  let expr = evaluate_expression ctx expr\r
-  and exprs = List.map (evaluate_expression ctx) exprs in\r
-  let exprs = List.map flatten_expression exprs in\r
-  let ctx' =\r
-    { ctx with\r
-      class_context = FunctionEvaluationContext (ctx, expr, exprs)\r
-    } in\r
-  evaluate_expression ctx' expr'\r
-\r
-and evaluate_function_invocation ctx exprs =\r
-  let exprs = List.map (evaluate_expression ctx) exprs in\r
-  let exprs = List.map flatten_expression exprs in\r
-  let evaluate_function_with_arguments = function\r
-    | ClassReference cl_def ->\r
-        evaluate_class_function_invocation cl_def exprs\r
-    | PredefinedIdentifier s ->\r
-        evaluate_predefined_function_invocation ctx s exprs\r
-    | ComponentReference _ ->\r
-        raise (InstantError\r
-          { err_msg = ["_NotYetImplemented"; "_ComponentFuncInvocation"];\r
-            err_info = [];\r
-            err_ctx = ctx })\r
-    | _ -> assert false (*error*) in\r
-  let rec evaluate_function_invocation' ctx = match ctx.class_context with\r
-    | FunctionEvaluationContext (_, expr, _) ->\r
-        evaluate_function_with_arguments expr\r
-    | ForContext (ctx', _) -> evaluate_function_invocation' ctx'\r
-    | InstanceContext _ | ToplevelContext -> assert false (*error*) in\r
-  evaluate_function_invocation' ctx\r
-\r
-and evaluate_if ctx alts default =\r
-  let create_if alts default = match alts with\r
-    | [] -> default\r
-    | _ :: _ -> If (alts, default) in\r
-  let rec evaluate_alternatives alts' alts = match alts with\r
-    | [] ->\r
-        let default = evaluate_expression ctx default in\r
-        create_if (List.rev alts') default\r
-    | (expr, expr') :: alts ->\r
-        let expr = evaluate_expression ctx expr in\r
-        evaluate_alternative expr expr' alts' alts\r
-  and evaluate_alternative expr expr' alts' alts = match expr with\r
-    | True ->\r
-        let default = evaluate_expression ctx expr' in\r
-        create_if (List.rev alts') default\r
-    | False -> evaluate_alternatives alts' alts\r
-    | _ ->\r
-        let expr' = evaluate_expression ctx expr' in\r
-        evaluate_alternatives ((expr, expr') :: alts') alts in\r
-  evaluate_alternatives [] alts\r
-\r
-and evaluate_indexed_access ctx expr exprs =\r
-  let rec vector_indexed_access exprs' exprs = match exprs with\r
-    | [] -> expr\r
-    | Integer i :: exprs ->\r
-        let expr' =\r
-          try\r
-            exprs'.(Int32.to_int i - 1)\r
-          with _ ->\r
-              raise (InstantError\r
-                { err_msg = ["_IndexOutOfBound"];\r
-                  err_info = [];\r
-                  err_ctx = ctx}) (*error*) in\r
-        evaluate_indexed_access ctx expr' exprs\r
-    | (Vector subs) :: exprs ->\r
-        let f sub = vector_indexed_access exprs' (sub :: exprs) in\r
-        Vector (Array.map f subs)\r
-    | _ -> IndexedAccess (expr, exprs)\r
-  and component_indexed_access cpnt_desc exprs =\r
-    let rec static_array_indexed_access cpnt_descs exprs = match exprs with\r
-      | [] -> expr\r
-      | Integer i :: exprs ->\r
-          let i' = Int32.to_int i in\r
-          if Array.length cpnt_descs >= i' then\r
-            let cpnt_desc = cpnt_descs.(i' - 1) in\r
-            let expr' = ComponentReference cpnt_desc in\r
-            evaluate_indexed_access ctx expr' exprs\r
-          else\r
-            raise (InstantError\r
-              { err_msg = ["_IndexOutOfBound"];\r
-                err_info = [];\r
-                err_ctx = ctx}) (*error*)\r
-      | (Vector subs) :: exprs ->\r
-          let f sub = static_array_indexed_access cpnt_descs (sub :: exprs) in\r
-          Vector (Array.map f subs)\r
-      | exprs -> IndexedAccess (expr, exprs) in\r
-    match evaluate cpnt_desc.component_nature with\r
-    | DynamicArray _ -> IndexedAccess (ComponentReference cpnt_desc, exprs)\r
-    | StaticArray cpnt_descs ->\r
-        static_array_indexed_access cpnt_descs exprs\r
-    | Instance _ | PredefinedTypeInstance _ -> expr in\r
-  match expr, exprs with\r
-  | _, [] -> expr\r
-  | ComponentReference cpnt_desc, _ ->\r
-      component_indexed_access cpnt_desc exprs\r
-  | Vector exprs', _ ->\r
-      vector_indexed_access exprs' exprs\r
-  | If (alts, default), _ ->\r
-      let f (cond, expr) = (cond, evaluate_indexed_access ctx expr exprs) in\r
-      If (List.map f alts, evaluate_indexed_access ctx default exprs)\r
-  | _ -> IndexedAccess (expr, exprs)\r
-\r
-and evaluate_local_identifier ctx level id =\r
-  let rec evaluate_local_identifier' ctx inst level =\r
-    match level, ctx.parent_context with\r
-      | 0, _ -> instance_field_access ctx inst id\r
-      | _, Some ctx -> evaluate_local_identifier ctx (level - 1) id\r
-      | _, None -> assert false (*error*) in\r
-  match ctx.class_context with\r
-    | ForContext (ctx, _) | FunctionEvaluationContext (ctx, _, _) ->\r
-        evaluate_local_identifier ctx level id\r
-    | InstanceContext inst -> evaluate_local_identifier' ctx inst level\r
-    | ToplevelContext -> assert false (*error*)\r
-\r
-and evaluate_loop_variable ctx level =\r
-  let rec evaluate_loop_variable' ctx level' =\r
-    match level', ctx.class_context with\r
-      | 0, ForContext (_, None) -> assert false (*LoopVariable level'*)\r
-      | 0, ForContext (_, Some expr) -> expr\r
-      | _, ForContext (ctx, _) -> evaluate_loop_variable ctx (level' - 1)\r
-      | _, FunctionEvaluationContext (ctx, _, _) ->\r
-          evaluate_loop_variable' ctx level'\r
-      | _, (InstanceContext _ | ToplevelContext) -> assert false (*error*) in\r
-  evaluate_loop_variable' ctx level\r
-\r
-and evaluate_no_event ctx expr =\r
-  let expr = evaluate_expression ctx expr in\r
-  match expr with\r
-    | True | False | Integer _ | Real _ | String _ | EnumerationElement _ ->\r
-        expr\r
-    | _ -> NoEvent expr\r
-\r
-and evaluate_range ctx start step stop =\r
-  let start = evaluate_expression ctx start\r
-  and step = evaluate_expression ctx step\r
-  and stop = evaluate_expression ctx stop in\r
-  let real_of_expression expr = match expr with\r
-    | Real r -> r\r
-    | Integer i -> Int32.to_float i\r
-    | _ -> assert false in\r
-  let integer_interval istart istep istop = match istart, istep, istop with\r
-    | _\r
-      when (Int32.compare istop istart) *\r
-        (Int32.compare istep Int32.zero) < 0 ->\r
-        Vector (Array.make 0 (Integer istart))\r
-    | _ ->\r
-        let n =\r
-          Int32.div (Int32.sub istop istart) istep in\r
-        let n' = Int32.to_int (Int32.succ n) in\r
-        let f i =\r
-          let i' = Int32.of_int i in\r
-          let j =\r
-            Int32.add istart (Int32.mul i' istep) in\r
-          Integer j in\r
-        Vector (Array.init n' f)\r
-  and real_interval rstart rstep rstop = match rstart, rstep, rstop with\r
-    | _ when (rstop -. rstart) /. rstep < 0. ->\r
-        Vector (Array.make 0 (Real rstart))\r
-    | _ ->\r
-        let n = truncate ((rstop -. rstart) /. rstep) + 1\r
-        and f i = Real (rstart +. float_of_int i *. rstep) in\r
-        Vector (Array.init n f) in\r
-  match start, step, stop with\r
-  | _, Integer istep, _\r
-    when Int32.compare istep Int32.zero = 0 ->\r
-      raise (InstantError\r
-        {err_msg = ["_RangeStepValueCannotBeNull"];\r
-         err_info = [];\r
-         err_ctx = ctx})\r
-  | _, Real rstep, _ when rstep = 0. ->\r
-      raise (InstantError\r
-        {err_msg = ["_RangeStepValueCannotBeNull"];\r
-         err_info = [];\r
-         err_ctx = ctx})\r
-  | Integer istart, Integer istep, Integer istop ->\r
-      integer_interval istart istep istop\r
-  | (Integer _ | Real _), (Integer _ | Real _), (Integer _ | Real _) ->\r
-      let rstart = real_of_expression start\r
-      and rstep = real_of_expression step\r
-      and rstop = real_of_expression stop in\r
-      real_interval rstart rstep rstop\r
-  | _, _, _ -> Range (start, step, stop)\r
-\r
-and evaluate_coercion ctx coer expr =\r
-  let rec evaluate_real_of_integer expr' = match expr' with\r
-    | Integer i -> Real (Int32.to_float i)\r
-    | Vector exprs ->\r
-        Vector (Array.map evaluate_real_of_integer exprs)\r
-    | _ -> expr' in\r
-  let expr' = evaluate_expression ctx expr in\r
-  match coer with\r
-  | NameResolve.RealOfInteger -> evaluate_real_of_integer expr'\r
-\r
-and evaluate_toplevel_identifier ctx id =\r
-  let elt_desc = List.assoc id (evaluate ctx.toplevel) in\r
-  match evaluate elt_desc.element_nature with\r
-    | Class cl_def -> ClassReference cl_def\r
-    | Component cpnt_desc -> ComponentReference cpnt_desc\r
-\r
-and evaluate_tuple ctx exprs =\r
-  Tuple (List.map (evaluate_expression ctx) exprs)\r
-\r
-and evaluate_unary_operation ctx unop expr =\r
-  let expr = evaluate_expression ctx expr in\r
-  let expr = flatten_expression expr in\r
-  match unop with\r
-    | NameResolve.Not -> evaluate_not expr\r
-    | NameResolve.UnaryMinus -> evaluate_unary_minus expr\r
-    | NameResolve.UnaryPlus -> expr\r
-\r
-(*and evaluate_vector_reduction ctx ranges expr =\r
-  let rec evaluate_vector_reduction' ctx = function\r
-    | [] -> evaluate_expression ctx expr\r
-    | ranges -> vector_of_reduction ctx ranges\r
-  and vector_of_reduction ctx = function\r
-    | Range (Integer start, Integer step, Integer stop) :: ranges ->\r
-        vector_of_range ctx start step stop ranges\r
-    | ranges ->\r
-        let ctx' =\r
-          { ctx with\r
-            class_context = ForContext (ctx, None)\r
-          } in\r
-        VectorReduction (ranges, evaluate_expression ctx' expr)\r
-  and vector_of_range ctx start step stop ranges =\r
-    let rec expression_list pred start = match pred start with\r
-      | true -> []\r
-      | false ->\r
-          let ctx' =\r
-            { ctx with\r
-              class_context = ForContext (ctx, Some (Integer start))\r
-            } in\r
-          let expr = evaluate_vector_reduction' ctx' ranges in\r
-          expr :: expression_list pred (Int32.add start step) in\r
-    let cmp = Int32.compare step 0l in\r
-    match cmp with\r
-      | 0 when Int32.compare start stop <> 0 -> assert false (*error*)\r
-      | 0 -> Vector [||]\r
-      | _ when cmp < 0 ->\r
-          let pred = function i -> Int32.compare i stop < 0 in\r
-          let exprs = expression_list pred start in\r
-          Vector (Array.of_list exprs)\r
-      | _ ->\r
-          let pred = function i -> Int32.compare i stop > 0 in\r
-          let exprs = expression_list pred start in\r
-          Vector (Array.of_list exprs) in\r
-  let ranges = List.map (evaluate_expression ctx) ranges in\r
-  evaluate_vector_reduction' ctx ranges*)\r
-\r
-and evaluate_vector_reduction ctx ranges expr =\r
-  let rec evaluate_vector_reduction' ctx = function\r
-    | [] -> evaluate_expression ctx expr\r
-    | ranges -> vector_of_reduction ctx ranges\r
-  and vector_of_reduction ctx = function\r
-    | Range (Integer u, Integer p, Integer v) :: ranges ->\r
-        vector_of_integer_range ctx u p v ranges\r
-    | Range (Real u, Real p, Real v) :: ranges ->\r
-        vector_of_real_range ctx u p v ranges\r
-    | Vector exprs :: ranges ->\r
-        let f i =\r
-          let ctx' =\r
-            { ctx with\r
-              class_context = ForContext (ctx, Some exprs.(i))\r
-            } in\r
-          evaluate_vector_reduction' ctx' ranges in\r
-        Vector (Array.init (Array.length exprs) f)\r
-    | _ -> assert false\r
-  and vector_of_integer_range ctx start step stop ranges =\r
-    let rec expression_list pred start = match pred start with\r
-      | true -> []\r
-      | false ->\r
-          let expr = Integer start in\r
-          let ctx' =\r
-            { ctx with\r
-              class_context =\r
-                ForContext (ctx, Some expr)\r
-            } in\r
-          let expr = evaluate_vector_reduction' ctx' ranges in\r
-          let next = Int32.add start step in\r
-          expr :: expression_list pred next in\r
-    match step with\r
-    | _ when Int32.compare step Int32.zero = 0 ->\r
-        raise (InstantError\r
-          {err_msg = ["_RangeStepValueCannotBeNull"];\r
-           err_info = [];\r
-           err_ctx = ctx})\r
-    | _ when Int32.compare step Int32.zero < 0 ->\r
-        let pred = function i -> (Int32.compare i stop < 0) in\r
-        Vector (Array.of_list (expression_list pred start))\r
-    | _ ->\r
-        let pred = function i -> (Int32.compare i stop > 0) in\r
-        Vector (Array.of_list (expression_list pred start))\r
-  and vector_of_real_range ctx start step stop ranges =\r
-    let rec expression_list pred start = match pred start with\r
-      | true -> []\r
-      | false ->\r
-          let expr = Real start in\r
-          let ctx' =\r
-            { ctx with\r
-              class_context = ForContext (ctx, Some expr)\r
-            } in\r
-          let expr = evaluate_vector_reduction' ctx' ranges in\r
-          expr :: expression_list pred (start +. step) in\r
-    match step with\r
-    | 0. ->\r
-        raise (InstantError\r
-          {err_msg = ["_RangeStepValueCannotBeNull"];\r
-           err_info = [];\r
-           err_ctx = ctx})\r
-    | _ when step < 0. ->\r
-        let pred = function f -> f < stop in\r
-        Vector (Array.of_list (expression_list pred start))\r
-    | _ ->\r
-        let pred = function f -> f > stop in\r
-        Vector (Array.of_list (expression_list pred start)) in\r
-  let ranges = List.map (evaluate_expression ctx) ranges in\r
-  evaluate_vector_reduction' ctx ranges\r
-\r
-and evaluate_vector ctx exprs =\r
-  let exprs = List.map (evaluate_expression ctx) exprs in\r
-  Vector (Array.of_list exprs)\r
-\r
-and evaluate_and expr expr' = match expr, expr' with\r
-  | False, (False | True) | True, False -> False\r
-  | True, True -> True\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_and exprs exprs')\r
-  | _ -> BinaryOperation (And, expr, expr')\r
-\r
-and evaluate_divide ctx expr expr' = match expr, expr' with\r
-  | _, Integer 0l ->\r
-      raise (InstantError\r
-        { err_msg = ["_DivisionByZero"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | Integer 0l, _ -> Integer 0l\r
-  | Integer i, Integer i' ->\r
-      Real ((Int32.to_float i) /. (Int32.to_float i'))\r
-  | _, Real 0. ->\r
-      raise (InstantError\r
-        { err_msg = ["_DivisionByZero"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | Integer i, Real f -> Real (Int32.to_float i /. f)\r
-  | Real f, Integer i -> Real (f /. Int32.to_float i)\r
-  | Real f, Real f' -> Real (f /. f')\r
-  | Vector exprs, _ ->\r
-      let divide_element expr = evaluate_divide ctx expr expr' in\r
-      Vector (Array.map divide_element exprs)\r
-  | _ -> BinaryOperation (Divide, expr, expr')\r
-\r
-and evaluate_equalequal expr expr' = match expr, expr' with\r
-  | Integer i, Integer i' when i = i' -> True\r
-  | Integer i, Real f | Real f, Integer i when f = Int32.to_float i -> True\r
-  | Real f, Real f' when f = f' -> True\r
-  | (Integer _ | Real _), (Integer _ | Real _) -> False\r
-  | Vector exprs, Vector exprs'\r
-    when\r
-      ArrayExt.for_all2\r
-        (fun expr expr' -> evaluate_equalequal expr expr' = True)\r
-        exprs\r
-        exprs' -> True\r
-  | Vector _, Vector _ -> False\r
-  | _ -> BinaryOperation (EqualEqual, expr, expr')\r
-\r
-and evaluate_greater_equal expr expr' = match expr, expr' with\r
-  | Integer i, Integer i' when i >= i' -> True\r
-  | Integer i, Real f when Int32.to_float i >= f -> True\r
-  | Real f, Integer i when f >= Int32.to_float i -> True\r
-  | Real f, Real f' when f >= f' -> True\r
-  | (Integer _ | Real _), (Integer _ | Real _) -> False\r
-  | _ -> BinaryOperation (GreaterEqual, expr, expr')\r
-\r
-and evaluate_greater expr expr' = match expr, expr' with\r
-  | Integer i, Integer i' when i > i' -> True\r
-  | Integer i, Real f when Int32.to_float i > f -> True\r
-  | Real f, Integer i when f > Int32.to_float i -> True\r
-  | Real f, Real f' when f > f' -> True\r
-  | (Integer _ | Real _), (Integer _ | Real _) -> False\r
-  | _ -> BinaryOperation (Greater, expr, expr')\r
-\r
-and evaluate_less_equal expr expr' = match expr, expr' with\r
-  | Integer i, Integer i' when i <= i' -> True\r
-  | Integer i, Real f when Int32.to_float i <= f -> True\r
-  | Real f, Integer i when f <= Int32.to_float i -> True\r
-  | Real f, Real f' when f <= f' -> True\r
-  | (Integer _ | Real _), (Integer _ | Real _) -> False\r
-  | _ -> BinaryOperation (LessEqual, expr, expr')\r
-\r
-and evaluate_less expr expr' = match expr, expr' with\r
-  | Integer i, Integer i' when i < i' -> True\r
-  | Integer i, Real f when Int32.to_float i < f -> True\r
-  | Real f, Integer i when f < Int32.to_float i -> True\r
-  | Real f, Real f' when f < f' -> True\r
-  | (Integer _ | Real _), (Integer _ | Real _) -> False\r
-  | _ -> BinaryOperation (Less, expr, expr')\r
-\r
-and evaluate_times expr expr' =\r
-  let rec line exprs i = match exprs.(i) with\r
-    | Vector exprs -> exprs\r
-    | _ -> assert false\r
-  and column exprs j =\r
-    let f i = match exprs.(i) with\r
-      | Vector exprs -> exprs.(j)\r
-      | _ -> assert false in\r
-    Array.init (Array.length exprs) f\r
-  and ndims expr = match expr with\r
-    | Vector exprs when Array.length exprs = 0 -> assert false\r
-    | Vector exprs -> 1 + ndims exprs.(0)\r
-    | _ -> 0\r
-  and size expr i = match expr, i with\r
-    | _, 0 -> assert false\r
-    | Vector exprs, 1 -> Array.length exprs\r
-    | _, 1 -> 0\r
-    | Vector exprs, _ when i > 1 -> size exprs.(0) (i - 1)\r
-    | _, _ -> assert false\r
-  and vector_mult exprs exprs' =\r
-    let exprs = ArrayExt.map2 evaluate_times exprs exprs' in\r
-    match Array.length exprs with\r
-    | 0 -> assert false\r
-    | 1 -> exprs.(0)\r
-    | n ->\r
-        let exprs' = Array.sub exprs 1 (n - 1) in\r
-        Array.fold_left evaluate_plus exprs.(0) exprs' in\r
-  match expr, expr' with\r
-  | Integer 0l, _ | _, Integer 0l -> Integer 0l\r
-  | Integer 1l, _ -> expr'\r
-  | _, Integer 1l -> expr\r
-  | Integer i, Integer i' -> Integer (Int32.mul i i')\r
-  | Integer i, Real f | Real f, Integer i -> Real (f *. Int32.to_float i)\r
-  | Real f, Real f' -> Real (f *. f')\r
-  | _, Vector exprs' when (ndims expr = 0) ->\r
-      Vector (Array.map (evaluate_times expr) exprs')\r
-  | Vector exprs, _ when (ndims expr' = 0) ->\r
-      Vector (Array.map (evaluate_times expr') exprs)\r
-  | Vector exprs, Vector exprs' when (ndims expr = 1) && (ndims expr' = 1) ->\r
-      vector_mult exprs exprs'\r
-  | Vector exprs, Vector exprs' when (ndims expr = 1) && (ndims expr' = 2) ->\r
-      let f j = vector_mult exprs (column exprs' j) in\r
-      Vector (Array.init (size expr' 2) f)\r
-  | Vector exprs, Vector exprs' when (ndims expr = 2) && (ndims expr' = 1) ->\r
-      let f i = vector_mult (line exprs i) exprs' in\r
-      Vector (Array.init (size expr 1) f)\r
-  | Vector exprs, Vector exprs' when (ndims expr = 2) && (ndims expr' = 2) ->\r
-      let f i j = vector_mult (line exprs i) (column exprs' j) in\r
-      let g i = Vector (Array.init (size expr' 2) (f i)) in\r
-      Vector (Array.init (size expr 1) g)\r
-  | _ -> BinaryOperation (Times, expr, expr')\r
-\r
-and evaluate_not_equal expr expr' = match expr, expr' with\r
-  | Integer i, Integer i' when i <> i' -> True\r
-  | Integer i, Real f | Real f, Integer i when f <> Int32.to_float i -> True\r
-  | Real f, Real f' when f <> f' -> True\r
-  | (Integer _ | Real _), (Integer _ | Real _) -> False\r
-  | Vector exprs, Vector exprs'\r
-    when\r
-      ArrayExt.exists2\r
-        (fun expr expr' -> evaluate_equalequal expr expr' = False)\r
-        exprs\r
-        exprs' -> True\r
-  | Vector _, Vector _ -> False\r
-  | _ -> BinaryOperation (NotEqual, expr, expr')\r
-\r
-and evaluate_or expr expr' = match expr, expr' with\r
-  | True, (False | True) | False, True -> True\r
-  | False, False -> False\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_or exprs exprs')\r
-  | _ -> BinaryOperation (Or, expr, expr')\r
-\r
-and evaluate_plus expr expr' = match expr, expr' with\r
-  | Integer 0l, _ -> expr'\r
-  | _, Integer 0l -> expr\r
-  | Integer i, Integer i' -> Integer (Int32.add i i')\r
-  | Integer i, Real f | Real f, Integer i -> Real (f +. Int32.to_float i)\r
-  | Real f, Real f' -> Real (f +. f')\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_plus exprs exprs')\r
-  | _ -> BinaryOperation (Plus, expr, expr')\r
-\r
-and evaluate_power ctx expr expr' =\r
-  match expr, expr' with\r
-  | (Integer 0l | Real 0.), (Integer 0l | Real 0.) ->\r
-      raise (InstantError\r
-        { err_msg = ["_ZeroRaisedToTheZeroPower"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | (Integer 0l | Real 0.), Integer i'\r
-    when Int32.compare i' 0l < 0 ->\r
-      raise (InstantError\r
-        { err_msg = ["_ZeroRaisedToNegativePower"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | (Integer 0l | Real 0.), Real f' when f' < 0. ->\r
-      raise (InstantError\r
-        { err_msg = ["_ZeroRaisedToNegativePower"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | Integer 0l, Integer _ ->\r
-      (* We know the answer for sure since second argument is constant *)\r
-      Real 0.\r
-  | (Integer 0l | Real 0.), (Integer _ | Real _) -> Real 0.\r
-  | Integer i, Real _ when Int32.compare i 0l < 0 ->\r
-      raise (InstantError\r
-        { err_msg = ["_RealExponentOfNegativeNumber"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | Real f, Real _ when f < 0. ->\r
-      raise (InstantError\r
-        { err_msg = ["_RealExponentOfNegativeNumber"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | Integer i, Integer i' ->\r
-      Real ((Int32.to_float i) ** (Int32.to_float i'))\r
-  | Integer i, Real f -> Real ((Int32.to_float i) ** f)\r
-  | Real f, Integer i' -> Real (f ** (Int32.to_float i'))\r
-  | Real f, Real f' -> Real (f ** f')\r
-  | Vector exprs, Integer i ->\r
-      raise (InstantError\r
-        { err_msg = ["_NotYetImplemented";\r
-                     "_VectorRaisedToIntegerPower"];\r
-          err_info = [];\r
-          err_ctx = ctx })\r
-  | _ -> BinaryOperation (Power, expr, expr')\r
-\r
-and evaluate_minus expr expr' = match expr, expr' with\r
-  | Integer 0l, _ -> evaluate_unary_minus expr'\r
-  | _, Integer 0l -> expr\r
-  | Integer i, Integer i' -> Integer (Int32.sub i i')\r
-  | Integer i, Real f -> Real (Int32.to_float i -. f)\r
-  | Real f, Integer i -> Real (f -. Int32.to_float i)\r
-  | Real f, Real f' -> Real (f -. f')\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_minus exprs exprs')\r
-  | _ -> BinaryOperation (Minus, expr, expr')\r
-\r
-and evaluate_class_function_invocation cl_def exprs =\r
-  FunctionCall (ClassReference cl_def, exprs)\r
-\r
-and evaluate_predefined_function_invocation ctx s exprs =\r
-  match s, exprs with\r
-  | "size", _ -> evaluate_size exprs\r
-  | "reinit", [expr; expr'] -> evaluate_reinit expr expr'\r
-  | "der", [expr] -> evaluate_der expr\r
-  | "pre", [expr] -> evaluate_pre expr\r
-  | ("edge" | "change" | "initial" | "terminal" | "sample" |\r
-    "delay" | "assert" | "terminate"), _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_NotYetImplemented"; "_PredefinedOperator"; s];\r
-          err_info = [];\r
-          err_ctx = ctx}) (*error*)\r
-  | "abs", [expr] -> evaluate_abs expr\r
-  | "sign", [expr] -> evaluate_sign expr\r
-  | "cos", [expr] -> evaluate_cos expr\r
-  | "sin", [expr] -> evaluate_sin expr\r
-  | "tan", [expr] -> evaluate_tan expr\r
-  | "exp", [expr] -> evaluate_exp expr\r
-  | "log", [expr] -> evaluate_log expr\r
-  | "sqrt", [expr] -> evaluate_sqrt expr\r
-  | "asin", [expr] -> evaluate_asin expr\r
-  | "acos", [expr] -> evaluate_acos expr\r
-  | "atan", [expr] -> evaluate_atan expr\r
-  | "sinh", [expr] -> evaluate_sinh expr\r
-  | "cosh", [expr] -> evaluate_cosh expr\r
-  | "tanh", [expr] -> evaluate_tanh expr\r
-  | "asinh", [expr] -> evaluate_asinh expr\r
-  | "acosh", [expr] -> evaluate_acosh expr\r
-  | "atanh", [expr] -> evaluate_atanh expr\r
-  | "log10", [expr] -> evaluate_log10 expr\r
-  | "max", [expr; expr'] -> evaluate_max expr expr'\r
-  | "min", [expr; expr'] -> evaluate_min expr expr'\r
-  | "div", [expr; expr'] -> evaluate_div ctx expr expr'\r
-  | "mod", [expr; expr'] -> evaluate_mod expr expr'\r
-  | "rem", [expr; expr'] -> evaluate_rem expr expr'\r
-  | "ceil", [expr] -> evaluate_ceil expr\r
-  | "floor", [expr] -> evaluate_floor expr\r
-  | "max", [expr] -> evaluate_max_array expr\r
-  | "min", [expr] -> evaluate_min_array expr\r
-  | "sum", [expr] -> evaluate_sum expr\r
-  | "product", [expr] -> evaluate_product expr\r
-  | "scalar", [expr] -> evaluate_scalar ctx expr\r
-  | "ones", exprs -> evaluate_ones ctx exprs\r
-  | "zeros", exprs -> evaluate_zeros ctx exprs\r
-  | "fill", expr :: exprs -> evaluate_fill ctx expr exprs\r
-  | "identity", [expr] -> evaluate_identity ctx expr\r
-  | "diagonal", [expr] -> evaluate_diagonal ctx expr\r
-  | "vector", [ expr ] -> evaluate_vector_operator ctx expr\r
-  | "matrix", [ expr ] -> evaluate_matrix_operator ctx expr\r
-  | "transpose", [ expr ] -> evaluate_transpose expr\r
-  | "symmetric", [ expr ] -> evaluate_symmetric ctx expr\r
-  | _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_UnknownFunction"; s];\r
-          err_info = [];\r
-          err_ctx = ctx}) (*error*)\r
-\r
-and evaluate_symmetric ctx expr = match expr with\r
-  | Vector [||] -> assert false\r
-  | Vector exprs when size exprs.(0) 0 <> Array.length exprs ->\r
-      raise (InstantError\r
-        { err_msg = ["_InvalidArgOfOper"; "symmetric"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | Vector exprs ->\r
-      let f i j =\r
-        if i > j then element i (element j expr)\r
-        else element j (element i expr) in\r
-      let n = Array.length exprs in\r
-      let g i = Vector (Array.init n (f i)) in\r
-      Vector (Array.init n g)\r
-   | _ -> assert false\r
-\r
-and evaluate_transpose expr =\r
-  match expr with\r
-  | Vector exprs  ->\r
-      let f i = Vector (Array.map (element i) exprs) in\r
-      Vector (Array.init (size expr 1) f)\r
-  | _ -> assert false\r
-\r
-and evaluate_matrix_operator ctx expr =\r
-  let rec scalar expr = match expr with\r
-    | Vector [| expr |] -> scalar expr\r
-    | Vector _ ->\r
-        raise (InstantError\r
-          { err_msg = ["_InvalidArgOfOper"; "matrix"];\r
-            err_info = [];\r
-            err_ctx = ctx }) (*error*)\r
-    | _ -> expr in\r
-  match expr with\r
-  | _ when ndims expr < 2 ->\r
-      evaluate_promote ctx 2 expr\r
-  | _ when ndims expr = 2 -> expr\r
-  | Vector exprs ->\r
-      let f expr = Vector (Array.map scalar (array_elements expr)) in\r
-      Vector (Array.map f exprs)\r
-  | _ -> assert false\r
-\r
-and evaluate_promote ctx n expr =\r
-  let rec evaluate_promote' i expr =\r
-    match expr with\r
-    | _ when i = 0 -> expr\r
-    | Vector exprs when i > 0 ->\r
-        Vector (Array.map (evaluate_promote' i) exprs)\r
-    | _ when i > 0 ->\r
-        Vector [| evaluate_promote' (i - 1) expr |]\r
-    | _ -> assert false in\r
-  match ndims expr with\r
-  | n' when n' < n ->\r
-      evaluate_promote' (n - n') expr\r
-  | _ -> expr\r
-\r
-and evaluate_vector_operator ctx expr =\r
-  let rec evaluate_scalar expr = match expr with\r
-    | Vector [| expr |] -> evaluate_scalar expr\r
-    | Vector _ ->\r
-        raise (InstantError\r
-          { err_msg = ["_InvalidArgOfOper"; "vector"];\r
-            err_info = [];\r
-            err_ctx = ctx }) (*error*)\r
-    | _ -> expr\r
-  and evaluate_vector_operator' expr = match expr with\r
-    | Vector [| expr |] -> evaluate_vector_operator' expr\r
-    | Vector exprs ->\r
-        Array.map evaluate_scalar exprs\r
-    | _ -> [| expr |] in\r
-  Vector (evaluate_vector_operator' expr)\r
-\r
-and evaluate_max_array expr =\r
-  let rec evaluate_max_list exprs = match exprs with\r
-    | [] -> assert false\r
-    | [ expr ] -> expr\r
-    | expr :: exprs ->\r
-        evaluate_max expr (evaluate_max_list exprs) in\r
-  evaluate_max_list (scalar_elements expr)\r
-\r
-and evaluate_min_array expr =\r
-  let rec evaluate_min_list exprs = match exprs with\r
-    | [] -> assert false\r
-    | [ expr ] -> expr\r
-    | expr :: exprs ->\r
-        evaluate_min expr (evaluate_min_list exprs) in\r
-  evaluate_min_list (scalar_elements expr)\r
-\r
-and evaluate_sum expr =\r
-  let rec evaluate_sum_list exprs = match exprs with\r
-    | [] -> Integer Int32.zero\r
-    | [ expr ] -> expr\r
-    | expr :: exprs ->\r
-        evaluate_plus expr (evaluate_sum_list exprs) in\r
-  match expr with\r
-  | Vector exprs ->\r
-      evaluate_sum_list (scalar_elements expr)\r
-  | _ -> assert false\r
-\r
-and evaluate_product expr =\r
-  let rec evaluate_product_list exprs = match exprs with\r
-    | [] -> Integer Int32.one\r
-    | [ expr ] -> expr\r
-    | expr :: exprs ->\r
-        evaluate_times expr (evaluate_product_list exprs) in\r
-  match expr with\r
-  | Vector exprs ->\r
-      evaluate_product_list (scalar_elements expr)\r
-  | _ -> assert false\r
-\r
-and evaluate_fill ctx expr exprs =\r
-  let rec evaluate_fill' dims = match dims with\r
-    | [] -> expr\r
-    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->\r
-      let i = Int32.to_int i in\r
-        Vector (Array.make i (evaluate_fill' dims))\r
-  | _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_InvalidArgOfOper"; "fill"];\r
-          err_info = [];\r
-            err_ctx = ctx }) (*error*) in\r
-  evaluate_fill' exprs\r
-\r
-and evaluate_zeros ctx exprs =\r
-  let rec evaluate_zeros' dims = match dims with\r
-    | [] -> Integer Int32.zero\r
-    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->\r
-      let i = Int32.to_int i in\r
-        Vector (Array.make i (evaluate_zeros' dims))\r
-  | _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_InvalidArgOfOper"; "zeros"];\r
-          err_info = [];\r
-            err_ctx = ctx }) (*error*) in\r
-  evaluate_zeros' exprs\r
-\r
-and evaluate_ones ctx exprs =\r
-  let rec evaluate_ones' dims = match dims with\r
-    | [] -> Integer Int32.one\r
-    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->\r
-      let i = Int32.to_int i in\r
-        Vector (Array.make i (evaluate_ones' dims))\r
-  | _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_InvalidArgOfOper"; "ones"];\r
-          err_info = [];\r
-            err_ctx = ctx }) (*error*) in\r
-  evaluate_ones' exprs\r
-\r
-and evaluate_identity ctx expr =\r
-  let n = match expr with\r
-    | Integer i when Int32.compare i Int32.zero > 0 ->\r
-        Int32.to_int i\r
-  | _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_InvalidArgOfOper"; "identity"];\r
-          err_info = [];\r
-            err_ctx = ctx }) (*error*) in\r
-  let f i j =\r
-    Integer (if j = i then Int32.one else Int32.zero) in\r
-  let g i = Vector (Array.init n (f i)) in\r
-  Vector (Array.init n g)\r
-\r
-and evaluate_diagonal ctx expr =\r
-  let exprs = match expr with\r
-    | Vector [||] ->\r
-      raise (InstantError\r
-        { err_msg = ["_InvalidArgOfOper"; "diagonal"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-    | Vector exprs -> exprs\r
-  | _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_InvalidArgOfOper"; "diagonal"];\r
-          err_info = [];\r
-            err_ctx = ctx }) (*error*) in\r
-  let n = Array.length exprs in\r
-  let f i j =\r
-    if j = i then exprs.(i) else Integer Int32.zero in\r
-  let g i = Vector (Array.init n (f i)) in\r
-  Vector (Array.init n g)\r
-\r
-and evaluate_scalar ctx expr =\r
-  let rec evaluate_scalar' expr = match expr with\r
-    | Vector [| expr |] -> evaluate_scalar' expr\r
-    | Vector _ ->\r
-        raise (InstantError\r
-          { err_msg = ["_InvalidArgOfOper"; "scalar"];\r
-            err_info = [];\r
-            err_ctx = ctx }) (*error*)\r
-    | _ -> expr in\r
-  match expr with\r
-  | Vector [| expr |] -> evaluate_scalar' expr\r
-  | _ ->\r
-      raise (InstantError\r
-        { err_msg = ["_InvalidArgOfOper"; "scalar"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-\r
-and evaluate_reinit expr expr' = match expr, expr' with\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_reinit exprs exprs')\r
-  | _, _ ->\r
-      FunctionCall (PredefinedIdentifier "reinit", [ expr; expr' ])\r
-\r
-and evaluate_der expr = match expr with\r
-  | Integer _ | String _ | Real _ -> Real 0.\r
-  | Vector exprs -> Vector (Array.map evaluate_der exprs)\r
-  | BinaryOperation (Plus, expr, expr') ->\r
-      let expr = evaluate_der expr\r
-      and expr' = evaluate_der expr' in\r
-      BinaryOperation (Plus, expr, expr')\r
-  | BinaryOperation (Minus, expr, expr') ->\r
-      let expr = evaluate_der expr\r
-      and expr' = evaluate_der expr' in\r
-      BinaryOperation (Minus, expr, expr')\r
-  | BinaryOperation (Times, expr1, expr2) ->\r
-      let expr1' = evaluate_der expr1\r
-      and expr2' = evaluate_der expr2 in\r
-      let expr1 = BinaryOperation (Times, expr1', expr2)\r
-      and expr2 = BinaryOperation (Times, expr1, expr2') in\r
-      BinaryOperation (Plus, expr1, expr2)\r
-  | BinaryOperation (Divide, expr1, expr2) ->\r
-      let expr1' = evaluate_der expr1\r
-      and expr2' = evaluate_der expr2 in\r
-      let expr1' = BinaryOperation (Times, expr1', expr2)\r
-      and expr2' = BinaryOperation (Times, expr1, expr2') in\r
-      let expr1 = BinaryOperation (Minus, expr1', expr2')\r
-      and expr2 = BinaryOperation (Times, expr2, expr2) in\r
-      BinaryOperation (Divide, expr1, expr2)\r
-  | BinaryOperation (Power, expr, Integer i) ->\r
-      let expr' = evaluate_der expr\r
-      and j = Int32.sub i Int32.one in\r
-      let expr' = BinaryOperation (Times, Integer i, expr')\r
-      and expr = BinaryOperation (Power, expr, Integer j) in\r
-      BinaryOperation (Times, expr', expr)\r
-  | BinaryOperation (Power, expr, Real f) ->\r
-      let expr' = evaluate_der expr\r
-      and f' = f -. 1. in\r
-      let expr' = BinaryOperation (Times, Real f, expr')\r
-      and expr = BinaryOperation (Power, expr, Real f') in\r
-      BinaryOperation (Times, expr', expr)\r
-  | FunctionCall (PredefinedIdentifier "cos", [ expr ]) ->\r
-      let expr' = evaluate_der expr\r
-      and expr = FunctionCall (PredefinedIdentifier "sin", [ expr ]) in\r
-      let expr = UnaryOperation (UnaryMinus, expr) in\r
-      BinaryOperation (Times, expr', expr)\r
-  | FunctionCall (PredefinedIdentifier "sin", [ expr ]) ->\r
-      let expr' = evaluate_der expr\r
-      and expr = FunctionCall (PredefinedIdentifier "cos", [ expr ]) in\r
-      BinaryOperation (Times, expr', expr)\r
-  | FunctionCall (PredefinedIdentifier "tan", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1\r
-      and expr = BinaryOperation (Times, expr, expr) in\r
-      let expr = BinaryOperation (Plus, Real 1., expr) in\r
-      BinaryOperation (Times, expr1', expr)\r
-  | FunctionCall (PredefinedIdentifier "exp", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      BinaryOperation (Times, expr1', expr)\r
-  | FunctionCall (PredefinedIdentifier "log", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      BinaryOperation (Divide, expr1', expr)\r
-  | FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) ->\r
-      evaluate_der (BinaryOperation (Power, expr1, Real 0.5))\r
-  | FunctionCall (PredefinedIdentifier "asin", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      let expr1 = BinaryOperation (Times, expr1, expr1) in\r
-      let expr1 = BinaryOperation (Minus, Real 1., expr1) in\r
-      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in\r
-      BinaryOperation (Divide, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "acos", [ expr1 ]) ->\r
-      let expr1' = UnaryOperation (UnaryMinus, evaluate_der expr1) in\r
-      let expr1 = BinaryOperation (Times, expr1, expr1) in\r
-      let expr1 = BinaryOperation (Minus, Real 1., expr1) in\r
-      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in\r
-      BinaryOperation (Divide, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "atan", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      let expr1 = BinaryOperation (Times, expr1, expr1) in\r
-      let expr1 = BinaryOperation (Plus, Real 1., expr1) in\r
-      BinaryOperation (Divide, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "sinh", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      let expr1 = FunctionCall (PredefinedIdentifier "cosh", [ expr1 ]) in\r
-      BinaryOperation (Times, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "cosh", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      let expr1 = FunctionCall (PredefinedIdentifier "sinh", [ expr1 ]) in\r
-      BinaryOperation (Times, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "tanh", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      let expr1 = BinaryOperation (Times, expr, expr) in\r
-      let expr1 = BinaryOperation (Minus, Real 1., expr1) in\r
-      BinaryOperation (Times, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "asinh", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      let expr1 = BinaryOperation (Times, expr1, expr1) in\r
-      let expr1 = BinaryOperation (Plus, Real 1., expr1) in\r
-      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in\r
-      BinaryOperation (Divide, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "acosh", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      let expr1 = BinaryOperation (Times, expr1, expr1) in\r
-      let expr1 = BinaryOperation (Minus, expr1, Real 1.) in\r
-      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in\r
-      BinaryOperation (Divide, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "atanh", [ expr1 ]) ->\r
-      let expr1' = evaluate_der expr1 in\r
-      let expr1 = BinaryOperation (Times, expr1, expr1) in\r
-      let expr1 = BinaryOperation (Minus, expr1, Real 1.) in\r
-      BinaryOperation (Divide, expr1', expr1)\r
-  | FunctionCall (PredefinedIdentifier "log10", [ expr1 ]) ->\r
-      let expr1 = FunctionCall (PredefinedIdentifier "log", [ expr1 ]) in\r
-      BinaryOperation (Divide, evaluate_der expr1, Real (log 10.))\r
-  | FunctionCall\r
-      (PredefinedIdentifier ("div" | "mod" | "rem" | "ceil" | "floor"), _) ->\r
-      Real 0.\r
-  | If (alts, default) ->\r
-      let alts' =\r
-        List.map (function (cond, expr) -> (cond, evaluate_der expr)) alts in\r
-      If (alts', evaluate_der default)\r
-  | NoEvent expr -> NoEvent (evaluate_der expr)\r
-  | UnaryOperation (UnaryMinus, expr) ->\r
-      UnaryOperation (UnaryMinus, evaluate_der expr)\r
-  | VectorReduction (exprs, expr) ->\r
-      VectorReduction (exprs, evaluate_der expr)\r
-  | _ -> FunctionCall (PredefinedIdentifier "der", [ expr ])\r
-\r
-and evaluate_pre expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_pre exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "pre", [ expr ])\r
-\r
-and evaluate_cos expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_cos exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "cos", [ expr ])\r
-\r
-and evaluate_sin expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_sin exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "sin", [ expr ])\r
-\r
-and evaluate_tan expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_tan exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "tan", [ expr ])\r
-\r
-and evaluate_exp expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_exp exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "exp", [ expr ])\r
-\r
-and evaluate_log expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_log exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "log", [ expr ])\r
-\r
-and evaluate_sqrt expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_sqrt exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "sqrt", [ expr ])\r
-\r
-and evaluate_asin expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_asin exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "asin", [ expr ])\r
-\r
-and evaluate_acos expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_acos exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "acos", [ expr ])\r
-\r
-and evaluate_atan expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_atan exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "atan", [ expr ])\r
-\r
-and evaluate_sinh expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_sinh exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "sinh", [ expr ])\r
-\r
-and evaluate_cosh expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_cosh exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "cosh", [ expr ])\r
-\r
-and evaluate_tanh expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_tanh exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "tanh", [ expr ])\r
-\r
-and evaluate_asinh expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_asinh exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "asinh", [ expr ])\r
-\r
-and evaluate_acosh expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_acosh exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "acosh", [ expr ])\r
-\r
-and evaluate_atanh expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_atanh exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "atanh", [ expr ])\r
-\r
-and evaluate_log10 expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_log10 exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "log10", [ expr ])\r
-\r
-and evaluate_max expr expr' = match expr, expr' with\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_max exprs exprs')\r
-  | Real f, Real f' -> Real (max f f')\r
-  | _, _ ->\r
-      let b = BinaryOperation (GreaterEqual, expr, expr') in\r
-      If ([b, expr], expr')\r
-\r
-and evaluate_min expr expr' = match expr, expr' with\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_min exprs exprs')\r
-  | Real f, Real f' -> Real (min f f')\r
-  | _, _ ->\r
-      let b = BinaryOperation (GreaterEqual, expr', expr) in\r
-      If ([b, expr], expr')\r
-\r
-and evaluate_abs expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_abs exprs)\r
-  | Real f -> Real (abs_float f)\r
-  | Integer i -> Integer (Int32.abs i)\r
-  | _ ->\r
-      let b = BinaryOperation (GreaterEqual, expr, Real 0.)\r
-      and default = UnaryOperation (UnaryMinus, expr) in\r
-      If ([b, expr], default)\r
-\r
-and evaluate_sign expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_sign exprs)\r
-  | Real f when f > 0. -> Real 1.\r
-  | Real f when f < 0. -> Real (-. 1.)\r
-  | Real _ -> Real 0.\r
-  | Integer i when Int32.compare i Int32.zero > 0 ->\r
-      Integer Int32.one\r
-  | Integer i when Int32.compare i Int32.zero < 0 ->\r
-      Integer Int32.minus_one\r
-  | Integer _ -> Integer Int32.zero\r
-  | _ ->\r
-      let b = BinaryOperation (Greater, expr, Real 0.)\r
-      and b' = BinaryOperation (Greater, Real 0., expr) in\r
-      If ([(b, Integer Int32.one); (b', Integer Int32.minus_one)],\r
-          Integer Int32.zero)\r
-\r
-and evaluate_div ctx expr expr' = match expr, expr' with\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 (evaluate_div ctx) exprs exprs')\r
-  | _, Real 0. ->\r
-      raise (InstantError\r
-        { err_msg = ["_DivisionByZero"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | _, Integer i when i = Int32.zero ->\r
-      raise (InstantError\r
-        { err_msg = ["_DivisionByZero"];\r
-          err_info = [];\r
-          err_ctx = ctx }) (*error*)\r
-  | Integer i, Integer i' -> Integer (Int32.div i i')\r
-  | Real f, Integer i' ->\r
-      let f' = Int32.to_float i' in\r
-      Real (float_of_int (truncate (f /. f')))\r
-  | Integer i, Real f' ->\r
-      let f = Int32.to_float i in\r
-      Real (float_of_int (truncate (f /. f')))\r
-  | Real f, Real f' ->\r
-      Real (float_of_int (truncate (f /. f')))\r
-  | _, _ ->\r
-      FunctionCall (PredefinedIdentifier "div", [ expr; expr' ])\r
-\r
-and evaluate_mod expr expr' = match expr, expr' with\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_mod exprs exprs')\r
-  | _, _ ->\r
-      FunctionCall (PredefinedIdentifier "mod", [ expr; expr' ])\r
-\r
-and evaluate_rem expr expr' = match expr, expr' with\r
-  | Vector exprs, Vector exprs' ->\r
-      Vector (ArrayExt.map2 evaluate_rem exprs exprs')\r
-  | _, _ ->\r
-      FunctionCall (PredefinedIdentifier "rem", [ expr; expr' ])\r
-\r
-and evaluate_ceil expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_ceil exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "ceil", [ expr ])\r
-\r
-and evaluate_floor expr = match expr with\r
-  | Vector exprs ->\r
-      Vector (Array.map evaluate_floor exprs)\r
-  | _ ->\r
-      FunctionCall (PredefinedIdentifier "floor", [ expr ])\r
-\r
-and evaluate_size exprs =\r
-  let rec evaluate_size' expr i = match expr, i with\r
-    | ComponentReference cpnt_desc, _ ->\r
-        evaluate_component_size cpnt_desc i\r
-    | Vector exprs, 1 -> Integer (Int32.of_int (Array.length exprs))\r
-    | Vector exprs, _ -> evaluate_size' exprs.(0) (i - 1)\r
-    | _ -> assert false (*error*)\r
-  and evaluate_component_size cpnt_desc i =\r
-    match evaluate cpnt_desc.component_nature, i with\r
-      | DynamicArray _, _ -> FunctionCall (PredefinedIdentifier "size", exprs)\r
-      | StaticArray cpnt_descs, 1 ->\r
-          Integer (Int32.of_int (Array.length cpnt_descs))\r
-      | StaticArray cpnt_descs, _ ->\r
-          evaluate_component_size cpnt_descs.(i) (i - 1)\r
-      | _ -> assert false (*error*)\r
-  and evaluate_size_list = function\r
-    | ComponentReference cpnt_desc -> assert false\r
-    | Vector exprs ->\r
-        let size = Integer (Int32.of_int (Array.length exprs)) in\r
-        size :: evaluate_size_list exprs.(0)\r
-    | _ -> [] in\r
-  match exprs with\r
-    | [expr] -> Vector (Array.of_list (evaluate_size_list expr))\r
-    | [expr; Integer i] -> evaluate_size' expr (Int32.to_int i)\r
-    | [expr; _] -> FunctionCall (PredefinedIdentifier "size", exprs)\r
-    | _ -> assert false (*error*)\r
-\r
-and evaluate_not expr = match expr with\r
-  | True -> False\r
-  | False -> True\r
-  | Vector exprs -> Vector (Array.map evaluate_not exprs)\r
-  | _ -> UnaryOperation (Not, expr)\r
-\r
-and evaluate_unary_minus expr = match expr with\r
-  | Integer i -> Integer (Int32.neg i)\r
-  | Real f -> Real (~-. f)\r
-  | Vector exprs -> Vector (Array.map evaluate_unary_minus exprs)\r
-  | _ -> UnaryOperation (UnaryMinus, expr)\r
-\r
-and field_access ctx expr id =\r
-  let rec field_access' = function\r
-    | ClassReference cl_def ->\r
-        let cpnt_desc = create_temporary_instance ctx cl_def in\r
-        component_field_access cpnt_desc\r
-    | ComponentReference cpnt_desc -> component_field_access cpnt_desc\r
-    | Record fields -> List.assoc id fields\r
-    | Vector exprs -> Vector (Array.map field_access' exprs)\r
-    | _ -> FieldAccess (expr, id)\r
-  and component_field_access cpnt_desc =\r
-    match evaluate cpnt_desc.component_nature with\r
-      | DynamicArray _ -> FieldAccess (expr, id)\r
-      | Instance inst -> instance_field_access ctx inst id\r
-      | PredefinedTypeInstance _ ->\r
-          raise (InstantError\r
-            { err_msg = ["_CannotAccessToPredefTypeAttrib"; id];\r
-              err_info = [];\r
-              err_ctx = ctx}) (*error*)\r
-      | StaticArray cpnt_descs ->\r
-          Vector (Array.map component_field_access cpnt_descs) in\r
-  field_access' expr\r
-\r
-and instance_field_access ctx inst id =\r
-  let evaluate_component cpnt_desc =\r
-    let evaluate_declaration_equation = function\r
-      | Some expr -> evaluate expr\r
-      | None ->\r
-          raise (InstantError\r
-            { err_msg = ["_MissingDeclEquForFixedId"; id];\r
-              err_info = [];\r
-              err_ctx = ctx}) (*error*) in\r
-    let rec evaluate_parameter cpnt_desc =\r
-      let evaluate_predefined_type_instance predef =\r
-        match evaluate (List.assoc "fixed" predef.attributes) with\r
-        | True -> evaluate_declaration_equation cpnt_desc.declaration_equation\r
-        | False -> ComponentReference cpnt_desc\r
-        | _ -> assert false (*error*) in\r
-      match evaluate cpnt_desc.component_nature with\r
-      | PredefinedTypeInstance predef\r
-        when List.mem_assoc "fixed" predef.attributes ->\r
-          evaluate_predefined_type_instance predef\r
-      | DynamicArray cpnt_desc -> assert false\r
-      | Instance _ -> ComponentReference cpnt_desc\r
-      | PredefinedTypeInstance _ ->\r
-          evaluate_declaration_equation cpnt_desc.declaration_equation\r
-      | StaticArray cpnt_descs ->\r
-          Vector (Array.map evaluate_parameter cpnt_descs)\r
-          (*let f i =\r
-            let decl_equ = cpnt_descs.(i).declaration_equation in\r
-            evaluate_declaration_equation decl_equ in\r
-          Vector (Array.init (Array.length cpnt_descs) f)*) in\r
-    match cpnt_desc.variability with\r
-      | Types.Constant ->\r
-          evaluate_declaration_equation cpnt_desc.declaration_equation\r
-      | Types.Parameter -> evaluate_parameter cpnt_desc\r
-      | _ -> ComponentReference cpnt_desc in\r
-  let elts = evaluate inst.elements in\r
-  let elt_desc = List.assoc id elts.named_elements in\r
-  match evaluate elt_desc.element_nature with\r
-  | Class cl_def -> ClassReference cl_def\r
-  | Component cpnt_desc -> evaluate_component cpnt_desc\r
-\r
-and expression_location ctx expr =\r
-  match expr.NameResolve.info.NameResolve.syntax with\r
-    | None -> ctx.location\r
-    | Some expr -> expr.Syntax.info\r
-\r
-and class_name_of_component cpnt_desc =\r
-  let type_spec = Lazy.force cpnt_desc.NameResolve.type_specifier in\r
-  let expr_info = type_spec.NameResolve.info in\r
-  match expr_info.NameResolve.syntax with\r
-  | None -> ""\r
-  | Some expr -> Syntax.string_of_expression expr\r
-\r
-and instance_nature_of_element elt_desc =\r
-  match elt_desc.NameResolve.element_nature with\r
-    | NameResolve.Component cpnt_desc ->\r
-        ComponentElement (class_name_of_component cpnt_desc)\r
-    | _ -> ClassElement\r
-\r
-and instance_class_name instance_nature =\r
-  match instance_nature with\r
-    | ComponentElement s -> s\r
-    | ClassElement -> ""\r
-\r
-and flatten_expression expr =\r
-  let rec flatten_component cpnt_desc =\r
-    match evaluate cpnt_desc.component_nature with\r
-    | StaticArray cpnt_descs ->\r
-        Vector (Array.map flatten_component cpnt_descs)\r
-    | _ -> ComponentReference cpnt_desc in\r
-  match expr with\r
-  | ComponentReference cpnt_desc ->\r
-      flatten_component cpnt_desc\r
-  | _ -> expr\r
-\r
-and size expr i = match expr, i with\r
-  | Vector [||], _ -> 0\r
-  | Vector exprs, 0 -> Array.length exprs\r
-  | Vector exprs, _ when i > 0 -> size exprs.(0) (i - 1)\r
-  | _ -> invalid_arg "_IndexOutOfBound"\r
-\r
-and sizes expr =\r
-  Array.init (ndims expr) (size expr)\r
-\r
-and ndims expr =\r
-  let rec ndims' i expr = match expr with\r
-    | Vector [||] -> i + 1\r
-    | Vector exprs -> ndims' (i + 1) exprs.(0)\r
-    | _ -> i in\r
-  ndims' 0 expr\r
-\r
-and element i expr = match expr with\r
-  | Vector exprs -> exprs.(i)\r
-  | _ -> assert false\r
-\r
-and array_elements expr = match expr with\r
-  | Vector exprs -> exprs\r
-  | _ -> assert false\r
-\r
-and scalar_elements expr = match expr with\r
-  | Vector exprs ->\r
-      let exprss =\r
-        Array.to_list (Array.map scalar_elements exprs) in\r
-      List.flatten exprss\r
-  | _ -> [ expr ]\r
-\r
-(* for debug*)\r
-\r
-and generate_expression oc = function\r
-  | BinaryOperation (bin_op, expr, expr') ->\r
-      generate_binary_operation oc bin_op expr expr'\r
-  | ClassReference cl_def ->\r
-      generate_class_reference oc cl_def\r
-  | ComponentReference cpnt_desc ->\r
-      generate_component_reference oc cpnt_desc\r
-  | EnumerationElement _ -> assert false\r
-  | False -> assert false\r
-  | FieldAccess _ -> assert false\r
-  | FunctionCall (expr, exprs) ->\r
-      generate_function_call oc expr exprs\r
-  | If (alts, expr) -> generate_if oc alts expr\r
-  | IndexedAccess _ -> assert false\r
-  | Integer i when Int32.to_int i >= 0 ->\r
-      Printf.fprintf oc "%ld" i\r
-  | Integer i ->\r
-      let expr = Integer (Int32.neg i)\r
-      and un_op = UnaryMinus in\r
-      generate_unary_operation oc un_op expr\r
-  | LoopVariable _ -> Printf.fprintf oc "LoopVariable"\r
-  | NoEvent expr -> generate_no_event oc expr\r
-  | PredefinedIdentifier id -> Printf.fprintf oc "%s" id\r
-  | Range _ -> Printf.fprintf oc "Range"\r
-  | Real f ->\r
-      Printf.fprintf oc "%s" (string_of_float f)\r
-  | Record _ -> Printf.fprintf oc "Record"\r
-  | String _ -> Printf.fprintf oc "String"\r
-  | True -> Printf.fprintf oc "True"\r
-  | Tuple _ -> Printf.fprintf oc "Tuple"\r
-  | UnaryOperation (un_op, expr) ->\r
-      generate_unary_operation oc un_op expr\r
-  | Vector exprs ->\r
-      generate_vector oc exprs\r
-  | VectorReduction _ -> Printf.fprintf oc "VectorReduction"\r
-\r
-and generate_binary_operation oc bin_op expr expr' =\r
-  let string_of_binary_operation_kind = function\r
-    | And -> "and"\r
-    | Divide -> "/"\r
-    | EqualEqual -> "=="\r
-    | GreaterEqual -> ">="\r
-    | Greater -> ">"\r
-    | LessEqual -> "<="\r
-    | Less -> "<"\r
-    | Times -> "*"\r
-    | NotEqual -> "<>"\r
-    | Or -> "or"\r
-    | Plus -> "+"\r
-    | Power -> "^"\r
-    | Minus -> "-" in\r
-  Printf.fprintf oc "(";\r
-  generate_expression oc expr;\r
-  Printf.fprintf oc " %s " (string_of_binary_operation_kind bin_op);\r
-  generate_expression oc expr';\r
-  Printf.fprintf oc ")"\r
-\r
-and generate_class_reference oc cl_def =\r
-  let rec last = function\r
-    | [] -> assert false\r
-    | [Name id] -> id\r
-    | [Index _] -> assert false\r
-    | _ :: path -> last path in\r
-  let generate_external_call ext_call =\r
-    match ext_call.NameResolve.nature with\r
-      | NameResolve.PrimitiveCall "builtin" ->\r
-          Printf.fprintf oc "builtin"\r
-      | NameResolve.PrimitiveCall "C" ->\r
-          Printf.fprintf oc "PrimitiveCall"\r
-      | NameResolve.PrimitiveCall lang -> assert false\r
-      | NameResolve.ExternalProcedureCall _ -> assert false in\r
-  let generate_long_dscription long_desc =\r
-    match evaluate long_desc.NameResolve.external_call with\r
-      | None -> assert false\r
-      | Some ext_call -> generate_external_call ext_call in\r
-  match cl_def.description with\r
-    | ClassDescription (_, cl_desc) ->\r
-        generate_long_dscription cl_desc.long_description\r
-    | PredefinedType _ -> assert false\r
-\r
-and generate_component_reference oc cpnt_desc =\r
-  let name = ident_of_path cpnt_desc.component_path in\r
-  Printf.fprintf oc "%s" name\r
-\r
-and generate_function_call oc expr exprs =\r
-  generate_expression oc expr;  \r
-  Printf.fprintf oc "(";\r
-  generate_expressions oc exprs;\r
-  Printf.fprintf oc ")"\r
-\r
-and generate_expressions oc = function\r
-  | [] -> ()\r
-  | [expr] -> generate_expression oc expr;\r
-  | expr :: exprs ->\r
-      generate_expression oc expr;\r
-      Printf.fprintf oc ", ";\r
-      generate_expressions oc exprs\r
-\r
-and generate_if oc alts expr =\r
-  let rec generate_alternatives = function\r
-    | [] -> Printf.fprintf oc " "; generate_expression oc expr\r
-    | (expr, expr') :: alts ->\r
-        Printf.fprintf oc "(if ";\r
-        generate_expression oc expr;\r
-        Printf.fprintf oc " then ";\r
-        generate_expression oc expr';\r
-        Printf.fprintf oc " else";\r
-        generate_alternatives alts;\r
-        Printf.fprintf oc ")" in\r
-  generate_alternatives alts\r
-\r
-and generate_no_event oc expr =\r
-  Printf.fprintf oc "noEvent(";\r
-  generate_expression oc expr;\r
-  Printf.fprintf oc ")"\r
-\r
-and generate_unary_operation oc un_op expr =\r
-  let string_of_unary_operation_kind = function\r
-    | Not -> "not"\r
-    | UnaryMinus -> "-" in\r
-  Printf.fprintf oc "(%s " (string_of_unary_operation_kind un_op);\r
-  generate_expression oc expr;\r
-  Printf.fprintf oc ")"\r
-\r
-and generate_vector oc exprs =\r
-  let exprs' = Array.to_list exprs in\r
-  Printf.fprintf oc "{ ";\r
-  generate_expressions oc exprs';\r
-  Printf.fprintf oc " }"\r
-\r
-and last_id path =\r
-  let rec last_id' id path = match path with\r
-    | [] -> id\r
-    | (Name id) :: path -> last_id' id path\r
-    | (Index _) :: path -> last_id' id path in\r
-  last_id' "" path\r
-\r
-and string_of_float f =\r
-  let add_parenthesis s =\r
-    if String.contains s '-' then Printf.sprintf "(%s)" s else s in\r
-  match Printf.sprintf "%.16g" f with\r
-  | s when (String.contains s '.') || (String.contains s 'e') ->\r
-      add_parenthesis s\r
-  | s -> add_parenthesis (Printf.sprintf "%s." s)\r
-\r
-and ident_of_path path =\r
-  let rec ident_of_path' path =\r
-    match path with\r
-    | [] -> assert false\r
-    | [Name id] -> id\r
-    | [Index i] -> Printf.sprintf "[%d]" (i + 1)\r
-    | Name id :: path ->\r
-        Printf.sprintf "%s.%s" id (ident_of_path' path)\r
-    | Index i :: path ->\r
-        Printf.sprintf "[%d].%s" (i + 1) (ident_of_path' path) in\r
-  match path with\r
-  | [] -> assert false\r
-  | [Name id] -> assert false\r
-  | [Index i] -> assert false\r
-  | Name id :: path ->\r
-      Printf.sprintf "`%s`" (ident_of_path' path)\r
-  | Index i :: path -> assert false\r
-\r
+(*
+ *  Translator from Modelica 2.x to flat Modelica
+ *
+ *  Copyright (C) 2005 - 2007 Imagine S.A.
+ *  For more information or commercial use please contact us at www.amesim.com
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *)
+
+type ('a, 'b) node =
+  {
+    nature: 'a;
+    info: 'b
+  }
+
+type instance =
+  {
+    enclosing_instance: instance option;
+    kind: Types.kind;
+    elements: instance_elements Lazy.t
+  }
+
+and instance_elements =
+  {
+    named_elements: (string * element_description) list;
+    unnamed_elements: equation_or_algorithm_clause list
+  }
+
+and element_description =
+  {
+    redeclare: bool;
+    element_nature: element_nature Lazy.t
+  }
+
+and element_nature =
+  | Class of class_definition
+  | Component of component_description
+
+and class_definition =
+  {
+    class_type: Types.class_specifier;
+    class_path: path;
+    class_flow: bool option;
+    class_variability: Types.variability option;
+    class_causality: Types.causality option;
+    description: description;
+    modification: modification_argument list;
+    class_location: Parser.location
+  }
+
+and path = path_element list
+
+and path_element =
+  | Name of string
+  | Index of int
+
+and description =
+  | ClassDescription of context * class_description
+  | PredefinedType of predefined_type
+
+and class_description =
+  {
+    class_kind: Types.kind;
+    class_annotations: (annotation list) Lazy.t;
+    long_description: NameResolve.long_description
+  }
+
+and annotation =
+  | InverseFunction of inverse_function Lazy.t
+  | UnknownAnnotation of Parser.location Syntax.class_modification Lazy.t
+
+and inverse_function =
+  {
+    function_class: class_definition;
+    arguments: (string * string) list
+  }
+
+and class_modification = (string * modification_argument) list
+
+and modification_argument =
+  {
+    each: bool;
+    action: modification_action
+  }
+
+and modification_action =
+  | ElementModification of modification
+  | ElementRedeclaration of element_description
+
+and modification =
+  | Modification of class_modification * expression Lazy.t option
+  | Assignment of expression Lazy.t
+  | Equality of expression Lazy.t
+
+and component_description =
+  {
+    component_path: path;
+    flow: bool;
+    variability: Types.variability;
+    causality: Types.causality;
+    component_nature: component_nature Lazy.t;
+    declaration_equation: expression Lazy.t option;
+    comment: string;
+    component_location: Parser.location;
+    class_name: string
+  }
+
+and component_nature =
+  | DynamicArray of component_description
+      (* one representative member of the collection *)
+  | Instance of instance
+  | PredefinedTypeInstance of predefined_type_instance
+  | StaticArray of component_description array
+
+and predefined_type_instance =
+  {
+    predefined_type: predefined_type;
+    attributes: (string * expression Lazy.t) list
+  }
+
+and predefined_type =
+  | BooleanType
+  | IntegerType
+  | RealType
+  | StringType
+  | EnumerationType
+
+and equation_or_algorithm_clause =
+  | EquationClause of NameResolve.validity * equation list Lazy.t
+  | AlgorithmClause of NameResolve.validity * algorithm list Lazy.t
+
+and validity = Initial | Permanent
+
+and equation = (equation_desc list, NameResolve.equation) node
+
+and equation_desc =
+  | Equal of expression * expression
+  | ConditionalEquationE of (expression * equation list) list *
+      equation list
+  | ConnectFlows of NameResolve.sign * expression *
+      NameResolve.sign * expression
+  | WhenClauseE of (expression * equation list) list
+
+and algorithm = (algorithm_desc list, NameResolve.algorithm) node
+
+and algorithm_desc =
+  | Assign of expression * expression
+  | FunctionCallA of expression * expression list
+  | MultipleAssign of expression list * expression * expression list
+  | Break
+  | Return
+  | ConditionalEquationA of (expression * algorithm list) list *
+      algorithm list
+  | ForClauseA of expression (* range *) * algorithm list
+  | WhileClause of expression * algorithm list
+  | WhenClauseA of (expression * algorithm list) list
+
+and expression =
+  | BinaryOperation of binary_operator_kind * expression * expression
+  | ClassReference of class_definition
+  | ComponentReference of component_description
+  | EnumerationElement of string
+  | False
+  | FieldAccess of expression * string
+  | FunctionCall of expression * expression list
+  | If of (expression (* condition *) * expression) list *
+      expression (* default *)
+  | IndexedAccess of expression * expression list (* subscripts *)
+  | Integer of int32
+  | LoopVariable of int (* number of nested for loops to skip *)
+  | NoEvent of expression
+  | PredefinedIdentifier of string
+  | Range of expression * expression * expression
+  | Real of float
+  | Record of (string * expression) list
+  | String of string
+  | True
+  | Tuple of expression list
+  | UnaryOperation of unary_operator_kind * expression
+  | Vector of expression array
+  | VectorReduction of expression list (* ranges *) * expression
+
+and unary_operator_kind =
+  | Not
+  | UnaryMinus
+
+and binary_operator_kind =
+  | And
+  | Divide
+  | EqualEqual
+  | GreaterEqual
+  | Greater
+  | LessEqual
+  | Less
+  | Times
+  | NotEqual
+  | Or
+  | Plus
+  | Power
+  | Minus
+
+and context =
+  {
+    toplevel: (string * element_description) list Lazy.t;
+    path: path;
+    context_flow: bool option;
+    context_variability: Types.variability option;
+    context_causality: Types.causality option;
+    parent_context: context option; (* for normal parent scope lookup *)
+    class_context: context_nature; (* for normal (class-based) lookup *)
+    instance_context: instance option; (* for dynamically scoped identifiers *)
+    location: Parser.location;
+    instance_nature: instance_nature
+  }
+
+and context_nature =
+  | ToplevelContext
+  | InstanceContext of instance
+  | ForContext of context *
+      expression option (* current value of the loop variable, if available *)
+  | FunctionEvaluationContext of context * expression * expression list
+
+(* Error description *)
+and error_description =
+  {
+    err_msg: string list;
+    err_info: (string * string) list;
+    err_ctx: context
+  }
+
+and instance_nature =
+  | ClassElement
+  | ComponentElement of string
+
+exception InstantError of error_description
+
+
+(* Utilities *)
+
+let levels = ref 0
+
+let spaces () = for i = 1 to !levels do Printf.printf "  " done
+
+let nest i =
+  spaces (); Printf.printf "ForContext %ld\n" i;
+  incr levels
+
+let nest2 i =
+  spaces (); Printf.printf "ReductionContext %ld\n" i;
+  incr levels
+
+let unnest () =
+  decr levels;
+  spaces (); Printf.printf "Leaving ForContext\n"
+
+let evaluate x = Lazy.force x
+
+module ArrayExt =
+  struct
+    let map2 f a a' =
+      let l = Array.length a
+      and l' = Array.length a' in
+      if l <> l' then invalid_arg "ArrayExt.map2"
+      else begin
+        let create_array i = f a.(i) a'.(i) in
+        Array.init l create_array
+      end
+    let for_all2 f a a' =
+      let l = Array.length a
+      and l' = Array.length a' in
+      if l <> l' then invalid_arg "ArrayExt.for_all2"
+      else begin
+        let rec for_all2' i =
+          i = l || (f a.(i) a'.(i) && for_all2' (i + 1)) in
+        for_all2' 0
+      end
+    let exists2 f a a' =
+      let l = Array.length a
+      and l' = Array.length a' in
+      if l <> l' then invalid_arg "ArrayExt.exists2"
+      else begin
+        let rec exists2' i =
+          i < l && (f a.(i) a'.(i) || exists2' (i + 1)) in
+        exists2' 0
+      end
+  end
+
+
+(* Instantiation functions *)
+
+let rec evaluate_toplevel_definitions dic defs =
+  let rec ctx =
+    {
+      toplevel = lazy (dic @ evaluate defs');
+      path = [];
+      context_flow = None;
+      context_variability = None;
+      context_causality = None;
+      parent_context = None;
+      class_context = ToplevelContext;
+      instance_context = None;
+      location = {Parser.start = 0; Parser.enddd = 0; filename = Parser.CommandLine};
+      instance_nature = ClassElement
+    }
+  and defs' = lazy (List.map (evaluate_toplevel_definition ctx) defs) in
+  evaluate defs'
+
+and evaluate_toplevel_definition ctx (id, elt_desc) =
+  let elt_loc = [Name id] in
+  let ctx = {ctx with
+               path = elt_loc;
+               location = elt_desc.NameResolve.element_location;
+               instance_nature = instance_nature_of_element elt_desc} in
+  let elt_nat = elt_desc.NameResolve.element_nature in
+  let elt_desc' =
+    {
+      redeclare = false;
+      element_nature = lazy (evaluate_toplevel_element ctx elt_loc elt_nat)
+    } in
+  id, elt_desc'
+
+and evaluate_toplevel_element ctx elt_loc = function
+  | NameResolve.Component cpnt_desc ->
+      let cpnt_desc' =
+        instantiate_component_description ctx [] None elt_loc cpnt_desc in
+      Component cpnt_desc'
+  | NameResolve.Class cl_def ->
+      let cl_def' = evaluate_class_definition ctx [] elt_loc cl_def in
+      Class cl_def'
+  | NameResolve.ComponentType _ ->
+      raise (InstantError
+        { err_msg = ["_NotYetImplemented"; "_ComponentTypeElemInstant"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | NameResolve.PredefinedType _ ->
+      raise (InstantError
+        { err_msg = ["_NotYetImplemented"; "_PredefinedTypeElemInstant"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+
+and instantiate_class_description ctx modifs rhs elt_loc cl_desc =
+  let elements inst =
+    let ctx' =
+      { ctx with
+        toplevel = lazy (evaluate ctx.toplevel);
+        path = elt_loc;
+        parent_context = Some ctx;
+        class_context = InstanceContext inst;
+        instance_context = None
+      } in
+    instantiate_class_elements ctx' modifs rhs cl_desc.long_description in
+  let rec inst =
+    {
+      enclosing_instance = enclosing_instance ctx;
+      kind = cl_desc.class_kind;
+      elements = lazy (elements inst)
+    } in
+  inst
+
+and enclosing_instance ctx = match ctx.class_context with
+  | ToplevelContext -> None
+  | InstanceContext inst -> Some inst
+  | ForContext (ctx', _) | FunctionEvaluationContext (ctx', _, _) ->
+      enclosing_instance ctx'
+
+and instantiate_class_elements ctx modifs rhs long_desc =
+  let rec merge_elements named_elts unnamed_elts = function
+    | [] ->
+        {
+          named_elements = named_elts;
+          unnamed_elements = unnamed_elts
+        }
+    | inherited_elts :: inherited_eltss ->
+        let named_elts' = named_elts @ inherited_elts.named_elements
+        and unnamed_elts' = unnamed_elts @ inherited_elts.unnamed_elements in
+        merge_elements named_elts' unnamed_elts' inherited_eltss in
+  let named_elts = long_desc.NameResolve.named_elements
+  and unnamed_elts = long_desc.NameResolve.unnamed_elements
+  and exts = long_desc.NameResolve.extensions in
+  let named_elts' = instantiate_local_named_elements ctx modifs rhs named_elts
+  and unnamed_elts' = instantiate_local_unnamed_elements ctx unnamed_elts
+  and inherited_eltss = instantiate_inherited_elements ctx modifs rhs exts in
+  merge_elements named_elts' unnamed_elts' inherited_eltss
+
+and instantiate_local_named_elements ctx modifs rhs named_elts =
+  List.fold_right (instantiate_local_named_element ctx modifs rhs) named_elts []
+
+and instantiate_local_named_element ctx modifs rhs (id, elt_desc) named_elts =
+  let rec filter_current_element_modifications = function
+    | [] -> []
+    | (id', arg) :: modifs when id' = id ->
+        arg :: filter_current_element_modifications modifs
+    | _ :: modifs -> filter_current_element_modifications modifs
+  and select_current_element_value = function
+    | None -> None
+    | Some expr -> Some (lazy (field_access ctx (evaluate expr) id)) in
+  let modifs' = filter_current_element_modifications modifs
+  and rhs' = select_current_element_value rhs
+  and elt_loc = ctx.path @ [Name id] in
+  let ctx = {ctx with
+               path = elt_loc;
+               location = elt_desc.NameResolve.element_location;
+               instance_nature = instance_nature_of_element elt_desc} in
+  let elt_nat =
+    lazy (instantiate_local_element_nature ctx modifs' rhs' elt_loc elt_desc) in
+  let named_elt =
+    id,
+    {
+      redeclare = elt_desc.NameResolve.redeclare;
+      element_nature = elt_nat
+    } in
+  named_elt :: named_elts
+
+and instantiate_local_element_nature ctx modifs rhs elt_loc elt_desc =
+  match elt_desc.NameResolve.element_nature with
+    | NameResolve.Component cpnt_desc ->
+        let cpnt_desc' =
+          instantiate_component_description ctx modifs rhs elt_loc cpnt_desc in
+       Component cpnt_desc'
+    | NameResolve.Class cl_def ->
+        let cl_def' = evaluate_class_definition ctx modifs elt_loc cl_def in
+        Class cl_def'
+    | NameResolve.ComponentType _ ->
+        raise (InstantError
+          { err_msg = ["_NotYetImplemented"; "_ComponentTypeElemInstant"];
+            err_info = [];
+            err_ctx = ctx })
+    | NameResolve.PredefinedType _ ->
+        raise (InstantError
+          { err_msg = ["_NotYetImplemented"; "_PredefinedTypeElemInstant"];
+            err_info = [];
+            err_ctx = ctx })
+
+and instantiate_component_description ctx modifs rhs elt_loc cpnt_desc =
+  let cpnt_type = evaluate cpnt_desc.NameResolve.component_type in
+  let flow = evaluate cpnt_type.Types.flow
+  and var = evaluate cpnt_type.Types.variability
+  and inout = evaluate cpnt_type.Types.causality
+  and type_spec = evaluate cpnt_desc.NameResolve.type_specifier
+  and dims = evaluate cpnt_desc.NameResolve.dimensions
+  and modifs' = match evaluate cpnt_desc.NameResolve.modification with
+    | None -> modifs
+    | Some modif ->
+        let modif' = evaluate_modification ctx modif in
+        modifs @ [{ each = false; action = ElementModification modif' }]
+  and cmt = cpnt_desc.NameResolve.comment in
+  component_nature ctx modifs' rhs elt_loc flow var inout type_spec dims cmt
+
+and component_nature ctx modifs rhs elt_loc flow var inout type_spec dims cmt =
+  let type_spec' = evaluate_expression ctx type_spec in
+  let ctx = {ctx with location = expression_location ctx type_spec} in
+  expand_array ctx modifs rhs elt_loc flow var inout type_spec' dims cmt
+
+and expand_array ctx modifs rhs elt_loc flow var inout type_spec dims cmt =
+  let rec expand_along_dimension dim dims = match dim with
+    | NameResolve.Colon -> expand_dynamic_array dims
+    | NameResolve.Expression expr ->
+        let expr' = evaluate_expression ctx expr in
+        expand_static_array dims expr' expr
+  and expand_dynamic_array dims =
+    (* No need to select modifications since all of them have 'each' set *)
+    let elt_loc' = elt_loc @ [Index 0] in
+    let ctx = { ctx with path = elt_loc' } in
+    let expr =
+      expand_array ctx modifs rhs elt_loc' flow var inout type_spec dims cmt in
+    DynamicArray expr
+  and expand_static_array dims expr' expr =
+    let ctx = {ctx with location = expression_location ctx expr} in
+    let expand_element i =
+      let rec select_subargument arg = match arg.each with
+        | true -> arg
+        | false -> { arg with action = select_subarray arg.action }
+      and select_subarray arg = match arg with
+       | ElementModification modif ->
+            ElementModification (select_submodification modif)
+        | ElementRedeclaration _ -> arg
+      and select_sub_class_modification_element (id, arg) =
+        id, select_subargument arg
+      and select_submodification = function
+        | Modification (modifs, rhs) ->
+            let modifs' = List.map select_sub_class_modification_element modifs
+            and rhs' = select_rhs_subarray rhs in
+            Modification (modifs', rhs')
+        | Assignment expr ->
+            let expr' = lazy (select_row i (evaluate expr)) in
+            Assignment expr'
+        | Equality expr ->
+            let expr' = lazy (select_row i (evaluate expr)) in
+            Equality expr'
+      and select_rhs_subarray = function
+        | None -> None
+        | Some expr -> Some (lazy (select_row i (evaluate expr)))
+      and select_row i = function
+             | Vector exprs ->
+            begin
+              try
+                exprs.(i)
+              with
+              | _ -> raise (InstantError
+                  { err_msg = ["_IndexOutOfBound"];
+                    err_info = [];
+                    err_ctx = ctx}) (*error*)
+            end
+        | expr ->
+            let subs = [Integer (Int32.succ (Int32.of_int i))] in
+            evaluate_indexed_access ctx expr subs in
+      let modifs = List.map select_subargument modifs
+      and rhs = select_rhs_subarray rhs
+      and elt_loc = elt_loc @ [Index i] in
+      expand_array ctx modifs rhs elt_loc flow var inout type_spec dims cmt in
+    match expr' with
+      | Integer i ->
+          let a = Array.init (Int32.to_int i) expand_element in
+          StaticArray a
+      | _ ->
+          raise (InstantError
+          { err_msg = ["_NonIntegerArrayDim"];
+            err_info = [];
+            err_ctx = ctx }) (*error*) in
+  match dims with
+    | [] ->
+        let cl_def = class_definition_of_type_specification ctx type_spec in
+        create_instance ctx modifs rhs elt_loc flow var inout cl_def cmt
+    | dim :: dims ->
+        {
+          component_path = elt_loc;
+          flow = flow;
+          variability = var;
+          causality = inout;
+          component_nature = lazy (expand_along_dimension dim dims);
+          declaration_equation = rhs;
+          comment = cmt;
+          component_location = ctx.location;
+          class_name = instance_class_name ctx.instance_nature
+        }
+
+and create_instance ctx modifs rhs elt_loc flow var inout cl_def cmt =
+  let merge_class_modifications arg modifs = match arg.action with
+    | ElementModification (Modification (modifs', _)) -> modifs' @ modifs
+    | ElementModification (Assignment _ | Equality _) -> modifs
+    | ElementRedeclaration _ -> modifs in
+  let rec declaration_equation modifs rhs =
+    let rec declaration_equation' = function
+      | [] -> None
+      | {
+          action =
+            ElementModification (
+              Modification (_, Some expr) | Assignment expr | Equality expr)
+        } :: _ -> Some expr
+      | _ :: args -> declaration_equation' args in
+    match rhs with
+      | None -> declaration_equation' modifs
+      | Some _ -> rhs in
+  let flow' = match cl_def.class_flow, ctx.context_flow with
+    | None, None -> flow
+    | Some flow', None | None, Some flow' -> flow || flow'
+    | Some flow', Some flow'' -> flow || flow' || flow''
+  and var' = match cl_def.class_variability, ctx.context_variability with
+    | None, None -> var
+    | Some var', None | None, Some var' -> Types.min_variability var var'
+    | Some var', Some var'' ->
+        Types.min_variability var (Types.min_variability var' var'')
+  and inout' = match inout, cl_def.class_causality with
+    | Types.Input, _ | _, Some Types.Input -> Types.Input
+    | Types.Output, _ | _, Some Types.Output -> Types.Output
+    | _ -> Types.Acausal in
+  let modifs' =
+    List.fold_right
+      merge_class_modifications
+      (modifs @ cl_def.modification)
+      []
+  and rhs' = declaration_equation modifs rhs in
+  match cl_def.description with
+    | ClassDescription (ctx', cl_desc) ->
+        let class_name = instance_class_name ctx.instance_nature in
+        let ctx' =
+          { ctx' with
+            context_flow = Some flow';
+            context_variability = Some var';
+            context_causality = Some inout';
+            instance_context = enclosing_instance ctx;
+            instance_nature = ComponentElement class_name
+          } in
+        {
+          component_path = elt_loc;
+          flow = flow';
+          variability = var';
+          causality = inout';
+          component_nature =
+            lazy (create_class_instance ctx' modifs' rhs' elt_loc cl_desc);
+          declaration_equation = rhs';
+          comment = cmt;
+          component_location = ctx'.location;
+          class_name = class_name
+        }
+    | PredefinedType predef ->
+        let class_name = instance_class_name ctx.instance_nature in
+        let ctx' =
+          { ctx with
+            context_flow = Some flow';
+            context_variability = Some var';
+            context_causality = Some inout';
+            instance_nature = ComponentElement class_name
+          } in
+        {
+          component_path = elt_loc;
+          flow = flow';
+          variability = var';
+          causality = inout';
+          component_nature =
+            lazy (create_predefined_type_instance ctx' modifs' predef);
+          declaration_equation = rhs';
+          comment = cmt;
+          component_location = ctx'.location;
+          class_name = class_name
+        }
+
+and create_temporary_instance ctx cl_def =
+  match cl_def.description with
+    | ClassDescription (ctx', cl_desc) ->
+        {
+          component_path = [];
+          flow = false;
+          variability = Types.Continuous;
+          causality = Types.Acausal;
+          component_nature =
+            lazy (create_class_instance ctx' [] None [] cl_desc);
+          declaration_equation = None;
+          comment = "";
+          component_location = ctx'.location;
+          class_name = instance_class_name ctx.instance_nature
+        }
+    | PredefinedType predef -> assert false (*error*)
+
+and class_definition_of_type_specification ctx type_spec =
+  let predefined_class_specifier = function
+    | "Boolean" -> Types.boolean_class_type
+    | "Integer" -> Types.integer_class_type
+    | "Real" -> Types.real_class_type
+    | "String" -> Types.string_class_type
+    | s ->
+        raise (InstantError
+          { err_msg = ["_UnknownIdentifier"; s];
+            err_info = [];
+            err_ctx = ctx }) (*error*)
+  and predefined_class_description = function
+    | "Boolean" -> PredefinedType BooleanType
+    | "Integer" -> PredefinedType IntegerType
+    | "Real" -> PredefinedType RealType
+    | "String" -> PredefinedType StringType
+    | s ->
+        raise (InstantError
+          { err_msg = ["_UnknownIdentifier"; s];
+            err_info = [];
+            err_ctx = ctx }) (*error*) in
+  match type_spec with
+    | ClassReference cl_def -> cl_def
+    | PredefinedIdentifier id ->
+        {
+          class_type = predefined_class_specifier id;
+          class_path = [Name id];
+          class_flow = None;
+          class_variability = None;
+          class_causality = None;
+          description = predefined_class_description id;
+          modification = [];
+          class_location = ctx.location
+        }
+    | _ -> assert false (*error*)
+
+and create_class_instance ctx modifs rhs elt_loc cl_desc =
+  let inst = instantiate_class_description ctx modifs rhs elt_loc cl_desc in
+  Instance inst
+
+and create_predefined_type_instance ctx modifs predef =
+  let inst =
+    {
+      predefined_type = predef;
+      attributes = predefined_type_attributes ctx modifs
+    } in
+  PredefinedTypeInstance inst
+
+and predefined_type_attributes ctx modifs =
+  let rec predefined_type_attributes attrs = function
+    | [] -> attrs
+    | (id, { action = ElementModification (Equality expr) }) :: modifs
+      when not (List.mem_assoc id attrs) ->
+        let attrs' = (id, expr) :: attrs in
+        predefined_type_attributes attrs' modifs
+    | _ :: modifs -> predefined_type_attributes attrs modifs in
+  predefined_type_attributes [] modifs
+
+and instantiate_inherited_elements ctx modifs rhs exts =
+  List.fold_right (instantiate_inherited_element ctx modifs rhs) exts []
+
+and instantiate_inherited_element ctx modifs rhs (_, modif_cl) inherited_elts =
+  let instantiate_inherited_element' modifs cl_def =
+    match cl_def.description with
+      | ClassDescription (ctx', cl_desc) ->
+          let ctx' = { ctx with parent_context = Some ctx' } in
+          let long_desc = cl_desc.long_description in
+          instantiate_class_elements ctx' modifs rhs long_desc
+      | PredefinedType _ -> assert false (*error*) in
+  let type_spec = evaluate modif_cl.NameResolve.base_class
+  and modifs' = evaluate modif_cl.NameResolve.class_modification in
+  let type_spec' = evaluate_expression ctx type_spec
+  and ctx = {ctx with location = expression_location ctx type_spec} in
+  let modifs = modifs @ evaluate_class_modification ctx modifs' in
+  match type_spec' with
+    | ClassReference cl_def ->
+        instantiate_inherited_element' modifs cl_def :: inherited_elts
+    | _ -> assert false (*error*)
+and evaluate_class_definition ctx modifs elt_loc cl_def =
+  match evaluate cl_def.NameResolve.description with
+    | NameResolve.LongDescription long_desc ->
+        let cl_anns = long_desc.NameResolve.class_annotations in
+        let cl_def' =
+          {
+            class_kind = Types.Class;
+            class_annotations = lazy (evaluate_class_annotations ctx cl_anns);
+            long_description = long_desc
+          } in
+        {
+          class_type = evaluate cl_def.NameResolve.class_type;
+          class_path = elt_loc;
+          class_flow = None;
+          class_variability = None;
+          class_causality = None;
+          description = ClassDescription (ctx, cl_def');
+          modification = modifs;
+          class_location = ctx.location
+        }
+    | NameResolve.ShortDescription short_desc ->
+        raise (InstantError
+          {err_msg = ["_NotYetImplemented"; "_ShortClassDef"];
+           err_info = [];
+           err_ctx = {ctx with path = elt_loc;
+                      instance_nature = ClassElement}})
+
+and evaluate_class_annotations ctx cl_anns =
+  let evaluate_inverse_function inv_func =
+    let inv_func = evaluate inv_func in
+    let expr =
+      evaluate_expression ctx inv_func.NameResolve.function_class in
+    match expr with
+    | ClassReference cl_def ->
+        {
+          function_class = cl_def;
+          arguments = inv_func.NameResolve.arguments
+        }
+    | _ -> assert false (*error*) in
+  let evaluate_class_annotation cl_ann = match cl_ann with
+    | NameResolve.InverseFunction inv_func ->
+        InverseFunction (lazy (evaluate_inverse_function inv_func))
+    | NameResolve.UnknownAnnotation cl_ann ->
+        UnknownAnnotation cl_ann in
+  List.map evaluate_class_annotation (evaluate cl_anns)
+
+and evaluate_class_modification ctx cl_modif =
+  let add_modification_argument arg cl_modif' =
+    match arg.NameResolve.action with
+      | None -> cl_modif'
+      | Some modif ->
+          let arg' =
+            arg.NameResolve.target,
+            {
+              each = arg.NameResolve.each;
+              action = evaluate_modification_action ctx modif
+            } in
+          arg' :: cl_modif' in
+  List.fold_right add_modification_argument cl_modif []
+
+and evaluate_modification_action ctx = function
+  | NameResolve.ElementModification modif ->
+      let modif' = evaluate_modification ctx modif in
+      ElementModification modif'
+  | NameResolve.ElementRedeclaration elt_desc ->
+      raise (InstantError
+        { err_msg = ["_NotYetImplemented"; "_ElementRedeclaration"];
+          err_info = [];
+          err_ctx = ctx })
+
+and evaluate_modification ctx = function
+  | NameResolve.Modification (modifs, rhs) ->
+      let modifs' = evaluate_class_modification ctx modifs
+      and rhs' = evaluate_modification_expression ctx rhs in
+      Modification (modifs', rhs')
+  | NameResolve.Assignment expr ->
+      let expr = evaluate expr in
+      let ctx = {ctx with location = expression_location ctx expr} in
+      raise (InstantError
+        { err_msg = ["_NotYetImplemented"; "_AssignExprInElemModif"];
+          err_info = [];
+          err_ctx = ctx })
+  | NameResolve.Equality expr ->
+      let expr' = lazy (evaluate_expression ctx (evaluate expr)) in
+      Equality expr'
+
+and evaluate_modification_expression ctx = function
+  | None -> None
+  | Some expr ->
+      let expr' = lazy (evaluate_expression ctx (evaluate expr)) in
+      Some expr'
+
+and instantiate_local_unnamed_elements ctx unnamed_elts =
+  List.map (instantiate_local_unnamed_element ctx) (evaluate unnamed_elts)
+
+and instantiate_local_unnamed_element ctx unnamed_elt =
+  match unnamed_elt with
+    | NameResolve.EquationClause (validity, equs) ->
+        EquationClause (validity, lazy (instantiate_equations ctx equs))
+    | NameResolve.AlgorithmClause (validity, algs) ->
+        raise (InstantError
+          { err_msg = ["_NotYetImplemented"; "_AlgoClause"];
+            err_info = [];
+            err_ctx = ctx })
+
+and instantiate_equations ctx equs =
+  let instantiate_equations' equ equs =
+    let equs' =  instantiate_equation ctx equ in
+    { nature = equs'; info = equ } :: equs in
+  List.fold_right instantiate_equations' equs []
+
+and instantiate_equation ctx equ = match equ.NameResolve.nature with
+  | NameResolve.Equal (expr, expr') -> instantiate_equal ctx expr expr'
+  | NameResolve.ConditionalEquationE (alts, default) ->
+      instantiate_conditional_equation ctx alts default
+  | NameResolve.ForClauseE (ranges, equs) ->
+      instantiate_for_clause_e ctx ranges equs
+  | NameResolve.ConnectFlows (sign, expr, sign', expr') ->
+      instantiate_connection ctx sign expr sign' expr'
+  | NameResolve.WhenClauseE alts ->
+      instantiate_when_clause_e ctx alts
+
+and instantiate_equal ctx expr expr' =
+  let rec equal_expr expr expr' =
+    match expr, expr' with
+    | BinaryOperation (bin_oper_kind, expr1, expr2),
+      BinaryOperation (bin_oper_kind', expr1', expr2') ->
+        (bin_oper_kind = bin_oper_kind') &&
+        (equal_expr expr1 expr1') &&
+        (equal_expr expr2 expr2')
+    | ClassReference cl_def, ClassReference cl_def' ->
+        cl_def.class_path = cl_def'.class_path
+    | ComponentReference cpnt_desc, ComponentReference cpnt_desc' ->
+        cpnt_desc.component_path = cpnt_desc'.component_path
+    | EnumerationElement s, EnumerationElement s' -> s = s'
+    | False, False -> true
+    | FieldAccess (expr, s), FieldAccess (expr', s') ->
+        (equal_expr expr expr') && (s = s')
+    | FunctionCall (expr, exprs), FunctionCall (expr', exprs') ->
+        (equal_expr expr expr') &&
+        (List.length exprs = List.length exprs') &&
+        (List.for_all2 (=) exprs exprs')
+    | If (alts, default), If (alts', default') ->
+        let f (cond, expr) (cond', expr') =
+          (equal_expr cond cond') && (equal_expr expr expr') in
+        (List.length alts = List.length alts') &&
+        (List.for_all2 f alts alts') &&
+        (equal_expr default default')
+    | IndexedAccess (expr, exprs), IndexedAccess (expr', exprs') ->
+        (equal_expr expr expr') &&
+        (List.length exprs = List.length exprs') &&
+        (List.for_all2 (=) exprs exprs')
+    | Integer i, Integer i' -> Int32.compare i i' = 0
+    | LoopVariable i, LoopVariable i' -> i = i'
+    | NoEvent expr, NoEvent expr' -> equal_expr expr expr'
+    | PredefinedIdentifier s, PredefinedIdentifier s' -> s = s'
+    | Range (start, step, stop), Range (start', step', stop') ->
+        (equal_expr start start') &&
+        (equal_expr step step') &&
+        (equal_expr stop stop')
+    | Real f, Real f' -> f = f'
+    | Record elts, Record elts' ->
+        let f (s, expr) (s', expr') =
+          (s = s') && (equal_expr expr expr') in
+        (List.length elts = List.length elts') &&
+        (List.for_all2 f elts elts')
+    | String s, String s' -> s = s'
+    | True, True -> true
+    | Tuple exprs, Tuple exprs' ->
+        (List.length exprs = List.length exprs') &&
+        (List.for_all2 equal_expr exprs exprs')
+    | UnaryOperation (un_oper_kind, expr),
+      UnaryOperation (un_oper_kind', expr') ->
+        (un_oper_kind = un_oper_kind') &&
+        (equal_expr expr expr')
+    | Vector exprs, Vector exprs' ->
+        (Array.length exprs = Array.length exprs') &&
+        (ArrayExt.for_all2 equal_expr exprs exprs')
+    | VectorReduction (exprs, expr), VectorReduction (exprs', expr') ->
+        (List.length exprs = List.length exprs') &&
+        (List.for_all2 equal_expr exprs exprs') &&
+        (equal_expr expr expr')
+    | _ -> false in
+  let expr = evaluate_expression ctx expr
+  and expr' = evaluate_expression ctx expr' in
+  match equal_expr expr expr' with
+  | true -> []
+  | false -> [ Equal (expr, expr') ]
+
+and instantiate_conditional_equation ctx alts default =
+  let rec instantiate_alternatives acc = function
+    | [] -> instantiate_default acc default
+    | (cond, equs) :: alts -> instantiate_alternative acc cond equs alts
+  and instantiate_alternative acc cond equs alts =
+    let cond' = evaluate_expression ctx cond in
+    match cond' with
+      | False -> instantiate_alternatives acc alts
+      | True -> instantiate_default acc equs
+      | _ ->
+          let equs' = instantiate_equations ctx equs in
+          instantiate_alternatives ((cond', equs') :: acc) alts
+  and instantiate_default acc equs =
+    let equs' = instantiate_equations ctx equs in
+    [ConditionalEquationE (List.rev acc, equs')] in
+  let alts' = instantiate_alternatives [] alts in
+  List.flatten (List.map (expand_equation ctx) alts')
+
+and expand_equation ctx equ =
+  let rec expand_equation' equ =
+    let expand_conditional_equation alts default =
+      let add_alternative (b, equs) altss =
+        let g equ = List.flatten (List.map expand_equation' equ.nature) in
+        let equs' = List.flatten (List.map g equs) in
+        let f (expr1, expr2) (expr1', expr2') = match expr1, expr2 with
+          | If (alts1, default1), If (alts2, default2) ->
+              If ((b, expr1') :: alts1, default1),
+              If ((b, expr2') :: alts2, default2)
+          | _ -> assert false in
+        try
+          List.map2 f altss equs'
+        with
+        | _ ->
+            raise (InstantError
+              {err_msg = ["_InvalidCondEquation"];
+               err_info = [];
+               err_ctx = ctx}) in
+      let g equ = List.flatten (List.map expand_equation' equ.nature) in
+      let default' = List.flatten (List.map g default) in
+      let f = function (expr1, expr2) -> If ([], expr1), If ([], expr2) in
+      List.fold_right add_alternative alts (List.map f default') in
+    match equ with
+    | ConditionalEquationE (alts, default) ->
+        expand_conditional_equation alts default
+    | Equal (expr, expr') -> [ expr, expr' ]
+    | _ ->
+        raise (InstantError
+          {err_msg = ["_InvalidCondEquation"];
+           err_info = [];
+           err_ctx = ctx}) in
+  let f (expr, expr') = Equal (expr, expr') in
+  List.map f (expand_equation' equ)
+
+and instantiate_when_clause_e ctx alts =
+  let instantiate_alternative (cond, equs) =
+    let cond' = evaluate_expression ctx cond in
+    let equs' = instantiate_equations ctx equs in
+    cond', equs' in
+  [WhenClauseE (List.map instantiate_alternative alts)]
+
+and instantiate_connection ctx sign expr sign' expr' =
+  let expr = evaluate_expression ctx expr
+  and expr' = evaluate_expression ctx expr' in
+  [ConnectFlows (sign, expr, sign', expr')]
+
+and instantiate_for_clause_e ctx ranges equs =
+  let rec instantiate_for_clause_e' ctx = function
+    | [] -> List.flatten (List.map (instantiate_equation ctx) equs)
+    | ranges -> equations_of_reduction ctx ranges
+  and equations_of_reduction ctx ranges = match ranges with
+    | (Vector exprs) :: ranges ->
+        let f expr =
+          let ctx' =
+            { ctx with
+              class_context = ForContext (ctx, Some expr)
+            } in
+          instantiate_for_clause_e' ctx' ranges in
+        List.flatten (List.map f (Array.to_list exprs))
+    | _ ->
+        raise (InstantError
+          {err_msg = ["_InvalidForClauseRange"];
+           err_info = [];
+           err_ctx = ctx}) in
+  let ranges = List.map (evaluate_expression ctx) ranges in
+  instantiate_for_clause_e' ctx ranges
+
+and evaluate_expression ctx expr =
+  let ctx = {ctx with location = expression_location ctx expr} in
+  match expr.NameResolve.nature with
+    | NameResolve.BinaryOperation (binop, expr, expr') ->
+        evaluate_binary_operation ctx binop expr expr'
+    | NameResolve.DynamicIdentifier (level, id) ->
+        evaluate_dynamic_identifier ctx level id
+    | NameResolve.False -> False
+    | NameResolve.FieldAccess (expr, id) ->
+        evaluate_field_access ctx expr id
+    | NameResolve.FunctionArgument pos -> evaluate_function_argument ctx pos
+    | NameResolve.FunctionCall (expr, exprs, expr') ->
+        evaluate_function_call ctx expr exprs expr'
+    | NameResolve.FunctionInvocation exprs ->
+        evaluate_function_invocation ctx exprs
+    | NameResolve.If (alts, default) -> evaluate_if ctx alts default
+    | NameResolve.IndexedAccess (expr, exprs) ->
+        let expr = evaluate_expression ctx expr
+        and exprs = List.map (evaluate_expression ctx) exprs in
+        evaluate_indexed_access ctx expr exprs
+    | NameResolve.Integer i -> Integer i
+    | NameResolve.LocalIdentifier (level, id) ->
+        evaluate_local_identifier ctx level id
+    | NameResolve.LoopVariable level -> evaluate_loop_variable ctx level
+    | NameResolve.NoEvent expr -> evaluate_no_event ctx expr
+    | NameResolve.PredefinedIdentifier id -> PredefinedIdentifier id
+    | NameResolve.Range (start, step, stop) ->
+        evaluate_range ctx start step stop
+    | NameResolve.Real f -> Real f
+    | NameResolve.String s -> String s
+    | NameResolve.ToplevelIdentifier id ->
+        evaluate_toplevel_identifier ctx id
+    | NameResolve.True -> True
+    | NameResolve.Tuple exprs -> evaluate_tuple ctx exprs
+    | NameResolve.UnaryOperation (unop, expr) ->
+        evaluate_unary_operation ctx unop expr
+    | NameResolve.VectorReduction (ranges, expr) ->
+        evaluate_vector_reduction ctx ranges expr
+    | NameResolve.Vector exprs -> evaluate_vector ctx exprs
+    | NameResolve.Coercion (coer, expr) ->
+        evaluate_coercion ctx coer expr
+
+and evaluate_binary_operation ctx binop expr expr' =
+  let expr = evaluate_expression ctx expr
+  and expr' = evaluate_expression ctx expr' in
+  let expr = flatten_expression expr
+  and expr' = flatten_expression expr' in
+  match binop with
+    | NameResolve.And -> evaluate_and expr expr'
+    | NameResolve.Divide -> evaluate_divide ctx expr expr'
+    | NameResolve.EqualEqual -> evaluate_equalequal expr expr'
+    | NameResolve.GreaterEqual -> evaluate_greater_equal expr expr'
+    | NameResolve.Greater -> evaluate_greater expr expr'
+    | NameResolve.LessEqual -> evaluate_less_equal expr expr'
+    | NameResolve.Less -> evaluate_less expr expr'
+    | NameResolve.Times -> evaluate_times expr expr'
+    | NameResolve.NotEqual -> evaluate_not_equal expr expr'
+    | NameResolve.Or -> evaluate_or expr expr'
+    | NameResolve.Plus -> evaluate_plus expr expr'
+    | NameResolve.Power -> evaluate_power ctx expr expr'
+    | NameResolve.Minus -> evaluate_minus expr expr'
+
+and evaluate_dynamic_identifier ctx level id =
+  let rec evaluate_dynamic_identifier' inst level =
+    match level, inst.enclosing_instance with
+    | 0, _ -> instance_field_access ctx inst id
+    | _, Some inst -> evaluate_dynamic_identifier' inst (level - 1)
+    | _, None -> assert false (*error*) in
+  match ctx.instance_context with
+    | Some inst -> evaluate_dynamic_identifier' inst level
+    | None -> assert false (*error*)
+
+and evaluate_field_access ctx expr id =
+  let expr = evaluate_expression ctx expr in
+  field_access ctx expr id
+
+and evaluate_function_argument ctx pos = match ctx.class_context with
+  | FunctionEvaluationContext (_, expr, _) when pos = 0 -> expr
+  | FunctionEvaluationContext (_, _, exprs) -> List.nth exprs (pos - 1)
+  | ForContext (ctx', _) -> evaluate_function_argument ctx' pos
+  | InstanceContext _ | ToplevelContext -> assert false (*error*)
+
+and evaluate_function_call ctx expr exprs expr' =
+  let expr = evaluate_expression ctx expr
+  and exprs = List.map (evaluate_expression ctx) exprs in
+  let exprs = List.map flatten_expression exprs in
+  let ctx' =
+    { ctx with
+      class_context = FunctionEvaluationContext (ctx, expr, exprs)
+    } in
+  evaluate_expression ctx' expr'
+
+and evaluate_function_invocation ctx exprs =
+  let exprs = List.map (evaluate_expression ctx) exprs in
+  let exprs = List.map flatten_expression exprs in
+  let evaluate_function_with_arguments = function
+    | ClassReference cl_def ->
+        evaluate_class_function_invocation cl_def exprs
+    | PredefinedIdentifier s ->
+        evaluate_predefined_function_invocation ctx s exprs
+    | ComponentReference _ ->
+        raise (InstantError
+          { err_msg = ["_NotYetImplemented"; "_ComponentFuncInvocation"];
+            err_info = [];
+            err_ctx = ctx })
+    | _ -> assert false (*error*) in
+  let rec evaluate_function_invocation' ctx = match ctx.class_context with
+    | FunctionEvaluationContext (_, expr, _) ->
+        evaluate_function_with_arguments expr
+    | ForContext (ctx', _) -> evaluate_function_invocation' ctx'
+    | InstanceContext _ | ToplevelContext -> assert false (*error*) in
+  evaluate_function_invocation' ctx
+
+and evaluate_if ctx alts default =
+  let create_if alts default = match alts with
+    | [] -> default
+    | _ :: _ -> If (alts, default) in
+  let rec evaluate_alternatives alts' alts = match alts with
+    | [] ->
+        let default = evaluate_expression ctx default in
+        create_if (List.rev alts') default
+    | (expr, expr') :: alts ->
+        let expr = evaluate_expression ctx expr in
+        evaluate_alternative expr expr' alts' alts
+  and evaluate_alternative expr expr' alts' alts = match expr with
+    | True ->
+        let default = evaluate_expression ctx expr' in
+        create_if (List.rev alts') default
+    | False -> evaluate_alternatives alts' alts
+    | _ ->
+        let expr' = evaluate_expression ctx expr' in
+        evaluate_alternatives ((expr, expr') :: alts') alts in
+  evaluate_alternatives [] alts
+
+and evaluate_indexed_access ctx expr exprs =
+  let rec vector_indexed_access exprs' exprs = match exprs with
+    | [] -> expr
+    | Integer i :: exprs ->
+        let expr' =
+          try
+            exprs'.(Int32.to_int i - 1)
+          with _ ->
+              raise (InstantError
+                { err_msg = ["_IndexOutOfBound"];
+                  err_info = [];
+                  err_ctx = ctx}) (*error*) in
+        evaluate_indexed_access ctx expr' exprs
+    | (Vector subs) :: exprs ->
+        let f sub = vector_indexed_access exprs' (sub :: exprs) in
+        Vector (Array.map f subs)
+    | _ -> IndexedAccess (expr, exprs)
+  and component_indexed_access cpnt_desc exprs =
+    let rec static_array_indexed_access cpnt_descs exprs = match exprs with
+      | [] -> expr
+      | Integer i :: exprs ->
+          let i' = Int32.to_int i in
+          if Array.length cpnt_descs >= i' then
+            let cpnt_desc = cpnt_descs.(i' - 1) in
+            let expr' = ComponentReference cpnt_desc in
+            evaluate_indexed_access ctx expr' exprs
+          else
+            raise (InstantError
+              { err_msg = ["_IndexOutOfBound"];
+                err_info = [];
+                err_ctx = ctx}) (*error*)
+      | (Vector subs) :: exprs ->
+          let f sub = static_array_indexed_access cpnt_descs (sub :: exprs) in
+          Vector (Array.map f subs)
+      | exprs -> IndexedAccess (expr, exprs) in
+    match evaluate cpnt_desc.component_nature with
+    | DynamicArray _ -> IndexedAccess (ComponentReference cpnt_desc, exprs)
+    | StaticArray cpnt_descs ->
+        static_array_indexed_access cpnt_descs exprs
+    | Instance _ | PredefinedTypeInstance _ -> expr in
+  match expr, exprs with
+  | _, [] -> expr
+  | ComponentReference cpnt_desc, _ ->
+      component_indexed_access cpnt_desc exprs
+  | Vector exprs', _ ->
+      vector_indexed_access exprs' exprs
+  | If (alts, default), _ ->
+      let f (cond, expr) = (cond, evaluate_indexed_access ctx expr exprs) in
+      If (List.map f alts, evaluate_indexed_access ctx default exprs)
+  | _ -> IndexedAccess (expr, exprs)
+
+and evaluate_local_identifier ctx level id =
+  let rec evaluate_local_identifier' ctx inst level =
+    match level, ctx.parent_context with
+      | 0, _ -> instance_field_access ctx inst id
+      | _, Some ctx -> evaluate_local_identifier ctx (level - 1) id
+      | _, None -> assert false (*error*) in
+  match ctx.class_context with
+    | ForContext (ctx, _) | FunctionEvaluationContext (ctx, _, _) ->
+        evaluate_local_identifier ctx level id
+    | InstanceContext inst -> evaluate_local_identifier' ctx inst level
+    | ToplevelContext -> assert false (*error*)
+
+and evaluate_loop_variable ctx level =
+  let rec evaluate_loop_variable' ctx level' =
+    match level', ctx.class_context with
+      | 0, ForContext (_, None) -> assert false (*LoopVariable level'*)
+      | 0, ForContext (_, Some expr) -> expr
+      | _, ForContext (ctx, _) -> evaluate_loop_variable ctx (level' - 1)
+      | _, FunctionEvaluationContext (ctx, _, _) ->
+          evaluate_loop_variable' ctx level'
+      | _, (InstanceContext _ | ToplevelContext) -> assert false (*error*) in
+  evaluate_loop_variable' ctx level
+
+and evaluate_no_event ctx expr =
+  let expr = evaluate_expression ctx expr in
+  match expr with
+    | True | False | Integer _ | Real _ | String _ | EnumerationElement _ ->
+        expr
+    | _ -> NoEvent expr
+
+and evaluate_range ctx start step stop =
+  let start = evaluate_expression ctx start
+  and step = evaluate_expression ctx step
+  and stop = evaluate_expression ctx stop in
+  let real_of_expression expr = match expr with
+    | Real r -> r
+    | Integer i -> Int32.to_float i
+    | _ -> assert false in
+  let integer_interval istart istep istop = match istart, istep, istop with
+    | _
+      when (Int32.compare istop istart) *
+        (Int32.compare istep Int32.zero) < 0 ->
+        Vector (Array.make 0 (Integer istart))
+    | _ ->
+        let n =
+          Int32.div (Int32.sub istop istart) istep in
+        let n' = Int32.to_int (Int32.succ n) in
+        let f i =
+          let i' = Int32.of_int i in
+          let j =
+            Int32.add istart (Int32.mul i' istep) in
+          Integer j in
+        Vector (Array.init n' f)
+  and real_interval rstart rstep rstop = match rstart, rstep, rstop with
+    | _ when (rstop -. rstart) /. rstep < 0. ->
+        Vector (Array.make 0 (Real rstart))
+    | _ ->
+        let n = truncate ((rstop -. rstart) /. rstep) + 1
+        and f i = Real (rstart +. float_of_int i *. rstep) in
+        Vector (Array.init n f) in
+  match start, step, stop with
+  | _, Integer istep, _
+    when Int32.compare istep Int32.zero = 0 ->
+      raise (InstantError
+        {err_msg = ["_RangeStepValueCannotBeNull"];
+         err_info = [];
+         err_ctx = ctx})
+  | _, Real rstep, _ when rstep = 0. ->
+      raise (InstantError
+        {err_msg = ["_RangeStepValueCannotBeNull"];
+         err_info = [];
+         err_ctx = ctx})
+  | Integer istart, Integer istep, Integer istop ->
+      integer_interval istart istep istop
+  | (Integer _ | Real _), (Integer _ | Real _), (Integer _ | Real _) ->
+      let rstart = real_of_expression start
+      and rstep = real_of_expression step
+      and rstop = real_of_expression stop in
+      real_interval rstart rstep rstop
+  | _, _, _ -> Range (start, step, stop)
+
+and evaluate_coercion ctx coer expr =
+  let rec evaluate_real_of_integer expr' = match expr' with
+    | Integer i -> Real (Int32.to_float i)
+    | Vector exprs ->
+        Vector (Array.map evaluate_real_of_integer exprs)
+    | _ -> expr' in
+  let expr' = evaluate_expression ctx expr in
+  match coer with
+  | NameResolve.RealOfInteger -> evaluate_real_of_integer expr'
+
+and evaluate_toplevel_identifier ctx id =
+  let elt_desc = List.assoc id (evaluate ctx.toplevel) in
+  match evaluate elt_desc.element_nature with
+    | Class cl_def -> ClassReference cl_def
+    | Component cpnt_desc -> ComponentReference cpnt_desc
+
+and evaluate_tuple ctx exprs =
+  Tuple (List.map (evaluate_expression ctx) exprs)
+
+and evaluate_unary_operation ctx unop expr =
+  let expr = evaluate_expression ctx expr in
+  let expr = flatten_expression expr in
+  match unop with
+    | NameResolve.Not -> evaluate_not expr
+    | NameResolve.UnaryMinus -> evaluate_unary_minus expr
+    | NameResolve.UnaryPlus -> expr
+
+(*and evaluate_vector_reduction ctx ranges expr =
+  let rec evaluate_vector_reduction' ctx = function
+    | [] -> evaluate_expression ctx expr
+    | ranges -> vector_of_reduction ctx ranges
+  and vector_of_reduction ctx = function
+    | Range (Integer start, Integer step, Integer stop) :: ranges ->
+        vector_of_range ctx start step stop ranges
+    | ranges ->
+        let ctx' =
+          { ctx with
+            class_context = ForContext (ctx, None)
+          } in
+        VectorReduction (ranges, evaluate_expression ctx' expr)
+  and vector_of_range ctx start step stop ranges =
+    let rec expression_list pred start = match pred start with
+      | true -> []
+      | false ->
+          let ctx' =
+            { ctx with
+              class_context = ForContext (ctx, Some (Integer start))
+            } in
+          let expr = evaluate_vector_reduction' ctx' ranges in
+          expr :: expression_list pred (Int32.add start step) in
+    let cmp = Int32.compare step 0l in
+    match cmp with
+      | 0 when Int32.compare start stop <> 0 -> assert false (*error*)
+      | 0 -> Vector [||]
+      | _ when cmp < 0 ->
+          let pred = function i -> Int32.compare i stop < 0 in
+          let exprs = expression_list pred start in
+          Vector (Array.of_list exprs)
+      | _ ->
+          let pred = function i -> Int32.compare i stop > 0 in
+          let exprs = expression_list pred start in
+          Vector (Array.of_list exprs) in
+  let ranges = List.map (evaluate_expression ctx) ranges in
+  evaluate_vector_reduction' ctx ranges*)
+
+and evaluate_vector_reduction ctx ranges expr =
+  let rec evaluate_vector_reduction' ctx = function
+    | [] -> evaluate_expression ctx expr
+    | ranges -> vector_of_reduction ctx ranges
+  and vector_of_reduction ctx = function
+    | Range (Integer u, Integer p, Integer v) :: ranges ->
+        vector_of_integer_range ctx u p v ranges
+    | Range (Real u, Real p, Real v) :: ranges ->
+        vector_of_real_range ctx u p v ranges
+    | Vector exprs :: ranges ->
+        let f i =
+          let ctx' =
+            { ctx with
+              class_context = ForContext (ctx, Some exprs.(i))
+            } in
+          evaluate_vector_reduction' ctx' ranges in
+        Vector (Array.init (Array.length exprs) f)
+    | _ -> assert false
+  and vector_of_integer_range ctx start step stop ranges =
+    let rec expression_list pred start = match pred start with
+      | true -> []
+      | false ->
+          let expr = Integer start in
+          let ctx' =
+            { ctx with
+              class_context =
+                ForContext (ctx, Some expr)
+            } in
+          let expr = evaluate_vector_reduction' ctx' ranges in
+          let next = Int32.add start step in
+          expr :: expression_list pred next in
+    match step with
+    | _ when Int32.compare step Int32.zero = 0 ->
+        raise (InstantError
+          {err_msg = ["_RangeStepValueCannotBeNull"];
+           err_info = [];
+           err_ctx = ctx})
+    | _ when Int32.compare step Int32.zero < 0 ->
+        let pred = function i -> (Int32.compare i stop < 0) in
+        Vector (Array.of_list (expression_list pred start))
+    | _ ->
+        let pred = function i -> (Int32.compare i stop > 0) in
+        Vector (Array.of_list (expression_list pred start))
+  and vector_of_real_range ctx start step stop ranges =
+    let rec expression_list pred start = match pred start with
+      | true -> []
+      | false ->
+          let expr = Real start in
+          let ctx' =
+            { ctx with
+              class_context = ForContext (ctx, Some expr)
+            } in
+          let expr = evaluate_vector_reduction' ctx' ranges in
+          expr :: expression_list pred (start +. step) in
+    match step with
+    | 0. ->
+        raise (InstantError
+          {err_msg = ["_RangeStepValueCannotBeNull"];
+           err_info = [];
+           err_ctx = ctx})
+    | _ when step < 0. ->
+        let pred = function f -> f < stop in
+        Vector (Array.of_list (expression_list pred start))
+    | _ ->
+        let pred = function f -> f > stop in
+        Vector (Array.of_list (expression_list pred start)) in
+  let ranges = List.map (evaluate_expression ctx) ranges in
+  evaluate_vector_reduction' ctx ranges
+
+and evaluate_vector ctx exprs =
+  let exprs = List.map (evaluate_expression ctx) exprs in
+  Vector (Array.of_list exprs)
+
+and evaluate_and expr expr' = match expr, expr' with
+  | False, (False | True) | True, False -> False
+  | True, True -> True
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_and exprs exprs')
+  | _ -> BinaryOperation (And, expr, expr')
+
+and evaluate_divide ctx expr expr' = match expr, expr' with
+  | _, Integer 0l ->
+      raise (InstantError
+        { err_msg = ["_DivisionByZero"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | Integer 0l, _ -> Integer 0l
+  | Integer i, Integer i' ->
+      Real ((Int32.to_float i) /. (Int32.to_float i'))
+  | _, Real 0. ->
+      raise (InstantError
+        { err_msg = ["_DivisionByZero"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | Integer i, Real f -> Real (Int32.to_float i /. f)
+  | Real f, Integer i -> Real (f /. Int32.to_float i)
+  | Real f, Real f' -> Real (f /. f')
+  | Vector exprs, _ ->
+      let divide_element expr = evaluate_divide ctx expr expr' in
+      Vector (Array.map divide_element exprs)
+  | _ -> BinaryOperation (Divide, expr, expr')
+
+and evaluate_equalequal expr expr' = match expr, expr' with
+  | Integer i, Integer i' when i = i' -> True
+  | Integer i, Real f | Real f, Integer i when f = Int32.to_float i -> True
+  | Real f, Real f' when f = f' -> True
+  | (Integer _ | Real _), (Integer _ | Real _) -> False
+  | Vector exprs, Vector exprs'
+    when
+      ArrayExt.for_all2
+        (fun expr expr' -> evaluate_equalequal expr expr' = True)
+        exprs
+        exprs' -> True
+  | Vector _, Vector _ -> False
+  | _ -> BinaryOperation (EqualEqual, expr, expr')
+
+and evaluate_greater_equal expr expr' = match expr, expr' with
+  | Integer i, Integer i' when i >= i' -> True
+  | Integer i, Real f when Int32.to_float i >= f -> True
+  | Real f, Integer i when f >= Int32.to_float i -> True
+  | Real f, Real f' when f >= f' -> True
+  | (Integer _ | Real _), (Integer _ | Real _) -> False
+  | _ -> BinaryOperation (GreaterEqual, expr, expr')
+
+and evaluate_greater expr expr' = match expr, expr' with
+  | Integer i, Integer i' when i > i' -> True
+  | Integer i, Real f when Int32.to_float i > f -> True
+  | Real f, Integer i when f > Int32.to_float i -> True
+  | Real f, Real f' when f > f' -> True
+  | (Integer _ | Real _), (Integer _ | Real _) -> False
+  | _ -> BinaryOperation (Greater, expr, expr')
+
+and evaluate_less_equal expr expr' = match expr, expr' with
+  | Integer i, Integer i' when i <= i' -> True
+  | Integer i, Real f when Int32.to_float i <= f -> True
+  | Real f, Integer i when f <= Int32.to_float i -> True
+  | Real f, Real f' when f <= f' -> True
+  | (Integer _ | Real _), (Integer _ | Real _) -> False
+  | _ -> BinaryOperation (LessEqual, expr, expr')
+
+and evaluate_less expr expr' = match expr, expr' with
+  | Integer i, Integer i' when i < i' -> True
+  | Integer i, Real f when Int32.to_float i < f -> True
+  | Real f, Integer i when f < Int32.to_float i -> True
+  | Real f, Real f' when f < f' -> True
+  | (Integer _ | Real _), (Integer _ | Real _) -> False
+  | _ -> BinaryOperation (Less, expr, expr')
+
+and evaluate_times expr expr' =
+  let rec line exprs i = match exprs.(i) with
+    | Vector exprs -> exprs
+    | _ -> assert false
+  and column exprs j =
+    let f i = match exprs.(i) with
+      | Vector exprs -> exprs.(j)
+      | _ -> assert false in
+    Array.init (Array.length exprs) f
+  and ndims expr = match expr with
+    | Vector exprs when Array.length exprs = 0 -> assert false
+    | Vector exprs -> 1 + ndims exprs.(0)
+    | _ -> 0
+  and size expr i = match expr, i with
+    | _, 0 -> assert false
+    | Vector exprs, 1 -> Array.length exprs
+    | _, 1 -> 0
+    | Vector exprs, _ when i > 1 -> size exprs.(0) (i - 1)
+    | _, _ -> assert false
+  and vector_mult exprs exprs' =
+    let exprs = ArrayExt.map2 evaluate_times exprs exprs' in
+    match Array.length exprs with
+    | 0 -> assert false
+    | 1 -> exprs.(0)
+    | n ->
+        let exprs' = Array.sub exprs 1 (n - 1) in
+        Array.fold_left evaluate_plus exprs.(0) exprs' in
+  match expr, expr' with
+  | Integer 0l, _ | _, Integer 0l -> Integer 0l
+  | Integer 1l, _ -> expr'
+  | _, Integer 1l -> expr
+  | Integer i, Integer i' -> Integer (Int32.mul i i')
+  | Integer i, Real f | Real f, Integer i -> Real (f *. Int32.to_float i)
+  | Real f, Real f' -> Real (f *. f')
+  | _, Vector exprs' when (ndims expr = 0) ->
+      Vector (Array.map (evaluate_times expr) exprs')
+  | Vector exprs, _ when (ndims expr' = 0) ->
+      Vector (Array.map (evaluate_times expr') exprs)
+  | Vector exprs, Vector exprs' when (ndims expr = 1) && (ndims expr' = 1) ->
+      vector_mult exprs exprs'
+  | Vector exprs, Vector exprs' when (ndims expr = 1) && (ndims expr' = 2) ->
+      let f j = vector_mult exprs (column exprs' j) in
+      Vector (Array.init (size expr' 2) f)
+  | Vector exprs, Vector exprs' when (ndims expr = 2) && (ndims expr' = 1) ->
+      let f i = vector_mult (line exprs i) exprs' in
+      Vector (Array.init (size expr 1) f)
+  | Vector exprs, Vector exprs' when (ndims expr = 2) && (ndims expr' = 2) ->
+      let f i j = vector_mult (line exprs i) (column exprs' j) in
+      let g i = Vector (Array.init (size expr' 2) (f i)) in
+      Vector (Array.init (size expr 1) g)
+  | _ -> BinaryOperation (Times, expr, expr')
+
+and evaluate_not_equal expr expr' = match expr, expr' with
+  | Integer i, Integer i' when i <> i' -> True
+  | Integer i, Real f | Real f, Integer i when f <> Int32.to_float i -> True
+  | Real f, Real f' when f <> f' -> True
+  | (Integer _ | Real _), (Integer _ | Real _) -> False
+  | Vector exprs, Vector exprs'
+    when
+      ArrayExt.exists2
+        (fun expr expr' -> evaluate_equalequal expr expr' = False)
+        exprs
+        exprs' -> True
+  | Vector _, Vector _ -> False
+  | _ -> BinaryOperation (NotEqual, expr, expr')
+
+and evaluate_or expr expr' = match expr, expr' with
+  | True, (False | True) | False, True -> True
+  | False, False -> False
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_or exprs exprs')
+  | _ -> BinaryOperation (Or, expr, expr')
+
+and evaluate_plus expr expr' = match expr, expr' with
+  | Integer 0l, _ -> expr'
+  | _, Integer 0l -> expr
+  | Integer i, Integer i' -> Integer (Int32.add i i')
+  | Integer i, Real f | Real f, Integer i -> Real (f +. Int32.to_float i)
+  | Real f, Real f' -> Real (f +. f')
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_plus exprs exprs')
+  | _ -> BinaryOperation (Plus, expr, expr')
+
+and evaluate_power ctx expr expr' =
+  match expr, expr' with
+  | (Integer 0l | Real 0.), (Integer 0l | Real 0.) ->
+      raise (InstantError
+        { err_msg = ["_ZeroRaisedToTheZeroPower"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | (Integer 0l | Real 0.), Integer i'
+    when Int32.compare i' 0l < 0 ->
+      raise (InstantError
+        { err_msg = ["_ZeroRaisedToNegativePower"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | (Integer 0l | Real 0.), Real f' when f' < 0. ->
+      raise (InstantError
+        { err_msg = ["_ZeroRaisedToNegativePower"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | Integer 0l, Integer _ ->
+      (* We know the answer for sure since second argument is constant *)
+      Real 0.
+  | (Integer 0l | Real 0.), (Integer _ | Real _) -> Real 0.
+  | Integer i, Real _ when Int32.compare i 0l < 0 ->
+      raise (InstantError
+        { err_msg = ["_RealExponentOfNegativeNumber"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | Real f, Real _ when f < 0. ->
+      raise (InstantError
+        { err_msg = ["_RealExponentOfNegativeNumber"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | Integer i, Integer i' ->
+      Real ((Int32.to_float i) ** (Int32.to_float i'))
+  | Integer i, Real f -> Real ((Int32.to_float i) ** f)
+  | Real f, Integer i' -> Real (f ** (Int32.to_float i'))
+  | Real f, Real f' -> Real (f ** f')
+  | Vector exprs, Integer i ->
+      raise (InstantError
+        { err_msg = ["_NotYetImplemented";
+                     "_VectorRaisedToIntegerPower"];
+          err_info = [];
+          err_ctx = ctx })
+  | _ -> BinaryOperation (Power, expr, expr')
+
+and evaluate_minus expr expr' = match expr, expr' with
+  | Integer 0l, _ -> evaluate_unary_minus expr'
+  | _, Integer 0l -> expr
+  | Integer i, Integer i' -> Integer (Int32.sub i i')
+  | Integer i, Real f -> Real (Int32.to_float i -. f)
+  | Real f, Integer i -> Real (f -. Int32.to_float i)
+  | Real f, Real f' -> Real (f -. f')
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_minus exprs exprs')
+  | _ -> BinaryOperation (Minus, expr, expr')
+
+and evaluate_class_function_invocation cl_def exprs =
+  FunctionCall (ClassReference cl_def, exprs)
+
+and evaluate_predefined_function_invocation ctx s exprs =
+  match s, exprs with
+  | "size", _ -> evaluate_size exprs
+  | "reinit", [expr; expr'] -> evaluate_reinit expr expr'
+  | "der", [expr] -> evaluate_der expr
+  | "pre", [expr] -> evaluate_pre expr
+  | ("edge" | "change" | "initial" | "terminal" | "sample" |
+    "delay" | "assert" | "terminate"), _ ->
+      raise (InstantError
+        { err_msg = ["_NotYetImplemented"; "_PredefinedOperator"; s];
+          err_info = [];
+          err_ctx = ctx}) (*error*)
+  | "abs", [expr] -> evaluate_abs expr
+  | "sign", [expr] -> evaluate_sign expr
+  | "cos", [expr] -> evaluate_cos expr
+  | "sin", [expr] -> evaluate_sin expr
+  | "tan", [expr] -> evaluate_tan expr
+  | "exp", [expr] -> evaluate_exp expr
+  | "log", [expr] -> evaluate_log expr
+  | "sqrt", [expr] -> evaluate_sqrt expr
+  | "asin", [expr] -> evaluate_asin expr
+  | "acos", [expr] -> evaluate_acos expr
+  | "atan", [expr] -> evaluate_atan expr
+  | "sinh", [expr] -> evaluate_sinh expr
+  | "cosh", [expr] -> evaluate_cosh expr
+  | "tanh", [expr] -> evaluate_tanh expr
+  | "asinh", [expr] -> evaluate_asinh expr
+  | "acosh", [expr] -> evaluate_acosh expr
+  | "atanh", [expr] -> evaluate_atanh expr
+  | "log10", [expr] -> evaluate_log10 expr
+  | "max", [expr; expr'] -> evaluate_max expr expr'
+  | "min", [expr; expr'] -> evaluate_min expr expr'
+  | "div", [expr; expr'] -> evaluate_div ctx expr expr'
+  | "mod", [expr; expr'] -> evaluate_mod expr expr'
+  | "rem", [expr; expr'] -> evaluate_rem expr expr'
+  | "ceil", [expr] -> evaluate_ceil expr
+  | "floor", [expr] -> evaluate_floor expr
+  | "max", [expr] -> evaluate_max_array expr
+  | "min", [expr] -> evaluate_min_array expr
+  | "sum", [expr] -> evaluate_sum expr
+  | "product", [expr] -> evaluate_product expr
+  | "scalar", [expr] -> evaluate_scalar ctx expr
+  | "ones", exprs -> evaluate_ones ctx exprs
+  | "zeros", exprs -> evaluate_zeros ctx exprs
+  | "fill", expr :: exprs -> evaluate_fill ctx expr exprs
+  | "identity", [expr] -> evaluate_identity ctx expr
+  | "diagonal", [expr] -> evaluate_diagonal ctx expr
+  | "vector", [ expr ] -> evaluate_vector_operator ctx expr
+  | "matrix", [ expr ] -> evaluate_matrix_operator ctx expr
+  | "transpose", [ expr ] -> evaluate_transpose expr
+  | "symmetric", [ expr ] -> evaluate_symmetric ctx expr
+  | _ ->
+      raise (InstantError
+        { err_msg = ["_UnknownFunction"; s];
+          err_info = [];
+          err_ctx = ctx}) (*error*)
+
+and evaluate_symmetric ctx expr = match expr with
+  | Vector [||] -> assert false
+  | Vector exprs when size exprs.(0) 0 <> Array.length exprs ->
+      raise (InstantError
+        { err_msg = ["_InvalidArgOfOper"; "symmetric"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | Vector exprs ->
+      let f i j =
+        if i > j then element i (element j expr)
+        else element j (element i expr) in
+      let n = Array.length exprs in
+      let g i = Vector (Array.init n (f i)) in
+      Vector (Array.init n g)
+   | _ -> assert false
+
+and evaluate_transpose expr =
+  match expr with
+  | Vector exprs  ->
+      let f i = Vector (Array.map (element i) exprs) in
+      Vector (Array.init (size expr 1) f)
+  | _ -> assert false
+
+and evaluate_matrix_operator ctx expr =
+  let rec scalar expr = match expr with
+    | Vector [| expr |] -> scalar expr
+    | Vector _ ->
+        raise (InstantError
+          { err_msg = ["_InvalidArgOfOper"; "matrix"];
+            err_info = [];
+            err_ctx = ctx }) (*error*)
+    | _ -> expr in
+  match expr with
+  | _ when ndims expr < 2 ->
+      evaluate_promote ctx 2 expr
+  | _ when ndims expr = 2 -> expr
+  | Vector exprs ->
+      let f expr = Vector (Array.map scalar (array_elements expr)) in
+      Vector (Array.map f exprs)
+  | _ -> assert false
+
+and evaluate_promote ctx n expr =
+  let rec evaluate_promote' i expr =
+    match expr with
+    | _ when i = 0 -> expr
+    | Vector exprs when i > 0 ->
+        Vector (Array.map (evaluate_promote' i) exprs)
+    | _ when i > 0 ->
+        Vector [| evaluate_promote' (i - 1) expr |]
+    | _ -> assert false in
+  match ndims expr with
+  | n' when n' < n ->
+      evaluate_promote' (n - n') expr
+  | _ -> expr
+
+and evaluate_vector_operator ctx expr =
+  let rec evaluate_scalar expr = match expr with
+    | Vector [| expr |] -> evaluate_scalar expr
+    | Vector _ ->
+        raise (InstantError
+          { err_msg = ["_InvalidArgOfOper"; "vector"];
+            err_info = [];
+            err_ctx = ctx }) (*error*)
+    | _ -> expr
+  and evaluate_vector_operator' expr = match expr with
+    | Vector [| expr |] -> evaluate_vector_operator' expr
+    | Vector exprs ->
+        Array.map evaluate_scalar exprs
+    | _ -> [| expr |] in
+  Vector (evaluate_vector_operator' expr)
+
+and evaluate_max_array expr =
+  let rec evaluate_max_list exprs = match exprs with
+    | [] -> assert false
+    | [ expr ] -> expr
+    | expr :: exprs ->
+        evaluate_max expr (evaluate_max_list exprs) in
+  evaluate_max_list (scalar_elements expr)
+
+and evaluate_min_array expr =
+  let rec evaluate_min_list exprs = match exprs with
+    | [] -> assert false
+    | [ expr ] -> expr
+    | expr :: exprs ->
+        evaluate_min expr (evaluate_min_list exprs) in
+  evaluate_min_list (scalar_elements expr)
+
+and evaluate_sum expr =
+  let rec evaluate_sum_list exprs = match exprs with
+    | [] -> Integer Int32.zero
+    | [ expr ] -> expr
+    | expr :: exprs ->
+        evaluate_plus expr (evaluate_sum_list exprs) in
+  match expr with
+  | Vector exprs ->
+      evaluate_sum_list (scalar_elements expr)
+  | _ -> assert false
+
+and evaluate_product expr =
+  let rec evaluate_product_list exprs = match exprs with
+    | [] -> Integer Int32.one
+    | [ expr ] -> expr
+    | expr :: exprs ->
+        evaluate_times expr (evaluate_product_list exprs) in
+  match expr with
+  | Vector exprs ->
+      evaluate_product_list (scalar_elements expr)
+  | _ -> assert false
+
+and evaluate_fill ctx expr exprs =
+  let rec evaluate_fill' dims = match dims with
+    | [] -> expr
+    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->
+      let i = Int32.to_int i in
+        Vector (Array.make i (evaluate_fill' dims))
+  | _ ->
+      raise (InstantError
+        { err_msg = ["_InvalidArgOfOper"; "fill"];
+          err_info = [];
+            err_ctx = ctx }) (*error*) in
+  evaluate_fill' exprs
+
+and evaluate_zeros ctx exprs =
+  let rec evaluate_zeros' dims = match dims with
+    | [] -> Integer Int32.zero
+    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->
+      let i = Int32.to_int i in
+        Vector (Array.make i (evaluate_zeros' dims))
+  | _ ->
+      raise (InstantError
+        { err_msg = ["_InvalidArgOfOper"; "zeros"];
+          err_info = [];
+            err_ctx = ctx }) (*error*) in
+  evaluate_zeros' exprs
+
+and evaluate_ones ctx exprs =
+  let rec evaluate_ones' dims = match dims with
+    | [] -> Integer Int32.one
+    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->
+      let i = Int32.to_int i in
+        Vector (Array.make i (evaluate_ones' dims))
+  | _ ->
+      raise (InstantError
+        { err_msg = ["_InvalidArgOfOper"; "ones"];
+          err_info = [];
+            err_ctx = ctx }) (*error*) in
+  evaluate_ones' exprs
+
+and evaluate_identity ctx expr =
+  let n = match expr with
+    | Integer i when Int32.compare i Int32.zero > 0 ->
+        Int32.to_int i
+  | _ ->
+      raise (InstantError
+        { err_msg = ["_InvalidArgOfOper"; "identity"];
+          err_info = [];
+            err_ctx = ctx }) (*error*) in
+  let f i j =
+    Integer (if j = i then Int32.one else Int32.zero) in
+  let g i = Vector (Array.init n (f i)) in
+  Vector (Array.init n g)
+
+and evaluate_diagonal ctx expr =
+  let exprs = match expr with
+    | Vector [||] ->
+      raise (InstantError
+        { err_msg = ["_InvalidArgOfOper"; "diagonal"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+    | Vector exprs -> exprs
+  | _ ->
+      raise (InstantError
+        { err_msg = ["_InvalidArgOfOper"; "diagonal"];
+          err_info = [];
+            err_ctx = ctx }) (*error*) in
+  let n = Array.length exprs in
+  let f i j =
+    if j = i then exprs.(i) else Integer Int32.zero in
+  let g i = Vector (Array.init n (f i)) in
+  Vector (Array.init n g)
+
+and evaluate_scalar ctx expr =
+  let rec evaluate_scalar' expr = match expr with
+    | Vector [| expr |] -> evaluate_scalar' expr
+    | Vector _ ->
+        raise (InstantError
+          { err_msg = ["_InvalidArgOfOper"; "scalar"];
+            err_info = [];
+            err_ctx = ctx }) (*error*)
+    | _ -> expr in
+  match expr with
+  | Vector [| expr |] -> evaluate_scalar' expr
+  | _ ->
+      raise (InstantError
+        { err_msg = ["_InvalidArgOfOper"; "scalar"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+
+and evaluate_reinit expr expr' = match expr, expr' with
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_reinit exprs exprs')
+  | _, _ ->
+      FunctionCall (PredefinedIdentifier "reinit", [ expr; expr' ])
+
+and evaluate_der expr = match expr with
+  | Integer _ | String _ | Real _ -> Real 0.
+  | Vector exprs -> Vector (Array.map evaluate_der exprs)
+  | BinaryOperation (Plus, expr, expr') ->
+      let expr = evaluate_der expr
+      and expr' = evaluate_der expr' in
+      BinaryOperation (Plus, expr, expr')
+  | BinaryOperation (Minus, expr, expr') ->
+      let expr = evaluate_der expr
+      and expr' = evaluate_der expr' in
+      BinaryOperation (Minus, expr, expr')
+  | BinaryOperation (Times, expr1, expr2) ->
+      let expr1' = evaluate_der expr1
+      and expr2' = evaluate_der expr2 in
+      let expr1 = BinaryOperation (Times, expr1', expr2)
+      and expr2 = BinaryOperation (Times, expr1, expr2') in
+      BinaryOperation (Plus, expr1, expr2)
+  | BinaryOperation (Divide, expr1, expr2) ->
+      let expr1' = evaluate_der expr1
+      and expr2' = evaluate_der expr2 in
+      let expr1' = BinaryOperation (Times, expr1', expr2)
+      and expr2' = BinaryOperation (Times, expr1, expr2') in
+      let expr1 = BinaryOperation (Minus, expr1', expr2')
+      and expr2 = BinaryOperation (Times, expr2, expr2) in
+      BinaryOperation (Divide, expr1, expr2)
+  | BinaryOperation (Power, expr, Integer i) ->
+      let expr' = evaluate_der expr
+      and j = Int32.sub i Int32.one in
+      let expr' = BinaryOperation (Times, Integer i, expr')
+      and expr = BinaryOperation (Power, expr, Integer j) in
+      BinaryOperation (Times, expr', expr)
+  | BinaryOperation (Power, expr, Real f) ->
+      let expr' = evaluate_der expr
+      and f' = f -. 1. in
+      let expr' = BinaryOperation (Times, Real f, expr')
+      and expr = BinaryOperation (Power, expr, Real f') in
+      BinaryOperation (Times, expr', expr)
+  | FunctionCall (PredefinedIdentifier "cos", [ expr ]) ->
+      let expr' = evaluate_der expr
+      and expr = FunctionCall (PredefinedIdentifier "sin", [ expr ]) in
+      let expr = UnaryOperation (UnaryMinus, expr) in
+      BinaryOperation (Times, expr', expr)
+  | FunctionCall (PredefinedIdentifier "sin", [ expr ]) ->
+      let expr' = evaluate_der expr
+      and expr = FunctionCall (PredefinedIdentifier "cos", [ expr ]) in
+      BinaryOperation (Times, expr', expr)
+  | FunctionCall (PredefinedIdentifier "tan", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1
+      and expr = BinaryOperation (Times, expr, expr) in
+      let expr = BinaryOperation (Plus, Real 1., expr) in
+      BinaryOperation (Times, expr1', expr)
+  | FunctionCall (PredefinedIdentifier "exp", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      BinaryOperation (Times, expr1', expr)
+  | FunctionCall (PredefinedIdentifier "log", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      BinaryOperation (Divide, expr1', expr)
+  | FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) ->
+      evaluate_der (BinaryOperation (Power, expr1, Real 0.5))
+  | FunctionCall (PredefinedIdentifier "asin", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      let expr1 = BinaryOperation (Times, expr1, expr1) in
+      let expr1 = BinaryOperation (Minus, Real 1., expr1) in
+      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in
+      BinaryOperation (Divide, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "acos", [ expr1 ]) ->
+      let expr1' = UnaryOperation (UnaryMinus, evaluate_der expr1) in
+      let expr1 = BinaryOperation (Times, expr1, expr1) in
+      let expr1 = BinaryOperation (Minus, Real 1., expr1) in
+      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in
+      BinaryOperation (Divide, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "atan", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      let expr1 = BinaryOperation (Times, expr1, expr1) in
+      let expr1 = BinaryOperation (Plus, Real 1., expr1) in
+      BinaryOperation (Divide, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "sinh", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      let expr1 = FunctionCall (PredefinedIdentifier "cosh", [ expr1 ]) in
+      BinaryOperation (Times, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "cosh", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      let expr1 = FunctionCall (PredefinedIdentifier "sinh", [ expr1 ]) in
+      BinaryOperation (Times, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "tanh", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      let expr1 = BinaryOperation (Times, expr, expr) in
+      let expr1 = BinaryOperation (Minus, Real 1., expr1) in
+      BinaryOperation (Times, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "asinh", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      let expr1 = BinaryOperation (Times, expr1, expr1) in
+      let expr1 = BinaryOperation (Plus, Real 1., expr1) in
+      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in
+      BinaryOperation (Divide, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "acosh", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      let expr1 = BinaryOperation (Times, expr1, expr1) in
+      let expr1 = BinaryOperation (Minus, expr1, Real 1.) in
+      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in
+      BinaryOperation (Divide, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "atanh", [ expr1 ]) ->
+      let expr1' = evaluate_der expr1 in
+      let expr1 = BinaryOperation (Times, expr1, expr1) in
+      let expr1 = BinaryOperation (Minus, expr1, Real 1.) in
+      BinaryOperation (Divide, expr1', expr1)
+  | FunctionCall (PredefinedIdentifier "log10", [ expr1 ]) ->
+      let expr1 = FunctionCall (PredefinedIdentifier "log", [ expr1 ]) in
+      BinaryOperation (Divide, evaluate_der expr1, Real (log 10.))
+  | FunctionCall
+      (PredefinedIdentifier ("div" | "mod" | "rem" | "ceil" | "floor"), _) ->
+      Real 0.
+  | If (alts, default) ->
+      let alts' =
+        List.map (function (cond, expr) -> (cond, evaluate_der expr)) alts in
+      If (alts', evaluate_der default)
+  | NoEvent expr -> NoEvent (evaluate_der expr)
+  | UnaryOperation (UnaryMinus, expr) ->
+      UnaryOperation (UnaryMinus, evaluate_der expr)
+  | VectorReduction (exprs, expr) ->
+      VectorReduction (exprs, evaluate_der expr)
+  | _ -> FunctionCall (PredefinedIdentifier "der", [ expr ])
+
+and evaluate_pre expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_pre exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "pre", [ expr ])
+
+and evaluate_cos expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_cos exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "cos", [ expr ])
+
+and evaluate_sin expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_sin exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "sin", [ expr ])
+
+and evaluate_tan expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_tan exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "tan", [ expr ])
+
+and evaluate_exp expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_exp exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "exp", [ expr ])
+
+and evaluate_log expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_log exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "log", [ expr ])
+
+and evaluate_sqrt expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_sqrt exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "sqrt", [ expr ])
+
+and evaluate_asin expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_asin exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "asin", [ expr ])
+
+and evaluate_acos expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_acos exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "acos", [ expr ])
+
+and evaluate_atan expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_atan exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "atan", [ expr ])
+
+and evaluate_sinh expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_sinh exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "sinh", [ expr ])
+
+and evaluate_cosh expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_cosh exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "cosh", [ expr ])
+
+and evaluate_tanh expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_tanh exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "tanh", [ expr ])
+
+and evaluate_asinh expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_asinh exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "asinh", [ expr ])
+
+and evaluate_acosh expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_acosh exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "acosh", [ expr ])
+
+and evaluate_atanh expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_atanh exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "atanh", [ expr ])
+
+and evaluate_log10 expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_log10 exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "log10", [ expr ])
+
+and evaluate_max expr expr' = match expr, expr' with
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_max exprs exprs')
+  | Real f, Real f' -> Real (max f f')
+  | _, _ ->
+      let b = BinaryOperation (GreaterEqual, expr, expr') in
+      If ([b, expr], expr')
+
+and evaluate_min expr expr' = match expr, expr' with
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_min exprs exprs')
+  | Real f, Real f' -> Real (min f f')
+  | _, _ ->
+      let b = BinaryOperation (GreaterEqual, expr', expr) in
+      If ([b, expr], expr')
+
+and evaluate_abs expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_abs exprs)
+  | Real f -> Real (abs_float f)
+  | Integer i -> Integer (Int32.abs i)
+  | _ ->
+      let b = BinaryOperation (GreaterEqual, expr, Real 0.)
+      and default = UnaryOperation (UnaryMinus, expr) in
+      If ([b, expr], default)
+
+and evaluate_sign expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_sign exprs)
+  | Real f when f > 0. -> Real 1.
+  | Real f when f < 0. -> Real (-. 1.)
+  | Real _ -> Real 0.
+  | Integer i when Int32.compare i Int32.zero > 0 ->
+      Integer Int32.one
+  | Integer i when Int32.compare i Int32.zero < 0 ->
+      Integer Int32.minus_one
+  | Integer _ -> Integer Int32.zero
+  | _ ->
+      let b = BinaryOperation (Greater, expr, Real 0.)
+      and b' = BinaryOperation (Greater, Real 0., expr) in
+      If ([(b, Integer Int32.one); (b', Integer Int32.minus_one)],
+          Integer Int32.zero)
+
+and evaluate_div ctx expr expr' = match expr, expr' with
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 (evaluate_div ctx) exprs exprs')
+  | _, Real 0. ->
+      raise (InstantError
+        { err_msg = ["_DivisionByZero"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | _, Integer i when i = Int32.zero ->
+      raise (InstantError
+        { err_msg = ["_DivisionByZero"];
+          err_info = [];
+          err_ctx = ctx }) (*error*)
+  | Integer i, Integer i' -> Integer (Int32.div i i')
+  | Real f, Integer i' ->
+      let f' = Int32.to_float i' in
+      Real (float_of_int (truncate (f /. f')))
+  | Integer i, Real f' ->
+      let f = Int32.to_float i in
+      Real (float_of_int (truncate (f /. f')))
+  | Real f, Real f' ->
+      Real (float_of_int (truncate (f /. f')))
+  | _, _ ->
+      FunctionCall (PredefinedIdentifier "div", [ expr; expr' ])
+
+and evaluate_mod expr expr' = match expr, expr' with
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_mod exprs exprs')
+  | _, _ ->
+      FunctionCall (PredefinedIdentifier "mod", [ expr; expr' ])
+
+and evaluate_rem expr expr' = match expr, expr' with
+  | Vector exprs, Vector exprs' ->
+      Vector (ArrayExt.map2 evaluate_rem exprs exprs')
+  | _, _ ->
+      FunctionCall (PredefinedIdentifier "rem", [ expr; expr' ])
+
+and evaluate_ceil expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_ceil exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "ceil", [ expr ])
+
+and evaluate_floor expr = match expr with
+  | Vector exprs ->
+      Vector (Array.map evaluate_floor exprs)
+  | _ ->
+      FunctionCall (PredefinedIdentifier "floor", [ expr ])
+
+and evaluate_size exprs =
+  let rec evaluate_size' expr i = match expr, i with
+    | ComponentReference cpnt_desc, _ ->
+        evaluate_component_size cpnt_desc i
+    | Vector exprs, 1 -> Integer (Int32.of_int (Array.length exprs))
+    | Vector exprs, _ -> evaluate_size' exprs.(0) (i - 1)
+    | _ -> assert false (*error*)
+  and evaluate_component_size cpnt_desc i =
+    match evaluate cpnt_desc.component_nature, i with
+      | DynamicArray _, _ -> FunctionCall (PredefinedIdentifier "size", exprs)
+      | StaticArray cpnt_descs, 1 ->
+          Integer (Int32.of_int (Array.length cpnt_descs))
+      | StaticArray cpnt_descs, _ ->
+          evaluate_component_size cpnt_descs.(i) (i - 1)
+      | _ -> assert false (*error*)
+  and evaluate_size_list = function
+    | ComponentReference cpnt_desc -> assert false
+    | Vector exprs ->
+        let size = Integer (Int32.of_int (Array.length exprs)) in
+        size :: evaluate_size_list exprs.(0)
+    | _ -> [] in
+  match exprs with
+    | [expr] -> Vector (Array.of_list (evaluate_size_list expr))
+    | [expr; Integer i] -> evaluate_size' expr (Int32.to_int i)
+    | [expr; _] -> FunctionCall (PredefinedIdentifier "size", exprs)
+    | _ -> assert false (*error*)
+
+and evaluate_not expr = match expr with
+  | True -> False
+  | False -> True
+  | Vector exprs -> Vector (Array.map evaluate_not exprs)
+  | _ -> UnaryOperation (Not, expr)
+
+and evaluate_unary_minus expr = match expr with
+  | Integer i -> Integer (Int32.neg i)
+  | Real f -> Real (~-. f)
+  | Vector exprs -> Vector (Array.map evaluate_unary_minus exprs)
+  | _ -> UnaryOperation (UnaryMinus, expr)
+
+and field_access ctx expr id =
+  let rec field_access' = function
+    | ClassReference cl_def ->
+        let cpnt_desc = create_temporary_instance ctx cl_def in
+        component_field_access cpnt_desc
+    | ComponentReference cpnt_desc -> component_field_access cpnt_desc
+    | Record fields -> List.assoc id fields
+    | Vector exprs -> Vector (Array.map field_access' exprs)
+    | _ -> FieldAccess (expr, id)
+  and component_field_access cpnt_desc =
+    match evaluate cpnt_desc.component_nature with
+      | DynamicArray _ -> FieldAccess (expr, id)
+      | Instance inst -> instance_field_access ctx inst id
+      | PredefinedTypeInstance _ ->
+          raise (InstantError
+            { err_msg = ["_CannotAccessToPredefTypeAttrib"; id];
+              err_info = [];
+              err_ctx = ctx}) (*error*)
+      | StaticArray cpnt_descs ->
+          Vector (Array.map component_field_access cpnt_descs) in
+  field_access' expr
+
+and instance_field_access ctx inst id =
+  let evaluate_component cpnt_desc =
+    let evaluate_declaration_equation = function
+      | Some expr -> evaluate expr
+      | None ->
+          raise (InstantError
+            { err_msg = ["_MissingDeclEquForFixedId"; id];
+              err_info = [];
+              err_ctx = ctx}) (*error*) in
+    let rec evaluate_parameter cpnt_desc =
+      let evaluate_predefined_type_instance predef =
+        match evaluate (List.assoc "fixed" predef.attributes) with
+        | True -> evaluate_declaration_equation cpnt_desc.declaration_equation
+        | False -> ComponentReference cpnt_desc
+        | _ -> assert false (*error*) in
+      match evaluate cpnt_desc.component_nature with
+      | PredefinedTypeInstance predef
+        when List.mem_assoc "fixed" predef.attributes ->
+          evaluate_predefined_type_instance predef
+      | DynamicArray cpnt_desc -> assert false
+      | Instance _ -> ComponentReference cpnt_desc
+      | PredefinedTypeInstance _ ->
+          evaluate_declaration_equation cpnt_desc.declaration_equation
+      | StaticArray cpnt_descs ->
+          Vector (Array.map evaluate_parameter cpnt_descs)
+          (*let f i =
+            let decl_equ = cpnt_descs.(i).declaration_equation in
+            evaluate_declaration_equation decl_equ in
+          Vector (Array.init (Array.length cpnt_descs) f)*) in
+    match cpnt_desc.variability with
+      | Types.Constant ->
+          evaluate_declaration_equation cpnt_desc.declaration_equation
+      | Types.Parameter -> evaluate_parameter cpnt_desc
+      | _ -> ComponentReference cpnt_desc in
+  let elts = evaluate inst.elements in
+  let elt_desc = List.assoc id elts.named_elements in
+  match evaluate elt_desc.element_nature with
+  | Class cl_def -> ClassReference cl_def
+  | Component cpnt_desc -> evaluate_component cpnt_desc
+
+and expression_location ctx expr =
+  match expr.NameResolve.info.NameResolve.syntax with
+    | None -> ctx.location
+    | Some expr -> expr.Syntax.info
+
+and class_name_of_component cpnt_desc =
+  let type_spec = Lazy.force cpnt_desc.NameResolve.type_specifier in
+  let expr_info = type_spec.NameResolve.info in
+  match expr_info.NameResolve.syntax with
+  | None -> ""
+  | Some expr -> Syntax.string_of_expression expr
+
+and instance_nature_of_element elt_desc =
+  match elt_desc.NameResolve.element_nature with
+    | NameResolve.Component cpnt_desc ->
+        ComponentElement (class_name_of_component cpnt_desc)
+    | _ -> ClassElement
+
+and instance_class_name instance_nature =
+  match instance_nature with
+    | ComponentElement s -> s
+    | ClassElement -> ""
+
+and flatten_expression expr =
+  let rec flatten_component cpnt_desc =
+    match evaluate cpnt_desc.component_nature with
+    | StaticArray cpnt_descs ->
+        Vector (Array.map flatten_component cpnt_descs)
+    | _ -> ComponentReference cpnt_desc in
+  match expr with
+  | ComponentReference cpnt_desc ->
+      flatten_component cpnt_desc
+  | _ -> expr
+
+and size expr i = match expr, i with
+  | Vector [||], _ -> 0
+  | Vector exprs, 0 -> Array.length exprs
+  | Vector exprs, _ when i > 0 -> size exprs.(0) (i - 1)
+  | _ -> invalid_arg "_IndexOutOfBound"
+
+and sizes expr =
+  Array.init (ndims expr) (size expr)
+
+and ndims expr =
+  let rec ndims' i expr = match expr with
+    | Vector [||] -> i + 1
+    | Vector exprs -> ndims' (i + 1) exprs.(0)
+    | _ -> i in
+  ndims' 0 expr
+
+and element i expr = match expr with
+  | Vector exprs -> exprs.(i)
+  | _ -> assert false
+
+and array_elements expr = match expr with
+  | Vector exprs -> exprs
+  | _ -> assert false
+
+and scalar_elements expr = match expr with
+  | Vector exprs ->
+      let exprss =
+        Array.to_list (Array.map scalar_elements exprs) in
+      List.flatten exprss
+  | _ -> [ expr ]
+
+(* for debug*)
+
+and generate_expression oc = function
+  | BinaryOperation (bin_op, expr, expr') ->
+      generate_binary_operation oc bin_op expr expr'
+  | ClassReference cl_def ->
+      generate_class_reference oc cl_def
+  | ComponentReference cpnt_desc ->
+      generate_component_reference oc cpnt_desc
+  | EnumerationElement _ -> assert false
+  | False -> assert false
+  | FieldAccess _ -> assert false
+  | FunctionCall (expr, exprs) ->
+      generate_function_call oc expr exprs
+  | If (alts, expr) -> generate_if oc alts expr
+  | IndexedAccess _ -> assert false
+  | Integer i when Int32.to_int i >= 0 ->
+      Printf.fprintf oc "%ld" i
+  | Integer i ->
+      let expr = Integer (Int32.neg i)
+      and un_op = UnaryMinus in
+      generate_unary_operation oc un_op expr
+  | LoopVariable _ -> Printf.fprintf oc "LoopVariable"
+  | NoEvent expr -> generate_no_event oc expr
+  | PredefinedIdentifier id -> Printf.fprintf oc "%s" id
+  | Range _ -> Printf.fprintf oc "Range"
+  | Real f ->
+      Printf.fprintf oc "%s" (string_of_float f)
+  | Record _ -> Printf.fprintf oc "Record"
+  | String _ -> Printf.fprintf oc "String"
+  | True -> Printf.fprintf oc "True"
+  | Tuple _ -> Printf.fprintf oc "Tuple"
+  | UnaryOperation (un_op, expr) ->
+      generate_unary_operation oc un_op expr
+  | Vector exprs ->
+      generate_vector oc exprs
+  | VectorReduction _ -> Printf.fprintf oc "VectorReduction"
+
+and generate_binary_operation oc bin_op expr expr' =
+  let string_of_binary_operation_kind = function
+    | And -> "and"
+    | Divide -> "/"
+    | EqualEqual -> "=="
+    | GreaterEqual -> ">="
+    | Greater -> ">"
+    | LessEqual -> "<="
+    | Less -> "<"
+    | Times -> "*"
+    | NotEqual -> "<>"
+    | Or -> "or"
+    | Plus -> "+"
+    | Power -> "^"
+    | Minus -> "-" in
+  Printf.fprintf oc "(";
+  generate_expression oc expr;
+  Printf.fprintf oc " %s " (string_of_binary_operation_kind bin_op);
+  generate_expression oc expr';
+  Printf.fprintf oc ")"
+
+and generate_class_reference oc cl_def =
+  let rec last = function
+    | [] -> assert false
+    | [Name id] -> id
+    | [Index _] -> assert false
+    | _ :: path -> last path in
+  let generate_external_call ext_call =
+    match ext_call.NameResolve.nature with
+      | NameResolve.PrimitiveCall "builtin" ->
+          Printf.fprintf oc "builtin"
+      | NameResolve.PrimitiveCall "C" ->
+          Printf.fprintf oc "PrimitiveCall"
+      | NameResolve.PrimitiveCall lang -> assert false
+      | NameResolve.ExternalProcedureCall _ -> assert false in
+  let generate_long_dscription long_desc =
+    match evaluate long_desc.NameResolve.external_call with
+      | None -> assert false
+      | Some ext_call -> generate_external_call ext_call in
+  match cl_def.description with
+    | ClassDescription (_, cl_desc) ->
+        generate_long_dscription cl_desc.long_description
+    | PredefinedType _ -> assert false
+
+and generate_component_reference oc cpnt_desc =
+  let name = ident_of_path cpnt_desc.component_path in
+  Printf.fprintf oc "%s" name
+
+and generate_function_call oc expr exprs =
+  generate_expression oc expr;  
+  Printf.fprintf oc "(";
+  generate_expressions oc exprs;
+  Printf.fprintf oc ")"
+
+and generate_expressions oc = function
+  | [] -> ()
+  | [expr] -> generate_expression oc expr;
+  | expr :: exprs ->
+      generate_expression oc expr;
+      Printf.fprintf oc ", ";
+      generate_expressions oc exprs
+
+and generate_if oc alts expr =
+  let rec generate_alternatives = function
+    | [] -> Printf.fprintf oc " "; generate_expression oc expr
+    | (expr, expr') :: alts ->
+        Printf.fprintf oc "(if ";
+        generate_expression oc expr;
+        Printf.fprintf oc " then ";
+        generate_expression oc expr';
+        Printf.fprintf oc " else";
+        generate_alternatives alts;
+        Printf.fprintf oc ")" in
+  generate_alternatives alts
+
+and generate_no_event oc expr =
+  Printf.fprintf oc "noEvent(";
+  generate_expression oc expr;
+  Printf.fprintf oc ")"
+
+and generate_unary_operation oc un_op expr =
+  let string_of_unary_operation_kind = function
+    | Not -> "not"
+    | UnaryMinus -> "-" in
+  Printf.fprintf oc "(%s " (string_of_unary_operation_kind un_op);
+  generate_expression oc expr;
+  Printf.fprintf oc ")"
+
+and generate_vector oc exprs =
+  let exprs' = Array.to_list exprs in
+  Printf.fprintf oc "{ ";
+  generate_expressions oc exprs';
+  Printf.fprintf oc " }"
+
+and last_id path =
+  let rec last_id' id path = match path with
+    | [] -> id
+    | (Name id) :: path -> last_id' id path
+    | (Index _) :: path -> last_id' id path in
+  last_id' "" path
+
+and string_of_float f =
+  let add_parenthesis s =
+    if String.contains s '-' then Printf.sprintf "(%s)" s else s in
+  match Printf.sprintf "%.16g" f with
+  | s when (String.contains s '.') || (String.contains s 'e') ->
+      add_parenthesis s
+  | s -> add_parenthesis (Printf.sprintf "%s." s)
+
+and ident_of_path path =
+  let rec ident_of_path' path =
+    match path with
+    | [] -> assert false
+    | [Name id] -> id
+    | [Index i] -> Printf.sprintf "[%d]" (i + 1)
+    | Name id :: path ->
+        Printf.sprintf "%s.%s" id (ident_of_path' path)
+    | Index i :: path ->
+        Printf.sprintf "[%d].%s" (i + 1) (ident_of_path' path) in
+  match path with
+  | [] -> assert false
+  | [Name id] -> assert false
+  | [Index i] -> assert false
+  | Name id :: path ->
+      Printf.sprintf "`%s`" (ident_of_path' path)
+  | Index i :: path -> assert false
+