the-sett / salix / L3

Defines the level 3 language for data models that have been annotated with properties indicating that the model has particular features needed by particular code generators.

A level 3 processor is something that consumes a data model with particular properties. It declares up-front what the properties it consumes are, and this allows its input to be checked against it prior to processing it; missing or invalid properties can be reported as errors back to the user.

A level 3 language combines together an L2 data model, and optionally a set of properties that are understood by a level 3 processor and control how it processes the model. An example might be a name property that tells an L3 processor how to name some code module that it generates; the L3 language says what value the name is to take, and the L3 processor expects that to be set and will consume that value when naming the module it generates.

The L3 data modelling language.


type alias L3 pos =
{ properties : L1.Properties
, declarations : Dict String (L1.Declarable pos L2.RefChecked) 
}

The L3 model. This consists of an L2 model and a set of top-level properties that a code generator needs to know.

Standardized interface to an L3 processor.


type alias Processor pos =
{ name : String
, defaults : DefaultProperties
, check : L3 pos -> ResultME Errors.Error (L3 pos) 
}

API for an L3 model processor.


type alias ProcessorImpl pos err =
{ name : String
, defaults : DefaultProperties
, check : L3 pos -> ResultME err (L3 pos)
, buildError : Errors.ErrorBuilder pos err 
}

SPI for an L3 model processor. Use the builder to turn one of these into a Processor.

builder : (pos -> SourcePos.SourceLines) -> ProcessorImpl pos err -> Processor pos

Builds an L3 Processor API from an implementation. A function to turn source code positions into quoted lines of source code needs to be supplied.

Common L3 error catalogue for property and dereferncing errors.


type L3Error
    = CheckedPropertyMissing String L1.PropSpec
    | CheckedPropertyWrongKind String L1.PropSpec
    | DerefDeclMissing String
    | NotExpectedKind String String

Common Errors that L3 processors may run into when fetching properties or dereferencing declarations from the model. One the model has been reference and property checked these error should not be possible, but we have to allow for the error code branches anyway.

As these errors should generally not happen, they should be reported as bugs when they do. This error type enumerates the possible dereferencing and property bugs.

errorBuilder : (pos -> SourcePos.SourceLines) -> L3Error -> Errors.Error

Convert prop check errors to standard errors.

errorCatalogue : Dict Basics.Int Errors.ErrorMessage

The error catalogue for this property checking.

The error message here are quite generic, and you likely want to re-write this error catalogue for specific modules in order to give better messages.

Defaulting of properties across the data model, and APIs to read properties.


type alias DefaultProperties =
{ top : ( L1.PropSpecs
, L1.Properties )
, alias : ( L1.PropSpecs
, L1.Properties )
, sum : ( L1.PropSpecs
, L1.Properties )
, enum : ( L1.PropSpecs
, L1.Properties )
, restricted : ( L1.PropSpecs
, L1.Properties )
, fields : ( L1.PropSpecs
, L1.Properties ) 
}

Allows the default properties on parts of the model to be defined.

emptyDefaultProperties : DefaultProperties

An empty set of default properties. Useful for querying models during L2 processing, as without an L3 there are no defaults. So an L2 model can be easily turned into one with a PropertiesAPI outside of the context of L3 procesing.


type alias PropertiesAPI pos =
{ top : PropertyGet
, declarable : L1.Declarable pos L2.RefChecked -> PropertyGet
, field : L1.Properties -> PropertyGet 
}

An API for supplying property readers for various parts of the data model.


type alias PropertyGet =
{ getStringProperty : String -> ResultME L3Error String
, getEnumProperty : Enum String -> String -> ResultME L3Error String
, getQNameProperty : String -> ResultME L3Error (List String)
, getBoolProperty : String -> ResultME L3Error Basics.Bool
, getOptionalStringProperty : String -> ResultME L3Error (Maybe String)
, getOptionalEnumProperty : Enum String -> String -> ResultME L3Error (Maybe String) 
}

An API for reading properties of various expected kinds.

makePropertiesAPI : DefaultProperties -> L3 pos -> PropertiesAPI pos

Creates a properties API from a set of defaulted property specs, and an L3 model.