Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Self-hosting - Use generated protocol models and metamodels #263

Open
12 of 27 tasks
akphi opened this issue Jun 16, 2021 · 0 comments
Open
12 of 27 tasks

RFC: Self-hosting - Use generated protocol models and metamodels #263

akphi opened this issue Jun 16, 2021 · 0 comments
Labels
Studio Core Team Opened by a member of the Studio core team Type: Discussion Type: Mega-thread Tracker for multiple related issues Type: Refactor
Milestone

Comments

@akphi
Copy link
Contributor

akphi commented Jun 16, 2021

💬 Request for Comments

We are a modelling tool, in fact, our protocols and metamodels are models we could build in Pure as well, and worse yet, we are not auto-generating these models but repeating their definition in 3 code bases legend-studio, legend-engine and legend-pure. We should model these in Pure and code-gen their definition into Typescript for consumption in Studio codebase.

Simplify metamodel

We need to simplify metamodels so that these can be auto-generated from models in Pure. After this, we're sure that the structure of metamodel more consistent and easier for code-generation

type Writable<T> = { -readonly [K in keyof T]: T[K] };

NOTE: there are fields that the UI does not and perhaps should not allow changing like class to a ClassView, but that's an UI decision, this field is not metadata, and it should not be made readonly

  • Remove all constructor parameters. Then remove all initialization logic from constructor, in fact, we could remove/make private the constructor all together and replace them by static creator methods
    • Do not initialize any value, as these should be taken care of by the static creator method
    • Use ! and ? in the property definition
    • Remove constructor
  • Move hashing logic out of metamodels:
    • After we move hashing and validation logic, revisit spots where we should use isStubbed_... method and use them, right now to avoid bad dependencies between models and the helpers method, we don't do this
    • Move remaining code-logic in DSL Diagram classes out to helpers.
    • Consider moving logic in Packageable Element out
    • Use the following technique to move hashing out. Remember that this is useful for derivations, which are the hardest things left to move. Hashing is one example of derivations which is useful to us and we should keep around. Also, if we don't do hashing at protocol level, I think doing hashing in the reactive manner is still the best, but we will see
// ModelExtension.ts
declare module './models/metamodels/pure/packageableElements/PackageableElement' {
  interface PackageableElement {
    get path(): string;
    get hashCode(): string;
  }
}

...

export {}; // export this so `Typescript` --isolatedModule check does not complain

// --------------------------------------------------------------

// Some file that we call once when we load the app
export const decorateMetamodel = (): void => {
  // e.g. Constraint
  Object.defineProperty(Constraint.prototype, 'hashCode', {
    get: function (this: Constraint) {
      return hashArray([
        HASH_STRUCTURE.CONSTRAINT,
        this.name,
      ]);
    }
  });
};

Other considerations

  • CONSIDER We probably would need to take care of visitors as part of code generation. JS does not support overloading like Java so we can't really have 2 accept() methods, we would need to have them differentiated, e.g. accept_SetImplementationVisitor() and accept_PropertyMappingVisitor() for embedded property mappings.
  • CONSIDER How do we support Typescript union type? Maybe we can use Any in Pure and then use a tagged-value to annotate union type?

Class/Interface swap:

Since Pure support multiple inheritance, we might need to do what legend-pure does by turning metamodels into interfaces to support multiple-inheritance (with C3 linearization support?), something like the following

  • Create CoreInstance interface and ConcreteCoreInstance class:
interface CoreInstance {
  /**
   * Can be used to uniquely identify the instance in a collection (used for UI majorly)
   */
  _UUID?: string;
}

class ConcreteCoreInstance implements CoreInstance {
  _UUID?: string;
}
  • We should turn each class into _Impl (that extends ConcreteCoreInstance) and have everything as interface that extends CoreInstance: i.e. Class vs ClassImpl.
  • MAYBE We should have optional UUID to each CoreInstance, add a method to allow setting this UUID. NOTE that if we make this non-optional, we're adding a lot of data to the graph
  • At this point, we lose the ability to do instanceof, to recover, for each interface, we can do the following:
// Class.ts
export interface Class {
  ...
}

export const Class_InheritanceSignature = 'Class';

// Class_Impl.ts
class Class_Impl implements Class {
  ...
}
Class_Impl.inheritanceSignature = Class_InheritanceSignature;
Class_Impl.prototype.superTypes = [PackageableElement_InheritanceSignature, CoreInstance_InheritanceSignature];

const instanceOf = <T>(val: unknown, inheritanceSignature: string): val is T => val.protoype.superTypes.includes(inheritanceSignature);
interface A {
  type: "1";
}

interface B {
  type: "2";
}

interface C extends A {}

class D implements C {
  type: "1" = "1";
}

class E implements B {
  type: "2" = "2";
}

const instanceOfA = (val: Record<PropertyKey, any>): val is A => {
  return "type" in val && val.type === "1";
};

const invD = (d: D): void => {
  console.log(d.type);
};

// NOTE: this line is perfectly fine in Javascript, but during compile time, Typescript will complain
invD(new E()); // Argument of type 'E' is not assignable to parameter of type 'D'
@akphi akphi changed the title RFC: Self-hosting - Autogenerating protocol models and metamodels RFC: (mega-thread) Self-hosting - Autogenerating protocol models and metamodels Jun 16, 2021
@akphi akphi changed the title RFC: (mega-thread) Self-hosting - Autogenerating protocol models and metamodels RFC: (mega-thread) Self-hosting - Use generated protocol models and metamodels Jun 16, 2021
@akphi akphi added Difficulty: Challenging Studio Core Team Opened by a member of the Studio core team Type: Mega-thread Tracker for multiple related issues labels Oct 29, 2021
@akphi akphi changed the title RFC: (mega-thread) Self-hosting - Use generated protocol models and metamodels RFC: Self-hosting - Use generated protocol models and metamodels Nov 6, 2021
@akphi akphi added this to the Marathon milestone Nov 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Studio Core Team Opened by a member of the Studio core team Type: Discussion Type: Mega-thread Tracker for multiple related issues Type: Refactor
Projects
None yet
Development

No branches or pull requests

2 participants