Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
825980ca31 | |||
0ba9ac30ea | |||
9632deccc7 | |||
aec14f0941 | |||
07a2011997 | |||
a4add937c8 |
4 changed files with 535 additions and 5 deletions
|
@ -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
|
Ava code. Ava is a way to get ideas out of my head, challenged, and further
|
||||||
explored.
|
explored.
|
||||||
|
|
||||||
## Notes
|
## Documentation
|
||||||
|
|
||||||
These notes are not guaranteed to be up to date and represent a large amount of
|
Please start with the [Documentation Contents](./docs), which provides links to
|
||||||
brainstorming and trying/discarding of ideas.
|
different iterations of the language.
|
||||||
|
|
||||||
Please start with the [Table of Contents](./notes/table-of-contents.md)
|
|
||||||
|
|
6
docs/README.md
Normal file
6
docs/README.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Ava Documentation
|
||||||
|
|
||||||
|
This documentation is currently organized by revision, where major updates are
|
||||||
|
made to the specification.
|
||||||
|
|
||||||
|
- [R2](./revision2.md)
|
463
docs/revision2.md
Normal file
463
docs/revision2.md
Normal file
|
@ -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 <name>[.<name>]*
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 <name>[.<name>]*[.\* | as <name>]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 <name>: <type> = <value>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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
|
||||||
|
```
|
63
docs/sketch-atomics-mutation.md
Normal file
63
docs/sketch-atomics-mutation.md
Normal file
|
@ -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
|
||||||
|
```
|
Loading…
Add table
Reference in a new issue