diff --git a/README.md b/README.md index cdfaabb..63adec6 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,7 @@ specification phase. There is no grammar, parser, compiler, or way to use any Ava code. Ava is a way to get ideas out of my head, challenged, and further explored. -## Notes +## Documentation -These notes are not guaranteed to be up to date and represent a large amount of -brainstorming and trying/discarding of ideas. - -Please start with the [Table of Contents](./notes/table-of-contents.md) +Please start with the [Documentation Contents](./docs), which provides links to +different iterations of the language. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..83afe61 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,6 @@ +# Ava Documentation + +This documentation is currently organized by revision, where major updates are +made to the specification. + +- [R2](./revision2.md) diff --git a/docs/revision2.md b/docs/revision2.md new file mode 100644 index 0000000..10abc33 --- /dev/null +++ b/docs/revision2.md @@ -0,0 +1,463 @@ +# Ava R2 + +This document specifies the second revision of the Ava programming language, +started 2024-07-18. + +## Table of Contents + +- [Names](#names) +- [Reserved Keywords](#reserved-keywords) +- [Reserved Symbols and Operators](#reserved-symbols-and-operators) +- [Namespaces](#namespaces) +- [Imports](#imports) +- [Definitions](#definitions) +- [Comments](#comments) +- [Constants](#constants) + +## Names + +_Names_ in Ava source code are user-defined strings that provide some form of +identifier to some component that may be named. All names in Ava follow the same +rules. + +### Name Rules + +- Names are UTF-8 strings. +- Names may **not** be a reserved keyword. +- Names may **not** be a reserved symbol/operator. +- Names may **not** include whitespace characters. +- Names may **not** include `.` +- Names may **not** include `"` +- Names may **not** include `'` +- Names may **not** include `,` +- Names may **not** include `:` +- Names may **not** include `\` +- Names may **not** include `(` +- Names may **not** include `)` +- Names may **not** begin with a number. +- Two definitions may **not** share the same name in scope. + - This implies that names may **not** reuse the name of any standard type + that is always considered in scope, such as `Int32` or `Boolean`. + +### Name Targets + +The following items may be named in Ava: + +- [Namespaces](#namespaces) +- [Definitions](#definitions) +- [Variables](#variables) +- [Function Arguments](#function-arguments) +- [Record Fields](#record-fields) +- [Destructured Fields](#destructured-fields) + +### Name Examples + +- `foo` +- `foo-bar` +- `foo_bar` +- `<=` +- `>` +- `==` +- `%` +- `f1` +- `_foo` +- `&&` +- `||` + +## Reserved Keywords + +### `namespace` + +Used to specify the [Namespace](#namespaces) of a file. + +### `import` + +Used to declare an [Import](#imports) within a file. + +### `private` + +Used to mark a [Definition](#definitions) as [Private](#private-accessibility). + +### `internal` + +Used to mark a [Definition](#definitions) as +[Internal](#internal-accessibility). + +### `let` + +Declares an immutable [Variable](#variables) binding. + +### `mut` + +Declares a mutable [Variable](#variables) binding. + +### `const` + +Declares a [Constant](#constants) definition. + +### `given` + +Used to define [type constructors](#type-constructors) within the scope of some +definition. + +### `fn` + +Indicates a [function](#functions) definition. Each function may or may not be +implemented. + +### `class` + +Indicates a [type class](#type-classes) definition. + +### `instance` + +Indicates the definition of a specific +[type class instance](#type-class-instances). + +### `match` + +Keyword that identifies a [match expression](#match-expressions). + +### `λ` + +Alias for the [case](#case) keyword. + +### `case` + +Defines a [pattern matching](#pattern-matching) case within some pattern +matching context (either a function implementation or a match expression). + +### `end` + +Used to indicate the end of some block. + +### `type` + +Declare a [type definition](#type-definitions). + +### `opaque` + +Declare an [opaque type](#opaque-types). + +### `record` + +Define a [record](#records) (immutable data structure). + +### `enum` + +Define a new [enumeration](#enumerations) (sum type). + +### `as` + +Used to rename a specific [import](#imports). + +### `if` + +Denotes an [if/then/else expression](#if-then-else-expressions). + +### `then` + +Required after the predicate of an +[if/then/else expression](#if-then-else-expressions). + +### `else` + +Required after the first block of an +[if/then/else expression](#if-then-else-expressions). + +### `true` + +The Boolean value `true`. + +### `false` + +The Boolean value `false`. + +### `object` + +Define a [singleton object](#singleton-objects). + +### MISSING SOME VALUES + +TODO: Things like `do`/`return`, `infix`, `const` + +TODO: Consider `abstract` to be used for abstract type class functions. + +## Reserved Symbols and Operators + +### `.` (Access Operator) +### `=` (Assignment Operator) +### `:` (Type Assignment Operator) +### `::` (Type Class Membership Operator) +### `(` (Open Parenthesis) +### `)` (Close Parenthesis) +### `,` (Comma) +### `=>` (Case Implementation Operator) +### `->` (Type Function Operator) +### `_` (Anonymous Value Binding) +### `|` (Type Union Operator) +### `--` (Comment Prefix) + +## Namespaces + +The primary organizational concept in Ava is the _namespace_. Namespaces must be +explicitly declared in _every_ Ava file. + +### Rules + +- Every Ava source file _must_ begin with a `namespace` declaration. +- The first non-comment code in any Ava source file _must_ be a `namespace` + declaration. +- Namespaces must contain at least one [name](#names). +- Namespaces may concatenate names using the `.` character. +- Multiple files may share the same namespace. +- Namespaces are **public** by default. This means that if any + [definition](#definition) is not marked [private](#definition-accessibility) + or [internal](#definition-accessibility), all definitions will be exported. + +### Syntax Specification + +``` +namespace [.]* +``` + +### Syntax Examples + +``` +namespace foo +namespace foo.bar +namespace foo.bar.baz_buzz +namespace foo.bar.v0 +``` + +## Imports + +An `import` can be used to pull other namespaces, or [definitions](#definitions) +from other namespaces, into the current scope. + +### Rules + +- Imports **must** follow the [namespace](#namespaces) declaration. +- Imports may **not** be placed after any definition. +- Glob imports may **not** use `as` to rename (since they have no specific + target to rename). + +### Syntax Specification + +``` +import [.]*[.\* | as ] +``` + +### Syntax Examples + +``` +-- import a namespace, which can be referenced by name +import foo.bar + +-- import everything within some namespace +import foo.bar.baz.* + +-- import a specific definition from within a namespace +import foo.bar.SomeDef + +-- import and rename a namespace +import baz.buzz as bb + +-- import and rename a specific definition from within a namespace +import baz.buzz.FooBar as Foo +``` + +## Definitions + +A "definition" is something that might be _defined_ at the top level of any Ava +source file. These include: + +- [Constants](#constants) +- [Functions](#functions) +- [Infix Functions](#infix-functions) +- [Type Classes](#type-classes) +- [Type Class Instances](#type-class-instances) +- [Enumerations](#enumerations) +- [Records](#records) +- [Type Definitions](#type-definitions) +- [Opaque Types](#opaque-types) + +### Definition Accessibility + +All definitions are **public** by default. All definitions **may** be modified +to be either [internal](#internal-accessibility) or +[private](#private-accessibility). + +### Internal Accessibility + +`internal` definitions are only accessible _within their namespace_. This means +that they are shared across files that share a namespace. + +``` +internal fn foo: Int32 -> Int32 + λ x => x + 1 +end fn +``` + +Unused `internal` definitions are considered errors. + +### Private Accessibility + +`private` definitions are only accessible _within their file_. Even if another +file shares a namespace, `private` definitions are invisible to that file. + +``` +private fn foo: Int32 -> Int32 + λ x => x + 1 +end fn +``` + +Unused `private` definitions are considered errors. + +## Comments + +_Comments_ are sections of code that are not parsed as code. They are used to +add in-code documentation. + +### Rules + +- All comments begin with `--`. This is a _prefix_, `--` tells the parser to + ignore any following content on sight. +- Multi-line comments are **not** supported. +- Names may _not_ include the comment designator. + +### Standard Comment Syntax + +Comments start with `--`. If that string is detected, the comment initializer to +the end of the line will be completely ignored. + +### Docstring Comment Syntax + +Docstrings start with `---` and must precede a _definition_ at the top level of +some source file. Docstrings _may_ be parsed in a separate process to produce a +documentation artifact. + +### Examples + +``` +--- This is a docstring for the function definition. +fn foo: String -> String + -- This is a regular comment. + --- This is a regular comment, because it is not at the definition level. + λ x => x + x +end fn +``` + +## Constants + +_Constants_ are top-level [definitions](#definitions) in Ava. They are named, +concrete values with a concrete type. + +### Rules + +- Constants must be defined at the top level of Ava source files. +- Constants must have an explicit type (they may not infer). +- Constants must have a concrete type. +- Constants must have a literal value. +- Constants _may_ reference the value of another constant. +- Constants _may_ be a record, itself defined in terms of literal values or + constant values. + +Note that these rules exist to permit constant definitions that are not limited +to literal values. + +### Syntax + +Constants are defined using the [const](#const) keyword. + +``` +const : = +``` + +### Examples + +``` +const foo: String = "foo" +const bar: Int32 = 12 + +record Foo + x: String, + y: Int32, +end record + +const baz: Foo = Foo(foo, bar) +``` + +## Functions + +_Functions_ are top-level [definitions](#definitions) in Ava, values in Ava, and +are the heart of programming in Ava. In general, functions have type `A -> B`, +where input of type `A` produces a result of type `B`. + +### Functions Without Arguments + +Technically, there are _no_ functions without arguments in Ava. All functions +are pure, and thus a function without arguments is just a value. The `Unit` type +can be used as a "nothing" argument, as it's a singleton object. + +``` +given A +record IO + thunk: Unit -> A +end record + +given A +fn io_new: (Unit -> A) -> IO A + λ thunk => IO(thunk = thunk) +end fn + +fn demonstrate: Unit -> IO Int32 + λ () => + block + let foo: Int32 = 10 + let bar: IO Int32 = io_new λ () => foo + bar + end block +end fn +``` + +### Functions With Multiple Arguments + +Arguments should be chained with `->` in Ava: + +``` +import ava.string + +fn example: String -> Int32 -> Int32 + λ x y => (string.length x) + y +end fn +``` + +Technically, this represents a curried function with left associativity: + +``` +A -> B -> C -> D == ((A -> B) -> C) -> D +``` + +This means that Ava naturally supports curried functions with partial +application: + +``` +fn example: Int32 -> Int32 -> Int32 -> Int32 + λ x y z => x + y + z +end fn + +let add1: Int32 -> Int32 -> Int32 = example 1 + +-- Result: 6 +let result = add1 2 3 +``` + +In this case, `example 1` invokes `example` with an input of literal value `1`, +which results in a partial application of example that looks like: + +``` +fn partial: Int32 -> Int32 -> Int32 + λ y z => 1 + y + z +end fn +``` diff --git a/docs/revision3.md b/docs/revision3.md new file mode 100644 index 0000000..b06f616 --- /dev/null +++ b/docs/revision3.md @@ -0,0 +1,75 @@ +``` +given A +def identity: A -> A + λ x => x +end def + +given A +class Semigroup A + def combine: A -> A -> A +end class + +given A :: Semigroup +class Monoid A + def empty: A +end class + +given F * +class Functor + given A + given B + def map: F A -> (A -> B) -> F B +end class + +given F * :: Functor +class Apply + given A + given B + def ap: F (A -> B) -> F A -> F B +end class + +given F * :: Apply +class Applicative + given A + def pure: A -> F A + + def unit: F () + pure () + end def +end class + +given F * :: Apply +class FlatMap + given A + given B + def fmap: F A -> (A -> F B) -> F B + + given A + def flatten: F (F A) -> F A + λ ffa => fmap ffa identity + end def +end class + +given F * :: FlatMap, Applicative +class Monad +end class + +instance Semigroup Int32 + def combine: Int32 -> Int32 -> Int32 + int32_add + end def +end instance + +given A :: Semigroup +def +: A -> A -> A + combine +end def + +def ex1: Int32 -> Int32 + λ x => x + x +end def + +def ex2: Int32 -> Int32 + λ x => combine x x +end def +``` diff --git a/docs/sketch-atomics-mutation.md b/docs/sketch-atomics-mutation.md new file mode 100644 index 0000000..33b5c5f --- /dev/null +++ b/docs/sketch-atomics-mutation.md @@ -0,0 +1,63 @@ +# Sketch: Atomics and Mutation + +What does it look like to mutate state outside of the scope of a function? + +## Problem Statement + +I want the ability to _modify_, _in-place_, the value of some reference or some +value on the stack. I want the ability to do this _outside_ of the scope of a +single function. + +## Example Functionality + +What is a `State`? How is a `state_set` implementation possible? + +``` +fn example: State String -> String -> IO Unit + λ state newValue => state_set state newValue +end fn +``` + +## Problem: Thread-Safe Access + +- All access to the `State` "thing" must be thread-safe. + +## Problem: Representation + +- Ava, to this point, has not had any record-mutable state or the notion of such + an object. +- Ava does not and will not have inheritance (precondition). +- Must Ava have a mutable primitive? +- How could Ava support mutability without direct access? This implies that + something like `mut` as a `record` field modifier is not sufficient. + +## Idea: Support via Modifiers + +The following implementation is incomplete and does not enforce any thread +safety, but illustrates how `private` access could help this work. + +Also, it demonstrates that anonymous function syntax needs to be considered. + +``` +given A +record State + private mut data: A, +end record + +given A +fn state_get: State A -> IO A + λ state => defer (λ => state.data) +end fn + +given A +fn state_set: State A -> A -> IO State A + λ state newValue => map (defer (λ => state.data = newValue)) (λ => state) +end fn + +given A +fn state_modify: State A -> (A -> A) -> IO State A + λ state f => + map + (defer λ => state.data = f state.data) + λ => state +```