{"full":"<p>I\u00a0need\u00a0to\u00a0construct\u00a0an\u00a0AST\u00a0for\u00a0an\u00a0object-oriented\u00a0language.\u00a0My\u00a0first\u00a0instinct\u00a0was\u00a0to\u00a0model\u00a0this\u00a0as\u00a0a\u00a0sealed\u00a0class\u00a0hierarchy:<\/p><pre>sealed\u00a0class\u00a0Element\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0name:\u00a0String\n}\n\nabstract\u00a0class\u00a0ClassElement\u00a0:\u00a0Element()\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0functions:\u00a0List&lt;FunctionElement&gt;\n}\n\n...\n\nabstract\u00a0class\u00a0FunctionElement\u00a0:\u00a0Element()\u00a0{\n\u00a0\u00a0\u00a0\u00a0...\n}<\/pre><p>The\u00a0AST\u00a0can\u00a0be\u00a0constructed\u00a0in\u00a0two\u00a0ways\u00a0from\u00a0two\u00a0different\u00a0source\u00a0data\u00a0structures.\u00a0So\u00a0the\u00a0AST\u00a0construction\u00a0needs\u00a0to\u00a0be\u00a0separated,\u00a0in\u00a0a\u00a0sense,\u00a0from\u00a0the\u00a0declaration\u00a0of\u00a0the\u00a0AST.\u00a0If\u00a0the\u00a0AST\u00a0class\u00a0hierarchy\u00a0would\u00a0consist\u00a0of\u00a0interfaces\u00a0it\u00a0would\u00a0be\u00a0easy\u00a0to\u00a0make\u00a0two\u00a0different\u00a0concrete\u00a0class\u00a0hierarchies\u00a0two\u00a0implement\u00a0the\u00a0AST:<br\/><br\/>Example:<\/p><pre>abstract\u00a0class\u00a0ElementA(sourceA:\u00a0SourceA)\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0sourceA.name\n}\n\nclass\u00a0ClassElementA(sourceA:\u00a0SourceA)\u00a0:\u00a0ClassElement,\u00a0Element\u00a0by\u00a0ElementA(sourceA)\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0functions\u00a0=\u00a0parseFunctions(sourceA)\n}<\/pre><p>This\u00a0way\u00a0the\u00a0common\u00a0code\u00a0for\u00a0<code>Element<\/code>\u00a0can\u00a0be\u00a0shared\u00a0by\u00a0all\u00a0subclasses.\u00a0But\u00a0because\u00a0it&#x27;s\u00a0a\u00a0<code>sealed<\/code>\u00a0class\u00a0hierarchy\u00a0and\u00a0not\u00a0interfaces,\u00a0this\u00a0is\u00a0not\u00a0possible.\u00a0Another\u00a0way\u00a0to\u00a0share\u00a0the\u00a0common\u00a0code\u00a0for\u00a0<code>Element<\/code>\u00a0might\u00a0be\u00a0to\u00a0use\u00a0a\u00a0delegate\u00a0class:<\/p><pre>class\u00a0ElementDelegateA(sourceA:\u00a0SourceA)\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0sourceA.name\n}\n\nclass\u00a0ClassElementA(sourceA:\u00a0SourceA)\u00a0:\u00a0ClassElement()\u00a0{\n\u00a0\u00a0\u00a0\u00a0private\u00a0val\u00a0delegate\u00a0=\u00a0ElementDelegateA(sourceA)\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0delegate.name\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0functions\u00a0by\u00a0lazy\u00a0{\u00a0parseFunctions(sourceA)\u00a0}\n}<\/pre><p>However,\u00a0this\u00a0turns\u00a0into\u00a0a\u00a0lot\u00a0of\u00a0boilerplate\u00a0and\u00a0the\u00a0delegate\u00a0has\u00a0no\u00a0official\u00a0relation\u00a0to\u00a0the\u00a0<code>sealed\u00a0class<\/code>\u00a0it\u00a0&quot;implements&quot;.\u00a0If\u00a0<code>Element<\/code>\u00a0changes\u00a0then\u00a0<code>ELementDelegateA<\/code>\u00a0gets\u00a0out\u00a0of\u00a0sync\u00a0and\u00a0the\u00a0compiler\u00a0can&#x27;t\u00a0help.\u00a0I\u00a0thought\u00a0about\u00a0introducing\u00a0an\u00a0internal\u00a0interface\u00a0for\u00a0every\u00a0sealed\u00a0class:<\/p><pre>internal\u00a0interface\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0name:\u00a0String\n}\n\nsealed\u00a0class\u00a0Element\u00a0:\u00a0ElementInterface\u00a0{}\n\nabstract\u00a0class\u00a0ClassElement\u00a0:\u00a0Element()\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0functions:\u00a0List&lt;FunctionElement&gt;\n}\n\n&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;\n\nclass\u00a0ElementDelegateA(sourceA:\u00a0SourceA)\u00a0:\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0sourceA.name\n}\n\nclass\u00a0ClassElementA(sourceA:\u00a0SourceA)\u00a0:\u00a0ClassElement(),\u00a0ElementInterface\u00a0by\u00a0ElementDelegateA(sourceA)\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0functions\u00a0by\u00a0lazy\u00a0{\u00a0parseFunctions(sourceA)\u00a0}\n}<\/pre><p>Not\u00a0very\u00a0elegant.\u00a0Oftentimes\u00a0the\u00a0properties\u00a0still\u00a0have\u00a0to\u00a0be\u00a0overwritten\u00a0and\u00a0call\u00a0<code>delegate.name<\/code>\u00a0explicitly\u00a0because\u00a0they\u00a0have\u00a0a\u00a0narrowed\u00a0return\u00a0type.<br\/><br\/>At\u00a0this\u00a0point\u00a0the\u00a0majority\u00a0of\u00a0the\u00a0AST\u00a0implementation\u00a0classes\u00a0is\u00a0the\u00a0delegation\u00a0boilerplate,\u00a0which\u00a0will\u00a0be\u00a0shared\u00a0by\u00a0both\u00a0of\u00a0the\u00a0two\u00a0AST\u00a0implementations.\u00a0So\u00a0it\u00a0might\u00a0be\u00a0better\u00a0to\u00a0make\u00a0the\u00a0AST\u00a0declaration\u00a0concrete\u00a0data\u00a0classes\u00a0and\u00a0then\u00a0have\u00a0regular\u00a0functions\u00a0to\u00a0construct\u00a0the\u00a0AST\u00a0instead\u00a0of\u00a0specialized\u00a0classes\u00a0with\u00a0constructors:<\/p><pre>internal\u00a0interface\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0name:\u00a0String\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0children:\u00a0List&lt;Element&gt;\n}\n\nsealed\u00a0class\u00a0Element\u00a0:\u00a0ElementInterface\u00a0{}\n\ndata\u00a0class\u00a0ClassElement(\n\u00a0\u00a0\u00a0\u00a0elementDelegate:\u00a0ElementInterface,\n\u00a0\u00a0\u00a0\u00a0superType:\u00a0Lazy&lt;Type&gt;\n)\u00a0:\u00a0Element(),\u00a0ElementInterface\u00a0by\u00a0elementDelegate\u00a0{\n\n\u00a0\u00a0\u00a0\u00a0&#x2F;&#x2F;\u00a0lazy\u00a0property\u00a0by\u00a0ctor\u00a0parameter\n\u00a0\u00a0\u00a0\u00a0val\u00a0superType:\u00a0Type\u00a0by\u00a0superType\n\n\u00a0\u00a0\u00a0\u00a0&#x2F;&#x2F;\u00a0narrowed\u00a0property\u00a0delegated\n\u00a0\u00a0\u00a0\u00a0val\u00a0children:\u00a0List&lt;FunctionElement&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0get\u00a0=\u00a0elementDelegate.children\u00a0as\u00a0List&lt;FunctionElement&gt;\n\n\u00a0\u00a0\u00a0\u00a0&#x2F;&#x2F;\u00a0advantage:\u00a0equals\u00a0implementation\u00a0guaranteed\u00a0to\u00a0be\u00a0the\u00a0same\n\u00a0\u00a0\u00a0\u00a0&#x2F;&#x2F;\u00a0independent\u00a0of\u00a0how\u00a0the\u00a0AST\u00a0element\u00a0was\u00a0constructed\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0equals(other:\u00a0ClassElement)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0this.name\u00a0=\u00a0other.name\n}\n\n&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;\n\nfun\u00a0makeElementFromA(sourceA:\u00a0SourceA):\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0return\u00a0object\u00a0:\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0sourceA.name\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0children\u00a0by\u00a0lazy\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0parseChildren(sourceA)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n}\n\nfun\u00a0makeClassElementFromA(sourceA:\u00a0SourceA):\u00a0ClassElement\u00a0{\n\u00a0\u00a0\u00a0\u00a0return\u00a0ClassElement(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0elementDelegate\u00a0=\u00a0makeElementFromA(sourceA)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0superType\u00a0=\u00a0lazy\u00a0{\u00a0parseSuperType(sourceA)\u00a0}\n\u00a0\u00a0\u00a0\u00a0)\n}<\/pre><p>It\u00a0certainly\u00a0looks\u00a0like\u00a0a\u00a0more\u00a0functional\u00a0way\u00a0but\u00a0I&#x27;m\u00a0not\u00a0sure\u00a0if\u00a0it&#x27;s\u00a0better\u00a0than\u00a0having\u00a0separate\u00a0implementation\u00a0classes\u00a0depending\u00a0on\u00a0how\u00a0it\u00a0was\u00a0constructed.\u00a0Separate\u00a0implementation\u00a0classes\u00a0make\u00a0debugging\u00a0easier\u00a0and\u00a0are\u00a0more\u00a0readable\u00a0when\u00a0the\u00a0construction\u00a0logic\u00a0is\u00a0more\u00a0complicated.\u00a0Every\u00a0property\u00a0is\u00a0computed\u00a0where\u00a0it\u00a0is\u00a0needed\u00a0in\u00a0a\u00a0declarative\u00a0fashion,\u00a0whereas\u00a0with\u00a0the\u00a0&quot;make&quot;\u00a0functions\u00a0all\u00a0the\u00a0properties\u00a0are\u00a0computed\u00a0in\u00a0the\u00a0function\u00a0imperatively\u00a0and\u00a0then\u00a0given\u00a0to\u00a0the\u00a0data\u00a0class\u00a0constructor.<br\/><br\/>Another\u00a0problem\u00a0is\u00a0that\u00a0AST\u00a0construction\u00a0is\u00a0not\u00a0always\u00a0possible\u00a0with\u00a0only\u00a0local\u00a0knowledge.\u00a0For\u00a0example,\u00a0to\u00a0construct\u00a0the\u00a0member\u00a0functions\u00a0of\u00a0my\u00a0AST\u00a0I\u00a0need\u00a0to\u00a0iterate\u00a0through\u00a0all\u00a0the\u00a0member\u00a0functions\u00a0of\u00a0the\u00a0enclosing\u00a0class\u00a0in\u00a0the\u00a0source\u00a0data\u00a0structure.\u00a0It&#x27;s\u00a0easy\u00a0to\u00a0see\u00a0that\u00a0this\u00a0is\u00a0O(n^2)\u00a0to\u00a0convert\u00a0all\u00a0the\u00a0member\u00a0functions\u00a0one\u00a0after\u00a0another.\u00a0So\u00a0it&#x27;s\u00a0better\u00a0to\u00a0convert\u00a0them\u00a0all\u00a0at\u00a0once\u00a0and\u00a0save\u00a0them\u00a0in\u00a0a\u00a0<code>HashMap&lt;SourceA.Function,\u00a0FunctionElement&gt;<\/code>\u00a0inside\u00a0the\u00a0enclosing\u00a0class\u00a0and\u00a0cache\u00a0all\u00a0the\u00a0<code>ClassElement<\/code>s\u00a0in\u00a0an\u00a0LRU\u00a0Cache\u00a0in\u00a0some\u00a0kind\u00a0of\u00a0factory.\u00a0Then,\u00a0whenever\u00a0I\u00a0am\u00a0asked\u00a0to\u00a0convert\u00a0a\u00a0<code>SourceA.Function<\/code>\u00a0to\u00a0my\u00a0AST&#x27;s\u00a0<code>FunctionElement<\/code>\u00a0I\u00a0can\u00a0get\u00a0the\u00a0enclosing\u00a0<code>ClassElement<\/code>\u00a0from\u00a0the\u00a0cache\u00a0and\u00a0query\u00a0it&#x27;s\u00a0<code>HashMap<\/code>\u00a0for\u00a0the\u00a0converted\u00a0<code>FunctionElement<\/code>.\u00a0That\u00a0means\u00a0I\u00a0need\u00a0to\u00a0contaminate\u00a0the\u00a0AST\u00a0delcaration\u00a0of\u00a0<code>ClassElement<\/code>\u00a0with\u00a0this\u00a0implementation\u00a0detail\u00a0which\u00a0is\u00a0only\u00a0relevant\u00a0for\u00a0conversion\u00a0from\u00a0<code>SourceA<\/code>\u00a0but\u00a0not\u00a0from\u00a0<code>SourceB<\/code>.<br\/><br\/>What do you think about this?<\/p>","preview":"<p>I\u00a0need\u00a0to\u00a0construct\u00a0an\u00a0AST\u00a0for\u00a0an\u00a0object-oriented\u00a0language.\u00a0My\u00a0first\u00a0instinct\u00a0was\u00a0to\u00a0model\u00a0this\u00a0as\u00a0a\u00a0sealed\u00a0class\u00a0hierarchy:<\/p><pre>sealed\u00a0class\u00a0Element\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0name:\u00a0String\n}\n\nabstract\u00a0class\u00a0ClassElement\u00a0:\u00a0Element()\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0functions:\u00a0List&lt;FunctionElement&gt;\n}\n\n...\n\nabstract\u00a0class\u00a0FunctionElement\u00a0:\u00a0Element()\u00a0{\n\u00a0\u00a0\u00a0\u00a0...\n}<\/pre><p>The\u00a0AST\u00a0can\u00a0be\u00a0constructed\u00a0in\u00a0two\u00a0ways\u00a0from\u00a0two\u00a0different\u00a0source\u00a0data\u00a0structures.\u00a0So\u00a0the\u00a0AST\u00a0construction\u00a0needs\u00a0to\u00a0be\u00a0separated,\u00a0in\u00a0a\u00a0sense,\u00a0from\u00a0the\u00a0declaration\u00a0of\u00a0the\u00a0AST.\u00a0If\u00a0the\u00a0AST\u00a0class\u00a0hierarchy\u00a0would\u00a0consist\u00a0of\u00a0interfaces\u00a0it\u00a0would\u00a0be\u00a0easy\u00a0to\u00a0make\u00a0two\u00a0different\u00a0concrete\u00a0class\u00a0hierarchies\u00a0two\u00a0implement\u00a0the\u00a0AST:<br\/><br\/>Example:<\/p><pre>abstract\u00a0class\u00a0ElementA(sourceA:\u00a0SourceA)\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0sourceA.name\n}\n\nclass\u00a0ClassElementA(sourceA:\u00a0SourceA)\u00a0:\u00a0ClassElement,\u00a0Element\u00a0by\u00a0ElementA(sourceA)\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0functions\u00a0=\u00a0parseFunctions(sourceA)\n}<\/pre><p>This\u00a0way\u00a0the\u00a0common\u00a0code\u00a0for\u00a0<code>Element<\/code>\u00a0can\u00a0be\u00a0shared\u00a0by\u00a0all\u00a0subclasses.\u00a0But\u00a0because\u00a0it&#x27;s\u00a0a\u00a0<code>sealed<\/code>\u00a0class\u00a0hierarchy\u00a0and\u00a0not\u00a0interfaces,\u00a0this\u00a0is\u00a0not\u00a0possible.\u00a0Another\u00a0way\u00a0to\u00a0share\u00a0the\u00a0common\u00a0code\u00a0for\u00a0<code>Element<\/code>\u00a0might\u00a0be\u00a0to\u00a0use\u00a0a\u00a0delegate\u00a0class:<\/p><pre>class\u00a0ElementDelegateA(sourceA:\u00a0SourceA)\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0sourceA.name\n}\n\nclass\u00a0ClassElementA(sourceA:\u00a0SourceA)\u00a0:\u00a0ClassElement()\u00a0{\n\u00a0\u00a0\u00a0\u00a0private\u00a0val\u00a0delegate\u00a0=\u00a0ElementDelegateA(sourceA)\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0delegate.name\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0functions\u00a0by\u00a0lazy\u00a0{\u00a0parseFunctions(sourceA)\u00a0}\n}<\/pre><p>However,\u00a0this\u00a0turns\u00a0into\u00a0a\u00a0lot\u00a0of\u00a0boilerplate\u00a0and\u00a0the\u00a0delegate\u00a0has\u00a0no\u00a0official\u00a0relation\u00a0to\u00a0the\u00a0<code>sealed\u00a0class<\/code>\u00a0it\u00a0&quot;implements&quot;.\u00a0If\u00a0<code>Element<\/code>\u00a0changes\u00a0then\u00a0<code>ELementDelegateA<\/code>\u00a0gets\u00a0out\u00a0of\u00a0sync\u00a0and\u00a0the\u00a0compiler\u00a0can&#x27;t\u00a0help.\u00a0I\u00a0thought\u00a0about\u00a0introducing\u00a0an\u00a0internal\u00a0interface\u00a0for\u00a0every\u00a0sealed\u00a0class:<\/p><pre>internal\u00a0interface\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0name:\u00a0String\n}\n\nsealed\u00a0class\u00a0Element\u00a0:\u00a0ElementInterface\u00a0{}\n\nabstract\u00a0class\u00a0ClassElement\u00a0:\u00a0Element()\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0functions:\u00a0List&lt;FunctionElement&gt;\n}\n\n&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;\n\nclass\u00a0ElementDelegateA(sourceA:\u00a0SourceA)\u00a0:\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0sourceA.name\n}\n\nclass\u00a0ClassElementA(sourceA:\u00a0SourceA)\u00a0:\u00a0ClassElement(),\u00a0ElementInterface\u00a0by\u00a0ElementDelegateA(sourceA)\u00a0{\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0functions\u00a0by\u00a0lazy\u00a0{\u00a0parseFunctions(sourceA)\u00a0}\n}<\/pre><p>Not\u00a0very\u00a0elegant.\u00a0Oftentimes\u00a0the\u00a0properties\u00a0still\u00a0have\u00a0to\u00a0be\u00a0overwritten\u00a0and\u00a0call\u00a0<code>delegate.name<\/code>\u00a0explicitly\u00a0because\u00a0they\u00a0have\u00a0a\u00a0narrowed\u00a0return\u00a0type.<br\/><br\/>At\u00a0this\u00a0point\u00a0the\u00a0majority\u00a0of\u00a0the\u00a0AST\u00a0implementation\u00a0classes\u00a0is\u00a0the\u00a0delegation\u00a0boilerplate,\u00a0which\u00a0will\u00a0be\u00a0shared\u00a0by\u00a0both\u00a0of\u00a0the\u00a0two\u00a0AST\u00a0implementations.\u00a0So\u00a0it\u00a0might\u00a0be\u00a0better\u00a0to\u00a0make\u00a0the\u00a0AST\u00a0declaration\u00a0concrete\u00a0data\u00a0classes\u00a0and\u00a0then\u00a0have\u00a0regular\u00a0functions\u00a0to\u00a0construct\u00a0the\u00a0AST\u00a0instead\u00a0of\u00a0specialized\u00a0classes\u00a0with\u00a0constructors:<\/p><pre>internal\u00a0interface\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0name:\u00a0String\n\u00a0\u00a0\u00a0\u00a0abstract\u00a0val\u00a0children:\u00a0List&lt;Element&gt;\n}\n\nsealed\u00a0class\u00a0Element\u00a0:\u00a0ElementInterface\u00a0{}\n\ndata\u00a0class\u00a0ClassElement(\n\u00a0\u00a0\u00a0\u00a0elementDelegate:\u00a0ElementInterface,\n\u00a0\u00a0\u00a0\u00a0superType:\u00a0Lazy&lt;Type&gt;\n)\u00a0:\u00a0Element(),\u00a0ElementInterface\u00a0by\u00a0elementDelegate\u00a0{\n\n\u00a0\u00a0\u00a0\u00a0&#x2F;&#x2F;\u00a0lazy\u00a0property\u00a0by\u00a0ctor\u00a0parameter\n\u00a0\u00a0\u00a0\u00a0val\u00a0superType:\u00a0Type\u00a0by\u00a0superType\n\n\u00a0\u00a0\u00a0\u00a0&#x2F;&#x2F;\u00a0narrowed\u00a0property\u00a0delegated\n\u00a0\u00a0\u00a0\u00a0val\u00a0children:\u00a0List&lt;FunctionElement&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0get\u00a0=\u00a0elementDelegate.children\u00a0as\u00a0List&lt;FunctionElement&gt;\n\n\u00a0\u00a0\u00a0\u00a0&#x2F;&#x2F;\u00a0advantage:\u00a0equals\u00a0implementation\u00a0guaranteed\u00a0to\u00a0be\u00a0the\u00a0same\n\u00a0\u00a0\u00a0\u00a0&#x2F;&#x2F;\u00a0independent\u00a0of\u00a0how\u00a0the\u00a0AST\u00a0element\u00a0was\u00a0constructed\n\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0equals(other:\u00a0ClassElement)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0this.name\u00a0=\u00a0other.name\n}\n\n&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;\n\nfun\u00a0makeElementFromA(sourceA:\u00a0SourceA):\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0return\u00a0object\u00a0:\u00a0ElementInterface\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0name\u00a0=\u00a0sourceA.name\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0override\u00a0val\u00a0children\u00a0by\u00a0lazy\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0parseChildren(sourceA)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n}\n\nfun\u00a0makeClassElementFromA(sourceA:\u00a0SourceA):\u00a0ClassElement\u00a0{\n\u00a0\u00a0\u00a0\u00a0return\u00a0ClassElement(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0elementDelegate\u00a0=\u00a0makeElementFromA(sourceA)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0superType\u00a0=\u00a0lazy\u00a0{\u00a0parseSuperType(sourceA)\u00a0}\n\u00a0\u00a0\u00a0\u00a0)\n}<\/pre><p>It\u00a0certainly\u00a0looks\u00a0like\u00a0a\u00a0more\u00a0functional\u00a0way\u00a0but\u00a0I&#x27;m\u00a0not\u00a0sure\u00a0if\u00a0it&#x27;s\u00a0better\u00a0than\u00a0having\u00a0separate\u00a0implementation\u00a0classes\u00a0depending\u00a0on\u00a0how\u00a0it\u00a0was\u00a0constructed.\u00a0Separate\u00a0implementation\u00a0classes\u00a0make\u00a0debugging\u00a0easier\u00a0and\u00a0are\u00a0more\u00a0readable\u00a0when\u00a0the\u00a0construction\u00a0logic\u00a0is\u00a0more\u00a0complicated.\u00a0Every\u00a0property\u00a0is\u00a0computed\u00a0where\u00a0it\u00a0is\u00a0needed\u00a0in\u00a0a\u00a0declarative\u00a0fashion,\u00a0whereas\u00a0with\u00a0the\u00a0&quot;make&quot;\u00a0functions\u00a0all\u00a0the\u00a0properties\u00a0are\u00a0computed\u00a0in\u00a0the\u00a0function\u00a0imperatively\u00a0and\u00a0then\u00a0given\u00a0to\u00a0the\u00a0data\u00a0class\u00a0constructor.<br\/><br\/>Another\u00a0problem\u00a0is\u00a0that\u00a0AST\u00a0construction\u00a0is\u00a0not\u00a0always\u00a0possible\u00a0with\u00a0only\u00a0local\u00a0knowledge.\u00a0For\u00a0example,\u00a0to\u00a0construct\u00a0the\u00a0member\u00a0functions\u00a0of\u00a0my\u00a0AST\u00a0I\u00a0need\u00a0to\u00a0iterate\u00a0through\u00a0all\u00a0the\u00a0member\u00a0functions\u00a0of\u00a0the\u00a0enclosing\u00a0class\u00a0in\u00a0the\u00a0source\u00a0data\u00a0structure.\u00a0It&#x27;s\u00a0easy\u00a0to\u00a0see\u00a0that\u00a0this\u00a0is\u00a0O(n^2)\u00a0to\u00a0convert\u00a0all\u00a0the\u00a0member\u00a0functions\u00a0one\u00a0after\u00a0another.\u00a0So\u00a0it&#x27;s\u00a0better\u00a0to\u00a0convert\u00a0them\u00a0all\u00a0at\u00a0once\u00a0and\u00a0save\u00a0them\u00a0in\u00a0a\u00a0<code>HashMap&lt;SourceA.Function,\u00a0FunctionElement&gt;<\/code>\u00a0inside\u00a0the\u00a0enclosing\u00a0class\u00a0and\u00a0cache\u00a0all\u00a0the\u00a0<code>ClassElement<\/code>s\u00a0in\u00a0an\u00a0LRU\u00a0Cache\u00a0in\u00a0some\u00a0kind\u00a0of\u00a0factory.\u00a0Then,\u00a0whenever\u00a0I\u00a0am\u00a0asked\u00a0to\u00a0convert\u00a0a\u00a0<code>SourceA.Function<\/code>\u00a0to\u00a0my\u00a0AST&#x27;s\u00a0<code>FunctionElement<\/code>\u00a0I\u00a0can\u00a0get\u00a0the\u00a0enclosing\u00a0<code>ClassElement<\/code>\u00a0from\u00a0the\u00a0cache\u00a0and\u00a0query\u00a0it&#x27;s\u00a0<code>HashMap<\/code>\u00a0for\u00a0the\u00a0converted\u00a0<code>FunctionElement<\/code>.\u00a0That\u00a0means\u00a0I\u00a0need\u00a0to\u00a0contaminate\u00a0the\u00a0AST\u00a0delcaration\u00a0of\u00a0<code>ClassElement<\/code>\u00a0with\u00a0this\u00a0implementation\u00a0detail\u00a0which\u00a0is\u00a0only\u00a0relevant\u00a0for\u00a0conversion\u00a0from\u00a0<code>SourceA<\/code>\u00a0but\u00a0not\u00a0from\u00a0<code>SourceB<\/code>.<br\/><br\/>What do you think about this?<\/p>"}