Compare commits

..
Author SHA1 Message Date
selimaj-dev e5df8df9b0 Release 0.1.7-alpha.1
[email protected]
[email protected]
[email protected]

Generated by cargo-workspaces
2026-06-01 13:50:49 +02:00
selimaj-dev ee40450f3a Merge pull request #57 from mist-go/module-system
Module system
2026-06-01 13:49:21 +02:00
selimaj-dev be6d2de39c improved code quality 2026-06-01 13:10:46 +02:00
selimaj-dev aff15f67c7 Working module system 2026-06-01 12:26:20 +02:00
selimaj-dev cfd1910f39 Working transpiler 2026-06-01 12:10:33 +02:00
selimaj-dev 082981f0bd Working module reading 2026-06-01 11:40:01 +02:00
selimaj-dev b384f55c77 Updated analyzer to remove the need for .mist/lib 2026-05-31 12:56:54 +02:00
selimaj-dev c4756262e1 ts sucks 2026-05-31 12:47:24 +02:00
selimaj-dev 74f10cc74b Removed lsp dev 2026-05-31 12:45:53 +02:00
selimaj-dev acef0888a3 Thinking of better ways to make analyzer work 2026-05-31 12:42:55 +02:00
selimaj-dev 18ab88af64 Thinking of better ways to make analyzer work 2026-05-31 12:41:48 +02:00
selimaj-dev 5e6cdc84b9 Updated cargo version 2026-05-31 12:39:10 +02:00
selimaj-dev 2dc5cdc9d9 Release 0.1.7-alpha.0
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

