Backup commit before crunch

This commit is contained in:
2023-05-16 18:32:25 +01:00
parent 33413b2b0f
commit 126494c63f
59 changed files with 847 additions and 236 deletions

View File

@@ -0,0 +1,19 @@
Orhid is a lazy, pure functional langauge with an execution model inspired by Haskell. It has a simple, principled syntax resembling mathematical notation commonly used to describe the lambda calculus. State is held in closures and multi-parameter functions are represented using currying.
This minimalism is in an effort to make parsing and code generation easier, as complex structures are defined using syntax-level macros. The macro system is insipred by generalized kerning which is a well-known Turing-complete system.
Macros consist of substitution rules applied to the tokenized, namespaced source. These rules can make use of placeholders to transform the expression tree. Placeholders can match exactly one, at least one, or any number of tokens. Macros are used to define infix operators, name bindings, friendly loop syntax over the Y-combinator and more.
Because substitution rules are applied to the namespaced tokens, macro programs can interact with each other; parts of the pattern that triggers a macro can be generated by other macros while other parts may be provided by the user. In this way, libraries can define extension interfaces where other libraries can integrate with their constructs, and an individual token can take on many meanings depending on context.
---
Orchid is designed to be embedded in a Rust application. The entire program lifecycle consists of three stages which can be individually configured:
1. The parser pipeline is responsible for converting text - usually files - into a module tree. It allows the embedder to define the environment the code will see in terms of a series of file trees that are parsed in the context of preceding layers.
2. The macro executor operates entirely on the output of the pipeline. Macro programs don't necessarily halt, so the executor provides an API to find and resolve one match at a time.
3. The interpreter is a single function operating on an expression with a symbol table for resolving named constants. It also allows setting a limit to the number of normalization steps - this is commonly known as gas.
Interfacing between eager procedural and lazy functional code can be challenging, especially with the vastly different suites of optimizations. To make this a little easier, we provides an array of Rust macros that streamline the process of exposing Rust functions to Orchid code. The usage of these is demonstrated in the standard library.

121
notes/papers/demo/slides.md Normal file
View File

@@ -0,0 +1,121 @@
---
marp: true
class: invert
---
# Orchid
some tagline
---
## Syntax
basically lambda calc
```
half := \n. div n 2
pair := \a.\b. \f. f a b
increment := add 1
```
---
## Macros
match and replace token sequences
```
if ...$cond then ...$true else ...$false ==> (ifthenelse (...$cond) (...$true) (...$false))
```
...while keeping parameters intact
```
$data -- a single token (including parenthesized sequences)
...$data -- at least one token
..$data -- zero or more tokens
```
---
## Macros
define operators...
```
...$a + ...$b ==> (add (...$a) (...$b))
```
...and name bindings...
```
let $name = ...$value in ...$body ==> (\$name. ...$body) ...$value
```
...and control structures
```
loop $r on (...$parameters) with ...$tail ==> Y (\$r.
bind_names (...$parameters) (...$tail)
) ...$parameters
-- bind each of the names in the first argument as a parameter for the second argument
bind_names ($name ..$rest) $payload ==> \$name. bind_names (..$rest) $payload
bind_names () (...$payload) ==> ...$payload
```
---
## Macros
can expose interfaces...
```
do { ...$statement ; ...$rest } ==> (statement (...$statement) do { ...$rest })
do { ...$return } ==> (...$return)
```
...to be used by others...
```
statement (let $name = ...$value) ...$next ==> ((\$name. ...$next) (...$value))
statement (cps $name = ...$operation) ...$next ==> ((...$operation) \$name. ...$next)
statement (cps ...$operation) ...$next ==> ((...$operation) (...$next))
```
...to define any syntax
```
export main := do{
cps data = readline;
let double = parse_float data * 2;
cps print (to_string double ++ "\n")
}
```
---
## Control
remains with the embedder
| | extension | supervision |
| ----------: | :----------------: | :--------------------: |
| pipeline | external libraries | file IO interception |
| macros | | step-by-step execution |
| interpreter | constants, input | gas |
---
## Extensions
```rs
use std::fmt::Debug;
use crate::external::litconv::with_lit;
use crate::representations::{interpreted::ExprInst, Literal};
use crate::{atomic_impl, atomic_redirect, externfn_impl};
#[derive(Clone)]
pub struct ToString1;
externfn_impl!(ToString1, |_: &Self, x: ExprInst| Ok(ToString0{x}));
#[derive(Debug, Clone)]
pub struct ToString0{ x: ExprInst }
atomic_redirect!(ToString0, x);
atomic_impl!(ToString0, |Self{ x }: &Self, _| {
let string = with_lit(x, |l| Ok(match l {
Literal::Char(c) => c.to_string(),
Literal::Uint(i) => i.to_string(),
Literal::Num(n) => n.to_string(),
Literal::Str(s) => s.clone()
}))?;
Ok(string.into())
});
```