Expand description
§The Compose Programming Language
println("'Hello, world' from Compose!");Compose is a functional-flavoured, interpreted programming language with Rust-like syntax.
Features:
- Expression focused: blocks and control flow (
if,match, loops) are expressions and produce values. - Functions as first-class citizens
- High quality diagnostics
- Variables are immutable by default
- Garbage collection
- Portable: runs on any platform that supports Rust
Compose is being developed as a hobby project and is not intended for production use.
§Documentation overview
- The
languagemodule documents Compose syntax and semantics. - The
implementationmodule documents the internals of the language implementation. - The
embeddingmodule documents how to embed Compose in your application. - The
climodule documents the CLI.
§Using this crate
Below follows a minimal example of embedding Compose in your application. If you want to take a deeper dive, check out the embedding documentation.
Add Compose to your dependencies:
[dependencies]
compose = { git = "https://github.com/Dutch-Raptor/compose.git" }§Creating a World
Compose is designed to be embedded in your application. All interactions with the outside world (like reading files, printing to the console, etc.) go through the World trait. This allows running Compose in a CLI, in tests, or embedded in another application.
A World should provide:
- The entrypoint source of the program.
- A way to access source files.
- Standard input and output.
- The standard library.
Source files could be loaded from disk, stored in memory, or come from any other source. Standard input and output can be virtualised. The standard library can be customised to provide additional functionality.
In this minimal example, we define a World that contains a single source file.
use compose::{
World,
library::Library,
library::diag::{FileError, FileResult},
syntax::{FileId, Source},
};
use std::collections::HashMap;
use std::io::{Read, Write};
struct ExampleWorld {
main: Source,
library: Library,
}
impl World for ExampleWorld {
fn entry_point(&self) -> FileId {
self.main.id()
}
// This example world only supports a single source, so that is the only source it can return.
fn source(&self, file_id: FileId) -> FileResult<Source> {
if file_id == self.main.id() {
Ok(self.main.clone())
} else {
Err(FileError::NotFound(file_id.path().as_path().clone()))
}
}
fn library(&self) -> &Library {
&self.library
}
// Write to stdout
fn write(
&self,
f: &mut dyn FnMut(&mut dyn Write) -> std::io::Result<()>,
) -> std::io::Result<()> {
let mut stdout_lock = std::io::stdout().lock();
f(&mut stdout_lock)
}
// read from stdin
fn read(
&self,
f: &mut dyn FnMut(&mut dyn Read) -> std::io::Result<()>,
) -> std::io::Result<()> {
let mut stdin_lock = std::io::stdin().lock();
f(&mut stdin_lock)
}
}
impl ExampleWorld {
fn new(main_source: Source) -> Self {
Self {
main: main_source,
library: Library::default(),
}
}
}§Loading source code
Compose source code is represented by the Source type.
use compose::syntax::Source;
let source_text = r#"
println("Hello from Compose");
2 + 3 // the value of the last expression is returned
"#;
let source = Source::from_string("main.cmps", source_text);§Evaluating source code
use compose::{
evaluation::{Machine, eval},
library::diag::print_diagnostics,
library::repr::Repr,
library::Value,
};
use std::process::exit;
let world = ExampleWorld::new(source.clone());
let mut vm = Machine::new(&world);
// `eval` evaluates the entrypoint source provided by the `world`.
let result = eval(&mut vm);
// Print any warnings
print_diagnostics(&world, &[], &result.warnings, false).unwrap();
let value = match result.value {
Ok(value) => value,
Err(errors) => {
print_diagnostics(&world, &errors, &[], false).unwrap();
exit(1);
}
};
// Print the resulting value
println!("{}", value.repr(&vm));
assert_eq!(Value::Int(5), value);
To learn more about embedding Compose in your application, check out the embedding documentation.
Modules§
- cli
- Compose CLI
- embedding
- Embedding Compose
- implementation
- Compose language implementation
- language
- Language overview
- test
Structs§
Traits§
- World
- Defines how Compose interacts with the outside world.
Functions§
- eval_
source - eval_
source_ range - Eval a source file.