From 6d7328c91e45bdd1ccd1e5157493f311cc5dfb96 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 20 Jul 2020 15:53:40 -0600 Subject: [PATCH] update flux type grammar, resolves #1215 --- .../reference/flux/language/statements.md | 81 ------------------- .../flux/language/system-built-ins.md | 24 +++++- content/v2.0/reference/flux/language/types.md | 49 ++++++++++- 3 files changed, 69 insertions(+), 85 deletions(-) diff --git a/content/v2.0/reference/flux/language/statements.md b/content/v2.0/reference/flux/language/statements.md index 7a83d5ee8..a03bbd9c2 100644 --- a/content/v2.0/reference/flux/language/statements.md +++ b/content/v2.0/reference/flux/language/statements.md @@ -79,84 +79,3 @@ ExpressionStatement = Expression . f() a ``` - -## Named types - -A named type can be created using a type assignment statement. -A named type is equivalent to the type it describes and may be used interchangeably. - -```js -TypeAssignment = "type" identifier "=" TypeExpression . -TypeExpression = identifier - | TypeParameter - | ObjectType - | ArrayType - | GeneratorType - | FunctionType . -TypeParameter = "'" identifier . -ObjectType = "{" PropertyTypeList [";" ObjectUpperBound ] "}" . -ObjectUpperBound = "any" | PropertyTypeList . -PropertyTypeList = PropertyType [ "," PropertyType ] . -PropertyType = identifier ":" TypeExpression - | string_lit ":" TypeExpression . -ArrayType = "[]" TypeExpression . -GeneratorType = "[...]" TypeExpression . -FunctionType = ParameterTypeList "->" TypeExpression -ParameterTypeList = "(" [ ParameterType { "," ParameterType } ] ")" . -ParameterType = identifier ":" [ pipe_receive_lit ] TypeExpression . -``` - -Named types are a separate namespace from values. -It is possible for a value and a type to have the same identifier. -The following named types are built-in. - -```js -bool // boolean -int // integer -uint // unsigned integer -float // floating point number -duration // duration of time -time // time -string // utf-8 encoded string -regexp // regular expression -bytes // sequence of byte values -type // a type that itself describes a type -``` - -When an object's upper bound is not specified, it is assumed to be equal to its lower bound. - -Parameters to function types define whether the parameter is a pipe forward -parameter and whether the parameter has a default value. -The `<-` indicates the parameter is the pipe forward parameter. - -###### Examples -```js - // alias the bool type - type boolean = bool - - // define a person as an object type - type person = { - name: string, - age: int, - } - - // Define addition on ints - type intAdd = (a: int, b: int) -> int - - // Define polymorphic addition - type add = (a: 'a, b: 'a) -> 'a - - // Define funcion with pipe parameter - type bar = (foo: <-string) -> string - - // Define object type with an empty lower bound and an explicit upper bound - type address = { - ; - street: string, - city: string, - state: string, - country: string, - province: string, - zip: int, - } -``` diff --git a/content/v2.0/reference/flux/language/system-built-ins.md b/content/v2.0/reference/flux/language/system-built-ins.md index ae519868d..a542bb8b9 100644 --- a/content/v2.0/reference/flux/language/system-built-ins.md +++ b/content/v2.0/reference/flux/language/system-built-ins.md @@ -12,15 +12,35 @@ menu: weight: 206 --- +Flux contains many preassigned values. These preassigned values are defined in the source files for the various built-in packages. + When a built-in value is not expressible in Flux, its value may be defined by the hosting environment. All such values must have a corresponding builtin statement to declare the existence and type of the built-in value. ```js -BuiltinStatement = "builtin" identifier ":" TypeExpression . +BuiltinStatement = "builtin" identifer ":" TypeExpression . +TypeExpression = MonoType ["where" Constraints] . + +MonoType = Tvar | Basic | Array | Record | Function . +Tvar = "A" … "Z" . +Basic = "int" | "uint" | "float" | "string" | "bool" | "time" | "duration" | "bytes" | "regexp" . +Array = "[" MonoType "]" . +Record = ( "{" [Properties] "}" ) | ( "{" Tvar "with" Properties "}" ) . +Function = "(" [Parameters] ")" "=>" MonoType . + +Properties = Property { "," Property } . +Property = identifier ":" MonoType . + +Parameters = Parameter { "," Parameter } . +Parameter = [ "<-" | "?" ] identifier ":" MonoType . + +Constraints = Constraint { "," Constraint } . +Constraint = Tvar ":" Kinds . +Kinds = identifier { "+" identifier } . ``` ##### Example ```js -builtin from : (bucket: string, bucketID: string) -> stream +builtin filter : (<-tables: [T], fn: (r: T) -> bool) -> [T] ``` diff --git a/content/v2.0/reference/flux/language/types.md b/content/v2.0/reference/flux/language/types.md index 2a273b15e..67ee26b39 100644 --- a/content/v2.0/reference/flux/language/types.md +++ b/content/v2.0/reference/flux/language/types.md @@ -14,9 +14,10 @@ Any section that is not currently implemented is commented with a **[IMPL#XXX]** **XXX** is an issue number tracking discussion and progress towards implementation. {{% /note %}} -A _type_ defines the set of values and operations on those values. -Types are never explicitly declared as part of the syntax. +A **type** defines the set of values and operations on those values. +Types are never explicitly declared as part of the syntax except as part of a [builtin statement](#system-built-ins). Types are always inferred from the usage of the value. +Type inference follows a Hindley-Milner style inference system. ## Union types A union type defines a set of types. @@ -154,3 +155,47 @@ The generated values may be of any other type, but must all be the same type. {{% note %}} [IMPL#658](https://github.com/influxdata/platform/query/issues/658) Implement Generators types. {{% /note %}} + +#### Polymorphism +Flux types can be polymorphic, meaning that a type may take on many different types. +Flux supports let-polymorphism and structural polymorphism. + +##### Let-polymorphism +Let-polymorphism is the concept that each time an identifier is referenced, it may take on a different type. +For example: + +```js +add = (a,b) => a + b +add(a:1,b:2) // 3 +add(a:1.5,b:2.0) // 3.5 +``` + +The identifiers, `a` and `b`, in the body of the `add` function are used as both `int` and `float` types. + +##### Structural polymorphism +Structural polymorphism is the concept that structures (objects in Flux) can be +used by the same function even if the structures themselves are different. +For example: + +```js +john = {name:"John", lastName:"Smith"} +jane = {name:"Jane", age:44} + +// John and Jane are objects with different types. +// We can still define a function that can operate on both objects safely. + +// name returns the name of a person +name = (person) => person.name + +name(person:john) // John +name(person:jane) // Jane + +device = {id: 125325, lat: 15.6163, lon: 62.6623} + +name(person:device) // Type error, "device" does not have a property name. +``` + +Objects of differing types can be used as the same type so long as they both contain the necessary properties. +Necessary properties are determined by the use of the object. +This form of polymorphism means that checks are performed during type inference and not during runtime. +Type errors are found and reported before runtime.