The Fortress Language Specification Version 1.0

methods have only headers; concrete methods also have definitions. A trait may extend other traits: it inherits the methods provided by the traits it extends. A trait provides the methods that it inherits as well as those explicitly declared in its declaration. Every object extends a set of traits (its “supertraits”). An object inherits the concrete methods of its supertraits and must include a definition for every method declared but not defined by its supertraits. object SolarSystem extends {StarSystem,OrbitingObject } sun = Sol planets = {Mercury,Venus,Earth,Mars, Jupiter,Saturn,Uranus,Neptune } position = Polar(25000 lightYears, 0 radians) ω : R64 AngularVelocity = 2π radians / 226 million years in seconds variation(ω∆) = ω += ω∆ end In this example, the object SolarSystem extends the traits StarSystem and OrbitingObject . The fields ω and position are defined with appropriate quantities. The field sun is defined to be another object named Sol , and the field planets is defined to be a set of objects. The method variation is defined to take a single parameter ω∆, and update the ω field of the object. As this example illustrates, Fortress provides static checking of physical units and dimensions on quantities. Note that the identifiers used in this example are not restricted to ASCII character sequences. Fortress allows the use of Unicode characters [27] in program identifiers, as well as subscripts and superscripts. (See Appendix E for a discussion of Unicode and support for entering programs in ASCII.) Fortress also includes a set of standard formatting rules that follow the conventions of mathematical notation. For example, most variable references in Fortress programs are italicized. Moreover, multiplication can be expressed by simple juxtaposition, as can be seen in the definition of ω. There is also support for operator overloading, as well as a facility for extending the syntax with domain-specific languages. Although Fortress is statically and nominally typed, types are not specified for all fields, nor for all method parameters and return values. Instead, wherever possible, type inference is used to reconstruct types. In the examples throughout this specification, we often omit the types when they are clear from context. Additionally, types can be parametric with respect to other types and values (most notably natural numbers). These design decisions are motivated in part by our goal of making the scientist/programmer’s life as easy as possible without compromising good software engineering. In particular, they allow us to write Fortress programs that preserve the look of standard mathematical notation. In addition to objects and traits, Fortress allows the programmer to define top-level functions. Functions are first-class values: They can be passed to and returned from functions, and assigned as values to fields and variables. Functions and methods can be overloaded, with calls to overloading methods resolved by multiple dynamic dispatch similarly to the manner described in [19]. Keyword parameters and variable size argument lists are also supported. Fortress programs are organized into components, which export and import APIs and can be linked together. APIs describe the “shape” of a component, specifying the types in traits, objects and functions provided by a component. All external references within a component (i.e., references to traits, objects and functions implemented by other components) are to APIs imported by the component. We discuss components and APIs in detail in Chapter 22. To address the needs of modern high-performance computation, Fortress also supports a rich set of operations for defining parallel execution and distribution of large data structures. This support is built into the core of the language. For example, for loops in Fortress are parallel by default.