memberGet method

  1. @override
dynamic memberGet(
  1. String id, {
  2. String? from,
  3. bool isRecursive = false,
  4. bool ignoreUndefined = true,
  5. String? cast,
})
override

Get the value of a member from this HTInstace via memberGet operator '.' for symbol searching, use the same name method on HTInstanceNamespace instead. HTInstance overrided HTObject's memberGet, with a new named parameter cast. If cast is provided, then the instance will only search that cast's corresponed HTInstanceNamespace.

Implementation

@override
dynamic memberGet(
  String id, {
  String? from,
  bool isRecursive = false,
  bool ignoreUndefined = true,
  String? cast,
}) {
  final getter = '${InternalIdentifier.getter}$id';

  if (cast == null) {
    for (final space in _namespaces.values) {
      if (space.symbols.containsKey(id)) {
        final decl = space.symbols[id];
        if (decl == null) return null;
        if (decl is HTDeclaration) {
          if (decl.isPrivate &&
              from != null &&
              !from.startsWith(namespace.fullName)) {
            throw HTError.privateMember(id);
          }
          decl.resolve();
          if (decl is HTFunction &&
              decl.category != FunctionCategory.literal) {
            decl.namespace = namespace;
            decl.instance = this;
          }
          return decl.value;
        } else {
          if (interpreter.lexicon.isPrivate(id) &&
              from != null &&
              !from.startsWith(namespace.fullName)) {
            throw HTError.privateMember(id);
          }
          return decl;
        }
      } else if (space.symbols.containsKey(getter)) {
        final decl = space.symbols[getter];
        if (decl == null || decl is! HTFunction) return null;
        if (decl.isPrivate &&
            from != null &&
            !from.startsWith(namespace.fullName)) {
          throw HTError.privateMember(id);
        }
        decl.resolve();
        decl.namespace = namespace;
        decl.instance = this;
        return decl.call();
      }
    }
  } else {
    final space = _namespaces[cast]!;
    if (space.symbols.containsKey(id)) {
      var decl = space.symbols[id];
      if (decl == null) return null;
      if (decl is HTDeclaration) {
        if (decl.isPrivate &&
            from != null &&
            !from.startsWith(namespace.fullName)) {
          throw HTError.privateMember(id);
        }
        if (decl is HTFunction && decl.category != FunctionCategory.literal) {
          decl = decl.clone();
          decl.namespace = _namespaces[classId];
          decl.instance = this;
        }
        decl.resolve();
        return decl.value;
      } else {
        if (interpreter.lexicon.isPrivate(id) &&
            from != null &&
            !from.startsWith(namespace.fullName)) {
          throw HTError.privateMember(id);
        }
        return decl;
      }
    } else if (space.symbols.containsKey(getter)) {
      final decl = space.symbols[getter];
      if (decl == null || decl is! HTFunction) return null;
      if (decl.isPrivate &&
          from != null &&
          !from.startsWith(namespace.fullName)) {
        throw HTError.privateMember(id);
      }
      decl.resolve();
      decl.namespace = _namespaces[classId];
      decl.instance = this;
      return decl.call();
    }
  }

  if (!ignoreUndefined) {
    throw HTError.undefined(id);
  }
}