1(*
2 *  Translator from Modelica 2.x to flat Modelica
3 *
4 *  Copyright (C) 2005 - 2007 Imagine S.A.
5 *  For more information or commercial use please contact us at www.amesim.com
6 *
7 *  This program is free software; you can redistribute it and/or
8 *  modify it under the terms of the GNU General Public License
9 *  as published by the Free Software Foundation; either version 2
10 *  of the License, or (at your option) any later version.
11 *
12 *  This program is distributed in the hope that it will be useful,
13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *  GNU General Public License for more details.
16 *
17 *  You should have received a copy of the GNU General Public License
18 *  along with this program; if not, write to the Free Software
19 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *)
22
23type ('a, 'b) node =
24  {
25    nature: 'a;
26    info: 'b
27  }
28
29type instance =
30  {
31    enclosing_instance: instance option;
32    kind: Types.kind;
33    elements: instance_elements Lazy.t
34  }
35
36and instance_elements =
37  {
38    named_elements: (string * element_description) list;
39    unnamed_elements: equation_or_algorithm_clause list
40  }
41
42and element_description =
43  {
44    redeclare: bool;
45    element_nature: element_nature Lazy.t
46  }
47
48and element_nature =
49  | Class of class_definition
50  | Component of component_description
51
52and class_definition =
53  {
54    class_type: Types.class_specifier;
55    class_path: path;
56    class_flow: bool option;
57    class_variability: Types.variability option;
58    class_causality: Types.causality option;
59    description: description;
60    modification: modification_argument list;
61    class_location: Parser.location
62  }
63
64and path = path_element list
65
66and path_element =
67  | Name of string
68  | Index of int
69
70and description =
71  | ClassDescription of context * class_description
72  | PredefinedType of predefined_type
73
74and class_description =
75  {
76    class_kind: Types.kind;
77    class_annotations: (annotation list) Lazy.t;
78    long_description: NameResolve.long_description
79  }
80
81and annotation =
82  | InverseFunction of inverse_function Lazy.t
83  | UnknownAnnotation of Parser.location Syntax.class_modification Lazy.t
84
85and inverse_function =
86  {
87    function_class: class_definition;
88    arguments: (string * string) list
89  }
90
91and class_modification = (string * modification_argument) list
92
93and modification_argument =
94  {
95    each: bool;
96    action: modification_action
97  }
98
99and modification_action =
100  | ElementModification of modification
101  | ElementRedeclaration of element_description
102
103and modification =
104  | Modification of class_modification * expression Lazy.t option
105  | Assignment of expression Lazy.t
106  | Equality of expression Lazy.t
107
108and component_description =
109  {
110    component_path: path;
111    flow: bool;
112    variability: Types.variability;
113    causality: Types.causality;
114    component_nature: component_nature Lazy.t;
115    declaration_equation: expression Lazy.t option;
116    comment: string;
117    component_location: Parser.location;
118    class_name: string
119  }
120
121and component_nature =
122  | DynamicArray of component_description
123      (* one representative member of the collection *)
124  | Instance of instance
125  | PredefinedTypeInstance of predefined_type_instance
126  | StaticArray of component_description array
127
128and predefined_type_instance =
129  {
130    predefined_type: predefined_type;
131    attributes: (string * expression Lazy.t) list
132  }
133
134and predefined_type =
135  | BooleanType
136  | IntegerType
137  | RealType
138  | StringType
139  | EnumerationType
140
141and equation_or_algorithm_clause =
142  | EquationClause of NameResolve.validity * equation list Lazy.t
143  | AlgorithmClause of NameResolve.validity * algorithm list Lazy.t
144
145and validity = Initial | Permanent
146
147and equation = (equation_desc list, NameResolve.equation) node
148
149and equation_desc =
150  | Equal of expression * expression
151  | ConditionalEquationE of (expression * equation list) list *
152      equation list
153  | ConnectFlows of NameResolve.sign * expression *
154      NameResolve.sign * expression
155  | WhenClauseE of (expression * equation list) list
156
157and algorithm = (algorithm_desc list, NameResolve.algorithm) node
158
159and algorithm_desc =
160  | Assign of expression * expression
161  | FunctionCallA of expression * expression list
162  | MultipleAssign of expression list * expression * expression list
163  | Break
164  | Return
165  | ConditionalEquationA of (expression * algorithm list) list *
166      algorithm list
167  | ForClauseA of expression (* range *) * algorithm list
168  | WhileClause of expression * algorithm list
169  | WhenClauseA of (expression * algorithm list) list
170
171and expression =
172  | BinaryOperation of binary_operator_kind * expression * expression
173  | ClassReference of class_definition
174  | ComponentReference of component_description
175  | EnumerationElement of string
176  | False
177  | FieldAccess of expression * string
178  | FunctionCall of expression * expression list
179  | If of (expression (* condition *) * expression) list *
180      expression (* default *)
181  | IndexedAccess of expression * expression list (* subscripts *)
182  | Integer of int32
183  | LoopVariable of int (* number of nested for loops to skip *)
184  | NoEvent of expression
185  | PredefinedIdentifier of string
186  | Range of expression * expression * expression
187  | Real of float
188  | Record of (string * expression) list
189  | String of string
190  | True
191  | Tuple of expression list
192  | UnaryOperation of unary_operator_kind * expression
193  | Vector of expression array
194  | VectorReduction of expression list (* ranges *) * expression
195
196and unary_operator_kind =
197  | Not
198  | UnaryMinus
199
200and binary_operator_kind =
201  | And
202  | Divide
203  | EqualEqual
204  | GreaterEqual
205  | Greater
206  | LessEqual
207  | Less
208  | Times
209  | NotEqual
210  | Or
211  | Plus
212  | Power
213  | Minus
214
215and context =
216  {
217    toplevel: (string * element_description) list Lazy.t;
218    path: path;
219    context_flow: bool option;
220    context_variability: Types.variability option;
221    context_causality: Types.causality option;
222    parent_context: context option; (* for normal parent scope lookup *)
223    class_context: context_nature; (* for normal (class-based) lookup *)
224    instance_context: instance option; (* for dynamically scoped identifiers *)
225    location: Parser.location;
226    instance_nature: instance_nature
227  }
228
229and context_nature =
230  | ToplevelContext
231  | InstanceContext of instance
232  | ForContext of context *
233      expression option (* current value of the loop variable, if available *)
234  | FunctionEvaluationContext of context * expression * expression list
235
236(* Error description *)
237and error_description =
238  {
239    err_msg: string list;
240    err_info: (string * string) list;
241    err_ctx: context
242  }
243
244and instance_nature =
245  | ClassElement
246  | ComponentElement of string
247
248exception InstantError of error_description
249
250
251(* Utilities *)
252
253let levels = ref 0
254
255let spaces () = for i = 1 to !levels do Printf.printf "  " done
256
257let nest i =
258  spaces (); Printf.printf "ForContext %ld\n" i;
259  incr levels
260
261let nest2 i =
262  spaces (); Printf.printf "ReductionContext %ld\n" i;
263  incr levels
264
265let unnest () =
266  decr levels;
267  spaces (); Printf.printf "Leaving ForContext\n"
268
269let evaluate x = Lazy.force x
270
271module ArrayExt =
272  struct
273    let map2 f a a' =
274      let l = Array.length a
275      and l' = Array.length a' in
276      if l <> l' then invalid_arg "ArrayExt.map2"
277      else begin
278        let create_array i = f a.(i) a'.(i) in
279        Array.init l create_array
280      end
281    let for_all2 f a a' =
282      let l = Array.length a
283      and l' = Array.length a' in
284      if l <> l' then invalid_arg "ArrayExt.for_all2"
285      else begin
286        let rec for_all2' i =
287          i = l || (f a.(i) a'.(i) && for_all2' (i + 1)) in
288        for_all2' 0
289      end
290    let exists2 f a a' =
291      let l = Array.length a
292      and l' = Array.length a' in
293      if l <> l' then invalid_arg "ArrayExt.exists2"
294      else begin
295        let rec exists2' i =
296          i < l && (f a.(i) a'.(i) || exists2' (i + 1)) in
297        exists2' 0
298      end
299  end
300
301
302(* Instantiation functions *)
303
304let rec evaluate_toplevel_definitions dic defs =
305  let rec ctx =
306    {
307      toplevel = lazy (dic @ evaluate defs');
308      path = [];
309      context_flow = None;
310      context_variability = None;
311      context_causality = None;
312      parent_context = None;
313      class_context = ToplevelContext;
314      instance_context = None;
315      location = {Parser.start = 0; Parser.enddd = 0; filename = Parser.CommandLine};
316      instance_nature = ClassElement
317    }
318  and defs' = lazy (List.map (evaluate_toplevel_definition ctx) defs) in
319  evaluate defs'
320
321and evaluate_toplevel_definition ctx (id, elt_desc) =
322  let elt_loc = [Name id] in
323  let ctx = {ctx with
324               path = elt_loc;
325               location = elt_desc.NameResolve.element_location;
326               instance_nature = instance_nature_of_element elt_desc} in
327  let elt_nat = elt_desc.NameResolve.element_nature in
328  let elt_desc' =
329    {
330      redeclare = false;
331      element_nature = lazy (evaluate_toplevel_element ctx elt_loc elt_nat)
332    } in
333  id, elt_desc'
334
335and evaluate_toplevel_element ctx elt_loc = function
336  | NameResolve.Component cpnt_desc ->
337      let cpnt_desc' =
338        instantiate_component_description ctx [] None elt_loc cpnt_desc in
339      Component cpnt_desc'
340  | NameResolve.Class cl_def ->
341      let cl_def' = evaluate_class_definition ctx [] elt_loc cl_def in
342      Class cl_def'
343  | NameResolve.ComponentType _ ->
344      raise (InstantError
345        { err_msg = ["_NotYetImplemented"; "_ComponentTypeElemInstant"];
346          err_info = [];
347          err_ctx = ctx }) (*error*)
348  | NameResolve.PredefinedType _ ->
349      raise (InstantError
350        { err_msg = ["_NotYetImplemented"; "_PredefinedTypeElemInstant"];
351          err_info = [];
352          err_ctx = ctx }) (*error*)
353
354and instantiate_class_description ctx modifs rhs elt_loc cl_desc =
355  let elements inst =
356    let ctx' =
357      { ctx with
358        toplevel = lazy (evaluate ctx.toplevel);
359        path = elt_loc;
360        parent_context = Some ctx;
361        class_context = InstanceContext inst;
362        instance_context = None
363      } in
364    instantiate_class_elements ctx' modifs rhs cl_desc.long_description in
365  let rec inst =
366    {
367      enclosing_instance = enclosing_instance ctx;
368      kind = cl_desc.class_kind;
369      elements = lazy (elements inst)
370    } in
371  inst
372
373and enclosing_instance ctx = match ctx.class_context with
374  | ToplevelContext -> None
375  | InstanceContext inst -> Some inst
376  | ForContext (ctx', _) | FunctionEvaluationContext (ctx', _, _) ->
377      enclosing_instance ctx'
378
379and instantiate_class_elements ctx modifs rhs long_desc =
380  let rec merge_elements named_elts unnamed_elts = function
381    | [] ->
382        {
383          named_elements = named_elts;
384          unnamed_elements = unnamed_elts
385        }
386    | inherited_elts :: inherited_eltss ->
387        let named_elts' = named_elts @ inherited_elts.named_elements
388        and unnamed_elts' = unnamed_elts @ inherited_elts.unnamed_elements in
389        merge_elements named_elts' unnamed_elts' inherited_eltss in
390  let named_elts = long_desc.NameResolve.named_elements
391  and unnamed_elts = long_desc.NameResolve.unnamed_elements
392  and exts = long_desc.NameResolve.extensions in
393  let named_elts' = instantiate_local_named_elements ctx modifs rhs named_elts
394  and unnamed_elts' = instantiate_local_unnamed_elements ctx unnamed_elts
395  and inherited_eltss = instantiate_inherited_elements ctx modifs rhs exts in
396  merge_elements named_elts' unnamed_elts' inherited_eltss
397
398and instantiate_local_named_elements ctx modifs rhs named_elts =
399  List.fold_right (instantiate_local_named_element ctx modifs rhs) named_elts []
400
401and instantiate_local_named_element ctx modifs rhs (id, elt_desc) named_elts =
402  let rec filter_current_element_modifications = function
403    | [] -> []
404    | (id', arg) :: modifs when id' = id ->
405        arg :: filter_current_element_modifications modifs
406    | _ :: modifs -> filter_current_element_modifications modifs
407  and select_current_element_value = function
408    | None -> None
409    | Some expr -> Some (lazy (field_access ctx (evaluate expr) id)) in
410  let modifs' = filter_current_element_modifications modifs
411  and rhs' = select_current_element_value rhs
412  and elt_loc = ctx.path @ [Name id] in
413  let ctx = {ctx with
414               path = elt_loc;
415               location = elt_desc.NameResolve.element_location;
416               instance_nature = instance_nature_of_element elt_desc} in
417  let elt_nat =
418    lazy (instantiate_local_element_nature ctx modifs' rhs' elt_loc elt_desc) in
419  let named_elt =
420    id,
421    {
422      redeclare = elt_desc.NameResolve.redeclare;
423      element_nature = elt_nat
424    } in
425  named_elt :: named_elts
426
427and instantiate_local_element_nature ctx modifs rhs elt_loc elt_desc =
428  match elt_desc.NameResolve.element_nature with
429    | NameResolve.Component cpnt_desc ->
430        let cpnt_desc' =
431          instantiate_component_description ctx modifs rhs elt_loc cpnt_desc in
432       Component cpnt_desc'
433    | NameResolve.Class cl_def ->
434        let cl_def' = evaluate_class_definition ctx modifs elt_loc cl_def in
435        Class cl_def'
436    | NameResolve.ComponentType _ ->
437        raise (InstantError
438          { err_msg = ["_NotYetImplemented"; "_ComponentTypeElemInstant"];
439            err_info = [];
440            err_ctx = ctx })
441    | NameResolve.PredefinedType _ ->
442        raise (InstantError
443          { err_msg = ["_NotYetImplemented"; "_PredefinedTypeElemInstant"];
444            err_info = [];
445            err_ctx = ctx })
446
447and instantiate_component_description ctx modifs rhs elt_loc cpnt_desc =
448  let cpnt_type = evaluate cpnt_desc.NameResolve.component_type in
449  let flow = evaluate cpnt_type.Types.flow
450  and var = evaluate cpnt_type.Types.variability
451  and inout = evaluate cpnt_type.Types.causality
452  and type_spec = evaluate cpnt_desc.NameResolve.type_specifier
453  and dims = evaluate cpnt_desc.NameResolve.dimensions
454  and modifs' = match evaluate cpnt_desc.NameResolve.modification with
455    | None -> modifs
456    | Some modif ->
457        let modif' = evaluate_modification ctx modif in
458        modifs @ [{ each = false; action = ElementModification modif' }]
459  and cmt = cpnt_desc.NameResolve.comment in
460  component_nature ctx modifs' rhs elt_loc flow var inout type_spec dims cmt
461
462and component_nature ctx modifs rhs elt_loc flow var inout type_spec dims cmt =
463  let type_spec' = evaluate_expression ctx type_spec in
464  let ctx = {ctx with location = expression_location ctx type_spec} in
465  expand_array ctx modifs rhs elt_loc flow var inout type_spec' dims cmt
466
467and expand_array ctx modifs rhs elt_loc flow var inout type_spec dims cmt =
468  let rec expand_along_dimension dim dims = match dim with
469    | NameResolve.Colon -> expand_dynamic_array dims
470    | NameResolve.Expression expr ->
471        let expr' = evaluate_expression ctx expr in
472        expand_static_array dims expr' expr
473  and expand_dynamic_array dims =
474    (* No need to select modifications since all of them have 'each' set *)
475    let elt_loc' = elt_loc @ [Index 0] in
476    let ctx = { ctx with path = elt_loc' } in
477    let expr =
478      expand_array ctx modifs rhs elt_loc' flow var inout type_spec dims cmt in
479    DynamicArray expr
480  and expand_static_array dims expr' expr =
481    let ctx = {ctx with location = expression_location ctx expr} in
482    let expand_element i =
483      let rec select_subargument arg = match arg.each with
484        | true -> arg
485        | false -> { arg with action = select_subarray arg.action }
486      and select_subarray arg = match arg with
487	| ElementModification modif ->
488            ElementModification (select_submodification modif)
489        | ElementRedeclaration _ -> arg
490      and select_sub_class_modification_element (id, arg) =
491        id, select_subargument arg
492      and select_submodification = function
493        | Modification (modifs, rhs) ->
494            let modifs' = List.map select_sub_class_modification_element modifs
495            and rhs' = select_rhs_subarray rhs in
496            Modification (modifs', rhs')
497        | Assignment expr ->
498            let expr' = lazy (select_row i (evaluate expr)) in
499            Assignment expr'
500        | Equality expr ->
501            let expr' = lazy (select_row i (evaluate expr)) in
502            Equality expr'
503      and select_rhs_subarray = function
504        | None -> None
505        | Some expr -> Some (lazy (select_row i (evaluate expr)))
506      and select_row i = function
507	      | Vector exprs ->
508            begin
509              try
510                exprs.(i)
511              with
512              | _ -> raise (InstantError
513                  { err_msg = ["_IndexOutOfBound"];
514                    err_info = [];
515                    err_ctx = ctx}) (*error*)
516            end
517        | expr ->
518            let subs = [Integer (Int32.succ (Int32.of_int i))] in
519            evaluate_indexed_access ctx expr subs in
520      let modifs = List.map select_subargument modifs
521      and rhs = select_rhs_subarray rhs
522      and elt_loc = elt_loc @ [Index i] in
523      expand_array ctx modifs rhs elt_loc flow var inout type_spec dims cmt in
524    match expr' with
525      | Integer i ->
526          let a = Array.init (Int32.to_int i) expand_element in
527          StaticArray a
528      | _ ->
529          raise (InstantError
530          { err_msg = ["_NonIntegerArrayDim"];
531            err_info = [];
532            err_ctx = ctx }) (*error*) in
533  match dims with
534    | [] ->
535        let cl_def = class_definition_of_type_specification ctx type_spec in
536        create_instance ctx modifs rhs elt_loc flow var inout cl_def cmt
537    | dim :: dims ->
538        {
539          component_path = elt_loc;
540          flow = flow;
541          variability = var;
542          causality = inout;
543          component_nature = lazy (expand_along_dimension dim dims);
544          declaration_equation = rhs;
545          comment = cmt;
546          component_location = ctx.location;
547          class_name = instance_class_name ctx.instance_nature
548        }
549
550and create_instance ctx modifs rhs elt_loc flow var inout cl_def cmt =
551  let merge_class_modifications arg modifs = match arg.action with
552    | ElementModification (Modification (modifs', _)) -> modifs' @ modifs
553    | ElementModification (Assignment _ | Equality _) -> modifs
554    | ElementRedeclaration _ -> modifs in
555  let rec declaration_equation modifs rhs =
556    let rec declaration_equation' = function
557      | [] -> None
558      | {
559          action =
560            ElementModification (
561              Modification (_, Some expr) | Assignment expr | Equality expr)
562        } :: _ -> Some expr
563      | _ :: args -> declaration_equation' args in
564    match rhs with
565      | None -> declaration_equation' modifs
566      | Some _ -> rhs in
567  let flow' = match cl_def.class_flow, ctx.context_flow with
568    | None, None -> flow
569    | Some flow', None | None, Some flow' -> flow || flow'
570    | Some flow', Some flow'' -> flow || flow' || flow''
571  and var' = match cl_def.class_variability, ctx.context_variability with
572    | None, None -> var
573    | Some var', None | None, Some var' -> Types.min_variability var var'
574    | Some var', Some var'' ->
575        Types.min_variability var (Types.min_variability var' var'')
576  and inout' = match inout, cl_def.class_causality with
577    | Types.Input, _ | _, Some Types.Input -> Types.Input
578    | Types.Output, _ | _, Some Types.Output -> Types.Output
579    | _ -> Types.Acausal in
580  let modifs' =
581    List.fold_right
582      merge_class_modifications
583      (modifs @ cl_def.modification)
584      []
585  and rhs' = declaration_equation modifs rhs in
586  match cl_def.description with
587    | ClassDescription (ctx', cl_desc) ->
588        let class_name = instance_class_name ctx.instance_nature in
589        let ctx' =
590          { ctx' with
591            context_flow = Some flow';
592            context_variability = Some var';
593            context_causality = Some inout';
594            instance_context = enclosing_instance ctx;
595            instance_nature = ComponentElement class_name
596          } in
597        {
598          component_path = elt_loc;
599          flow = flow';
600          variability = var';
601          causality = inout';
602          component_nature =
603            lazy (create_class_instance ctx' modifs' rhs' elt_loc cl_desc);
604          declaration_equation = rhs';
605          comment = cmt;
606          component_location = ctx'.location;
607          class_name = class_name
608        }
609    | PredefinedType predef ->
610        let class_name = instance_class_name ctx.instance_nature in
611        let ctx' =
612          { ctx with
613            context_flow = Some flow';
614            context_variability = Some var';
615            context_causality = Some inout';
616            instance_nature = ComponentElement class_name
617          } in
618        {
619          component_path = elt_loc;
620          flow = flow';
621          variability = var';
622          causality = inout';
623          component_nature =
624            lazy (create_predefined_type_instance ctx' modifs' predef);
625          declaration_equation = rhs';
626          comment = cmt;
627          component_location = ctx'.location;
628          class_name = class_name
629        }
630
631and create_temporary_instance ctx cl_def =
632  match cl_def.description with
633    | ClassDescription (ctx', cl_desc) ->
634        {
635          component_path = [];
636          flow = false;
637          variability = Types.Continuous;
638          causality = Types.Acausal;
639          component_nature =
640            lazy (create_class_instance ctx' [] None [] cl_desc);
641          declaration_equation = None;
642          comment = "";
643          component_location = ctx'.location;
644          class_name = instance_class_name ctx.instance_nature
645        }
646    | PredefinedType predef -> assert false (*error*)
647
648and class_definition_of_type_specification ctx type_spec =
649  let predefined_class_specifier = function
650    | "Boolean" -> Types.boolean_class_type
651    | "Integer" -> Types.integer_class_type
652    | "Real" -> Types.real_class_type
653    | "String" -> Types.string_class_type
654    | s ->
655        raise (InstantError
656          { err_msg = ["_UnknownIdentifier"; s];
657            err_info = [];
658            err_ctx = ctx }) (*error*)
659  and predefined_class_description = function
660    | "Boolean" -> PredefinedType BooleanType
661    | "Integer" -> PredefinedType IntegerType
662    | "Real" -> PredefinedType RealType
663    | "String" -> PredefinedType StringType
664    | s ->
665        raise (InstantError
666          { err_msg = ["_UnknownIdentifier"; s];
667            err_info = [];
668            err_ctx = ctx }) (*error*) in
669  match type_spec with
670    | ClassReference cl_def -> cl_def
671    | PredefinedIdentifier id ->
672        {
673          class_type = predefined_class_specifier id;
674          class_path = [Name id];
675          class_flow = None;
676          class_variability = None;
677          class_causality = None;
678          description = predefined_class_description id;
679          modification = [];
680          class_location = ctx.location
681        }
682    | _ -> assert false (*error*)
683
684and create_class_instance ctx modifs rhs elt_loc cl_desc =
685  let inst = instantiate_class_description ctx modifs rhs elt_loc cl_desc in
686  Instance inst
687
688and create_predefined_type_instance ctx modifs predef =
689  let inst =
690    {
691      predefined_type = predef;
692      attributes = predefined_type_attributes ctx modifs
693    } in
694  PredefinedTypeInstance inst
695
696and predefined_type_attributes ctx modifs =
697  let rec predefined_type_attributes attrs = function
698    | [] -> attrs
699    | (id, { action = ElementModification (Equality expr) }) :: modifs
700      when not (List.mem_assoc id attrs) ->
701        let attrs' = (id, expr) :: attrs in
702        predefined_type_attributes attrs' modifs
703    | _ :: modifs -> predefined_type_attributes attrs modifs in
704  predefined_type_attributes [] modifs
705
706and instantiate_inherited_elements ctx modifs rhs exts =
707  List.fold_right (instantiate_inherited_element ctx modifs rhs) exts []
708
709and instantiate_inherited_element ctx modifs rhs (_, modif_cl) inherited_elts =
710  let instantiate_inherited_element' modifs cl_def =
711    match cl_def.description with
712      | ClassDescription (ctx', cl_desc) ->
713          let ctx' = { ctx with parent_context = Some ctx' } in
714          let long_desc = cl_desc.long_description in
715          instantiate_class_elements ctx' modifs rhs long_desc
716      | PredefinedType _ -> assert false (*error*) in
717  let type_spec = evaluate modif_cl.NameResolve.base_class
718  and modifs' = evaluate modif_cl.NameResolve.class_modification in
719  let type_spec' = evaluate_expression ctx type_spec
720  and ctx = {ctx with location = expression_location ctx type_spec} in
721  let modifs = modifs @ evaluate_class_modification ctx modifs' in
722  match type_spec' with
723    | ClassReference cl_def ->
724        instantiate_inherited_element' modifs cl_def :: inherited_elts
725    | _ -> assert false (*error*)
726
727and evaluate_class_definition ctx modifs elt_loc cl_def =
728  match evaluate cl_def.NameResolve.description with
729    | NameResolve.LongDescription long_desc ->
730        let cl_anns = long_desc.NameResolve.class_annotations in
731        let cl_def' =
732          {
733            class_kind = Types.Class;
734            class_annotations = lazy (evaluate_class_annotations ctx cl_anns);
735            long_description = long_desc
736          } in
737        {
738          class_type = evaluate cl_def.NameResolve.class_type;
739          class_path = elt_loc;
740          class_flow = None;
741          class_variability = None;
742          class_causality = None;
743          description = ClassDescription (ctx, cl_def');
744          modification = modifs;
745          class_location = ctx.location
746        }
747    | NameResolve.ShortDescription short_desc ->
748        raise (InstantError
749          {err_msg = ["_NotYetImplemented"; "_ShortClassDef"];
750           err_info = [];
751           err_ctx = {ctx with path = elt_loc;
752                      instance_nature = ClassElement}})
753
754and evaluate_class_annotations ctx cl_anns =
755  let evaluate_inverse_function inv_func =
756    let inv_func = evaluate inv_func in
757    let expr =
758      evaluate_expression ctx inv_func.NameResolve.function_class in
759    match expr with
760    | ClassReference cl_def ->
761        {
762          function_class = cl_def;
763          arguments = inv_func.NameResolve.arguments
764        }
765    | _ -> assert false (*error*) in
766  let evaluate_class_annotation cl_ann = match cl_ann with
767    | NameResolve.InverseFunction inv_func ->
768        InverseFunction (lazy (evaluate_inverse_function inv_func))
769    | NameResolve.UnknownAnnotation cl_ann ->
770        UnknownAnnotation cl_ann in
771  List.map evaluate_class_annotation (evaluate cl_anns)
772
773and evaluate_class_modification ctx cl_modif =
774  let add_modification_argument arg cl_modif' =
775    match arg.NameResolve.action with
776      | None -> cl_modif'
777      | Some modif ->
778          let arg' =
779            arg.NameResolve.target,
780            {
781              each = arg.NameResolve.each;
782              action = evaluate_modification_action ctx modif
783            } in
784          arg' :: cl_modif' in
785  List.fold_right add_modification_argument cl_modif []
786
787and evaluate_modification_action ctx = function
788  | NameResolve.ElementModification modif ->
789      let modif' = evaluate_modification ctx modif in
790      ElementModification modif'
791  | NameResolve.ElementRedeclaration elt_desc ->
792      raise (InstantError
793        { err_msg = ["_NotYetImplemented"; "_ElementRedeclaration"];
794          err_info = [];
795          err_ctx = ctx })
796
797and evaluate_modification ctx = function
798  | NameResolve.Modification (modifs, rhs) ->
799      let modifs' = evaluate_class_modification ctx modifs
800      and rhs' = evaluate_modification_expression ctx rhs in
801      Modification (modifs', rhs')
802  | NameResolve.Assignment expr ->
803      let expr = evaluate expr in
804      let ctx = {ctx with location = expression_location ctx expr} in
805      raise (InstantError
806        { err_msg = ["_NotYetImplemented"; "_AssignExprInElemModif"];
807          err_info = [];
808          err_ctx = ctx })
809  | NameResolve.Equality expr ->
810      let expr' = lazy (evaluate_expression ctx (evaluate expr)) in
811      Equality expr'
812
813and evaluate_modification_expression ctx = function
814  | None -> None
815  | Some expr ->
816      let expr' = lazy (evaluate_expression ctx (evaluate expr)) in
817      Some expr'
818
819and instantiate_local_unnamed_elements ctx unnamed_elts =
820  List.map (instantiate_local_unnamed_element ctx) (evaluate unnamed_elts)
821
822and instantiate_local_unnamed_element ctx unnamed_elt =
823  match unnamed_elt with
824    | NameResolve.EquationClause (validity, equs) ->
825        EquationClause (validity, lazy (instantiate_equations ctx equs))
826    | NameResolve.AlgorithmClause (validity, algs) ->
827        raise (InstantError
828          { err_msg = ["_NotYetImplemented"; "_AlgoClause"];
829            err_info = [];
830            err_ctx = ctx })
831
832and instantiate_equations ctx equs =
833  let instantiate_equations' equ equs =
834    let equs' =  instantiate_equation ctx equ in
835    { nature = equs'; info = equ } :: equs in
836  List.fold_right instantiate_equations' equs []
837
838and instantiate_equation ctx equ = match equ.NameResolve.nature with
839  | NameResolve.Equal (expr, expr') -> instantiate_equal ctx expr expr'
840  | NameResolve.ConditionalEquationE (alts, default) ->
841      instantiate_conditional_equation ctx alts default
842  | NameResolve.ForClauseE (ranges, equs) ->
843      instantiate_for_clause_e ctx ranges equs
844  | NameResolve.ConnectFlows (sign, expr, sign', expr') ->
845      instantiate_connection ctx sign expr sign' expr'
846  | NameResolve.WhenClauseE alts ->
847      instantiate_when_clause_e ctx alts
848
849and instantiate_equal ctx expr expr' =
850  let rec equal_expr expr expr' =
851    match expr, expr' with
852    | BinaryOperation (bin_oper_kind, expr1, expr2),
853      BinaryOperation (bin_oper_kind', expr1', expr2') ->
854        (bin_oper_kind = bin_oper_kind') &&
855        (equal_expr expr1 expr1') &&
856        (equal_expr expr2 expr2')
857    | ClassReference cl_def, ClassReference cl_def' ->
858        cl_def.class_path = cl_def'.class_path
859    | ComponentReference cpnt_desc, ComponentReference cpnt_desc' ->
860        cpnt_desc.component_path = cpnt_desc'.component_path
861    | EnumerationElement s, EnumerationElement s' -> s = s'
862    | False, False -> true
863    | FieldAccess (expr, s), FieldAccess (expr', s') ->
864        (equal_expr expr expr') && (s = s')
865    | FunctionCall (expr, exprs), FunctionCall (expr', exprs') ->
866        (equal_expr expr expr') &&
867        (List.length exprs = List.length exprs') &&
868        (List.for_all2 (=) exprs exprs')
869    | If (alts, default), If (alts', default') ->
870        let f (cond, expr) (cond', expr') =
871          (equal_expr cond cond') && (equal_expr expr expr') in
872        (List.length alts = List.length alts') &&
873        (List.for_all2 f alts alts') &&
874        (equal_expr default default')
875    | IndexedAccess (expr, exprs), IndexedAccess (expr', exprs') ->
876        (equal_expr expr expr') &&
877        (List.length exprs = List.length exprs') &&
878        (List.for_all2 (=) exprs exprs')
879    | Integer i, Integer i' -> Int32.compare i i' = 0
880    | LoopVariable i, LoopVariable i' -> i = i'
881    | NoEvent expr, NoEvent expr' -> equal_expr expr expr'
882    | PredefinedIdentifier s, PredefinedIdentifier s' -> s = s'
883    | Range (start, step, stop), Range (start', step', stop') ->
884        (equal_expr start start') &&
885        (equal_expr step step') &&
886        (equal_expr stop stop')
887    | Real f, Real f' -> f = f'
888    | Record elts, Record elts' ->
889        let f (s, expr) (s', expr') =
890          (s = s') && (equal_expr expr expr') in
891        (List.length elts = List.length elts') &&
892        (List.for_all2 f elts elts')
893    | String s, String s' -> s = s'
894    | True, True -> true
895    | Tuple exprs, Tuple exprs' ->
896        (List.length exprs = List.length exprs') &&
897        (List.for_all2 equal_expr exprs exprs')
898    | UnaryOperation (un_oper_kind, expr),
899      UnaryOperation (un_oper_kind', expr') ->
900        (un_oper_kind = un_oper_kind') &&
901        (equal_expr expr expr')
902    | Vector exprs, Vector exprs' ->
903        (Array.length exprs = Array.length exprs') &&
904        (ArrayExt.for_all2 equal_expr exprs exprs')
905    | VectorReduction (exprs, expr), VectorReduction (exprs', expr') ->
906        (List.length exprs = List.length exprs') &&
907        (List.for_all2 equal_expr exprs exprs') &&
908        (equal_expr expr expr')
909    | _ -> false in
910  let expr = evaluate_expression ctx expr
911  and expr' = evaluate_expression ctx expr' in
912  match equal_expr expr expr' with
913  | true -> []
914  | false -> [ Equal (expr, expr') ]
915
916and instantiate_conditional_equation ctx alts default =
917  let rec instantiate_alternatives acc = function
918    | [] -> instantiate_default acc default
919    | (cond, equs) :: alts -> instantiate_alternative acc cond equs alts
920  and instantiate_alternative acc cond equs alts =
921    let cond' = evaluate_expression ctx cond in
922    match cond' with
923      | False -> instantiate_alternatives acc alts
924      | True -> instantiate_default acc equs
925      | _ ->
926          let equs' = instantiate_equations ctx equs in
927          instantiate_alternatives ((cond', equs') :: acc) alts
928  and instantiate_default acc equs =
929    let equs' = instantiate_equations ctx equs in
930    [ConditionalEquationE (List.rev acc, equs')] in
931  let alts' = instantiate_alternatives [] alts in
932  List.flatten (List.map (expand_equation ctx) alts')
933
934and expand_equation ctx equ =
935  let rec expand_equation' equ =
936    let expand_conditional_equation alts default =
937      let add_alternative (b, equs) altss =
938        let g equ = List.flatten (List.map expand_equation' equ.nature) in
939        let equs' = List.flatten (List.map g equs) in
940        let f (expr1, expr2) (expr1', expr2') = match expr1, expr2 with
941          | If (alts1, default1), If (alts2, default2) ->
942              If ((b, expr1') :: alts1, default1),
943              If ((b, expr2') :: alts2, default2)
944          | _ -> assert false in
945        try
946          List.map2 f altss equs'
947        with
948        | _ ->
949            raise (InstantError
950              {err_msg = ["_InvalidCondEquation"];
951               err_info = [];
952               err_ctx = ctx}) in
953      let g equ = List.flatten (List.map expand_equation' equ.nature) in
954      let default' = List.flatten (List.map g default) in
955      let f = function (expr1, expr2) -> If ([], expr1), If ([], expr2) in
956      List.fold_right add_alternative alts (List.map f default') in
957    match equ with
958    | ConditionalEquationE (alts, default) ->
959        expand_conditional_equation alts default
960    | Equal (expr, expr') -> [ expr, expr' ]
961    | _ ->
962        raise (InstantError
963          {err_msg = ["_InvalidCondEquation"];
964           err_info = [];
965           err_ctx = ctx}) in
966  let f (expr, expr') = Equal (expr, expr') in
967  List.map f (expand_equation' equ)
968
969and instantiate_when_clause_e ctx alts =
970  let instantiate_alternative (cond, equs) =
971    let cond' = evaluate_expression ctx cond in
972    let equs' = instantiate_equations ctx equs in
973    cond', equs' in
974  [WhenClauseE (List.map instantiate_alternative alts)]
975
976and instantiate_connection ctx sign expr sign' expr' =
977  let expr = evaluate_expression ctx expr
978  and expr' = evaluate_expression ctx expr' in
979  [ConnectFlows (sign, expr, sign', expr')]
980
981and instantiate_for_clause_e ctx ranges equs =
982  let rec instantiate_for_clause_e' ctx = function
983    | [] -> List.flatten (List.map (instantiate_equation ctx) equs)
984    | ranges -> equations_of_reduction ctx ranges
985  and equations_of_reduction ctx ranges = match ranges with
986    | (Vector exprs) :: ranges ->
987        let f expr =
988          let ctx' =
989            { ctx with
990              class_context = ForContext (ctx, Some expr)
991            } in
992          instantiate_for_clause_e' ctx' ranges in
993        List.flatten (List.map f (Array.to_list exprs))
994    | _ ->
995        raise (InstantError
996          {err_msg = ["_InvalidForClauseRange"];
997           err_info = [];
998           err_ctx = ctx}) in
999  let ranges = List.map (evaluate_expression ctx) ranges in
1000  instantiate_for_clause_e' ctx ranges
1001
1002and evaluate_expression ctx expr =
1003  let ctx = {ctx with location = expression_location ctx expr} in
1004  match expr.NameResolve.nature with
1005    | NameResolve.BinaryOperation (binop, expr, expr') ->
1006        evaluate_binary_operation ctx binop expr expr'
1007    | NameResolve.DynamicIdentifier (level, id) ->
1008        evaluate_dynamic_identifier ctx level id
1009    | NameResolve.False -> False
1010    | NameResolve.FieldAccess (expr, id) ->
1011        evaluate_field_access ctx expr id
1012    | NameResolve.FunctionArgument pos -> evaluate_function_argument ctx pos
1013    | NameResolve.FunctionCall (expr, exprs, expr') ->
1014        evaluate_function_call ctx expr exprs expr'
1015    | NameResolve.FunctionInvocation exprs ->
1016        evaluate_function_invocation ctx exprs
1017    | NameResolve.If (alts, default) -> evaluate_if ctx alts default
1018    | NameResolve.IndexedAccess (expr, exprs) ->
1019        let expr = evaluate_expression ctx expr
1020        and exprs = List.map (evaluate_expression ctx) exprs in
1021        evaluate_indexed_access ctx expr exprs
1022    | NameResolve.Integer i -> Integer i
1023    | NameResolve.LocalIdentifier (level, id) ->
1024        evaluate_local_identifier ctx level id
1025    | NameResolve.LoopVariable level -> evaluate_loop_variable ctx level
1026    | NameResolve.NoEvent expr -> evaluate_no_event ctx expr
1027    | NameResolve.PredefinedIdentifier id -> PredefinedIdentifier id
1028    | NameResolve.Range (start, step, stop) ->
1029        evaluate_range ctx start step stop
1030    | NameResolve.Real f -> Real f
1031    | NameResolve.String s -> String s
1032    | NameResolve.ToplevelIdentifier id ->
1033        evaluate_toplevel_identifier ctx id
1034    | NameResolve.True -> True
1035    | NameResolve.Tuple exprs -> evaluate_tuple ctx exprs
1036    | NameResolve.UnaryOperation (unop, expr) ->
1037        evaluate_unary_operation ctx unop expr
1038    | NameResolve.VectorReduction (ranges, expr) ->
1039        evaluate_vector_reduction ctx ranges expr
1040    | NameResolve.Vector exprs -> evaluate_vector ctx exprs
1041    | NameResolve.Coercion (coer, expr) ->
1042        evaluate_coercion ctx coer expr
1043
1044and evaluate_binary_operation ctx binop expr expr' =
1045  let expr = evaluate_expression ctx expr
1046  and expr' = evaluate_expression ctx expr' in
1047  let expr = flatten_expression expr
1048  and expr' = flatten_expression expr' in
1049  match binop with
1050    | NameResolve.And -> evaluate_and expr expr'
1051    | NameResolve.Divide -> evaluate_divide ctx expr expr'
1052    | NameResolve.EqualEqual -> evaluate_equalequal expr expr'
1053    | NameResolve.GreaterEqual -> evaluate_greater_equal expr expr'
1054    | NameResolve.Greater -> evaluate_greater expr expr'
1055    | NameResolve.LessEqual -> evaluate_less_equal expr expr'
1056    | NameResolve.Less -> evaluate_less expr expr'
1057    | NameResolve.Times -> evaluate_times expr expr'
1058    | NameResolve.NotEqual -> evaluate_not_equal expr expr'
1059    | NameResolve.Or -> evaluate_or expr expr'
1060    | NameResolve.Plus -> evaluate_plus expr expr'
1061    | NameResolve.Power -> evaluate_power ctx expr expr'
1062    | NameResolve.Minus -> evaluate_minus expr expr'
1063
1064and evaluate_dynamic_identifier ctx level id =
1065  let rec evaluate_dynamic_identifier' inst level =
1066    match level, inst.enclosing_instance with
1067    | 0, _ -> instance_field_access ctx inst id
1068    | _, Some inst -> evaluate_dynamic_identifier' inst (level - 1)
1069    | _, None -> assert false (*error*) in
1070  match ctx.instance_context with
1071    | Some inst -> evaluate_dynamic_identifier' inst level
1072    | None -> assert false (*error*)
1073
1074and evaluate_field_access ctx expr id =
1075  let expr = evaluate_expression ctx expr in
1076  field_access ctx expr id
1077
1078and evaluate_function_argument ctx pos = match ctx.class_context with
1079  | FunctionEvaluationContext (_, expr, _) when pos = 0 -> expr
1080  | FunctionEvaluationContext (_, _, exprs) -> List.nth exprs (pos - 1)
1081  | ForContext (ctx', _) -> evaluate_function_argument ctx' pos
1082  | InstanceContext _ | ToplevelContext -> assert false (*error*)
1083
1084and evaluate_function_call ctx expr exprs expr' =
1085  let expr = evaluate_expression ctx expr
1086  and exprs = List.map (evaluate_expression ctx) exprs in
1087  let exprs = List.map flatten_expression exprs in
1088  let ctx' =
1089    { ctx with
1090      class_context = FunctionEvaluationContext (ctx, expr, exprs)
1091    } in
1092  evaluate_expression ctx' expr'
1093
1094and evaluate_function_invocation ctx exprs =
1095  let exprs = List.map (evaluate_expression ctx) exprs in
1096  let exprs = List.map flatten_expression exprs in
1097  let evaluate_function_with_arguments = function
1098    | ClassReference cl_def ->
1099        evaluate_class_function_invocation cl_def exprs
1100    | PredefinedIdentifier s ->
1101        evaluate_predefined_function_invocation ctx s exprs
1102    | ComponentReference _ ->
1103        raise (InstantError
1104          { err_msg = ["_NotYetImplemented"; "_ComponentFuncInvocation"];
1105            err_info = [];
1106            err_ctx = ctx })
1107    | _ -> assert false (*error*) in
1108  let rec evaluate_function_invocation' ctx = match ctx.class_context with
1109    | FunctionEvaluationContext (_, expr, _) ->
1110        evaluate_function_with_arguments expr
1111    | ForContext (ctx', _) -> evaluate_function_invocation' ctx'
1112    | InstanceContext _ | ToplevelContext -> assert false (*error*) in
1113  evaluate_function_invocation' ctx
1114
1115and evaluate_if ctx alts default =
1116  let create_if alts default = match alts with
1117    | [] -> default
1118    | _ :: _ -> If (alts, default) in
1119  let rec evaluate_alternatives alts' alts = match alts with
1120    | [] ->
1121        let default = evaluate_expression ctx default in
1122        create_if (List.rev alts') default
1123    | (expr, expr') :: alts ->
1124        let expr = evaluate_expression ctx expr in
1125        evaluate_alternative expr expr' alts' alts
1126  and evaluate_alternative expr expr' alts' alts = match expr with
1127    | True ->
1128        let default = evaluate_expression ctx expr' in
1129        create_if (List.rev alts') default
1130    | False -> evaluate_alternatives alts' alts
1131    | _ ->
1132        let expr' = evaluate_expression ctx expr' in
1133        evaluate_alternatives ((expr, expr') :: alts') alts in
1134  evaluate_alternatives [] alts
1135
1136and evaluate_indexed_access ctx expr exprs =
1137  let rec vector_indexed_access exprs' exprs = match exprs with
1138    | [] -> expr
1139    | Integer i :: exprs ->
1140        let expr' =
1141          try
1142            exprs'.(Int32.to_int i - 1)
1143          with _ ->
1144              raise (InstantError
1145                { err_msg = ["_IndexOutOfBound"];
1146                  err_info = [];
1147                  err_ctx = ctx}) (*error*) in
1148        evaluate_indexed_access ctx expr' exprs
1149    | (Vector subs) :: exprs ->
1150        let f sub = vector_indexed_access exprs' (sub :: exprs) in
1151        Vector (Array.map f subs)
1152    | _ -> IndexedAccess (expr, exprs)
1153  and component_indexed_access cpnt_desc exprs =
1154    let rec static_array_indexed_access cpnt_descs exprs = match exprs with
1155      | [] -> expr
1156      | Integer i :: exprs ->
1157          let i' = Int32.to_int i in
1158          if Array.length cpnt_descs >= i' then
1159            let cpnt_desc = cpnt_descs.(i' - 1) in
1160            let expr' = ComponentReference cpnt_desc in
1161            evaluate_indexed_access ctx expr' exprs
1162          else
1163            raise (InstantError
1164              { err_msg = ["_IndexOutOfBound"];
1165                err_info = [];
1166                err_ctx = ctx}) (*error*)
1167      | (Vector subs) :: exprs ->
1168          let f sub = static_array_indexed_access cpnt_descs (sub :: exprs) in
1169          Vector (Array.map f subs)
1170      | exprs -> IndexedAccess (expr, exprs) in
1171    match evaluate cpnt_desc.component_nature with
1172    | DynamicArray _ -> IndexedAccess (ComponentReference cpnt_desc, exprs)
1173    | StaticArray cpnt_descs ->
1174        static_array_indexed_access cpnt_descs exprs
1175    | Instance _ | PredefinedTypeInstance _ -> expr in
1176  match expr, exprs with
1177  | _, [] -> expr
1178  | ComponentReference cpnt_desc, _ ->
1179      component_indexed_access cpnt_desc exprs
1180  | Vector exprs', _ ->
1181      vector_indexed_access exprs' exprs
1182  | If (alts, default), _ ->
1183      let f (cond, expr) = (cond, evaluate_indexed_access ctx expr exprs) in
1184      If (List.map f alts, evaluate_indexed_access ctx default exprs)
1185  | _ -> IndexedAccess (expr, exprs)
1186
1187and evaluate_local_identifier ctx level id =
1188  let rec evaluate_local_identifier' ctx inst level =
1189    match level, ctx.parent_context with
1190      | 0, _ -> instance_field_access ctx inst id
1191      | _, Some ctx -> evaluate_local_identifier ctx (level - 1) id
1192      | _, None -> assert false (*error*) in
1193  match ctx.class_context with
1194    | ForContext (ctx, _) | FunctionEvaluationContext (ctx, _, _) ->
1195        evaluate_local_identifier ctx level id
1196    | InstanceContext inst -> evaluate_local_identifier' ctx inst level
1197    | ToplevelContext -> assert false (*error*)
1198
1199and evaluate_loop_variable ctx level =
1200  let rec evaluate_loop_variable' ctx level' =
1201    match level', ctx.class_context with
1202      | 0, ForContext (_, None) -> assert false (*LoopVariable level'*)
1203      | 0, ForContext (_, Some expr) -> expr
1204      | _, ForContext (ctx, _) -> evaluate_loop_variable ctx (level' - 1)
1205      | _, FunctionEvaluationContext (ctx, _, _) ->
1206          evaluate_loop_variable' ctx level'
1207      | _, (InstanceContext _ | ToplevelContext) -> assert false (*error*) in
1208  evaluate_loop_variable' ctx level
1209
1210and evaluate_no_event ctx expr =
1211  let expr = evaluate_expression ctx expr in
1212  match expr with
1213    | True | False | Integer _ | Real _ | String _ | EnumerationElement _ ->
1214        expr
1215    | _ -> NoEvent expr
1216
1217and evaluate_range ctx start step stop =
1218  let start = evaluate_expression ctx start
1219  and step = evaluate_expression ctx step
1220  and stop = evaluate_expression ctx stop in
1221  let real_of_expression expr = match expr with
1222    | Real r -> r
1223    | Integer i -> Int32.to_float i
1224    | _ -> assert false in
1225  let integer_interval istart istep istop = match istart, istep, istop with
1226    | _
1227      when (Int32.compare istop istart) *
1228        (Int32.compare istep Int32.zero) < 0 ->
1229        Vector (Array.make 0 (Integer istart))
1230    | _ ->
1231        let n =
1232          Int32.div (Int32.sub istop istart) istep in
1233        let n' = Int32.to_int (Int32.succ n) in
1234        let f i =
1235          let i' = Int32.of_int i in
1236          let j =
1237            Int32.add istart (Int32.mul i' istep) in
1238          Integer j in
1239        Vector (Array.init n' f)
1240  and real_interval rstart rstep rstop = match rstart, rstep, rstop with
1241    | _ when (rstop -. rstart) /. rstep < 0. ->
1242        Vector (Array.make 0 (Real rstart))
1243    | _ ->
1244        let n = truncate ((rstop -. rstart) /. rstep) + 1
1245        and f i = Real (rstart +. float_of_int i *. rstep) in
1246        Vector (Array.init n f) in
1247  match start, step, stop with
1248  | _, Integer istep, _
1249    when Int32.compare istep Int32.zero = 0 ->
1250      raise (InstantError
1251        {err_msg = ["_RangeStepValueCannotBeNull"];
1252         err_info = [];
1253         err_ctx = ctx})
1254  | _, Real rstep, _ when rstep = 0. ->
1255      raise (InstantError
1256        {err_msg = ["_RangeStepValueCannotBeNull"];
1257         err_info = [];
1258         err_ctx = ctx})
1259  | Integer istart, Integer istep, Integer istop ->
1260      integer_interval istart istep istop
1261  | (Integer _ | Real _), (Integer _ | Real _), (Integer _ | Real _) ->
1262      let rstart = real_of_expression start
1263      and rstep = real_of_expression step
1264      and rstop = real_of_expression stop in
1265      real_interval rstart rstep rstop
1266  | _, _, _ -> Range (start, step, stop)
1267
1268and evaluate_coercion ctx coer expr =
1269  let rec evaluate_real_of_integer expr' = match expr' with
1270    | Integer i -> Real (Int32.to_float i)
1271    | Vector exprs ->
1272        Vector (Array.map evaluate_real_of_integer exprs)
1273    | _ -> expr' in
1274  let expr' = evaluate_expression ctx expr in
1275  match coer with
1276  | NameResolve.RealOfInteger -> evaluate_real_of_integer expr'
1277
1278and evaluate_toplevel_identifier ctx id =
1279  let elt_desc = List.assoc id (evaluate ctx.toplevel) in
1280  match evaluate elt_desc.element_nature with
1281    | Class cl_def -> ClassReference cl_def
1282    | Component cpnt_desc -> ComponentReference cpnt_desc
1283
1284and evaluate_tuple ctx exprs =
1285  Tuple (List.map (evaluate_expression ctx) exprs)
1286
1287and evaluate_unary_operation ctx unop expr =
1288  let expr = evaluate_expression ctx expr in
1289  let expr = flatten_expression expr in
1290  match unop with
1291    | NameResolve.Not -> evaluate_not expr
1292    | NameResolve.UnaryMinus -> evaluate_unary_minus expr
1293    | NameResolve.UnaryPlus -> expr
1294
1295(*and evaluate_vector_reduction ctx ranges expr =
1296  let rec evaluate_vector_reduction' ctx = function
1297    | [] -> evaluate_expression ctx expr
1298    | ranges -> vector_of_reduction ctx ranges
1299  and vector_of_reduction ctx = function
1300    | Range (Integer start, Integer step, Integer stop) :: ranges ->
1301        vector_of_range ctx start step stop ranges
1302    | ranges ->
1303        let ctx' =
1304          { ctx with
1305            class_context = ForContext (ctx, None)
1306          } in
1307        VectorReduction (ranges, evaluate_expression ctx' expr)
1308  and vector_of_range ctx start step stop ranges =
1309    let rec expression_list pred start = match pred start with
1310      | true -> []
1311      | false ->
1312          let ctx' =
1313            { ctx with
1314              class_context = ForContext (ctx, Some (Integer start))
1315            } in
1316          let expr = evaluate_vector_reduction' ctx' ranges in
1317          expr :: expression_list pred (Int32.add start step) in
1318    let cmp = Int32.compare step 0l in
1319    match cmp with
1320      | 0 when Int32.compare start stop <> 0 -> assert false (*error*)
1321      | 0 -> Vector [||]
1322      | _ when cmp < 0 ->
1323          let pred = function i -> Int32.compare i stop < 0 in
1324          let exprs = expression_list pred start in
1325          Vector (Array.of_list exprs)
1326      | _ ->
1327          let pred = function i -> Int32.compare i stop > 0 in
1328          let exprs = expression_list pred start in
1329          Vector (Array.of_list exprs) in
1330  let ranges = List.map (evaluate_expression ctx) ranges in
1331  evaluate_vector_reduction' ctx ranges*)
1332
1333and evaluate_vector_reduction ctx ranges expr =
1334  let rec evaluate_vector_reduction' ctx = function
1335    | [] -> evaluate_expression ctx expr
1336    | ranges -> vector_of_reduction ctx ranges
1337  and vector_of_reduction ctx = function
1338    | Range (Integer u, Integer p, Integer v) :: ranges ->
1339        vector_of_integer_range ctx u p v ranges
1340    | Range (Real u, Real p, Real v) :: ranges ->
1341        vector_of_real_range ctx u p v ranges
1342    | Vector exprs :: ranges ->
1343        let f i =
1344          let ctx' =
1345            { ctx with
1346              class_context = ForContext (ctx, Some exprs.(i))
1347            } in
1348          evaluate_vector_reduction' ctx' ranges in
1349        Vector (Array.init (Array.length exprs) f)
1350    | _ -> assert false
1351  and vector_of_integer_range ctx start step stop ranges =
1352    let rec expression_list pred start = match pred start with
1353      | true -> []
1354      | false ->
1355          let expr = Integer start in
1356          let ctx' =
1357            { ctx with
1358              class_context =
1359                ForContext (ctx, Some expr)
1360            } in
1361          let expr = evaluate_vector_reduction' ctx' ranges in
1362          let next = Int32.add start step in
1363          expr :: expression_list pred next in
1364    match step with
1365    | _ when Int32.compare step Int32.zero = 0 ->
1366        raise (InstantError
1367          {err_msg = ["_RangeStepValueCannotBeNull"];
1368           err_info = [];
1369           err_ctx = ctx})
1370    | _ when Int32.compare step Int32.zero < 0 ->
1371        let pred = function i -> (Int32.compare i stop < 0) in
1372        Vector (Array.of_list (expression_list pred start))
1373    | _ ->
1374        let pred = function i -> (Int32.compare i stop > 0) in
1375        Vector (Array.of_list (expression_list pred start))
1376  and vector_of_real_range ctx start step stop ranges =
1377    let rec expression_list pred start = match pred start with
1378      | true -> []
1379      | false ->
1380          let expr = Real start in
1381          let ctx' =
1382            { ctx with
1383              class_context = ForContext (ctx, Some expr)
1384            } in
1385          let expr = evaluate_vector_reduction' ctx' ranges in
1386          expr :: expression_list pred (start +. step) in
1387    match step with
1388    | 0. ->
1389        raise (InstantError
1390          {err_msg = ["_RangeStepValueCannotBeNull"];
1391           err_info = [];
1392           err_ctx = ctx})
1393    | _ when step < 0. ->
1394        let pred = function f -> f < stop in
1395        Vector (Array.of_list (expression_list pred start))
1396    | _ ->
1397        let pred = function f -> f > stop in
1398        Vector (Array.of_list (expression_list pred start)) in
1399  let ranges = List.map (evaluate_expression ctx) ranges in
1400  evaluate_vector_reduction' ctx ranges
1401
1402and evaluate_vector ctx exprs =
1403  let exprs = List.map (evaluate_expression ctx) exprs in
1404  Vector (Array.of_list exprs)
1405
1406and evaluate_and expr expr' = match expr, expr' with
1407  | False, (False | True) | True, False -> False
1408  | True, True -> True
1409  | Vector exprs, Vector exprs' ->
1410      Vector (ArrayExt.map2 evaluate_and exprs exprs')
1411  | _ -> BinaryOperation (And, expr, expr')
1412
1413and evaluate_divide ctx expr expr' = match expr, expr' with
1414  | _, Integer 0l ->
1415      raise (InstantError
1416        { err_msg = ["_DivisionByZero"];
1417          err_info = [];
1418          err_ctx = ctx }) (*error*)
1419  | Integer 0l, _ -> Integer 0l
1420  | Integer i, Integer i' ->
1421      Real ((Int32.to_float i) /. (Int32.to_float i'))
1422  | _, Real 0. ->
1423      raise (InstantError
1424        { err_msg = ["_DivisionByZero"];
1425          err_info = [];
1426          err_ctx = ctx }) (*error*)
1427  | Integer i, Real f -> Real (Int32.to_float i /. f)
1428  | Real f, Integer i -> Real (f /. Int32.to_float i)
1429  | Real f, Real f' -> Real (f /. f')
1430  | Vector exprs, _ ->
1431      let divide_element expr = evaluate_divide ctx expr expr' in
1432      Vector (Array.map divide_element exprs)
1433  | _ -> BinaryOperation (Divide, expr, expr')
1434
1435and evaluate_equalequal expr expr' = match expr, expr' with
1436  | Integer i, Integer i' when i = i' -> True
1437  | Integer i, Real f | Real f, Integer i when f = Int32.to_float i -> True
1438  | Real f, Real f' when f = f' -> True
1439  | (Integer _ | Real _), (Integer _ | Real _) -> False
1440  | Vector exprs, Vector exprs'
1441    when
1442      ArrayExt.for_all2
1443        (fun expr expr' -> evaluate_equalequal expr expr' = True)
1444        exprs
1445        exprs' -> True
1446  | Vector _, Vector _ -> False
1447  | _ -> BinaryOperation (EqualEqual, expr, expr')
1448
1449and evaluate_greater_equal expr expr' = match expr, expr' with
1450  | Integer i, Integer i' when i >= i' -> True
1451  | Integer i, Real f when Int32.to_float i >= f -> True
1452  | Real f, Integer i when f >= Int32.to_float i -> True
1453  | Real f, Real f' when f >= f' -> True
1454  | (Integer _ | Real _), (Integer _ | Real _) -> False
1455  | _ -> BinaryOperation (GreaterEqual, expr, expr')
1456
1457and evaluate_greater expr expr' = match expr, expr' with
1458  | Integer i, Integer i' when i > i' -> True
1459  | Integer i, Real f when Int32.to_float i > f -> True
1460  | Real f, Integer i when f > Int32.to_float i -> True
1461  | Real f, Real f' when f > f' -> True
1462  | (Integer _ | Real _), (Integer _ | Real _) -> False
1463  | _ -> BinaryOperation (Greater, expr, expr')
1464
1465and evaluate_less_equal expr expr' = match expr, expr' with
1466  | Integer i, Integer i' when i <= i' -> True
1467  | Integer i, Real f when Int32.to_float i <= f -> True
1468  | Real f, Integer i when f <= Int32.to_float i -> True
1469  | Real f, Real f' when f <= f' -> True
1470  | (Integer _ | Real _), (Integer _ | Real _) -> False
1471  | _ -> BinaryOperation (LessEqual, expr, expr')
1472
1473and evaluate_less expr expr' = match expr, expr' with
1474  | Integer i, Integer i' when i < i' -> True
1475  | Integer i, Real f when Int32.to_float i < f -> True
1476  | Real f, Integer i when f < Int32.to_float i -> True
1477  | Real f, Real f' when f < f' -> True
1478  | (Integer _ | Real _), (Integer _ | Real _) -> False
1479  | _ -> BinaryOperation (Less, expr, expr')
1480
1481and evaluate_times expr expr' =
1482  let rec line exprs i = match exprs.(i) with
1483    | Vector exprs -> exprs
1484    | _ -> assert false
1485  and column exprs j =
1486    let f i = match exprs.(i) with
1487      | Vector exprs -> exprs.(j)
1488      | _ -> assert false in
1489    Array.init (Array.length exprs) f
1490  and ndims expr = match expr with
1491    | Vector exprs when Array.length exprs = 0 -> assert false
1492    | Vector exprs -> 1 + ndims exprs.(0)
1493    | _ -> 0
1494  and size expr i = match expr, i with
1495    | _, 0 -> assert false
1496    | Vector exprs, 1 -> Array.length exprs
1497    | _, 1 -> 0
1498    | Vector exprs, _ when i > 1 -> size exprs.(0) (i - 1)
1499    | _, _ -> assert false
1500  and vector_mult exprs exprs' =
1501    let exprs = ArrayExt.map2 evaluate_times exprs exprs' in
1502    match Array.length exprs with
1503    | 0 -> assert false
1504    | 1 -> exprs.(0)
1505    | n ->
1506        let exprs' = Array.sub exprs 1 (n - 1) in
1507        Array.fold_left evaluate_plus exprs.(0) exprs' in
1508  match expr, expr' with
1509  | Integer 0l, _ | _, Integer 0l -> Integer 0l
1510  | Integer 1l, _ -> expr'
1511  | _, Integer 1l -> expr
1512  | Integer i, Integer i' -> Integer (Int32.mul i i')
1513  | Integer i, Real f | Real f, Integer i -> Real (f *. Int32.to_float i)
1514  | Real f, Real f' -> Real (f *. f')
1515  | _, Vector exprs' when (ndims expr = 0) ->
1516      Vector (Array.map (evaluate_times expr) exprs')
1517  | Vector exprs, _ when (ndims expr' = 0) ->
1518      Vector (Array.map (evaluate_times expr') exprs)
1519  | Vector exprs, Vector exprs' when (ndims expr = 1) && (ndims expr' = 1) ->
1520      vector_mult exprs exprs'
1521  | Vector exprs, Vector exprs' when (ndims expr = 1) && (ndims expr' = 2) ->
1522      let f j = vector_mult exprs (column exprs' j) in
1523      Vector (Array.init (size expr' 2) f)
1524  | Vector exprs, Vector exprs' when (ndims expr = 2) && (ndims expr' = 1) ->
1525      let f i = vector_mult (line exprs i) exprs' in
1526      Vector (Array.init (size expr 1) f)
1527  | Vector exprs, Vector exprs' when (ndims expr = 2) && (ndims expr' = 2) ->
1528      let f i j = vector_mult (line exprs i) (column exprs' j) in
1529      let g i = Vector (Array.init (size expr' 2) (f i)) in
1530      Vector (Array.init (size expr 1) g)
1531  | _ -> BinaryOperation (Times, expr, expr')
1532
1533and evaluate_not_equal expr expr' = match expr, expr' with
1534  | Integer i, Integer i' when i <> i' -> True
1535  | Integer i, Real f | Real f, Integer i when f <> Int32.to_float i -> True
1536  | Real f, Real f' when f <> f' -> True
1537  | (Integer _ | Real _), (Integer _ | Real _) -> False
1538  | Vector exprs, Vector exprs'
1539    when
1540      ArrayExt.exists2
1541        (fun expr expr' -> evaluate_equalequal expr expr' = False)
1542        exprs
1543        exprs' -> True
1544  | Vector _, Vector _ -> False
1545  | _ -> BinaryOperation (NotEqual, expr, expr')
1546
1547and evaluate_or expr expr' = match expr, expr' with
1548  | True, (False | True) | False, True -> True
1549  | False, False -> False
1550  | Vector exprs, Vector exprs' ->
1551      Vector (ArrayExt.map2 evaluate_or exprs exprs')
1552  | _ -> BinaryOperation (Or, expr, expr')
1553
1554and evaluate_plus expr expr' = match expr, expr' with
1555  | Integer 0l, _ -> expr'
1556  | _, Integer 0l -> expr
1557  | Integer i, Integer i' -> Integer (Int32.add i i')
1558  | Integer i, Real f | Real f, Integer i -> Real (f +. Int32.to_float i)
1559  | Real f, Real f' -> Real (f +. f')
1560  | Vector exprs, Vector exprs' ->
1561      Vector (ArrayExt.map2 evaluate_plus exprs exprs')
1562  | _ -> BinaryOperation (Plus, expr, expr')
1563
1564and evaluate_power ctx expr expr' =
1565  match expr, expr' with
1566  | (Integer 0l | Real 0.), (Integer 0l | Real 0.) ->
1567      raise (InstantError
1568        { err_msg = ["_ZeroRaisedToTheZeroPower"];
1569          err_info = [];
1570          err_ctx = ctx }) (*error*)
1571  | (Integer 0l | Real 0.), Integer i'
1572    when Int32.compare i' 0l < 0 ->
1573      raise (InstantError
1574        { err_msg = ["_ZeroRaisedToNegativePower"];
1575          err_info = [];
1576          err_ctx = ctx }) (*error*)
1577  | (Integer 0l | Real 0.), Real f' when f' < 0. ->
1578      raise (InstantError
1579        { err_msg = ["_ZeroRaisedToNegativePower"];
1580          err_info = [];
1581          err_ctx = ctx }) (*error*)
1582  | Integer 0l, Integer _ ->
1583      (* We know the answer for sure since second argument is constant *)
1584      Real 0.
1585  | (Integer 0l | Real 0.), (Integer _ | Real _) -> Real 0.
1586  | Integer i, Real _ when Int32.compare i 0l < 0 ->
1587      raise (InstantError
1588        { err_msg = ["_RealExponentOfNegativeNumber"];
1589          err_info = [];
1590          err_ctx = ctx }) (*error*)
1591  | Real f, Real _ when f < 0. ->
1592      raise (InstantError
1593        { err_msg = ["_RealExponentOfNegativeNumber"];
1594          err_info = [];
1595          err_ctx = ctx }) (*error*)
1596  | Integer i, Integer i' ->
1597      Real ((Int32.to_float i) ** (Int32.to_float i'))
1598  | Integer i, Real f -> Real ((Int32.to_float i) ** f)
1599  | Real f, Integer i' -> Real (f ** (Int32.to_float i'))
1600  | Real f, Real f' -> Real (f ** f')
1601  | Vector exprs, Integer i ->
1602      raise (InstantError
1603        { err_msg = ["_NotYetImplemented";
1604                     "_VectorRaisedToIntegerPower"];
1605          err_info = [];
1606          err_ctx = ctx })
1607  | _ -> BinaryOperation (Power, expr, expr')
1608
1609and evaluate_minus expr expr' = match expr, expr' with
1610  | Integer 0l, _ -> evaluate_unary_minus expr'
1611  | _, Integer 0l -> expr
1612  | Integer i, Integer i' -> Integer (Int32.sub i i')
1613  | Integer i, Real f -> Real (Int32.to_float i -. f)
1614  | Real f, Integer i -> Real (f -. Int32.to_float i)
1615  | Real f, Real f' -> Real (f -. f')
1616  | Vector exprs, Vector exprs' ->
1617      Vector (ArrayExt.map2 evaluate_minus exprs exprs')
1618  | _ -> BinaryOperation (Minus, expr, expr')
1619
1620and evaluate_class_function_invocation cl_def exprs =
1621  FunctionCall (ClassReference cl_def, exprs)
1622
1623and evaluate_predefined_function_invocation ctx s exprs =
1624  match s, exprs with
1625  | "size", _ -> evaluate_size exprs
1626  | "reinit", [expr; expr'] -> evaluate_reinit expr expr'
1627  | "der", [expr] -> evaluate_der expr
1628  | "pre", [expr] -> evaluate_pre expr
1629  | ("edge" | "change" | "initial" | "terminal" | "sample" |
1630    "delay" | "assert" | "terminate"), _ ->
1631      raise (InstantError
1632        { err_msg = ["_NotYetImplemented"; "_PredefinedOperator"; s];
1633          err_info = [];
1634          err_ctx = ctx}) (*error*)
1635  | "abs", [expr] -> evaluate_abs expr
1636  | "sign", [expr] -> evaluate_sign expr
1637  | "cos", [expr] -> evaluate_cos expr
1638  | "sin", [expr] -> evaluate_sin expr
1639  | "tan", [expr] -> evaluate_tan expr
1640  | "exp", [expr] -> evaluate_exp expr
1641  | "log", [expr] -> evaluate_log expr
1642  | "sqrt", [expr] -> evaluate_sqrt expr
1643  | "asin", [expr] -> evaluate_asin expr
1644  | "acos", [expr] -> evaluate_acos expr
1645  | "atan", [expr] -> evaluate_atan expr
1646  | "sinh", [expr] -> evaluate_sinh expr
1647  | "cosh", [expr] -> evaluate_cosh expr
1648  | "tanh", [expr] -> evaluate_tanh expr
1649  | "asinh", [expr] -> evaluate_asinh expr
1650  | "acosh", [expr] -> evaluate_acosh expr
1651  | "atanh", [expr] -> evaluate_atanh expr
1652  | "log10", [expr] -> evaluate_log10 expr
1653  | "max", [expr; expr'] -> evaluate_max expr expr'
1654  | "min", [expr; expr'] -> evaluate_min expr expr'
1655  | "div", [expr; expr'] -> evaluate_div ctx expr expr'
1656  | "mod", [expr; expr'] -> evaluate_mod expr expr'
1657  | "rem", [expr; expr'] -> evaluate_rem expr expr'
1658  | "ceil", [expr] -> evaluate_ceil expr
1659  | "floor", [expr] -> evaluate_floor expr
1660  | "max", [expr] -> evaluate_max_array expr
1661  | "min", [expr] -> evaluate_min_array expr
1662  | "sum", [expr] -> evaluate_sum expr
1663  | "product", [expr] -> evaluate_product expr
1664  | "scalar", [expr] -> evaluate_scalar ctx expr
1665  | "ones", exprs -> evaluate_ones ctx exprs
1666  | "zeros", exprs -> evaluate_zeros ctx exprs
1667  | "fill", expr :: exprs -> evaluate_fill ctx expr exprs
1668  | "identity", [expr] -> evaluate_identity ctx expr
1669  | "diagonal", [expr] -> evaluate_diagonal ctx expr
1670  | "vector", [ expr ] -> evaluate_vector_operator ctx expr
1671  | "matrix", [ expr ] -> evaluate_matrix_operator ctx expr
1672  | "transpose", [ expr ] -> evaluate_transpose expr
1673  | "symmetric", [ expr ] -> evaluate_symmetric ctx expr
1674  | _ ->
1675      raise (InstantError
1676        { err_msg = ["_UnknownFunction"; s];
1677          err_info = [];
1678          err_ctx = ctx}) (*error*)
1679
1680and evaluate_symmetric ctx expr = match expr with
1681  | Vector [||] -> assert false
1682  | Vector exprs when size exprs.(0) 0 <> Array.length exprs ->
1683      raise (InstantError
1684        { err_msg = ["_InvalidArgOfOper"; "symmetric"];
1685          err_info = [];
1686          err_ctx = ctx }) (*error*)
1687  | Vector exprs ->
1688      let f i j =
1689        if i > j then element i (element j expr)
1690        else element j (element i expr) in
1691      let n = Array.length exprs in
1692      let g i = Vector (Array.init n (f i)) in
1693      Vector (Array.init n g)
1694   | _ -> assert false
1695
1696and evaluate_transpose expr =
1697  match expr with
1698  | Vector exprs  ->
1699      let f i = Vector (Array.map (element i) exprs) in
1700      Vector (Array.init (size expr 1) f)
1701  | _ -> assert false
1702
1703and evaluate_matrix_operator ctx expr =
1704  let rec scalar expr = match expr with
1705    | Vector [| expr |] -> scalar expr
1706    | Vector _ ->
1707        raise (InstantError
1708          { err_msg = ["_InvalidArgOfOper"; "matrix"];
1709            err_info = [];
1710            err_ctx = ctx }) (*error*)
1711    | _ -> expr in
1712  match expr with
1713  | _ when ndims expr < 2 ->
1714      evaluate_promote ctx 2 expr
1715  | _ when ndims expr = 2 -> expr
1716  | Vector exprs ->
1717      let f expr = Vector (Array.map scalar (array_elements expr)) in
1718      Vector (Array.map f exprs)
1719  | _ -> assert false
1720
1721and evaluate_promote ctx n expr =
1722  let rec evaluate_promote' i expr =
1723    match expr with
1724    | _ when i = 0 -> expr
1725    | Vector exprs when i > 0 ->
1726        Vector (Array.map (evaluate_promote' i) exprs)
1727    | _ when i > 0 ->
1728        Vector [| evaluate_promote' (i - 1) expr |]
1729    | _ -> assert false in
1730  match ndims expr with
1731  | n' when n' < n ->
1732      evaluate_promote' (n - n') expr
1733  | _ -> expr
1734
1735and evaluate_vector_operator ctx expr =
1736  let rec evaluate_scalar expr = match expr with
1737    | Vector [| expr |] -> evaluate_scalar expr
1738    | Vector _ ->
1739        raise (InstantError
1740          { err_msg = ["_InvalidArgOfOper"; "vector"];
1741            err_info = [];
1742            err_ctx = ctx }) (*error*)
1743    | _ -> expr
1744  and evaluate_vector_operator' expr = match expr with
1745    | Vector [| expr |] -> evaluate_vector_operator' expr
1746    | Vector exprs ->
1747        Array.map evaluate_scalar exprs
1748    | _ -> [| expr |] in
1749  Vector (evaluate_vector_operator' expr)
1750
1751and evaluate_max_array expr =
1752  let rec evaluate_max_list exprs = match exprs with
1753    | [] -> assert false
1754    | [ expr ] -> expr
1755    | expr :: exprs ->
1756        evaluate_max expr (evaluate_max_list exprs) in
1757  evaluate_max_list (scalar_elements expr)
1758
1759and evaluate_min_array expr =
1760  let rec evaluate_min_list exprs = match exprs with
1761    | [] -> assert false
1762    | [ expr ] -> expr
1763    | expr :: exprs ->
1764        evaluate_min expr (evaluate_min_list exprs) in
1765  evaluate_min_list (scalar_elements expr)
1766
1767and evaluate_sum expr =
1768  let rec evaluate_sum_list exprs = match exprs with
1769    | [] -> Integer Int32.zero
1770    | [ expr ] -> expr
1771    | expr :: exprs ->
1772        evaluate_plus expr (evaluate_sum_list exprs) in
1773  match expr with
1774  | Vector exprs ->
1775      evaluate_sum_list (scalar_elements expr)
1776  | _ -> assert false
1777
1778and evaluate_product expr =
1779  let rec evaluate_product_list exprs = match exprs with
1780    | [] -> Integer Int32.one
1781    | [ expr ] -> expr
1782    | expr :: exprs ->
1783        evaluate_times expr (evaluate_product_list exprs) in
1784  match expr with
1785  | Vector exprs ->
1786      evaluate_product_list (scalar_elements expr)
1787  | _ -> assert false
1788
1789and evaluate_fill ctx expr exprs =
1790  let rec evaluate_fill' dims = match dims with
1791    | [] -> expr
1792    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->
1793      let i = Int32.to_int i in
1794        Vector (Array.make i (evaluate_fill' dims))
1795  | _ ->
1796      raise (InstantError
1797        { err_msg = ["_InvalidArgOfOper"; "fill"];
1798          err_info = [];
1799            err_ctx = ctx }) (*error*) in
1800  evaluate_fill' exprs
1801
1802and evaluate_zeros ctx exprs =
1803  let rec evaluate_zeros' dims = match dims with
1804    | [] -> Integer Int32.zero
1805    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->
1806      let i = Int32.to_int i in
1807        Vector (Array.make i (evaluate_zeros' dims))
1808  | _ ->
1809      raise (InstantError
1810        { err_msg = ["_InvalidArgOfOper"; "zeros"];
1811          err_info = [];
1812            err_ctx = ctx }) (*error*) in
1813  evaluate_zeros' exprs
1814
1815and evaluate_ones ctx exprs =
1816  let rec evaluate_ones' dims = match dims with
1817    | [] -> Integer Int32.one
1818    | Integer i :: dims when Int32.compare i Int32.zero > 0 ->
1819      let i = Int32.to_int i in
1820        Vector (Array.make i (evaluate_ones' dims))
1821  | _ ->
1822      raise (InstantError
1823        { err_msg = ["_InvalidArgOfOper"; "ones"];
1824          err_info = [];
1825            err_ctx = ctx }) (*error*) in
1826  evaluate_ones' exprs
1827
1828and evaluate_identity ctx expr =
1829  let n = match expr with
1830    | Integer i when Int32.compare i Int32.zero > 0 ->
1831        Int32.to_int i
1832  | _ ->
1833      raise (InstantError
1834        { err_msg = ["_InvalidArgOfOper"; "identity"];
1835          err_info = [];
1836            err_ctx = ctx }) (*error*) in
1837  let f i j =
1838    Integer (if j = i then Int32.one else Int32.zero) in
1839  let g i = Vector (Array.init n (f i)) in
1840  Vector (Array.init n g)
1841
1842and evaluate_diagonal ctx expr =
1843  let exprs = match expr with
1844    | Vector [||] ->
1845      raise (InstantError
1846        { err_msg = ["_InvalidArgOfOper"; "diagonal"];
1847          err_info = [];
1848          err_ctx = ctx }) (*error*)
1849    | Vector exprs -> exprs
1850  | _ ->
1851      raise (InstantError
1852        { err_msg = ["_InvalidArgOfOper"; "diagonal"];
1853          err_info = [];
1854            err_ctx = ctx }) (*error*) in
1855  let n = Array.length exprs in
1856  let f i j =
1857    if j = i then exprs.(i) else Integer Int32.zero in
1858  let g i = Vector (Array.init n (f i)) in
1859  Vector (Array.init n g)
1860
1861and evaluate_scalar ctx expr =
1862  let rec evaluate_scalar' expr = match expr with
1863    | Vector [| expr |] -> evaluate_scalar' expr
1864    | Vector _ ->
1865        raise (InstantError
1866          { err_msg = ["_InvalidArgOfOper"; "scalar"];
1867            err_info = [];
1868            err_ctx = ctx }) (*error*)
1869    | _ -> expr in
1870  match expr with
1871  | Vector [| expr |] -> evaluate_scalar' expr
1872  | _ ->
1873      raise (InstantError
1874        { err_msg = ["_InvalidArgOfOper"; "scalar"];
1875          err_info = [];
1876          err_ctx = ctx }) (*error*)
1877
1878and evaluate_reinit expr expr' = match expr, expr' with
1879  | Vector exprs, Vector exprs' ->
1880      Vector (ArrayExt.map2 evaluate_reinit exprs exprs')
1881  | _, _ ->
1882      FunctionCall (PredefinedIdentifier "reinit", [ expr; expr' ])
1883
1884and evaluate_der expr = match expr with
1885  | Integer _ | String _ | Real _ -> Real 0.
1886  | Vector exprs -> Vector (Array.map evaluate_der exprs)
1887  | BinaryOperation (Plus, expr, expr') ->
1888      let expr = evaluate_der expr
1889      and expr' = evaluate_der expr' in
1890      BinaryOperation (Plus, expr, expr')
1891  | BinaryOperation (Minus, expr, expr') ->
1892      let expr = evaluate_der expr
1893      and expr' = evaluate_der expr' in
1894      BinaryOperation (Minus, expr, expr')
1895  | BinaryOperation (Times, expr1, expr2) ->
1896      let expr1' = evaluate_der expr1
1897      and expr2' = evaluate_der expr2 in
1898      let expr1 = BinaryOperation (Times, expr1', expr2)
1899      and expr2 = BinaryOperation (Times, expr1, expr2') in
1900      BinaryOperation (Plus, expr1, expr2)
1901  | BinaryOperation (Divide, expr1, expr2) ->
1902      let expr1' = evaluate_der expr1
1903      and expr2' = evaluate_der expr2 in
1904      let expr1' = BinaryOperation (Times, expr1', expr2)
1905      and expr2' = BinaryOperation (Times, expr1, expr2') in
1906      let expr1 = BinaryOperation (Minus, expr1', expr2')
1907      and expr2 = BinaryOperation (Times, expr2, expr2) in
1908      BinaryOperation (Divide, expr1, expr2)
1909  | BinaryOperation (Power, expr, Integer i) ->
1910      let expr' = evaluate_der expr
1911      and j = Int32.sub i Int32.one in
1912      let expr' = BinaryOperation (Times, Integer i, expr')
1913      and expr = BinaryOperation (Power, expr, Integer j) in
1914      BinaryOperation (Times, expr', expr)
1915  | BinaryOperation (Power, expr, Real f) ->
1916      let expr' = evaluate_der expr
1917      and f' = f -. 1. in
1918      let expr' = BinaryOperation (Times, Real f, expr')
1919      and expr = BinaryOperation (Power, expr, Real f') in
1920      BinaryOperation (Times, expr', expr)
1921  | FunctionCall (PredefinedIdentifier "cos", [ expr ]) ->
1922      let expr' = evaluate_der expr
1923      and expr = FunctionCall (PredefinedIdentifier "sin", [ expr ]) in
1924      let expr = UnaryOperation (UnaryMinus, expr) in
1925      BinaryOperation (Times, expr', expr)
1926  | FunctionCall (PredefinedIdentifier "sin", [ expr ]) ->
1927      let expr' = evaluate_der expr
1928      and expr = FunctionCall (PredefinedIdentifier "cos", [ expr ]) in
1929      BinaryOperation (Times, expr', expr)
1930  | FunctionCall (PredefinedIdentifier "tan", [ expr1 ]) ->
1931      let expr1' = evaluate_der expr1
1932      and expr = BinaryOperation (Times, expr, expr) in
1933      let expr = BinaryOperation (Plus, Real 1., expr) in
1934      BinaryOperation (Times, expr1', expr)
1935  | FunctionCall (PredefinedIdentifier "exp", [ expr1 ]) ->
1936      let expr1' = evaluate_der expr1 in
1937      BinaryOperation (Times, expr1', expr)
1938  | FunctionCall (PredefinedIdentifier "log", [ expr1 ]) ->
1939      let expr1' = evaluate_der expr1 in
1940      BinaryOperation (Divide, expr1', expr)
1941  | FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) ->
1942      evaluate_der (BinaryOperation (Power, expr1, Real 0.5))
1943  | FunctionCall (PredefinedIdentifier "asin", [ expr1 ]) ->
1944      let expr1' = evaluate_der expr1 in
1945      let expr1 = BinaryOperation (Times, expr1, expr1) in
1946      let expr1 = BinaryOperation (Minus, Real 1., expr1) in
1947      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in
1948      BinaryOperation (Divide, expr1', expr1)
1949  | FunctionCall (PredefinedIdentifier "acos", [ expr1 ]) ->
1950      let expr1' = UnaryOperation (UnaryMinus, evaluate_der expr1) in
1951      let expr1 = BinaryOperation (Times, expr1, expr1) in
1952      let expr1 = BinaryOperation (Minus, Real 1., expr1) in
1953      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in
1954      BinaryOperation (Divide, expr1', expr1)
1955  | FunctionCall (PredefinedIdentifier "atan", [ expr1 ]) ->
1956      let expr1' = evaluate_der expr1 in
1957      let expr1 = BinaryOperation (Times, expr1, expr1) in
1958      let expr1 = BinaryOperation (Plus, Real 1., expr1) in
1959      BinaryOperation (Divide, expr1', expr1)
1960  | FunctionCall (PredefinedIdentifier "sinh", [ expr1 ]) ->
1961      let expr1' = evaluate_der expr1 in
1962      let expr1 = FunctionCall (PredefinedIdentifier "cosh", [ expr1 ]) in
1963      BinaryOperation (Times, expr1', expr1)
1964  | FunctionCall (PredefinedIdentifier "cosh", [ expr1 ]) ->
1965      let expr1' = evaluate_der expr1 in
1966      let expr1 = FunctionCall (PredefinedIdentifier "sinh", [ expr1 ]) in
1967      BinaryOperation (Times, expr1', expr1)
1968  | FunctionCall (PredefinedIdentifier "tanh", [ expr1 ]) ->
1969      let expr1' = evaluate_der expr1 in
1970      let expr1 = BinaryOperation (Times, expr, expr) in
1971      let expr1 = BinaryOperation (Minus, Real 1., expr1) in
1972      BinaryOperation (Times, expr1', expr1)
1973  | FunctionCall (PredefinedIdentifier "asinh", [ expr1 ]) ->
1974      let expr1' = evaluate_der expr1 in
1975      let expr1 = BinaryOperation (Times, expr1, expr1) in
1976      let expr1 = BinaryOperation (Plus, Real 1., expr1) in
1977      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in
1978      BinaryOperation (Divide, expr1', expr1)
1979  | FunctionCall (PredefinedIdentifier "acosh", [ expr1 ]) ->
1980      let expr1' = evaluate_der expr1 in
1981      let expr1 = BinaryOperation (Times, expr1, expr1) in
1982      let expr1 = BinaryOperation (Minus, expr1, Real 1.) in
1983      let expr1 = FunctionCall (PredefinedIdentifier "sqrt", [ expr1 ]) in
1984      BinaryOperation (Divide, expr1', expr1)
1985  | FunctionCall (PredefinedIdentifier "atanh", [ expr1 ]) ->
1986      let expr1' = evaluate_der expr1 in
1987      let expr1 = BinaryOperation (Times, expr1, expr1) in
1988      let expr1 = BinaryOperation (Minus, expr1, Real 1.) in
1989      BinaryOperation (Divide, expr1', expr1)
1990  | FunctionCall (PredefinedIdentifier "log10", [ expr1 ]) ->
1991      let expr1 = FunctionCall (PredefinedIdentifier "log", [ expr1 ]) in
1992      BinaryOperation (Divide, evaluate_der expr1, Real (log 10.))
1993  | FunctionCall
1994      (PredefinedIdentifier ("div" | "mod" | "rem" | "ceil" | "floor"), _) ->
1995      Real 0.
1996  | If (alts, default) ->
1997      let alts' =
1998        List.map (function (cond, expr) -> (cond, evaluate_der expr)) alts in
1999      If (alts', evaluate_der default)
2000  | NoEvent expr -> NoEvent (evaluate_der expr)
2001  | UnaryOperation (UnaryMinus, expr) ->
2002      UnaryOperation (UnaryMinus, evaluate_der expr)
2003  | VectorReduction (exprs, expr) ->
2004      VectorReduction (exprs, evaluate_der expr)
2005  | _ -> FunctionCall (PredefinedIdentifier "der", [ expr ])
2006
2007and evaluate_pre expr = match expr with
2008  | Vector exprs ->
2009      Vector (Array.map evaluate_pre exprs)
2010  | _ ->
2011      FunctionCall (PredefinedIdentifier "pre", [ expr ])
2012
2013and evaluate_cos expr = match expr with
2014  | Vector exprs ->
2015      Vector (Array.map evaluate_cos exprs)
2016  | _ ->
2017      FunctionCall (PredefinedIdentifier "cos", [ expr ])
2018
2019and evaluate_sin expr = match expr with
2020  | Vector exprs ->
2021      Vector (Array.map evaluate_sin exprs)
2022  | _ ->
2023      FunctionCall (PredefinedIdentifier "sin", [ expr ])
2024
2025and evaluate_tan expr = match expr with
2026  | Vector exprs ->
2027      Vector (Array.map evaluate_tan exprs)
2028  | _ ->
2029      FunctionCall (PredefinedIdentifier "tan", [ expr ])
2030
2031and evaluate_exp expr = match expr with
2032  | Vector exprs ->
2033      Vector (Array.map evaluate_exp exprs)
2034  | _ ->
2035      FunctionCall (PredefinedIdentifier "exp", [ expr ])
2036
2037and evaluate_log expr = match expr with
2038  | Vector exprs ->
2039      Vector (Array.map evaluate_log exprs)
2040  | _ ->
2041      FunctionCall (PredefinedIdentifier "log", [ expr ])
2042
2043and evaluate_sqrt expr = match expr with
2044  | Vector exprs ->
2045      Vector (Array.map evaluate_sqrt exprs)
2046  | _ ->
2047      FunctionCall (PredefinedIdentifier "sqrt", [ expr ])
2048
2049and evaluate_asin expr = match expr with
2050  | Vector exprs ->
2051      Vector (Array.map evaluate_asin exprs)
2052  | _ ->
2053      FunctionCall (PredefinedIdentifier "asin", [ expr ])
2054
2055and evaluate_acos expr = match expr with
2056  | Vector exprs ->
2057      Vector (Array.map evaluate_acos exprs)
2058  | _ ->
2059      FunctionCall (PredefinedIdentifier "acos", [ expr ])
2060
2061and evaluate_atan expr = match expr with
2062  | Vector exprs ->
2063      Vector (Array.map evaluate_atan exprs)
2064  | _ ->
2065      FunctionCall (PredefinedIdentifier "atan", [ expr ])
2066
2067and evaluate_sinh expr = match expr with
2068  | Vector exprs ->
2069      Vector (Array.map evaluate_sinh exprs)
2070  | _ ->
2071      FunctionCall (PredefinedIdentifier "sinh", [ expr ])
2072
2073and evaluate_cosh expr = match expr with
2074  | Vector exprs ->
2075      Vector (Array.map evaluate_cosh exprs)
2076  | _ ->
2077      FunctionCall (PredefinedIdentifier "cosh", [ expr ])
2078
2079and evaluate_tanh expr = match expr with
2080  | Vector exprs ->
2081      Vector (Array.map evaluate_tanh exprs)
2082  | _ ->
2083      FunctionCall (PredefinedIdentifier "tanh", [ expr ])
2084
2085and evaluate_asinh expr = match expr with
2086  | Vector exprs ->
2087      Vector (Array.map evaluate_asinh exprs)
2088  | _ ->
2089      FunctionCall (PredefinedIdentifier "asinh", [ expr ])
2090
2091and evaluate_acosh expr = match expr with
2092  | Vector exprs ->
2093      Vector (Array.map evaluate_acosh exprs)
2094  | _ ->
2095      FunctionCall (PredefinedIdentifier "acosh", [ expr ])
2096
2097and evaluate_atanh expr = match expr with
2098  | Vector exprs ->
2099      Vector (Array.map evaluate_atanh exprs)
2100  | _ ->
2101      FunctionCall (PredefinedIdentifier "atanh", [ expr ])
2102
2103and evaluate_log10 expr = match expr with
2104  | Vector exprs ->
2105      Vector (Array.map evaluate_log10 exprs)
2106  | _ ->
2107      FunctionCall (PredefinedIdentifier "log10", [ expr ])
2108
2109and evaluate_max expr expr' = match expr, expr' with
2110  | Vector exprs, Vector exprs' ->
2111      Vector (ArrayExt.map2 evaluate_max exprs exprs')
2112  | Real f, Real f' -> Real (max f f')
2113  | _, _ ->
2114      let b = BinaryOperation (GreaterEqual, expr, expr') in
2115      If ([b, expr], expr')
2116
2117and evaluate_min expr expr' = match expr, expr' with
2118  | Vector exprs, Vector exprs' ->
2119      Vector (ArrayExt.map2 evaluate_min exprs exprs')
2120  | Real f, Real f' -> Real (min f f')
2121  | _, _ ->
2122      let b = BinaryOperation (GreaterEqual, expr', expr) in
2123      If ([b, expr], expr')
2124
2125and evaluate_abs expr = match expr with
2126  | Vector exprs ->
2127      Vector (Array.map evaluate_abs exprs)
2128  | Real f -> Real (abs_float f)
2129  | Integer i -> Integer (Int32.abs i)
2130  | _ ->
2131      let b = BinaryOperation (GreaterEqual, expr, Real 0.)
2132      and default = UnaryOperation (UnaryMinus, expr) in
2133      If ([b, expr], default)
2134
2135and evaluate_sign expr = match expr with
2136  | Vector exprs ->
2137      Vector (Array.map evaluate_sign exprs)
2138  | Real f when f > 0. -> Real 1.
2139  | Real f when f < 0. -> Real (-. 1.)
2140  | Real _ -> Real 0.
2141  | Integer i when Int32.compare i Int32.zero > 0 ->
2142      Integer Int32.one
2143  | Integer i when Int32.compare i Int32.zero < 0 ->
2144      Integer Int32.minus_one
2145  | Integer _ -> Integer Int32.zero
2146  | _ ->
2147      let b = BinaryOperation (Greater, expr, Real 0.)
2148      and b' = BinaryOperation (Greater, Real 0., expr) in
2149      If ([(b, Integer Int32.one); (b', Integer Int32.minus_one)],
2150          Integer Int32.zero)
2151
2152and evaluate_div ctx expr expr' = match expr, expr' with
2153  | Vector exprs, Vector exprs' ->
2154      Vector (ArrayExt.map2 (evaluate_div ctx) exprs exprs')
2155  | _, Real 0. ->
2156      raise (InstantError
2157        { err_msg = ["_DivisionByZero"];
2158          err_info = [];
2159          err_ctx = ctx }) (*error*)
2160  | _, Integer i when i = Int32.zero ->
2161      raise (InstantError
2162        { err_msg = ["_DivisionByZero"];
2163          err_info = [];
2164          err_ctx = ctx }) (*error*)
2165  | Integer i, Integer i' -> Integer (Int32.div i i')
2166  | Real f, Integer i' ->
2167      let f' = Int32.to_float i' in
2168      Real (float_of_int (truncate (f /. f')))
2169  | Integer i, Real f' ->
2170      let f = Int32.to_float i in
2171      Real (float_of_int (truncate (f /. f')))
2172  | Real f, Real f' ->
2173      Real (float_of_int (truncate (f /. f')))
2174  | _, _ ->
2175      FunctionCall (PredefinedIdentifier "div", [ expr; expr' ])
2176
2177and evaluate_mod expr expr' = match expr, expr' with
2178  | Vector exprs, Vector exprs' ->
2179      Vector (ArrayExt.map2 evaluate_mod exprs exprs')
2180  | _, _ ->
2181      FunctionCall (PredefinedIdentifier "mod", [ expr; expr' ])
2182
2183and evaluate_rem expr expr' = match expr, expr' with
2184  | Vector exprs, Vector exprs' ->
2185      Vector (ArrayExt.map2 evaluate_rem exprs exprs')
2186  | _, _ ->
2187      FunctionCall (PredefinedIdentifier "rem", [ expr; expr' ])
2188
2189and evaluate_ceil expr = match expr with
2190  | Vector exprs ->
2191      Vector (Array.map evaluate_ceil exprs)
2192  | _ ->
2193      FunctionCall (PredefinedIdentifier "ceil", [ expr ])
2194
2195and evaluate_floor expr = match expr with
2196  | Vector exprs ->
2197      Vector (Array.map evaluate_floor exprs)
2198  | _ ->
2199      FunctionCall (PredefinedIdentifier "floor", [ expr ])
2200
2201and evaluate_size exprs =
2202  let rec evaluate_size' expr i = match expr, i with
2203    | ComponentReference cpnt_desc, _ ->
2204        evaluate_component_size cpnt_desc i
2205    | Vector exprs, 1 -> Integer (Int32.of_int (Array.length exprs))
2206    | Vector exprs, _ -> evaluate_size' exprs.(0) (i - 1)
2207    | _ -> assert false (*error*)
2208  and evaluate_component_size cpnt_desc i =
2209    match evaluate cpnt_desc.component_nature, i with
2210      | DynamicArray _, _ -> FunctionCall (PredefinedIdentifier "size", exprs)
2211      | StaticArray cpnt_descs, 1 ->
2212          Integer (Int32.of_int (Array.length cpnt_descs))
2213      | StaticArray cpnt_descs, _ ->
2214          evaluate_component_size cpnt_descs.(i) (i - 1)
2215      | _ -> assert false (*error*)
2216  and evaluate_size_list = function
2217    | ComponentReference cpnt_desc -> assert false
2218    | Vector exprs ->
2219        let size = Integer (Int32.of_int (Array.length exprs)) in
2220        size :: evaluate_size_list exprs.(0)
2221    | _ -> [] in
2222  match exprs with
2223    | [expr] -> Vector (Array.of_list (evaluate_size_list expr))
2224    | [expr; Integer i] -> evaluate_size' expr (Int32.to_int i)
2225    | [expr; _] -> FunctionCall (PredefinedIdentifier "size", exprs)
2226    | _ -> assert false (*error*)
2227
2228and evaluate_not expr = match expr with
2229  | True -> False
2230  | False -> True
2231  | Vector exprs -> Vector (Array.map evaluate_not exprs)
2232  | _ -> UnaryOperation (Not, expr)
2233
2234and evaluate_unary_minus expr = match expr with
2235  | Integer i -> Integer (Int32.neg i)
2236  | Real f -> Real (~-. f)
2237  | Vector exprs -> Vector (Array.map evaluate_unary_minus exprs)
2238  | _ -> UnaryOperation (UnaryMinus, expr)
2239
2240and field_access ctx expr id =
2241  let rec field_access' = function
2242    | ClassReference cl_def ->
2243        let cpnt_desc = create_temporary_instance ctx cl_def in
2244        component_field_access cpnt_desc
2245    | ComponentReference cpnt_desc -> component_field_access cpnt_desc
2246    | Record fields -> List.assoc id fields
2247    | Vector exprs -> Vector (Array.map field_access' exprs)
2248    | _ -> FieldAccess (expr, id)
2249  and component_field_access cpnt_desc =
2250    match evaluate cpnt_desc.component_nature with
2251      | DynamicArray _ -> FieldAccess (expr, id)
2252      | Instance inst -> instance_field_access ctx inst id
2253      | PredefinedTypeInstance _ ->
2254          raise (InstantError
2255            { err_msg = ["_CannotAccessToPredefTypeAttrib"; id];
2256              err_info = [];
2257              err_ctx = ctx}) (*error*)
2258      | StaticArray cpnt_descs ->
2259          Vector (Array.map component_field_access cpnt_descs) in
2260  field_access' expr
2261
2262and instance_field_access ctx inst id =
2263  let evaluate_component cpnt_desc =
2264    let evaluate_declaration_equation = function
2265      | Some expr -> evaluate expr
2266      | None ->
2267          raise (InstantError
2268            { err_msg = ["_MissingDeclEquForFixedId"; id];
2269              err_info = [];
2270              err_ctx = ctx}) (*error*) in
2271    let rec evaluate_parameter cpnt_desc =
2272      let evaluate_predefined_type_instance predef =
2273        match evaluate (List.assoc "fixed" predef.attributes) with
2274        | True -> evaluate_declaration_equation cpnt_desc.declaration_equation
2275        | False -> ComponentReference cpnt_desc
2276        | _ -> assert false (*error*) in
2277      match evaluate cpnt_desc.component_nature with
2278      | PredefinedTypeInstance predef
2279        when List.mem_assoc "fixed" predef.attributes ->
2280          evaluate_predefined_type_instance predef
2281      | DynamicArray cpnt_desc -> assert false
2282      | Instance _ -> ComponentReference cpnt_desc
2283      | PredefinedTypeInstance _ ->
2284          evaluate_declaration_equation cpnt_desc.declaration_equation
2285      | StaticArray cpnt_descs ->
2286          Vector (Array.map evaluate_parameter cpnt_descs)
2287          (*let f i =
2288            let decl_equ = cpnt_descs.(i).declaration_equation in
2289            evaluate_declaration_equation decl_equ in
2290          Vector (Array.init (Array.length cpnt_descs) f)*) in
2291    match cpnt_desc.variability with
2292      | Types.Constant ->
2293          evaluate_declaration_equation cpnt_desc.declaration_equation
2294      | Types.Parameter -> evaluate_parameter cpnt_desc
2295      | _ -> ComponentReference cpnt_desc in
2296  let elts = evaluate inst.elements in
2297  let elt_desc = List.assoc id elts.named_elements in
2298  match evaluate elt_desc.element_nature with
2299  | Class cl_def -> ClassReference cl_def
2300  | Component cpnt_desc -> evaluate_component cpnt_desc
2301
2302and expression_location ctx expr =
2303  match expr.NameResolve.info.NameResolve.syntax with
2304    | None -> ctx.location
2305    | Some expr -> expr.Syntax.info
2306
2307and class_name_of_component cpnt_desc =
2308  let type_spec = Lazy.force cpnt_desc.NameResolve.type_specifier in
2309  let expr_info = type_spec.NameResolve.info in
2310  match expr_info.NameResolve.syntax with
2311  | None -> ""
2312  | Some expr -> Syntax.string_of_expression expr
2313
2314and instance_nature_of_element elt_desc =
2315  match elt_desc.NameResolve.element_nature with
2316    | NameResolve.Component cpnt_desc ->
2317        ComponentElement (class_name_of_component cpnt_desc)
2318    | _ -> ClassElement
2319
2320and instance_class_name instance_nature =
2321  match instance_nature with
2322    | ComponentElement s -> s
2323    | ClassElement -> ""
2324
2325and flatten_expression expr =
2326  let rec flatten_component cpnt_desc =
2327    match evaluate cpnt_desc.component_nature with
2328    | StaticArray cpnt_descs ->
2329        Vector (Array.map flatten_component cpnt_descs)
2330    | _ -> ComponentReference cpnt_desc in
2331  match expr with
2332  | ComponentReference cpnt_desc ->
2333      flatten_component cpnt_desc
2334  | _ -> expr
2335
2336and size expr i = match expr, i with
2337  | Vector [||], _ -> 0
2338  | Vector exprs, 0 -> Array.length exprs
2339  | Vector exprs, _ when i > 0 -> size exprs.(0) (i - 1)
2340  | _ -> invalid_arg "_IndexOutOfBound"
2341
2342and sizes expr =
2343  Array.init (ndims expr) (size expr)
2344
2345and ndims expr =
2346  let rec ndims' i expr = match expr with
2347    | Vector [||] -> i + 1
2348    | Vector exprs -> ndims' (i + 1) exprs.(0)
2349    | _ -> i in
2350  ndims' 0 expr
2351
2352and element i expr = match expr with
2353  | Vector exprs -> exprs.(i)
2354  | _ -> assert false
2355
2356and array_elements expr = match expr with
2357  | Vector exprs -> exprs
2358  | _ -> assert false
2359
2360and scalar_elements expr = match expr with
2361  | Vector exprs ->
2362      let exprss =
2363        Array.to_list (Array.map scalar_elements exprs) in
2364      List.flatten exprss
2365  | _ -> [ expr ]
2366
2367(* for debug*)
2368
2369and generate_expression oc = function
2370  | BinaryOperation (bin_op, expr, expr') ->
2371      generate_binary_operation oc bin_op expr expr'
2372  | ClassReference cl_def ->
2373      generate_class_reference oc cl_def
2374  | ComponentReference cpnt_desc ->
2375      generate_component_reference oc cpnt_desc
2376  | EnumerationElement _ -> assert false
2377  | False -> assert false
2378  | FieldAccess _ -> assert false
2379  | FunctionCall (expr, exprs) ->
2380      generate_function_call oc expr exprs
2381  | If (alts, expr) -> generate_if oc alts expr
2382  | IndexedAccess _ -> assert false
2383  | Integer i when Int32.to_int i >= 0 ->
2384      Printf.fprintf oc "%ld" i
2385  | Integer i ->
2386      let expr = Integer (Int32.neg i)
2387      and un_op = UnaryMinus in
2388      generate_unary_operation oc un_op expr
2389  | LoopVariable _ -> Printf.fprintf oc "LoopVariable"
2390  | NoEvent expr -> generate_no_event oc expr
2391  | PredefinedIdentifier id -> Printf.fprintf oc "%s" id
2392  | Range _ -> Printf.fprintf oc "Range"
2393  | Real f ->
2394      Printf.fprintf oc "%s" (string_of_float f)
2395  | Record _ -> Printf.fprintf oc "Record"
2396  | String _ -> Printf.fprintf oc "String"
2397  | True -> Printf.fprintf oc "True"
2398  | Tuple _ -> Printf.fprintf oc "Tuple"
2399  | UnaryOperation (un_op, expr) ->
2400      generate_unary_operation oc un_op expr
2401  | Vector exprs ->
2402      generate_vector oc exprs
2403  | VectorReduction _ -> Printf.fprintf oc "VectorReduction"
2404
2405and generate_binary_operation oc bin_op expr expr' =
2406  let string_of_binary_operation_kind = function
2407    | And -> "and"
2408    | Divide -> "/"
2409    | EqualEqual -> "=="
2410    | GreaterEqual -> ">="
2411    | Greater -> ">"
2412    | LessEqual -> "<="
2413    | Less -> "<"
2414    | Times -> "*"
2415    | NotEqual -> "<>"
2416    | Or -> "or"
2417    | Plus -> "+"
2418    | Power -> "^"
2419    | Minus -> "-" in
2420  Printf.fprintf oc "(";
2421  generate_expression oc expr;
2422  Printf.fprintf oc " %s " (string_of_binary_operation_kind bin_op);
2423  generate_expression oc expr';
2424  Printf.fprintf oc ")"
2425
2426and generate_class_reference oc cl_def =
2427  let rec last = function
2428    | [] -> assert false
2429    | [Name id] -> id
2430    | [Index _] -> assert false
2431    | _ :: path -> last path in
2432  let generate_external_call ext_call =
2433    match ext_call.NameResolve.nature with
2434      | NameResolve.PrimitiveCall "builtin" ->
2435          Printf.fprintf oc "builtin"
2436      | NameResolve.PrimitiveCall "C" ->
2437          Printf.fprintf oc "PrimitiveCall"
2438      | NameResolve.PrimitiveCall lang -> assert false
2439      | NameResolve.ExternalProcedureCall _ -> assert false in
2440  let generate_long_dscription long_desc =
2441    match evaluate long_desc.NameResolve.external_call with
2442      | None -> assert false
2443      | Some ext_call -> generate_external_call ext_call in
2444  match cl_def.description with
2445    | ClassDescription (_, cl_desc) ->
2446        generate_long_dscription cl_desc.long_description
2447    | PredefinedType _ -> assert false
2448
2449and generate_component_reference oc cpnt_desc =
2450  let name = ident_of_path cpnt_desc.component_path in
2451  Printf.fprintf oc "%s" name
2452
2453and generate_function_call oc expr exprs =
2454  generate_expression oc expr;
2455  Printf.fprintf oc "(";
2456  generate_expressions oc exprs;
2457  Printf.fprintf oc ")"
2458
2459and generate_expressions oc = function
2460  | [] -> ()
2461  | [expr] -> generate_expression oc expr;
2462  | expr :: exprs ->
2463      generate_expression oc expr;
2464      Printf.fprintf oc ", ";
2465      generate_expressions oc exprs
2466
2467and generate_if oc alts expr =
2468  let rec generate_alternatives = function
2469    | [] -> Printf.fprintf oc " "; generate_expression oc expr
2470    | (expr, expr') :: alts ->
2471        Printf.fprintf oc "(if ";
2472        generate_expression oc expr;
2473        Printf.fprintf oc " then ";
2474        generate_expression oc expr';
2475        Printf.fprintf oc " else";
2476        generate_alternatives alts;
2477        Printf.fprintf oc ")" in
2478  generate_alternatives alts
2479
2480and generate_no_event oc expr =
2481  Printf.fprintf oc "noEvent(";
2482  generate_expression oc expr;
2483  Printf.fprintf oc ")"
2484
2485and generate_unary_operation oc un_op expr =
2486  let string_of_unary_operation_kind = function
2487    | Not -> "not"
2488    | UnaryMinus -> "-" in
2489  Printf.fprintf oc "(%s " (string_of_unary_operation_kind un_op);
2490  generate_expression oc expr;
2491  Printf.fprintf oc ")"
2492
2493and generate_vector oc exprs =
2494  let exprs' = Array.to_list exprs in
2495  Printf.fprintf oc "{ ";
2496  generate_expressions oc exprs';
2497  Printf.fprintf oc " }"
2498
2499and last_id path =
2500  let rec last_id' id path = match path with
2501    | [] -> id
2502    | (Name id) :: path -> last_id' id path
2503    | (Index _) :: path -> last_id' id path in
2504  last_id' "" path
2505
2506and string_of_float f =
2507  let add_parenthesis s =
2508    if String.contains s '-' then Printf.sprintf "(%s)" s else s in
2509  match Printf.sprintf "%.16g" f with
2510  | s when (String.contains s '.') || (String.contains s 'e') ->
2511      add_parenthesis s
2512  | s -> add_parenthesis (Printf.sprintf "%s." s)
2513
2514and ident_of_path path =
2515  let rec ident_of_path' path =
2516    match path with
2517    | [] -> assert false
2518    | [Name id] -> id
2519    | [Index i] -> Printf.sprintf "[%d]" (i + 1)
2520    | Name id :: path ->
2521        Printf.sprintf "%s.%s" id (ident_of_path' path)
2522    | Index i :: path ->
2523        Printf.sprintf "[%d].%s" (i + 1) (ident_of_path' path) in
2524  match path with
2525  | [] -> assert false
2526  | [Name id] -> assert false
2527  | [Index i] -> assert false
2528  | Name id :: path ->
2529      Printf.sprintf "`%s`" (ident_of_path' path)
2530  | Index i :: path -> assert false
2531
2532