getType()

in lib/semantic.js [2900:3058]


  getType(t, extern) {
    if (t.tag === Tag.TYPE && t.lexeme === 'object') {
      return {
        type: 'map',
        keyType: _basic('string'),
        valueType: _basic('any')
      };
    }

    if (t.tag === Tag.TYPE) {
      this.usedTypes.set(t.lexeme, true);
      return _basic(t.lexeme);
    }

    if (t.tag === Tag.ID) {
      if (t.idType === 'module' || t.idType === 'builtin_module') {
        return {
          type: 'module_instance',
          name: t.lexeme,
          parentModuleIds: this.getParentModuleIds(t.lexeme),
        };
      }


      if (t.lexeme.startsWith('$')) {
        return _model(t.lexeme);
      }

      if (extern) {
        this.usedExternModel.get(extern).add(t.lexeme);
        if (t.idType === 'typedef') {
          return _typedef(t.lexeme, extern);
        }
        if (t.idType === 'enum') {
          return _enum(t.lexeme, extern);
        }

        const checker = this.dependencies.get(extern);
        return checker.getModel(t.lexeme, extern);
      }

      if (this.dependencies.has(t.lexeme)) {
        return {
          type: 'module_instance',
          name: t.lexeme,
          parentModuleIds: this.getParentModuleIds(t.lexeme),
        };
      }

      if (this.enums.has(t.lexeme)) {
        return _enum(t.lexeme);
      }

      if (this.typedefs.has(t.lexeme)) {
        return _typedef(t.lexeme);
      }

      return this.getModel(t.lexeme);
    }

    if (t.type === 'array') {
      return {
        type: 'array',
        itemType: this.getType(t.subType)
      };
    }

    if (t.type === 'map') {
      if (t.valueType.type === 'subModel_or_moduleModel') {
        this.checkType(t.valueType);
        return {
          type: 'map',
          keyType: _type(t.keyType),
          valueType: t.valueType
        };
      }
      return {
        type: 'map',
        keyType: _type(t.keyType),
        valueType: this.getType(t.valueType)
      };
    }

    if (t.type === 'entry') {
      if (t.valueType.type === 'subModel_or_moduleModel') {
        this.checkType(t.valueType);
        
        return {
          type: 'entry',
          valueType: t.valueType
        };
      }
      return {
        type: 'entry',
        valueType: this.getType(t.valueType)
      };
    }

    if (t.type === 'iterator' || t.type === 'asyncIterator') {
      if (t.valueType.type === 'subModel_or_moduleModel') {
        this.checkType(t.valueType);
        return {
          type: t.type,
          valueType: t.valueType
        };
      }

      return {
        type: t.type,
        valueType: this.getType(t.valueType)
      };
    }

    if (t.type === 'subModel_or_moduleModel') {
      this.checkType(t);
    }

    if (t.type === 'moduleModel') {
      const [mainId, ...rest] = t.path;
      const typeName = rest.map((item) => {
        return item.lexeme;
      }).join('.');
      const moduleName = mainId.lexeme;
      this.usedExternModel.get(moduleName).add(typeName);
      const checker = this.dependencies.get(moduleName);
      return checker.getModel(typeName, moduleName);
    }

    if (t.type === 'subModel') {
      let modelName = t.path.map((tag) => {
        return tag.lexeme;
      }).join('.');
      return this.getModel(modelName);
    }

    if (t.type === 'moduleEnum') {
      const [mainId, ...rest] = t.path;
      const typeName = rest.map((item) => {
        return item.lexeme;
      }).join('.');
      this.usedExternModel.get(mainId.lexeme).add(typeName);
      return _enum(typeName, mainId.lexeme);
    }

    if (t.type === 'moduleTypedef') {
      const [mainId, ...rest] = t.path;
      const typeName = rest.map((item) => {
        return item.lexeme;
      }).join('.');
      this.usedExternModel.get(mainId.lexeme).add(typeName);
      return _typedef(typeName, mainId.lexeme);
    }
    // return _model(t.path.map((item) => {
    //   return item.lexeme;
    // }).join('.'));

    console.log(t);
    throw new Error('un-implemented');
  }