starting project Albireo

This commit is contained in:
nganhkhoa 2024-02-16 02:07:52 +07:00
commit 546af734e7
8 changed files with 412 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

212
Cargo.lock generated Normal file
View File

@ -0,0 +1,212 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "albireo"
version = "0.1.0"
dependencies = [
"pest",
"pest_derive",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpufeatures"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "memchr"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "pest"
version = "2.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "219c0dcc30b6a27553f9cc242972b67f75b60eb0db71f0b5462f38b058c41546"
dependencies = [
"memchr",
"thiserror",
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e1288dbd7786462961e69bfd4df7848c1e37e8b74303dbdab82c3a9cdd2809"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1381c29a877c6d34b8c176e734f35d7f7f5b3adaefe940cb4d1bb7af94678e2e"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pest_meta"
version = "2.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0934d6907f148c22a3acbda520c7eed243ad7487a30f51f6ce52b58b7077a8a"
dependencies = [
"once_cell",
"pest",
"sha2",
]
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "ucd-trie"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"

10
Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "albireo"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
pest = "2.7.6"
pest_derive = "2.7.6"

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# Albireo Programming Language
## Purpose of this project
For the sake of learning programming language theory, I decide to practice by applying what I knew and implementing them as I learn theories.
The language should be strictly typed and everything is pure. In that context, I design a language where everything is an expression. Side-effects will be handled either by Monads (or Applicative programming) or by using Effect Handlers (so called Algebraic Effects).
Complex types should be implemented, choices are Sub-typing, Row-Polymorphism, Algebraic Datatypes. Higher-Order Types (so called Kind) will also be implemented.
Advanced theory on Graded Types, Substructural Types (Linear or Affine) will be considered for implementation.
Everything is experimental and the current state of the language should reflect my personal experience as well as knowledge on programming language theory, including type theory and semantics. I do not intend to work extensively on compiler technology, although I am originated from learning assembly and binary analysis of programs.

117
src/albireo.pest Normal file
View File

@ -0,0 +1,117 @@
keywords = {
"number"
| "bool"
| "string"
| "fn"
| "true"
| "false"
| "is"
| "in"
| "if"
| "then"
| "else"
| "let"
| "only"
| "as"
| "function"
| "import"
| "module"
| "export"
}
identifier = @{ !keywords ~ ASCII_ALPHA ~ ASCII_ALPHANUMERIC* }
function_type_param = { type }
function_type_return = { type }
function_type = {
"fn" ~ function_type_param* ~ "=>" ~ function_type_return
}
type = {
function_type
| "number"
| "bool"
| "string"
}
number = @{ ASCII_DIGIT+ }
string = @{ "\"" ~ !("\"") ~ ASCII_ALPHANUMERIC* ~ "\"" }
bool = @{ "true" | "false" }
function = { "function" ~ function_param* ~ "is" ~ function_body }
function_param = { identifier }
function_body = {
binding* ~ expr
}
binding = {
"let" ~ identifier ~ "=" ~ expr ~ "in"
}
// will be expr in later version of the language
if_cond = { identifier }
if_branch = { identifier }
else_branch = { identifier }
if_expr = {
// "if" ~ expr ~ "then" ~ expr ~ "else" ~ expr
"if" ~ if_cond ~ "then" ~ if_branch ~ "else" ~ else_branch
}
call_function = { identifier }
call_param = { identifier | identifier ~ call_param }
call_expr = {
call_function ~ "(" ~ call_param? ~ ")"
}
expr = {
if_expr
| call_expr
| identifier
| value
}
// function is a value only if we allow to have thunks
// or that function is a first-class citizen, FG-CBV
// but it would a thunk if CBPV
value = _{
number
| string
| bool
| function
}
declaration = {
identifier ~ ":" ~ type ~ "=" ~ expr
}
module_name = @{ identifier }
export_list = _{
identifier
| identifier ~ "," ~ export_list
}
module_export = {
"export" ~ export_list
}
// import module
// import module only name, name
// import module as change_name
import_list = _{
identifier ~ "," ~ import_list
| identifier
}
import_selective = { "only" ~ import_list }
import_change_name = { "as" ~ module_name }
import_types = {
import_selective
| import_change_name
}
module_import = { "import" ~ module_name ~ import_types? }
module_declare = {
"module" ~ module_name ~ module_export* ~ module_import*
}
program = {
module_declare ~ declaration*
}
WHITESPACE = _{ " " | NEWLINE }
COMMENT = _{ ";.*" ~ NEWLINE }

33
src/albireo.rs Normal file
View File

@ -0,0 +1,33 @@
#[derive(pest_derive::Parser)]
#[grammar = "albireo.pest"]
pub struct AlbireoParser;
use pest::iterators::Pair;
struct Module {
name: String,
declaration: HashMap<String, Declaration>
}
struct Declaration {
type: Type,
definition: Expression,
}
enum Type {
Number,
String,
Bool,
Function(/*inputs*/Vec<Type>, /*output*/Type)
}
// limitation as of now, everything must be passed in as identifier
enum Expression {
IfClause(String, String, String),
Application(/*function name*/String, /*params*/Vec<String>), // function call
Identifier(String),
Number(u64),
String(String),
Bool(bool),
Function(String, Vec<Binding>, Expression),
}

17
src/main.rs Normal file
View File

@ -0,0 +1,17 @@
mod albireo;
use crate::albireo::{AlbireoParser, Rule};
use std::fs;
use pest::Parser;
fn main() {
let input = fs::read_to_string("test/simple/main.air").expect("cannot read file");
let program = AlbireoParser::parse(Rule::program, &input)
.expect("file format is wrong or the parser is wrong")
.next()
.expect("cannot parse input file as a Albireo program");
println!("{:?}", program);
}

9
test/simple/main.air Normal file
View File

@ -0,0 +1,9 @@
module main
c : fn => bool = function is
let a = b in
c(a)
b : bool = false
a : number = 1