function isAssignable()

in lib/semantic.js [216:308]


function isAssignable(expected, actual, expr) {

  if (isSameType(expected, actual)) {
    return true;
  }

  if (isSameNumber(expected, actual)) {
    return true;
  }

  if(expected.type === 'model' && actual.type === 'model') {
    // $Model vs model
    if(expected.name === '$Model') {
      return true;
    }

    // $Error vs exception
    if(expected.name === '$Error' && actual.isException) {
      return true;
    }

    if (isExtendOn(expected, actual)) {
      return true;
    }
  }

  // actual is null
  if (actual.type === 'basic' && actual.name === 'null') {
    return true;
  }

  if (expected.type === 'map' && actual.type === 'map') {
    if (expr && expr.type === 'object' && expr.fields.length === 0) {
      return true;
    }

    if (isAssignable(expected.valueType, actual.valueType)) {
      return true;
    }
  }

  if (expected.type === 'entry' && actual.type === 'entry') {
    if (expr && expr.type === 'object' && expr.fields.length === 0) {
      return true;
    }

    if (isAssignable(expected.valueType, actual.valueType)) {
      return true;
    }
  }

  if (expected.type === 'array' && actual.type === 'array') {

    if (expr && expr.type === 'array' && expr.items.length === 0) {
      return true;
    }

    if (isAssignable(expected.itemType, actual.itemType)) {
      return true;
    }
  }

  if (expected.type === 'basic' && expected.name === 'readable') {
    // readable = string should ok
    if (actual.type === 'basic' && actual.name === 'string') {
      return true;
    }

    // readable = bytes should ok
    if (actual.type === 'basic' && actual.name === 'bytes') {
      return true;
    }
  }

  if (expected.type === 'basic' && expected.name === 'any') {
    // any = other type
    return true;
  }

  if (expected.type === 'basic' && expected.name === 'object') {
    // object = other type
    return true;
  }

  if (expected.type === 'module_instance' && actual.type === 'module_instance') {
    if (actual.parentModuleIds.includes(expected.name)) {
      // basicModule = new derivedModule
      return true;
    }
  }

  return false;
}