Generated by cargo-workspaces
2026-05-31 12:36:23 +02:00
selimaj-dev 893c981a41 Merge pull request #56 from mist-go/future-proofed-modules
Future proofed module stucture
2026-05-29 20:35:12 +02:00
selimaj-dev 0b3c4b8143 Module structure 2026-05-29 20:33:30 +02:00
selimaj-dev 86a1df7ad5 Mist Module system basic structure 2026-05-29 16:13:52 +02:00
selimaj-dev 3fa04cddd0 mist api lsp 2026-05-29 09:17:51 +02:00
selimaj-dev 371365b8cf Separated mist api 2026-05-29 09:04:58 +02:00
selimaj-dev b74da3255a Init mist-api 2026-05-29 08:58:42 +02:00
selimaj-dev 83e5e98641 Added mist.toml 2026-05-29 08:52:30 +02:00
selimaj-dev c774737074 Merge pull request #53 from mist-go/inheritance
Inheritance
2026-05-28 17:43:56 +02:00
selimaj-dev 9e1b9ad564 Fixed attributes 2026-05-28 16:28:20 +02:00
selimaj-dev 97b2cc4413 Working inheritance 2026-05-28 16:21:36 +02:00
selimaj-dev 99ff0ead2d Inheritance gen 2026-05-28 16:08:31 +02:00
selimaj-dev b0f3dccc87 Inheritance parsing 2026-05-28 15:55:00 +02:00
selimaj-dev 86a781c3f2 Merge pull request #52 from mist-go/parser-patches
Parser patches
2026-05-28 15:47:44 +02:00
selimaj-dev 583d51141f Fixed empty items 2026-05-28 15:44:52 +02:00
selimaj-dev ad11a3bd6a Improved match item span 2026-05-28 12:16:28 +02:00
selimaj-dev 7a2ba74d9c Working mut pattern 2026-05-28 11:52:40 +02:00
selimaj-dev 7007aa32f1 Refactored mutability 2026-05-28 11:45:26 +02:00
selimaj-dev 3444f93546 Updated codegen 2026-05-28 11:36:28 +02:00
selimaj-dev e09c7926e5 Updated pattern ast 2026-05-28 11:34:14 +02:00
selimaj-dev 83e98573aa Updated pattern grammar 2026-05-28 11:30:47 +02:00
32 changed files with 439 additions and 288 deletions
Generated
+19 -12
View File
@@ -442,7 +442,7 @@ dependencies = [
[[package]] [[package]]
name = "mist-analyzer" name = "mist-analyzer"
version = "0.0.3" version = "0.1.7-alpha.1"
dependencies = [ dependencies = [
"cargo_metadata", "cargo_metadata",
"dashmap 6.1.0", "dashmap 6.1.0",
@@ -456,27 +456,34 @@ dependencies = [
] ]
[[package]] [[package]]
name = "mist-codegen" name = "mist-api"
version = "0.1.2" version = "0.1.7-alpha.1"
dependencies = [
"mist-parser",
]
[[package]]
name = "mist-lang"
version = "0.0.5-alpha0"
dependencies = [ dependencies = [
"cargo_metadata", "cargo_metadata",
"mist-analyzer",
"mist-codegen", "mist-codegen",
"mist-parser", "mist-parser",
"serde", "serde",
"serde_json", "serde_json",
] ]
[[package]]
name = "mist-codegen"
version = "0.1.7-alpha.0"
dependencies = [
"mist-parser",
]
[[package]]
name = "mist-lang"
version = "0.1.7-alpha.1"
dependencies = [
"mist-analyzer",
"mist-api",
]
[[package]] [[package]]
name = "mist-parser" name = "mist-parser"
version = "0.1.6" version = "0.1.7-alpha.0"
dependencies = [ dependencies = [
"pest", "pest",
"pest_derive", "pest_derive",
+7 -18
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "mist-lang" name = "mist-lang"
version = "0.0.5-alpha0" version = "0.1.7-alpha.1"
edition = "2024" edition = "2024"
description = "The Mist programming language compiler" description = "The Mist programming language compiler"
license = "Apache-2.0" license = "Apache-2.0"
@@ -16,19 +16,15 @@ include = [
] ]
[dependencies] [dependencies]
mist-parser = { workspace = true }
mist-analyzer = { workspace = true } mist-analyzer = { workspace = true }
mist-codegen = { workspace = true } mist-api = { workspace = true }
serde = { version = "1.0.228", features = ["serde_derive"] }
serde_json = "1.0.149"
cargo_metadata = "0.23.1"
[workspace] [workspace]
members = [ members = [
"crates/parser", "crates/parser",
"crates/analyzer", "crates/analyzer",
"crates/codegen", "crates/codegen",
"crates/mist-api",
] ]
exclude = [ exclude = [
@@ -36,22 +32,15 @@ exclude = [
] ]
[workspace.dependencies] [workspace.dependencies]
mist-parser = { path = "crates/parser", version = "0.1.6" } mist-parser = { path = "crates/parser", version = "0.1.7-alpha.0" }
mist-analyzer = { path = "crates/analyzer", version = "0.0.3" } mist-analyzer = { path = "crates/analyzer", version = "0.1.7-alpha.0" }
mist-codegen = { path = "crates/codegen", version = "0.1.2" } mist-codegen = { path = "crates/codegen", version = "0.1.7-alpha.0" }
mist-api = { path = "crates/mist-api", version = "0.1.7-alpha.0" }
[[bin]] [[bin]]
name = "mist" name = "mist"
path = ".mist/src/main.rs" path = ".mist/src/main.rs"
[[bin]]
name = "mist-lsp"
path = ".mist/lsp/main.rs"
[[bin]]
name = "mist-header"
path = "src/_header.rs"
[[bin]] [[bin]]
name = "mist-analyzer" name = "mist-analyzer"
path = ".mist/src/analyzer.rs" path = ".mist/src/analyzer.rs"
+1
View File
@@ -0,0 +1 @@
package = "main.mist"
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "mist-analyzer" name = "mist-analyzer"
version = "0.0.3" version = "0.1.7-alpha.1"
edition = "2024" edition = "2024"
description = "The Mist programming language Analyzer LSP" description = "The Mist programming language Analyzer LSP"
license = "Apache-2.0" license = "Apache-2.0"
+2 -3
View File
@@ -573,7 +573,7 @@ pub fn from_mist_to_rust(mut path: PathBuf) -> PathBuf {
let mut comps: Vec<Component> = path.components().collect(); let mut comps: Vec<Component> = path.components().collect();
if let Some(pos) = comps.iter().rposition(|c| c.as_os_str() == "src") { if let Some(pos) = comps.iter().rposition(|c| c.as_os_str() == "src") {
let replacement = std::path::Path::new(".mist/lsp"); let replacement = std::path::Path::new(".mist/src");
comps.splice(pos..=pos, replacement.components()); comps.splice(pos..=pos, replacement.components());
comps.iter().collect() comps.iter().collect()
} else { } else {
@@ -587,8 +587,7 @@ pub fn from_rust_to_mist(mut path: PathBuf) -> PathBuf {
let comps: Vec<Component> = path.components().collect(); let comps: Vec<Component> = path.components().collect();
// pattern we originally inserted: ".mist/lsp" let pattern: Vec<Component> = std::path::Path::new(".mist/src").components().collect();
let pattern: Vec<Component> = std::path::Path::new(".mist/lsp").components().collect();
// find the last occurrence of the pattern // find the last occurrence of the pattern
if let Some(pos) = comps if let Some(pos) = comps
+1 -1
View File
@@ -7,7 +7,7 @@ use mist_parser::{ast::TopLevel, error::ParseError};
pub fn build(root: &PathBuf) { pub fn build(root: &PathBuf) {
let src_dir = root.join("src"); let src_dir = root.join("src");
let out_dir = root.join(".mist/lsp"); let out_dir = root.join(".mist/src");
if let Err(e) = build_dir(root, &src_dir, &src_dir, &out_dir) { if let Err(e) = build_dir(root, &src_dir, &src_dir, &out_dir) {
eprintln!("Warning: Build directory run aborted safely: {e}"); eprintln!("Warning: Build directory run aborted safely: {e}");
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "mist-codegen" name = "mist-codegen"
version = "0.1.2" version = "0.1.7-alpha.0"
edition = "2024" edition = "2024"
description = "The Mist programming language Rust code generator" description = "The Mist programming language Rust code generator"
license = "Apache-2.0" license = "Apache-2.0"
+19 -16
View File
@@ -4,10 +4,6 @@ pub mod top_level;
use mist_parser::ast::*; use mist_parser::ast::*;
pub fn get_mutable(mutable: bool) -> String {
if mutable { "mut " } else { "" }.to_string()
}
pub struct Context { pub struct Context {
pub expr_ensure_semicolon: bool, pub expr_ensure_semicolon: bool,
} }
@@ -112,11 +108,12 @@ impl GenRust for Attribute {
match self { match self {
Self::Path(path) => cg.add(&path.get_rust()), Self::Path(path) => cg.add(&path.get_rust()),
Self::NameValue { path, value } => { Self::NameValue { path, value } => {
cg.add(&format!("{} =", path.get_rust())); cg.add(&format!("{} = ", path.get_rust()));
value.gen_rust(ctx, cg); value.gen_rust(ctx, cg);
} }
Self::List { path, items } => { Self::List { path, items } => {
cg.add(&path.get_rust()); cg.add(&path.get_rust());
cg.add("(");
for (i, item) in items.iter().enumerate() { for (i, item) in items.iter().enumerate() {
if i > 0 { if i > 0 {
cg.add(", "); cg.add(", ");
@@ -124,6 +121,7 @@ impl GenRust for Attribute {
item.gen_rust(ctx, cg); item.gen_rust(ctx, cg);
} }
cg.add(")");
} }
} }
} }
@@ -238,34 +236,39 @@ impl GetRust for TypeExprKind {
impl GenRust for Pattern { impl GenRust for Pattern {
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
match self { match self {
Self::Id(id) => cg.add(&id.get_rust()), Self::Path(mutable, path) => {
Self::Path(path) => cg.add(&path.get_rust()), if *mutable {
cg.add("mut ");
};
cg.add(&path.get_rust())
}
Self::Literal(lit) => lit.gen_rust(ctx, cg), Self::Literal(lit) => lit.gen_rust(ctx, cg),
Self::Struct(path, ids) => { Self::Struct(path, inner) => {
cg.add(&path.get_rust()); cg.add(&path.get_rust());
cg.add(" {"); cg.add(" {");
for id in ids { for pat in inner {
cg.add(&id.get_rust()); pat.gen_rust(ctx, cg);
cg.add(","); cg.add(",");
} }
cg.add("}"); cg.add("}");
} }
Self::NamedTuple(path, ids) => { Self::NamedTuple(path, inner) => {
cg.add(&path.get_rust()); cg.add(&path.get_rust());
cg.add(" ("); cg.add(" (");
for id in ids { for pat in inner {
cg.add(&id.get_rust()); pat.gen_rust(ctx, cg);
cg.add(","); cg.add(",");
} }
cg.add(")"); cg.add(")");
} }
Self::Tuple(ids) => { Self::Tuple(inner) => {
cg.add("("); cg.add("(");
for id in ids { for pat in inner {
cg.add(&id.get_rust()); pat.gen_rust(ctx, cg);
cg.add(","); cg.add(",");
} }
cg.add(")"); cg.add(")");
+6 -6
View File
@@ -1,6 +1,6 @@
use mist_parser::ast::*; use mist_parser::ast::*;
use crate::{Context, get_mutable}; use crate::Context;
use crate::{GenRust, GetRust, RustCodegen}; use crate::{GenRust, GetRust, RustCodegen};
@@ -59,7 +59,11 @@ impl GenRust for Statement {
cg.add(" {"); cg.add(" {");
cg.indent += 1; cg.indent += 1;
for (pat, body) in match_items { for match_item in match_items {
cg.add_indentedln(&match_item.get_comment());
let MatchItem(pat, body) = &match_item.item;
for (i, p) in pat.iter().enumerate() { for (i, p) in pat.iter().enumerate() {
cg.addln(""); cg.addln("");
cg.add_indented(""); cg.add_indented("");
@@ -158,13 +162,11 @@ impl GenRust for Statement {
} }
Statement::For { Statement::For {
mutable,
pattern, pattern,
iterator, iterator,
body, body,
} => { } => {
cg.add("for "); cg.add("for ");
cg.add(&get_mutable(*mutable));
pattern.gen_rust(ctx, cg); pattern.gen_rust(ctx, cg);
cg.add(" in "); cg.add(" in ");
iterator.gen_rust(ctx, cg); iterator.gen_rust(ctx, cg);
@@ -186,8 +188,6 @@ impl GenRust for Statement {
impl GenRust for VarDecl { impl GenRust for VarDecl {
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
cg.add(&get_mutable(self.mutable));
self.name.gen_rust(ctx, cg); self.name.gen_rust(ctx, cg);
cg.add( cg.add(
+40 -2
View File
@@ -212,8 +212,7 @@ impl GenRust for (&Vec<Spanned<FieldDeclStmt>>, &Spanned<ClassConstructor>) {
cg.add_indentedln("}\n"); cg.add_indentedln("}\n");
let mut constructor_params = vec![VarDecl { let mut constructor_params = vec![VarDecl {
mutable: false, name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])),
name: Pattern::Id(Identifier(String::from("self"))),
type_: Some(TypeExpr( type_: Some(TypeExpr(
TypeExprKind::Path(Path(vec![Identifier(String::from("Self"))])), TypeExprKind::Path(Path(vec![Identifier(String::from("Self"))])),
vec![TypePostfix::RefMut], vec![TypePostfix::RefMut],
@@ -326,6 +325,7 @@ impl GenRust for TopLevelKind {
visibility, visibility,
name, name,
generics, generics,
inherits,
fields, fields,
constructor, constructor,
items, items,
@@ -339,6 +339,12 @@ impl GenRust for TopLevelKind {
)); ));
cg.indent += 1; cg.indent += 1;
if let Some(inherits) = inherits {
cg.add_indented("pub _super: ");
cg.add(&inherits.get_rust());
cg.addln(",");
}
for field in fields.clone() { for field in fields.clone() {
cg.add_indentedln(&field.get_comment()); cg.add_indentedln(&field.get_comment());
cg.add_indentedln(&field.item.decl.get_rust()); cg.add_indentedln(&field.item.decl.get_rust());
@@ -396,6 +402,38 @@ impl GenRust for TopLevelKind {
ClassItem::Method(_) => {} ClassItem::Method(_) => {}
} }
} }
if let Some(inherits) = inherits {
cg.add("impl std::ops::Deref for ");
cg.add(&name.get_rust());
cg.addln(" {");
cg.indent += 1;
cg.add_indented("type Target = ");
cg.add(&inherits.get_rust());
cg.addln(";");
cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}");
cg.indent -= 1;
cg.addln("}");
// Mut
cg.add("impl std::ops::DerefMut for ");
cg.add(&name.get_rust());
cg.addln(" {");
cg.indent += 1;
cg.add_indentedln(
"fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}",
);
cg.indent -= 1;
cg.addln("}");
}
} }
} }
} }
+26
View File
@@ -0,0 +1,26 @@
[package]
name = "mist-api"
version = "0.1.7-alpha.1"
edition = "2024"
description = "The Mist programming language module system"
license = "Apache-2.0"
repository = "https://github.com/mist-go/mist"
keywords = ["compiler", "language", "mist", "module-system"]
categories = ["compilers"]
include = [
".mist/src/**",
"Cargo.toml",
"README.md",
]
[dependencies]
serde = { version = "1.0.228", features = ["serde_derive"] }
serde_json = "1.0.149"
cargo_metadata = "0.23.1"
mist-parser = { workspace = true }
mist-codegen = { workspace = true }
[lib]
name = "mist_api"
path = ".mist/src/lib.rs"
+3
View File
@@ -0,0 +1,3 @@
pub mod builder;
pub mod transpiler;
pub mod modules;
+5
View File
@@ -0,0 +1,5 @@
pub mod builder;
pub mod transpiler;
pub mod modules;
void main() {}
+117
View File
@@ -0,0 +1,117 @@
use <std::path::Path>;
use <std::path::PathBuf>;
use <std::fs>;
use <std::process>;
#[derive(Debug)]
pub class Module {
pub String name;
pub PathBuf path;
pub Vec<Self> children;
pub constructor(String name, PathBuf mist_path, PathBuf rust_path) {
self.children = new Vec();
self.name = name;
self.path = mist_path;
if (self.path.is_dir()) {
PathBuf dir = self.path.clone();
// Behavior 2: It's a directory node. Check for gateway package.mist first.
PathBuf pkg_gate = self.path.join("package.mist");
if (pkg_gate.exists()) {
self.path = pkg_gate;
}
self.scan_directory(&dir, &rust_path);
}
}
void scan_directory(self mut*, Path* search_dir, Path* rust_path) {
var entries = match (fs::read_dir(search_dir)) {
Ok[entries] => entries;
Err[e] => {
eprintln!("error: failed to read directory {}\n {}", search_dir.display(), e);
process::exit(1);
}
};
for (entry : entries) {
var entry = match (entry) {
Ok[entry] => entry;
Err[e] => {
eprintln!("error: failed to read directory entry\n {}", e);
process::exit(1);
}
};
PathBuf child_path = entry.path();
if (child_path == self.path) {
continue;
}
String child_name = child_path.file_stem()
.and_then(|var s| s.to_str())
.expect("Failed to get module name")
.to_string();
PathBuf child_output = rust_path.join(&child_name).with_extension("rs");
if (!child_path.is_dir() && should_skip(&child_path, &child_output)) {
continue;
}
self.children.push(new Module(child_name, child_path, child_output));
}
}
pub PathBuf output_dir(self*, PathBuf* parent_dir) {
if (self.path.is_dir() || Some("package.mist") == self.path.file_name().unwrap().to_str()) {
parent_dir.join(&self.name)
} else {
parent_dir.clone()
}
}
pub PathBuf output_path(self*, PathBuf* parent_dir) {
if (self.path.is_dir() || Some("package.mist") == self.path.file_name().unwrap().to_str()) {
parent_dir.join(&self.name).join("mod.rs")
} else {
parent_dir.join(&self.name).with_extension("rs")
}
}
}
pub Module master_package(PathBuf mist_path, PathBuf rust_path) {
String name = mist_path.file_stem()
.and_then(|var s| s.to_str())
.expect("Failed to get module name")
.to_string();
var mut root_mod = new Module(name, mist_path.clone(), rust_path.clone());
if (!mist_path.is_dir()) {
PathBuf parent_dir = mist_path.parent()
.expect("Failed to get parent directory of root file")
.to_path_buf();
root_mod.scan_directory(&parent_dir, &rust_path);
}
root_mod
}
bool should_skip(Path* source, Path* output) {
var src_time = fs::metadata(source)
.ok()
.and_then(|var v| v.modified().ok());
var out_time = fs::metadata(output)
.ok()
.and_then(|var v| v.modified().ok());
out_time
.map(|var out_time| out_time >= src_time.unwrap())
.unwrap_or_default()
}
+122
View File
@@ -0,0 +1,122 @@
use <std::fs>;
use <std::path::Path>;
use <std::path::PathBuf>;
use <std::process>;
use <std::time>;
use <std::env>;
use <mist_parser::error>;
use <crate::modules>;
pub PathBuf build(bool force) {
var start = time::Instant::now();
var root = env::current_dir().expect("Unable to find project root");
PathBuf src = root.join("src");
PathBuf out = root.join(".mist/src");
var master = modules::master_package(src.join("main.mist"), out.join("main.rs"));
master.transpile(&out);
var elapsed = start.elapsed();
println!(
"\x1b[32m\nTranspile successful\x1b[0m in \x1b[34m{:.2?}\x1b[0m",
elapsed
);
root
}
impl modules::Module {
String transpile(self*, PathBuf* parent_dir) {
PathBuf dir = self.output_dir(&parent_dir);
PathBuf output_file = self.output_path(&parent_dir);
var _ = fs::create_dir_all(&dir);
String mut output = String::new();
for (child : &self.children) {
output.push_str(&child.transpile(&dir));
}
if (self.path.is_dir()) {
var res = fs::write(&output_file, output);
if (res.is_err()) {
eprintln!(
"error: failed to write output {}\n {}",
output_file.display(),
res.unwrap_err(),
);
process::exit(1);
}
} else {
transpile_file(&self.path, &output_file, &output);
}
format!("pub mod {};\n", self.name)
}
}
void transpile_file(PathBuf* path, PathBuf* output_file, str* mod_decl) {
String source = match (fs::read_to_string(path)) {
Ok[s] => s;
Err[e] => {
eprintln!("error: failed to read file {}\n {}", path.display(), e);
process::exit(1);
}
};
var mut gc = mist_codegen::RustCodegen::new();
String output = gc.generate(match (mist_parser::parse(&source)) {
Ok[ast] => ast;
Err[e] => {
match (e) {
error::ParseError::Ast[e] => {
var start_pos = e.span.start_pos().line_col();
var span = e.span.as_str();
eprintln!(
"\n{}:{}:{}\n \x1b[31mError\x1b[0m: {}\n\t{}{}\t{}",
path.as_os_str().display(),
start_pos.0,
start_pos.1,
e.error_message,
span,
if span.ends_with("\n") { "" } else { "\n" },
"^".repeat(span.trim().len()),
);
process::exit(1);
}
error::ParseError::PreAst[e] => {
eprintln!("error: parse failed in {}\n{}", path.display(), e);
process::exit(1);
}
}
}
});
var res = fs::write(&output_file, format!("{mod_decl}{output}"));
if (res.is_err()) {
eprintln!(
"error: failed to write output {}\n {}",
output_file.display(),
res.unwrap_err(),
);
process::exit(1);
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "mist-parser" name = "mist-parser"
version = "0.1.6" version = "0.1.7-alpha.0"
edition = "2024" edition = "2024"
description = "The Mist programming language parser" description = "The Mist programming language parser"
license = "Apache-2.0" license = "Apache-2.0"
+4 -5
View File
@@ -32,12 +32,11 @@ pub enum Literal {
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub enum Pattern { pub enum Pattern {
NamedTuple(Path, Vec<Identifier>), NamedTuple(Path, Vec<Box<Pattern>>),
Struct(Path, Vec<Identifier>), Struct(Path, Vec<Box<Pattern>>),
Tuple(Vec<Identifier>), Tuple(Vec<Box<Pattern>>),
Literal(Literal), Literal(Literal),
Path(Path), Path(bool, Path),
Id(Identifier),
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
+4 -3
View File
@@ -31,12 +31,11 @@ pub enum Statement {
body: StatementBody, body: StatementBody,
}, },
For { For {
mutable: bool,
pattern: Pattern, pattern: Pattern,
iterator: Expression, iterator: Expression,
body: StatementBody, body: StatementBody,
}, },
Match(Expression, Vec<(Vec<Pattern>, Expression)>), Match(Expression, Vec<Spanned<MatchItem>>),
VarDecl(VarDeclStmt), VarDecl(VarDeclStmt),
Return(Option<Expression>), Return(Option<Expression>),
@@ -44,9 +43,11 @@ pub enum Statement {
Continue, Continue,
} }
#[derive(Debug, Clone, Serialize)]
pub struct MatchItem(pub Vec<Pattern>, pub Expression);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct VarDecl { pub struct VarDecl {
pub mutable: bool,
pub name: Pattern, pub name: Pattern,
pub type_: Option<TypeExpr>, pub type_: Option<TypeExpr>,
} }
+1
View File
@@ -54,6 +54,7 @@ pub enum TopLevelKind {
visibility: Visibility, visibility: Visibility,
name: Identifier, name: Identifier,
generics: GenericsDecl, generics: GenericsDecl,
inherits: Option<TypeExpr>,
fields: Vec<Spanned<FieldDeclStmt>>, fields: Vec<Spanned<FieldDeclStmt>>,
constructor: Spanned<ClassConstructor>, constructor: Spanned<ClassConstructor>,
items: Vec<ClassItem>, items: Vec<ClassItem>,
+22 -14
View File
@@ -134,16 +134,24 @@ literal = {
// PATTERNS // PATTERNS
// ====================================================== // ======================================================
multi_pat_template = _{
(pattern ~ ("," ~ pattern)*)?
}
tuple_pattern = { tuple_pattern = {
"[" ~ (identifier ~ ("," ~ identifier)*) ~ "]" "[" ~ multi_pat_template ~ "]"
} }
named_tuple_pattern = { named_tuple_pattern = {
static_path ~ "[" ~ (identifier ~ ("," ~ identifier)*)? ~ "]" static_path ~ "[" ~ multi_pat_template ~ "]"
} }
struct_pattern = { struct_pattern = {
static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" static_path ~ "{" ~ multi_pat_template ~ "}"
}
path_pattern = {
mutable? ~ static_path
} }
pattern = _{ pattern = _{
@@ -151,7 +159,7 @@ pattern = _{
| tuple_pattern | tuple_pattern
| struct_pattern | struct_pattern
| literal | literal
| static_path | path_pattern
} }
// ====================================================== // ======================================================
@@ -171,7 +179,7 @@ meta = {
} }
meta_list = { meta_list = {
meta ~ ("," ~ meta)* ~ ","? (meta ~ ("," ~ meta)* ~ ","?)?
} }
attributes = { attributes = {
@@ -182,7 +190,7 @@ attributes = {
// DECLARATION HELPERS // DECLARATION HELPERS
// ====================================================== // ======================================================
var_decl = { var_decl = {
(var | type_expr) ~ mutable? ~ pattern (var | type_expr) ~ pattern
} }
field = { field = {
@@ -190,11 +198,11 @@ field = {
} }
field_list = { field_list = {
field ~ ("," ~ field)* ~ ","? (field ~ ("," ~ field)* ~ ","?)?
} }
param_list = { param_list = {
var_decl ~ ("," ~ var_decl)* ~ ","? (var_decl ~ ("," ~ var_decl)* ~ ","?)?
} }
// ====================================================== // ======================================================
@@ -252,7 +260,7 @@ enum_decl = {
// ====================================================== // ======================================================
class_constructor = { class_constructor = {
visibility? ~ "constructor" ~ generics_decl? ~ "(" ~ param_list? ~ ")" ~ block visibility? ~ "constructor" ~ generics_decl? ~ "(" ~ param_list ~ ")" ~ block
} }
class_fields = { class_fields = {
@@ -268,7 +276,7 @@ self_param = {
} }
method = { method = {
visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ block visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list)? ~ ")" ~ block
} }
class_item = _{ class_item = _{
@@ -277,7 +285,7 @@ class_item = _{
} }
class_decl = { class_decl = {
visibility? ~ "class" ~ identifier ~ generics_decl? ~ "{" ~ class_fields ~ class_constructor ~ class_item* ~ "}" visibility? ~ "class" ~ identifier ~ generics_decl? ~ (":" ~ type_expr)? ~ "{" ~ class_fields ~ class_constructor ~ class_item* ~ "}"
} }
// ====================================================== // ======================================================
@@ -297,7 +305,7 @@ impl_decl = {
trait_requirements = { ":" ~ type_expr_param ~ ("+" ~ type_expr_param)* } trait_requirements = { ":" ~ type_expr_param ~ ("+" ~ type_expr_param)* }
method_no_body = { method_no_body = {
visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ semicolon visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list)? ~ ")" ~ semicolon
} }
trait_item = _{ trait_item = _{
@@ -314,7 +322,7 @@ trait_decl = {
// ====================================================== // ======================================================
function_decl = { function_decl = {
visibility? ~ type_expr ~ identifier ~ "(" ~ param_list? ~ ")" ~ block visibility? ~ type_expr ~ identifier ~ "(" ~ param_list ~ ")" ~ block
} }
// ====================================================== // ======================================================
@@ -415,7 +423,7 @@ c_for_stmt = {
} }
for_stmt = { for_stmt = {
"for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body "for" ~ "(" ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body
} }
loop_stmt = { loop_stmt = {
+1 -5
View File
@@ -2,8 +2,7 @@ use crate::{
Rule, Rule,
ast::*, ast::*,
ast_expr, ast_expr,
error::{AstError, AstResult, IntoErr}, error::{AstError, IntoErr},
parser::listen_rule,
}; };
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for VarDeclStmt { impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for VarDeclStmt {
@@ -63,13 +62,10 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for VarDecl {
}) })
.transpose(); .transpose();
let mutable: AstResult<'_, bool> = Ok(listen_rule(&mut inner, Rule::mutable));
let name = Pattern::try_from(inner.next().unwrap()); let name = Pattern::try_from(inner.next().unwrap());
ast_expr!(VarDecl { ast_expr!(VarDecl {
type_: type_, type_: type_,
mutable: mutable,
name: name, name: name,
}) })
} }
+11 -8
View File
@@ -7,8 +7,8 @@ use crate::{
Rule, Rule,
ast::*, ast::*,
ast_ensure, ast_expr, ast_ensure, ast_expr,
error::{AstError, IntoErr, collect_recovered}, error::{AstError, AstResult, IntoErr, collect_recovered, collect_recovered_map},
parser::consume_rule, parser::{consume_rule, listen_rule},
}; };
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Identifier { impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Identifier {
@@ -60,23 +60,26 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Pattern {
let mut inner = pair.clone().into_inner(); let mut inner = pair.clone().into_inner();
match rule { match rule {
Rule::tuple_pattern => ast_expr!(Pattern::Tuple(collect_recovered(pair.into_inner()))), Rule::tuple_pattern => ast_expr!(Pattern::Tuple(collect_recovered_map(inner, |v| {
Self::try_from(v).map(Box::new)
}))),
Rule::named_tuple_pattern => ast_expr!(Pattern::NamedTuple( Rule::named_tuple_pattern => ast_expr!(Pattern::NamedTuple(
Path::try_from(inner.next().unwrap()), Path::try_from(inner.next().unwrap()),
collect_recovered(inner), collect_recovered_map(inner, |v| Self::try_from(v).map(Box::new)),
)), )),
Rule::struct_pattern => ast_expr!(Pattern::Struct( Rule::struct_pattern => ast_expr!(Pattern::Struct(
Path::try_from(inner.next().unwrap()), Path::try_from(inner.next().unwrap()),
collect_recovered(inner), collect_recovered_map(inner, |v| Self::try_from(v).map(Box::new)),
)), )),
Rule::literal => ast_expr!(Pattern::Literal(pair.try_into())), Rule::literal => ast_expr!(Pattern::Literal(pair.try_into())),
Rule::identifier => ast_expr!(Pattern::Id(pair.try_into())), Rule::path_pattern => ast_expr!(Pattern::Path(
Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
Rule::static_path => ast_expr!(Pattern::Path(pair.try_into())), inner.next().unwrap().try_into()
)),
_ => AstError::bug_unimplemented(pair), _ => AstError::bug_unimplemented(pair),
} }
+15 -12
View File
@@ -2,8 +2,7 @@ use crate::{
Rule, Rule,
ast::*, ast::*,
ast_ensure, ast_expr, ast_ensure, ast_expr,
error::{AstError, AstResult, IntoErr, collect_recovered}, error::{AstError, IntoErr, collect_recovered},
parser::listen_rule,
}; };
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Block { impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Block {
@@ -97,7 +96,6 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
}), }),
Rule::for_stmt => ast_expr!(Statement::For { Rule::for_stmt => ast_expr!(Statement::For {
mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
pattern: inner.next().unwrap().try_into(), pattern: inner.next().unwrap().try_into(),
iterator: inner.next().unwrap().try_into(), iterator: inner.next().unwrap().try_into(),
body: inner.next().unwrap().try_into(), body: inner.next().unwrap().try_into(),
@@ -105,18 +103,23 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
Rule::match_stmt => ast_expr!(Statement::Match( Rule::match_stmt => ast_expr!(Statement::Match(
inner.next().unwrap().try_into(), inner.next().unwrap().try_into(),
inner collect_recovered(inner),
.map(|match_itms| {
let mut match_inner = match_itms.into_inner();
Ok((
collect_recovered(match_inner.next().unwrap().into_inner()).get()?,
Expression::try_from(match_inner.next().unwrap()).get()?,
))
})
.collect::<AstResult<'a, Vec<_>>>(),
)), )),
_ => AstError::bug_unimplemented(pair), _ => AstError::bug_unimplemented(pair),
} }
} }
} }
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for MatchItem {
type Error = AstError<'a, Self>;
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
let mut match_inner = pair.into_inner();
Ok(MatchItem(
collect_recovered(match_inner.next().unwrap().into_inner()).get()?,
Expression::try_from(match_inner.next().unwrap()).get()?,
))
}
}
+2 -2
View File
@@ -28,11 +28,11 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Attribute {
} }
Some(next) => match next.as_rule() { Some(next) => match next.as_rule() {
Rule::primary => { Rule::literal => {
// #[path = literal] // #[path = literal]
Ok(Attribute::NameValue { Ok(Attribute::NameValue {
path, path,
value: inner.next().unwrap().try_into().get()?, value: next.try_into().get()?,
}) })
} }
+1 -4
View File
@@ -23,14 +23,11 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for FunctionDecl {
let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| {
let mut param_inner = param.into_inner(); let mut param_inner = param.into_inner();
let name = Pattern::Id(Identifier(String::from("self")));
let mutable = listen_rule(&mut param_inner, Rule::mutable); let mutable = listen_rule(&mut param_inner, Rule::mutable);
let is_ref = listen_rule(&mut param_inner, Rule::deref_px); let is_ref = listen_rule(&mut param_inner, Rule::deref_px);
let name = Pattern::Path(mutable && !is_ref, Path(vec![Identifier(String::from("self"))]));
VarDecl { VarDecl {
mutable: mutable && !is_ref,
name: name.clone(), name: name.clone(),
type_: Some(TypeExpr( type_: Some(TypeExpr(
TypeExprKind::Path(Path(vec![Identifier("Self".to_string())])), TypeExprKind::Path(Path(vec![Identifier("Self".to_string())])),
+4
View File
@@ -69,6 +69,10 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for TopLevelKind {
.transpose() .transpose()
.map(|v| v.unwrap_or_default()), .map(|v| v.unwrap_or_default()),
inherits: consume_rule(&mut inner, Rule::type_expr)
.map(TypeExpr::try_from)
.transpose(),
fields: collect_recovered(inner.next().unwrap().into_inner()), fields: collect_recovered(inner.next().unwrap().into_inner()),
constructor: inner.next().unwrap().try_into(), constructor: inner.next().unwrap().try_into(),
+1
View File
@@ -0,0 +1 @@
package = "main.mist"
-6
View File
@@ -1,9 +1,3 @@
pub mod app;
pub mod task;
pub mod plugin;
pub mod logger;
pub mod event;
void main() { void main() {
var mut app_instance = new app::Application("mist-app"); var mut app_instance = new app::Application("mist-app");
-3
View File
@@ -1,3 +0,0 @@
pub mod builder;
fn main() {}
+2 -3
View File
@@ -1,9 +1,8 @@
use <std::process>; use <std::process>;
use <std::env>; use <std::env>;
use <std::fs>; use <std::fs>;
use <mist_api::builder>;
pub mod builder; use <mist_api::transpiler>;
pub mod transpiler;
void main() { void main() {
Vec<String> args = env::args().collect(); Vec<String> args = env::args().collect();
-162
View File
@@ -1,162 +0,0 @@
use <std::fs>;
use <std::path::Path>;
use <std::path::PathBuf>;
use <std::process>;
use <std::time>;
use <std::env>;
use <mist_parser::error>;
pub PathBuf build(bool force) {
var start = time::Instant::now();
var root = env::current_dir().expect("Unable to find project root");
PathBuf src = root.join("src");
PathBuf out = root.join(".mist/src");
build_dir(&root, &src, &src, &out, force);
var elapsed = start.elapsed();
println!(
"\x1b[32m\nTranspile successful\x1b[0m in \x1b[34m{:.2?}\x1b[0m",
elapsed
);
root
}
void build_dir(Path* root, Path* base_src, Path* current, Path* out, bool force) {
var entries = match (fs::read_dir(current)) {
Ok[entries] => entries;
Err[e] => {
eprintln!(
"error: failed to read directory {}\n {}",
current.display(),
e
);
process::exit(1);
}
};
for (entry : entries) {
var entry = match (entry) {
Ok[entry] => entry;
Err[e] => {
eprintln!("error: failed to read directory entry\n {}", e);
process::exit(1);
}
};
PathBuf path = entry.path();
if (path.is_dir()) {
build_dir(root, base_src, &path, out, force);
continue;
}
Path* relative = path.strip_prefix(base_src).expect("Failed to strip base src from path");
if (path.extension().and_then(|var e| e.to_str()) != Some("mist")) {
PathBuf dest = out.join(relative);
Option<Path*> parent = dest.parent();
if (parent.is_some()) {
fs::create_dir_all(parent.unwrap()).expect("failed to create output directory");
}
if (!force && should_skip(&path, &dest)) {
continue
}
fs::copy(&path, dest).expect("Failed to copy non-mist file");
continue;
}
PathBuf output_file = out.join(relative).with_extension("rs");
if (!force && should_skip(&path, &output_file)) {
continue;
}
Option<Path*> parent = output_file.parent();
if (parent.is_some()) {
fs::create_dir_all(parent.unwrap()).expect("failed to create output directory");
}
String source = match (fs::read_to_string(&path)) {
Ok[s] => s;
Err[e] => {
eprintln!("error: failed to read file {}\n {}", path.display(), e);
process::exit(1);
}
};
var mut gc = mist_codegen::RustCodegen::new();
String output = gc.generate(match (mist_parser::parse(&source)) {
Ok[ast] => ast;
Err[e] => {
match (e) {
error::ParseError::Ast[e] => {
var start_pos = e.span.start_pos().line_col();
var span = e.span.as_str();
eprintln!(
"\n{}:{}:{}\n \x1b[31mError\x1b[0m: {}\n\t{}{}\t{}",
path.as_os_str().display(),
start_pos.0,
start_pos.1,
e.error_message,
span,
if span.ends_with("\n") { "" } else { "\n" },
"^".repeat(span.trim().len()),
);
process::exit(1);
}
error::ParseError::PreAst[e] => {
eprintln!("error: parse failed in {}\n{}", path.display(), e);
process::exit(1);
}
}
}
});
var res = fs::write(&output_file, output);
if (res.is_err()) {
eprintln!(
"error: failed to write output {}\n {}",
output_file.display(),
res.unwrap_err(),
);
process::exit(1);
}
}
}
bool should_skip(Path* source, Path* output) {
var src_time = fs::metadata(source)
.ok()
.and_then(|var v| v.modified().ok());
var out_time = fs::metadata(output)
.ok()
.and_then(|var v| v.modified().ok());
out_time
.map(|var out_time| out_time >= src_time.unwrap())
.unwrap_or_default()
}