@@ -319,9 +319,11 @@ algorithm
319319 Integer idx;
320320 list< Equation > eq, ieq;
321321 list< list< Statement >> alg, ialg;
322- Option < InstNode > special_ext;
323322 InstNode n;
324323 Modifier mod;
324+ list< ComponentNode > ext_nodes;
325+ Option < ComponentNode > builtin_ext;
326+ ComponentNode builtin_comp;
325327
326328 case SCode . CLASS (classDef = SCode . DERIVED (typeSpec = ty, modifications = der_mod))
327329 algorithm
@@ -340,31 +342,26 @@ algorithm
340342 Instance . PARTIAL_CLASS (classes = scope, elements = elements, modifier = mod) :=
341343 InstNode . instance(node);
342344
343- // Change the instance to an expanded instance, to avoid instantiation loops.
345+ // Change the instance to an empty expanded instance, to avoid instantiation loops.
344346 i := Instance . initExpandedClass(scope);
345347 node := InstNode . setInstance(i, node);
346348
347349 // Expand all the extends clauses.
348- (components, scope, special_ext) := expandExtends(elements, def. name, node, scope);
349-
350- if isSome(special_ext) then
351- SOME (n) := special_ext;
352- i := InstNode . instance(n);
353- mod := Modifier . merge(Instance . getModifier(i), mod);
354- i := Instance . setModifier(mod, i);
355- _ := InstNode . setInstance(i, node);
356- node := InstNode . setInstance(i, n);
350+ (components, scope, ext_nodes, builtin_ext) :=
351+ expandExtends(elements, def. name, node, scope);
352+
353+ if isSome(builtin_ext) then
354+ SOME (builtin_comp) := builtin_ext;
355+ node := expandBuiltinExtends(builtin_comp, ext_nodes, components, scope, mod, node);
357356 else
358357 // Add component ID:s to the scope.
359358 idx := 1 ;
360359 for c in components loop
361- if Component . isNamedComponent(ComponentNode . component(c)) then
362- // TODO: Handle components with the same name.
363- // TODO: If duplicate components should be handled here, also
364- // remove them from the list of components.
365- scope := ClassTree . add(scope, ComponentNode . name(c),
366- ClassTree . Entry . COMPONENT (idx), ClassTree . addConflictReplace);
367- end if ;
360+ // // TODO: Handle components with the same name.
361+ // // TODO: If duplicate components should be handled here, also
362+ // // remove them from the list of components.
363+ scope := ClassTree . add(scope, ComponentNode . name(c),
364+ ClassTree . Entry . COMPONENT (idx), ClassTree . addConflictReplace);
368365
369366 idx := idx + 1 ;
370367 end for ;
@@ -374,7 +371,7 @@ algorithm
374371 alg := instAlgorithmSections(cdef. normalAlgorithmLst, node);
375372 ialg := instAlgorithmSections(cdef. initialAlgorithmLst, node);
376373
377- i := Instance . EXPANDED_CLASS (scope, listArray(components), mod, eq, ieq, alg, ialg);
374+ i := Instance . EXPANDED_CLASS (scope, ext_nodes, listArray(components), mod, eq, ieq, alg, ialg);
378375 node := InstNode . setInstance(i, node);
379376 end if ;
380377 then
@@ -401,13 +398,15 @@ function expandExtends
401398 input InstNode currentScope;
402399 output list< ComponentNode > components = {};
403400 input output ClassTree . Tree scope;
404- output Option < InstNode > specialExtends = NONE ();
401+ output list< ComponentNode > extendsNodes = {};
402+ output Option < ComponentNode > builtinExtends = NONE ();
405403protected
406404 InstNode ext_node;
407405 Instance ext_inst;
408406 Modifier mod;
409407 ModifierScope mod_scope;
410- Boolean is_builtin;
408+ Boolean is_builtin, builtin_ext;
409+ ComponentNode ext_comp;
411410algorithm
412411 for e in elements loop
413412 () := match e
@@ -431,17 +430,23 @@ algorithm
431430 mod_scope := ModifierScope . EXTENDS_SCOPE (e. baseClassPath);
432431 mod := Modifier . create(e. modifications, "" , mod_scope, currentScope);
433432
434- // Apply the modifier to the expanded instance of the extended class .
433+ // Apply the modifier from the extends clause to the expanded instance .
435434 ext_inst := InstNode . instance(ext_node);
436435 ext_inst := applyModifier(mod, ext_inst, mod_scope);
437436 ext_node := InstNode . setInstance(ext_inst, ext_node);
438437
439- if not is_builtin then
440- components := addInheritedComponentRefs(ext_inst, components);
438+ ext_comp := ComponentNode . newExtends(ext_node, e);
439+ ext_inst := InstNode . instance(ext_node);
440+ builtin_ext := isBuiltinExtends(ext_inst);
441+
442+ if not builtin_ext then
443+ components := addInheritedComponentRefs(ext_inst, components, ext_comp);
441444 scope := addInheritedClasses(ext_inst, scope);
442445 else
443- specialExtends := SOME (ext_node );
446+ builtinExtends := SOME (ext_comp );
444447 end if ;
448+
449+ extendsNodes := ext_comp :: extendsNodes;
445450 then
446451 ();
447452
@@ -462,6 +467,52 @@ algorithm
462467 end for ;
463468end expandExtends;
464469
470+ function isBuiltinExtends
471+ "Checks if an extends is extending a builtin type."
472+ input Instance instance;
473+ output Boolean isBuiltinExtends;
474+ algorithm
475+ isBuiltinExtends := match instance
476+ case Instance . PARTIAL_BUILTIN () then true ;
477+ else false ;
478+ end match;
479+ end isBuiltinExtends;
480+
481+ function expandBuiltinExtends
482+ "This function handles the case where a class extends from a builtin type."
483+ input ComponentNode builtinExtends;
484+ input list< ComponentNode > extendsNodes;
485+ input list< ComponentNode > components;
486+ input ClassTree . Tree scope;
487+ input Modifier modifier;
488+ input output InstNode node;
489+ protected
490+ InstNode n;
491+ Instance i;
492+ Modifier mod;
493+ algorithm
494+ Component . EXTENDS_NODE (node = n) := ComponentNode . component(builtinExtends);
495+
496+ // A class extending from a builtin type may not have any other elements.
497+ if listLength(extendsNodes) <> 1 or listLength(components) > 0 or
498+ not ClassTree . isEmpty(scope) then
499+ Error . addSourceMessage(Error . BUILTIN_EXTENDS_INVALID_ELEMENTS ,
500+ {InstNode . name(n)},
501+ SCode . elementInfo(ComponentNode . definition(builtinExtends)));
502+ fail();
503+ end if ;
504+
505+ // Fetch the instance of the builtin type.
506+ i := InstNode . instance(n);
507+
508+ // Apply the given modifier to the instance.
509+ mod := Modifier . merge(Instance . getModifier(i), modifier);
510+ i := Instance . setModifier(mod, i);
511+
512+ // Replace the instance of the class we're expanding with the builtin type's instance.
513+ node := InstNode . setInstance(i, node);
514+ end expandBuiltinExtends;
515+
465516function applyModifier
466517 "Takes a modifier and applies the submodifiers in it to an instance."
467518 input Modifier modifier;
@@ -474,6 +525,7 @@ algorithm
474525 ClassTree . Tree elements;
475526 array< ComponentNode > components;
476527 ClassTree . Entry entry;
528+ InstNode node;
477529
478530 case Instance . EXPANDED_CLASS (elements = elements, components = components)
479531 algorithm
@@ -503,11 +555,26 @@ algorithm
503555
504556 case ClassTree . Entry . CLASS ()
505557 algorithm
506- // If a class is modified it's probably going to be used, so we
507- // might as well partially instantiate it now to simplify the
508- // modifier handling a bit.
509- entry. node := partialInstClass(entry. node);
510- InstNode . apply(entry. node, Instance . setModifier, m);
558+ _ := match m
559+ case Modifier . MODIFIER ()
560+ algorithm
561+ // If a class is modified it's probably going to be used, so we
562+ // might as well partially instantiate it now to simplify the
563+ // modifier handling a bit.
564+ entry. node := partialInstClass(entry. node);
565+ InstNode . apply(entry. node, Instance . setModifier, m);
566+ then
567+ ();
568+
569+ case Modifier . REDECLARE ()
570+ algorithm
571+ node := InstNode . new(SCode . elementName(m. element), m. element, m. scope);
572+ elements := ClassTree . add(elements, InstNode . name(node),
573+ ClassTree . Entry . CLASS (node), ClassTree . addConflictReplace);
574+ then
575+ ();
576+
577+ end match;
511578 then
512579 ();
513580
@@ -529,6 +596,7 @@ end applyModifier;
529596function addInheritedComponentRefs
530597 input Instance extendsInstance;
531598 input output list< ComponentNode > components;
599+ input ComponentNode parent;
532600protected
533601 ComponentNode cn;
534602algorithm
@@ -539,9 +607,10 @@ algorithm
539607 cn := arrayGet(extendsInstance. components, i);
540608
541609 components := match ComponentNode . component(cn)
610+ // Collect all the component definitions.
542611 case Component . COMPONENT_DEF () then cn :: components;
543- case Component . EXTENDS_NODE () then components;
544612
613+ // Any other component shouldn't show up here.
545614 else
546615 algorithm
547616 Error . addInternalError("NFInst.addInheritedComponentRefs got unknown component." ,
@@ -591,7 +660,9 @@ protected
591660 Modifier type_mod, mod;
592661 list< Modifier > type_mods, inst_type_mods;
593662 Binding binding;
594- InstNode cur_scope;
663+ InstNode n, cur_scope;
664+ list< ComponentNode > ext_nodes;
665+ Component c;
595666algorithm
596667 i := InstNode . instance(node);
597668
@@ -607,7 +678,17 @@ algorithm
607678 i_mod := applyModifier(modifier, i,
608679 ModifierScope . CLASS_SCOPE (InstNode . name(node)));
609680
610- // Instantiate all the components.
681+ // Instantiate all the extends nodes first.
682+ Instance . EXPANDED_CLASS (extendsNodes = ext_nodes) := i_mod;
683+ for ext in ext_nodes loop
684+ Component . EXTENDS_NODE (node = n) := ComponentNode . component(ext);
685+ // No modifier, the modifier on the extends clause has already been
686+ // applied in expandExtends.
687+ instClass(n, Modifier . NOMOD (), ext);
688+ end for ;
689+
690+ // Instantiate all local components. This will skip inherited
691+ // components, since those have already been instantiated.
611692 components := Array . map(Instance . components(i_mod),
612693 function instComponent(parent = parent, scope = node));
613694
@@ -648,7 +729,7 @@ algorithm
648729 end for ;
649730 end if ;
650731
651- i_mod := Instance . INSTANCED_BUILTIN (inst_type_mods);
732+ i_mod := Instance . INSTANCED_BUILTIN (i . name, inst_type_mods);
652733 node := InstNode . setInstance(i_mod, node);
653734 then
654735 ();
@@ -687,7 +768,7 @@ algorithm
687768 algorithm
688769 name := ComponentNode . name(node);
689770 node := ComponentNode . clone(node);
690- node := ComponentNode . setParent (parent, node);
771+ node := ComponentNode . setOrphanParent (parent, node);
691772
692773 // Merge the modifier from the component.
693774 comp_mod := Modifier . create(comp. modifications, name,
@@ -712,14 +793,6 @@ algorithm
712793 then
713794 ();
714795
715- case Component . EXTENDS_NODE ()
716- algorithm
717- cls := instClass(component. node, Modifier . NOMOD (), parent);
718- component. node := cls;
719- node := ComponentNode . updateComponent(component, node);
720- then
721- ();
722-
723796 else ();
724797 end match;
725798end instComponent;
0 commit comments