main = <No Member>;
library from "org-dartlang-test:///lib.dart" as lib {

  import "dart:ffi";

  @#C3
  @#C8
  class Coordinate extends dart.ffi::Struct {
    @#C3
    static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
    @#C3
    constructor #fromPointer(dynamic #pointer) → dynamic
      : super dart.ffi::Struct::_fromPointer(#pointer)
      ;
    static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
      return null;
    }
    abstract member-signature get /* from org-dartlang-sdk:///sdk/lib/ffi/struct.dart */ _addressOf() → dart.core::Object*; -> dart.ffi::Struct::_addressOf
    abstract member-signature get /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
    abstract member-signature method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
    abstract member-signature method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
    abstract member-signature method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
    abstract member-signature method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
    abstract member-signature operator /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
    abstract member-signature get /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ hashCode() → dart.core::int*; -> dart.core::Object::hashCode
    abstract member-signature method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ toString() → dart.core::String*; -> dart.core::Object::toString
    abstract member-signature method /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
    abstract member-signature get /* from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/object_patch.dart */ runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
    get x() → dart.core::double*
      return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()));
    set x(dart.core::double* #v) → void
      return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v);
    get y() → dart.core::double*
      return dart.ffi::_loadDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()));
    set y(dart.core::double* #v) → void
      return dart.ffi::_storeDouble(this.{dart.ffi::Struct::_addressOf}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v);
    get next() → dart.ffi::Pointer<lib::Coordinate*>*
      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi())));
    set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
  }
}
library from "org-dartlang-test:///main.dart" as main {

  import "org-dartlang-test:///lib.dart";

  static method main() → dynamic {
    lib::Coordinate* coordinate = lib::Coordinate::allocate(42.0, 42.0, null);
    dart.core::print(coordinate.{lib::Coordinate::x});
    dart.core::print(coordinate.{lib::Coordinate::y});
    dart.core::print(coordinate.{lib::Coordinate::next});
  }
}
constants  {
  #C1 = "vm:entry-point"
  #C2 = null
  #C3 = dart.core::pragma {name:#C1, options:#C2}
  #C4 = "vm:ffi:struct-fields"
  #C5 = TypeLiteralConstant(dart.ffi::Double)
  #C6 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
  #C7 = <dart.core::Type>[#C5, #C5, #C6]
  #C8 = dart.core::pragma {name:#C4, options:#C7}
  #C9 = 24
  #C10 = 20
  #C11 = <dart.core::int*>[#C9, #C10, #C9]
  #C12 = 0
  #C13 = <dart.core::int*>[#C12, #C12, #C12]
  #C14 = 8
  #C15 = <dart.core::int*>[#C14, #C14, #C14]
  #C16 = 16
  #C17 = <dart.core::int*>[#C16, #C16, #C16]
}
