The Microsoft code name "M" Modeling Language Specification - Computed and Stored Values

Microsoft Corporation

November 2009

[This content is no longer valid. For the latest information on "M", "Quadrant", SQL Server Modeling Services, and the Repository, see the Model Citizen blog.]

[This documentation targets the Microsoft SQL Server Modeling CTP (November 2009) and is subject to change in future releases. Blank topics are included as placeholders.]

Sections:
1: Introduction to "M"
2: Lexical Structure
3: Text Pattern Expressions
4: Productions
5: Rules
6: Languages
7: Types
8: Computed and Stored Values
9: Expressions
10: Module
11: Attributes
12: Catalog
13: Standard Library
14: Glossary

8 Computed and Stored Values

M provides two primary means for values to come into existence: computed values and stored values (a.k.a. fields). Computed values occur within module declarations.

A computed value is derived from evaluating an expression. In contrast, a field stores a value and the contents may change over time .

8.1 Computed Value Declaration

A ComputedValueDeclaration binds a name to an expression that is used to compute the resultant value.

syntax ComputedValueDeclaration

    = Identifier FormalParameters ReturnTypeopt ExpressionBody

    | "extern" Identifer FormalParameters ReturnType  ";";

syntax FormalParameters

    = "(" Parameters? ")";

syntax Parameters

    = Parameter

    | Parameters ","  Parameter;

syntax Parameter

    = Identifier TypeAscription?;

syntax ReturnType

    = TypeAscription;

syntax ExpressionBody

    = "=>" Expression ";";

If the type of a parameter or the ReturnType is not explicitly specified, the parameter or return type will be implicitly inferred from the ExpressionBody. For example, the following two ComputedValueDeclarations have the same meaning:

Add(x : Integer32, y : Integer32) => x + y;

Add(x : Integer32, y : Integer32) : Integer32 => x + y ;

ComputedValueDeclaration introduces the formal parameters into scope. It is an error to have more than one formal parameter with the same Identifier. 

8.1.1 Overloading

A module may define multiple computed values with the same name. In this case, selection is determined based on the number of arguments. It is an error to define two computed values with the same name and the same number of arguments.

Within a module the names of computed values, extents and types must be disjoint.

8.2 Fields

A field is a storage location. A field declaration specifies the name of the field and optionally a type ascription which constrains values in the field to be of the ascribed type. An initial value may be defined by either equating the field with an Expression or using an InitializationExpression (§9.3).

If an initializer is present without a TypeAscription, the type of the field is the type of the initializer. If both an initializer and TypeAscription are present, then the initializer must conform to the TypeAscription.

syntax FieldDeclaration

    = DottedIdentifer  TypeAscription? "=>" Expression ";"

    | DottedIdentifier  TypeAscription?  InitializationExpression ";"?;

DottedIdentifers  TypeAscription? ";"

    = "extern" Identifier TypeAscription ";";

syntax DottedIdentifiers

    | DottedIdentifier

    | DottedIdentifiers "," DottedIdentifier;

syntax DottedIdentifer

    = IdentifierPath

    | "."  IdentifierPath;

syntax IdentifierPath

    | Identifier

    | IdentifierPath "." Identifier;

The only DottedIdentifer that is legal within an entity type declaration is a single Identifer.

A leading dot resolves the identifier within the top level module scope rather than the lexical scope.

8.3 External Declarations

The extern feature allows an M author to declare the ‘shape’ or signature of some construct, while the implementation of a runtime not defined in M. Only module level fields (extents) and computed values may be marked extern.

The M language defines a keyword, extern which can be applied to computed value or extent declarations. When applied to a computed value declaration, that declaration must explicitly specify a return type and must not provide a body for the computed value. When applied to an extent declaration, that declaration must specify a type.

module Microsoft.Samples

{

    extern Add (x:Integer32, y:Integer32) : Integer32;

    extern HostName() : Text;

    extern People : {{

           Id : Integer32 => AutoNumber;

           Name : Text;

           Age : Integer16;

    }*} where identity Id;

}

A declaration marked with extern can be referred to anywhere such a declaration could be referred to if it were not marked extern. That is, marking a declaration as extern does not affect where that declaration can be referred to in M. Unless an extern declaration is explicitly exported, it may only be used by the declaring module.