Directive
| Statement |
Directives pass instructions and information to the HiLang compiler that are not part of the model (but may describe it)
Function
Declares a function that will be implemented externally. Parameters are
- {set, aggregate, unary}
- Function name used in hilang source
- The full name of the implementation. The first parameter is {set, aggregate, unary},
- Optional data type of the function (needed for unary functions)
The standard prelude includes declaration of in-built aggregate functions, with Hiperspace.Functions providing the implementation
%function ( aggregate, sum, Functions.Sum); /* takes an attribute and collection */
%function ( aggregate, avg, Functions.Avg);
%function ( aggregate, max, Functions.Max);
%function ( aggregate, min, Functions.Min);
%function ( aggregate, count, Functions.Count);
%function ( aggregate, deltasum, Functions.DeltaSum); /* sums and subtracts the value */
%function ( aggregate, deltamax, Functions.DeltaMax); /* prior to the DeltaFrom timestamp */
%function ( aggregate, deltamin, Functions.DeltaMin); /* used when opening the subspace */
%function ( aggregate, deltacount, Functions.DeltaCount); /* with a delta parameter */
QLNet is an example of the declaration of external functions with Helper.cs providing the implementation
%function(unary, makeBusinessDayConvention, QL.Helper.BusinessDayConvention, QLNet.BusinessDayConvention);
%function(unary, makeCalendar, QL.Helper.Calendar, QLNet.Calendar);
%function(unary, makeCurve, QL.Helper.FlatForward, QLNet.Handle<QLNet.YieldTermStructure>);
%function(unary, makeDayCounter, QL.Helper.DayCounter, QLNet.DayCounter);
%function(unary, makeEngine, QL.Helper.Engine, QLNet.IPricingEngine);
%function(unary, makeFixedRateBond, QL.Helper.FixedRateBond, QLNet.FixedRateBond);
%function(unary, makeInstrument, QL.Helper.Make, QLNet.Instrument);
%function(unary, makePeriod, QL.Helper.Period, QLNet.Period);
%function(unary, makeRule, QL.Helper.DateRule, QLNet.DateGeneration.Rule);
%function(unary, makeSchedule, QL.Helper.Schedule, QLNet.Schedule);
%function(unary, NPV, QL.Helper.NPV, Double);
%function(unary, CASH, QL.Helper.CASH, Double);
Functions can be arbitrarily complicated / recursive, and traverse the entire Hiperspace if needed. The Cousins Problem includes %function (unary, relation, Cousins.Helper.Relations, List<Path>);
that finds all relations for a person, and classifieds them by relationship like cousin and implemented in Helper.cs
domain
Name of the DomainSpace that will be generated with SetSpace<> members for each of the Entity, Segment, aspect, view in the domain model. %domain (Cousins);
produced
namespace Cousins
{
public partial class CousinsSpace : Hiperspace.SubSpace
{
....
}
}
import
Include another “.hilang” file in the generation. %import ("Element.hilang");
includes the content of the "Element.hilang" file in the HiLang compilation.
This is useful for very large models where different parts of the model are owned/maintained by different groups
sql
'%sql;` indicates that additional property attributes should be generated for interoperability with Microsoft Entity Framework (for relational database interoperability)
json
%json;
indicates that references to SetSpace
should be marked as excluded from JSON serialization with System.Text.Json.
odata
%odata;
indicates that value types should be presented as embeded json text
ids
If a #id is not added to the definition of an {element, key, value, extent, index} an id is auto allocated during the compilation of a .hilang file. It is best practice to add #id field to simplify the evolution of a schema since the internal #id can never be changed (to a different data type) or reused for a different purpose since it wil invalidate historic views of data. This can be a problem when {element, key, value, extent, index} are dropped and the #id is then used for a later addition. To simplify maintenance the directive %ids;
has been added to optionally add the generated #id to the source file
the source entity Customer (Id : Int32) {Name :String} [SameName = Customer(Name = Name];
defines an entity Customer with a key Id and value Name and an index SameName that can be used to find Customers or to apply horizon validation 'Horizon<Customer>("Duplicate Name", (customer, read) => customer.SameName == null || read).
When the %ids;
directive is added, the the source is auto edited to entity Customer #1 (Id : Int32 #1) {Name : String #2} [SameName = Customer(Name = Name) #2];
to indicate that Customer has #1 id and CustomerSameNameIndex has #2 (stored items have unique #id, but SameName is not stored with customer, so does not need to be unique within the element)
If we decide to break Name into First_Name and Family_Name we'd change the entity to
entity Customer #1 (Id : Int32 #1)
{First_Name : String #3, Family_Name : String #4}
[Name = First_Name + " " + Family_Name, SameName #3 = Customer( Family_Name = Family_Name, First_Name = First_Name];
Adding %ids;
directive simplifies the process of avoiding clashes that will prevent the hiperspace being opened with updated code.
DeltaIndex
The @DeltaIndex
property of an entity provides indexes access to elements that have changed since a date-time stamp. The property has been updated to include the option to define the #id for the index by adding a parameter @DeltaIndex(4)
CubeFact
The @CubeFact
property of an element creates a fact element (the code @CubeFact entity Account
adds an additional Account_Fact table to the hiperspace for stored historic aggregates of @CubeMeasure values).
The property has been updated to include the #id of the fact table @CubeFact(5)
indicates that the fact table has #id of 5.
%ids;
is optional since #id's will be allocated (during compilation) for intermediate elements that will be pruned before generation resulting in gaps in the generated #id numbers