Merge pull request #43 from mist-go/rewritten-codegen
Rewritten codegen
This commit is contained in:
Generated
+8
@@ -449,12 +449,20 @@ dependencies = [
|
|||||||
"tower-lsp",
|
"tower-lsp",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mist-codegen"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"mist-parser",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mist-lang"
|
name = "mist-lang"
|
||||||
version = "0.0.3-alpha4"
|
version = "0.0.3-alpha4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cargo_metadata",
|
"cargo_metadata",
|
||||||
"mist-analyzer",
|
"mist-analyzer",
|
||||||
|
"mist-codegen",
|
||||||
"mist-parser",
|
"mist-parser",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ serde = { version = "1.0.228", features = ["serde_derive"] }
|
|||||||
serde_json = "1.0.149"
|
serde_json = "1.0.149"
|
||||||
mist-parser = { path = "./parser", version = "0.1.4"}
|
mist-parser = { path = "./parser", version = "0.1.4"}
|
||||||
mist-analyzer = { path = "./analyzer", version = "0.0.1"}
|
mist-analyzer = { path = "./analyzer", version = "0.0.1"}
|
||||||
|
mist-codegen = { path = "./codegen", version = "0.1.0"}
|
||||||
cargo_metadata = "0.23.1"
|
cargo_metadata = "0.23.1"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ impl LanguageServer for Backend {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn completion(&self, params: CompletionParams) -> Result<Option<CompletionResponse>> {
|
async fn completion(&self, _params: CompletionParams) -> Result<Option<CompletionResponse>> {
|
||||||
self.client
|
self.client
|
||||||
.log_message(MessageType::INFO, "getting completion")
|
.log_message(MessageType::INFO, "getting completion")
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "mist-codegen"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
description = "The Mist programming language Rust code generator"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
repository = "https://github.com/mist-go/mist"
|
||||||
|
keywords = ["compiler", "language", "mist"]
|
||||||
|
categories = ["compilers"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
mist-parser = { path = "../parser", version = "0.1.4"}
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
use mist_parser::ast::*;
|
||||||
|
|
||||||
|
use crate::Context;
|
||||||
|
|
||||||
|
use crate::{GenRust, GetRust, RustCodegen};
|
||||||
|
|
||||||
|
impl GetRust for ExprPath {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.map(ExprPathSegment::get_rust)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("::")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for ExprPathSegment {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"{}{}",
|
||||||
|
self.ident.get_rust(),
|
||||||
|
self.generics
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| format!("::{}", v.get_rust()))
|
||||||
|
.unwrap_or_default()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for Literal {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
match self {
|
||||||
|
Self::Int(n) => cg.add(&n.to_string()),
|
||||||
|
Self::Float(n) => cg.add(&format!("{n:?}")),
|
||||||
|
Self::Bool(b) => cg.add(&b.to_string()),
|
||||||
|
Self::String(s) => cg.add(&format!("\"{s}\"")),
|
||||||
|
|
||||||
|
Self::Tuple(values) => {
|
||||||
|
cg.add("(");
|
||||||
|
|
||||||
|
for val in values {
|
||||||
|
val.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.add(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::Array(values) => {
|
||||||
|
cg.add("[");
|
||||||
|
|
||||||
|
for val in values {
|
||||||
|
val.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.add("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::ArrayRepeat(value, repeat) => {
|
||||||
|
cg.add("[");
|
||||||
|
value.gen_rust(ctx, cg);
|
||||||
|
cg.add("; ");
|
||||||
|
repeat.gen_rust(ctx, cg);
|
||||||
|
cg.add("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for Expression {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
let ensure_semicolon = if ctx.expr_ensure_semicolon {
|
||||||
|
ctx.expr_ensure_semicolon = false;
|
||||||
|
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Expression::Path(path) => cg.add(&path.get_rust()),
|
||||||
|
Expression::Literal(literal) => literal.gen_rust(ctx, cg),
|
||||||
|
Expression::Statement(stmt) => stmt.gen_rust(ctx, cg),
|
||||||
|
Expression::Fix {
|
||||||
|
initial,
|
||||||
|
prefixes,
|
||||||
|
postfixes,
|
||||||
|
} => {
|
||||||
|
cg.add(&prefixes.get_rust());
|
||||||
|
initial.gen_rust(ctx, cg);
|
||||||
|
cg.add(&Some(prefixes).get_rust());
|
||||||
|
for postfix in postfixes {
|
||||||
|
postfix.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Safely integrated to handle the tree structure built by the Pratt Parser
|
||||||
|
Expression::Binary { lhs, op, rhs } => {
|
||||||
|
lhs.gen_rust(ctx, cg);
|
||||||
|
cg.add(op);
|
||||||
|
rhs.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ensure_semicolon {
|
||||||
|
ctx.expr_ensure_semicolon = true;
|
||||||
|
cg.add(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for Prefix {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Deref => "*",
|
||||||
|
Self::Ref => "&",
|
||||||
|
Self::RefMut => "&mut ",
|
||||||
|
Self::Not => "!",
|
||||||
|
Self::New(_) => "",
|
||||||
|
Self::Neg => "-",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for Vec<Prefix> {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
self.into_iter().map(Prefix::get_rust).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for Option<&Vec<Prefix>> {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
if let Some(prefixes) = self {
|
||||||
|
prefixes
|
||||||
|
.into_iter()
|
||||||
|
.last()
|
||||||
|
.map(|p| match p {
|
||||||
|
Prefix::New(generics) => format!(
|
||||||
|
"::new{}",
|
||||||
|
generics
|
||||||
|
.clone()
|
||||||
|
.map(|v| format!("::{}", v.get_rust()))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
),
|
||||||
|
_ => String::new(),
|
||||||
|
})
|
||||||
|
.unwrap_or_default()
|
||||||
|
.to_string()
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for Postfix {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
match self {
|
||||||
|
Postfix::FieldAccess(field, generics) => cg.add(&format!(
|
||||||
|
".{}{}",
|
||||||
|
field.get_rust(),
|
||||||
|
generics
|
||||||
|
.iter()
|
||||||
|
.map(|v| format!("::{}", v.get_rust()))
|
||||||
|
.collect::<String>()
|
||||||
|
)),
|
||||||
|
|
||||||
|
Postfix::Call(args) => {
|
||||||
|
cg.add("(");
|
||||||
|
|
||||||
|
for arg in args {
|
||||||
|
arg.gen_rust(ctx, cg);
|
||||||
|
cg.add(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.add(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
Postfix::MacroCall(inner) => {
|
||||||
|
cg.add("!(");
|
||||||
|
cg.add(inner);
|
||||||
|
cg.add(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
Postfix::StructCall(fields) => {
|
||||||
|
cg.add("{");
|
||||||
|
|
||||||
|
for (name, expr) in fields {
|
||||||
|
cg.add(&name.get_rust());
|
||||||
|
cg.add(": ");
|
||||||
|
expr.gen_rust(ctx, cg);
|
||||||
|
cg.add(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.add("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Postfix::Index(idx) => {
|
||||||
|
cg.add("[");
|
||||||
|
idx.gen_rust(ctx, cg);
|
||||||
|
cg.add("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
Postfix::As(ty) => {
|
||||||
|
cg.add(" as ");
|
||||||
|
cg.add(&ty.get_rust());
|
||||||
|
}
|
||||||
|
|
||||||
|
Postfix::Try => cg.add("?"),
|
||||||
|
|
||||||
|
Postfix::Assign(cmp, expr) => {
|
||||||
|
cg.add(" ");
|
||||||
|
cg.add(cmp);
|
||||||
|
expr.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
Postfix::Increment => cg.add("+=1"),
|
||||||
|
Postfix::Decrement => cg.add("-=1"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for Generics {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
if self.0.len() == 0 {
|
||||||
|
String::new()
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"<{}>",
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.map(Generic::get_rust)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for Generic {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Lifetime(name) => format!("'{}", name.get_rust()),
|
||||||
|
Self::Type(ty) => ty.get_rust(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
pub mod expr;
|
||||||
|
pub mod statement;
|
||||||
|
pub mod top_level;
|
||||||
|
|
||||||
|
use mist_parser::ast::*;
|
||||||
|
|
||||||
|
pub fn get_mutable(mutable: bool) -> String {
|
||||||
|
if mutable { "mut " } else { "" }.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Context {
|
||||||
|
pub expr_ensure_semicolon: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GenRust {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GetRust {
|
||||||
|
fn get_rust(&self) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RustCodegen {
|
||||||
|
output: String,
|
||||||
|
indent: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RustCodegen {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
output: String::new(),
|
||||||
|
indent: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn indent_str(&self) -> String {
|
||||||
|
" ".repeat(self.indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&mut self, s: &str) {
|
||||||
|
self.output.push_str(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addln(&mut self, s: &str) {
|
||||||
|
self.add(s);
|
||||||
|
self.add("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_indented(&mut self, s: &str) {
|
||||||
|
let line = format!("{}{}", self.indent_str(), s);
|
||||||
|
self.add(&line);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_indentedln(&mut self, s: &str) {
|
||||||
|
let line = format!("{}{}\n", self.indent_str(), s);
|
||||||
|
self.add(&line);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate(&mut self, toplevels: Vec<TopLevel>) -> String {
|
||||||
|
let mut ctx = Context {
|
||||||
|
expr_ensure_semicolon: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
for tl in toplevels {
|
||||||
|
tl.gen_rust(&mut ctx, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.output.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ensure_brackets(&mut self, ctx: &mut Context, stmt: &Box<Statement>) {
|
||||||
|
match &**stmt {
|
||||||
|
Statement::Block(_) => stmt.gen_rust(ctx, self),
|
||||||
|
_ => {
|
||||||
|
self.add("{");
|
||||||
|
self.indent += 1;
|
||||||
|
stmt.gen_rust(ctx, self);
|
||||||
|
self.indent -= 1;
|
||||||
|
self.add("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for Attribute {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
match self {
|
||||||
|
Self::Path(path) => cg.add(&path.get_rust()),
|
||||||
|
Self::NameValue { path, value } => {
|
||||||
|
cg.add(&format!("{} =", path.get_rust()));
|
||||||
|
value.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
Self::List { path, items } => {
|
||||||
|
cg.add(&path.get_rust());
|
||||||
|
for (i, item) in items.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
cg.add(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
item.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GetRust> GetRust for Spanned<T> {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"/* {}:{} */ {}",
|
||||||
|
self.line,
|
||||||
|
self.column,
|
||||||
|
self.item.get_rust()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GenRust> GenRust for Spanned<T> {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
cg.add_indentedln(&format!("/* {}:{} */", self.line, self.column));
|
||||||
|
cg.add_indented("");
|
||||||
|
self.item.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for Path {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.map(Identifier::get_rust)
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("::")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for TypePostfix {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
match self {
|
||||||
|
TypePostfix::Ref => format!("&"),
|
||||||
|
TypePostfix::RefMut => format!("&mut "),
|
||||||
|
TypePostfix::RefLifetime(lifetime) => format!("&'{} ", lifetime.get_rust()),
|
||||||
|
TypePostfix::RefMutLifetime(lifetime) => format!("&'{} mut ", lifetime.get_rust()),
|
||||||
|
TypePostfix::Dyn => format!("dyn "),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for Visibility {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Visibility::Public => "pub ".to_string(),
|
||||||
|
Visibility::PublicTarget(path) => format!("pub({}) ", path.get_rust()),
|
||||||
|
Visibility::Private => "".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for Identifier {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
self.0.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for TypeExpr {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
self.1
|
||||||
|
.iter()
|
||||||
|
.map(TypePostfix::get_rust)
|
||||||
|
.rev()
|
||||||
|
.collect::<String>()
|
||||||
|
+ &self.0.get_rust()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_static_type_path(path: &Path) -> String {
|
||||||
|
let rust_path = path.get_rust();
|
||||||
|
|
||||||
|
if rust_path == "void" {
|
||||||
|
format!("()")
|
||||||
|
} else {
|
||||||
|
rust_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for TypeExprKind {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
match self {
|
||||||
|
TypeExprKind::Path(path) => get_static_type_path(path),
|
||||||
|
TypeExprKind::Lifetime(name) => format!("'{}", name.get_rust()),
|
||||||
|
TypeExprKind::PathParams(path, params) => {
|
||||||
|
format!(
|
||||||
|
"{}<{}>",
|
||||||
|
get_static_type_path(path),
|
||||||
|
params
|
||||||
|
.into_iter()
|
||||||
|
.map(|t| t.get_rust())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
TypeExprKind::Tuple(types) => format!(
|
||||||
|
"({})",
|
||||||
|
types
|
||||||
|
.into_iter()
|
||||||
|
.map(|t| t.get_rust())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for Pattern {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
match self {
|
||||||
|
Self::Id(id) => cg.add(&id.get_rust()),
|
||||||
|
Self::Path(path) => cg.add(&path.get_rust()),
|
||||||
|
Self::Literal(lit) => lit.gen_rust(ctx, cg),
|
||||||
|
|
||||||
|
Self::Struct(path, ids) => {
|
||||||
|
cg.add(&path.get_rust());
|
||||||
|
cg.add(" {");
|
||||||
|
for id in ids {
|
||||||
|
cg.add(&id.get_rust());
|
||||||
|
cg.add(",");
|
||||||
|
}
|
||||||
|
cg.add("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::NamedTuple(path, ids) => {
|
||||||
|
cg.add(&path.get_rust());
|
||||||
|
cg.add(" (");
|
||||||
|
for id in ids {
|
||||||
|
cg.add(&id.get_rust());
|
||||||
|
cg.add(",");
|
||||||
|
}
|
||||||
|
cg.add(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::Tuple(ids) => {
|
||||||
|
cg.add("(");
|
||||||
|
for id in ids {
|
||||||
|
cg.add(&id.get_rust());
|
||||||
|
cg.add(",");
|
||||||
|
}
|
||||||
|
cg.add(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
use mist_parser::ast::*;
|
||||||
|
|
||||||
|
use crate::{Context, get_mutable};
|
||||||
|
|
||||||
|
use crate::{GenRust, GetRust, RustCodegen};
|
||||||
|
|
||||||
|
impl GenRust for Block {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
cg.addln("{");
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
for stmt in &self.0 {
|
||||||
|
ctx.expr_ensure_semicolon = true;
|
||||||
|
stmt.gen_rust(ctx, cg);
|
||||||
|
cg.addln("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(soft_return) = &self.1 {
|
||||||
|
ctx.expr_ensure_semicolon = false;
|
||||||
|
soft_return.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.add_indentedln("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for Statement {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
match self {
|
||||||
|
Statement::Block(block) => block.gen_rust(ctx, cg),
|
||||||
|
|
||||||
|
Statement::VarDecl(VarDeclStmt { decl, init }) => {
|
||||||
|
cg.add("let ");
|
||||||
|
decl.gen_rust(ctx, cg);
|
||||||
|
|
||||||
|
if let Some(init) = init {
|
||||||
|
cg.add(" = ");
|
||||||
|
init.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::Match(expr, match_items) => {
|
||||||
|
cg.add("match ");
|
||||||
|
expr.gen_rust(ctx, cg);
|
||||||
|
cg.add(" {");
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
for (pat, body) in match_items {
|
||||||
|
for (i, p) in pat.iter().enumerate() {
|
||||||
|
cg.addln("");
|
||||||
|
cg.add_indented("");
|
||||||
|
if i > 0 {
|
||||||
|
cg.add(" | ");
|
||||||
|
}
|
||||||
|
|
||||||
|
p.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.add(" => {");
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
body.gen_rust(ctx, cg);
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.add_indentedln("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.add_indentedln("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::If {
|
||||||
|
initial,
|
||||||
|
else_if,
|
||||||
|
else_branch,
|
||||||
|
} => {
|
||||||
|
cg.add("if ");
|
||||||
|
initial.condition.gen_rust(ctx, cg);
|
||||||
|
cg.ensure_brackets(ctx, &initial.body);
|
||||||
|
|
||||||
|
for else_if_branch in else_if {
|
||||||
|
cg.add("else if");
|
||||||
|
else_if_branch.condition.gen_rust(ctx, cg);
|
||||||
|
cg.ensure_brackets(ctx, &else_if_branch.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(else_br) = else_branch {
|
||||||
|
cg.add("else");
|
||||||
|
cg.ensure_brackets(ctx, else_br);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::While(StatementBranch { condition, body }) => {
|
||||||
|
cg.add("while ");
|
||||||
|
condition.gen_rust(ctx, cg);
|
||||||
|
cg.ensure_brackets(ctx, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::CStyleFor {
|
||||||
|
init,
|
||||||
|
condition,
|
||||||
|
update,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
cg.add_indentedln("{");
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
init.gen_rust(ctx, cg);
|
||||||
|
|
||||||
|
cg.add("while ");
|
||||||
|
|
||||||
|
condition.gen_rust(ctx, cg);
|
||||||
|
|
||||||
|
cg.add("{");
|
||||||
|
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
cg.ensure_brackets(ctx, body);
|
||||||
|
|
||||||
|
update.gen_rust(ctx, cg);
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.add_indentedln("}");
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.add_indentedln("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::For {
|
||||||
|
mutable,
|
||||||
|
pattern,
|
||||||
|
iterator,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
cg.add("for ");
|
||||||
|
cg.add(&get_mutable(*mutable));
|
||||||
|
pattern.gen_rust(ctx, cg);
|
||||||
|
cg.add(" in ");
|
||||||
|
iterator.gen_rust(ctx, cg);
|
||||||
|
cg.ensure_brackets(ctx, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::Return(expr) => {
|
||||||
|
cg.add("return ");
|
||||||
|
if let Some(expr) = expr {
|
||||||
|
expr.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement::Break => cg.add_indentedln("break"),
|
||||||
|
Statement::Continue => cg.add_indentedln("continue"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for VarDecl {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
cg.add(&get_mutable(self.mutable));
|
||||||
|
|
||||||
|
self.name.gen_rust(ctx, cg);
|
||||||
|
|
||||||
|
cg.add(
|
||||||
|
&self
|
||||||
|
.type_
|
||||||
|
.as_ref()
|
||||||
|
.map(|t| format!(": {}", t.get_rust()))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,402 @@
|
|||||||
|
use mist_parser::ast::*;
|
||||||
|
|
||||||
|
use crate::Context;
|
||||||
|
|
||||||
|
use crate::{GenRust, GetRust, RustCodegen};
|
||||||
|
|
||||||
|
impl GetRust for GenericsDecl {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
if self.0.len() == 0 {
|
||||||
|
String::new()
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"<{}>",
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.get_rust())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for GenericDecl {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
match self {
|
||||||
|
GenericDecl::Lifetime(name) => format!("'{}", name.get_rust()),
|
||||||
|
GenericDecl::Type(name, requirements) => {
|
||||||
|
name.get_rust()
|
||||||
|
+ &(if requirements.len() != 0 {
|
||||||
|
format!(
|
||||||
|
": {}",
|
||||||
|
requirements
|
||||||
|
.into_iter()
|
||||||
|
.map(TypeExpr::get_rust)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("+")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for ImplDecl {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
if let Some(trait_) = &self.trait_ {
|
||||||
|
cg.add_indentedln(&format!(
|
||||||
|
"impl{} {} for {} {{",
|
||||||
|
self.generics.get_rust(),
|
||||||
|
trait_.get_rust(),
|
||||||
|
self.target.get_rust()
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
cg.add_indentedln(&format!(
|
||||||
|
"impl{} {} {{",
|
||||||
|
self.generics.get_rust(),
|
||||||
|
self.target.get_rust()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
for method in &self.methods {
|
||||||
|
method.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.add_indentedln("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for FunctionDecl {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
cg.add(&format!(
|
||||||
|
"{}fn {}{}(",
|
||||||
|
self.visibility.get_rust(),
|
||||||
|
self.name.get_rust(),
|
||||||
|
self.generics.get_rust(),
|
||||||
|
));
|
||||||
|
|
||||||
|
for (i, param) in self.params.0.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
cg.add(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
param.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.add(") -> ");
|
||||||
|
cg.add(&self.return_type.get_rust());
|
||||||
|
|
||||||
|
if let Some(body) = &self.body {
|
||||||
|
cg.add(" ");
|
||||||
|
body.gen_rust(ctx, cg);
|
||||||
|
} else {
|
||||||
|
cg.add(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for FieldDecl {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"{}{}: {},",
|
||||||
|
self.visibility.get_rust(),
|
||||||
|
self.name.get_rust(),
|
||||||
|
self.type_.get_rust()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetRust for EnumItem {
|
||||||
|
fn get_rust(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Named(id) => id.get_rust(),
|
||||||
|
Self::Struct(id, s) => format!(
|
||||||
|
"{} {{{}}}",
|
||||||
|
id.get_rust(),
|
||||||
|
s.into_iter()
|
||||||
|
.map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust()))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
),
|
||||||
|
Self::Tuple(id, t) => format!(
|
||||||
|
"{} ({})",
|
||||||
|
id.get_rust(),
|
||||||
|
t.into_iter()
|
||||||
|
.map(TypeExpr::get_rust)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for ParamList {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
for (i, param) in self.0.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
cg.add(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
param.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for TopLevel {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
if let TopLevelKind::ModAttribute = self.0.item {
|
||||||
|
for attr in &self.1 {
|
||||||
|
cg.add("#![");
|
||||||
|
attr.gen_rust(ctx, cg);
|
||||||
|
cg.addln("]");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for attr in &self.1 {
|
||||||
|
cg.add("#[");
|
||||||
|
attr.gen_rust(ctx, cg);
|
||||||
|
cg.addln("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.0.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for (&Vec<Spanned<FieldDeclStmt>>, &Spanned<ClassConstructor>) {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
cg.add_indented(&format!(
|
||||||
|
"{}fn new{}(",
|
||||||
|
self.1.item.visibility.get_rust(),
|
||||||
|
self.1.item.generics.get_rust()
|
||||||
|
));
|
||||||
|
|
||||||
|
self.1.item.params.gen_rust(ctx, cg);
|
||||||
|
|
||||||
|
cg.addln(") -> Self {");
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::<Self>::zeroed().assume_init() };");
|
||||||
|
|
||||||
|
for field in self.0 {
|
||||||
|
let comment = field.get_comment();
|
||||||
|
|
||||||
|
if let Some(init) = &field.item.init {
|
||||||
|
cg.add_indentedln(&comment);
|
||||||
|
|
||||||
|
cg.add_indentedln(&format!("this.{} = ", field.item.decl.name.get_rust()));
|
||||||
|
|
||||||
|
init.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.add_indented(&format!("this.constructor("));
|
||||||
|
|
||||||
|
for (i, param) in self.1.item.params.0.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
cg.add(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
param.name.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.addln(");");
|
||||||
|
|
||||||
|
cg.add_indentedln("this");
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.add_indentedln("}\n");
|
||||||
|
|
||||||
|
let mut constructor_params = vec![VarDecl {
|
||||||
|
mutable: false,
|
||||||
|
name: Pattern::Id(Identifier(String::from("self"))),
|
||||||
|
type_: Some(TypeExpr(
|
||||||
|
TypeExprKind::Path(Path(vec![Identifier(String::from("Self"))])),
|
||||||
|
vec![TypePostfix::RefMut],
|
||||||
|
)),
|
||||||
|
}];
|
||||||
|
|
||||||
|
constructor_params.append(&mut self.1.item.params.0.clone());
|
||||||
|
|
||||||
|
Spanned {
|
||||||
|
line: self.1.line,
|
||||||
|
column: self.1.column,
|
||||||
|
item: FunctionDecl {
|
||||||
|
visibility: self.1.item.visibility.clone(),
|
||||||
|
name: Identifier(String::from("constructor")),
|
||||||
|
generics: self.1.item.generics.clone(),
|
||||||
|
params: ParamList(constructor_params),
|
||||||
|
return_type: TypeExpr::no_px(TypeExprKind::Tuple(Vec::new())),
|
||||||
|
body: Some(self.1.item.body.clone()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenRust for TopLevelKind {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
match self {
|
||||||
|
Self::ModAttribute => {}
|
||||||
|
Self::Import(vis, path) => {
|
||||||
|
cg.addln(&format!("{}use {};", vis.get_rust(), path.get_rust()))
|
||||||
|
}
|
||||||
|
Self::Mod(vis, id) => cg.addln(&format!("{}mod {};", vis.get_rust(), id.get_rust())),
|
||||||
|
Self::FunctionDecl(decl) => decl.gen_rust(ctx, cg),
|
||||||
|
Self::ImplDecl(impl_) => impl_.gen_rust(ctx, cg),
|
||||||
|
Self::StructDecl {
|
||||||
|
visibility,
|
||||||
|
name,
|
||||||
|
generics,
|
||||||
|
fields,
|
||||||
|
} => {
|
||||||
|
cg.addln(&format!(
|
||||||
|
"{}struct {}{} {{",
|
||||||
|
visibility.get_rust(),
|
||||||
|
name.get_rust(),
|
||||||
|
generics.get_rust()
|
||||||
|
));
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
for field in fields {
|
||||||
|
cg.add_indentedln(&field.get_rust());
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.addln("}\n");
|
||||||
|
}
|
||||||
|
Self::EnumDecl {
|
||||||
|
visibility,
|
||||||
|
name,
|
||||||
|
generics,
|
||||||
|
fields,
|
||||||
|
} => {
|
||||||
|
cg.addln(&format!(
|
||||||
|
"{}enum {}{} {{",
|
||||||
|
visibility.get_rust(),
|
||||||
|
name.get_rust(),
|
||||||
|
generics.get_rust()
|
||||||
|
));
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
for field in fields {
|
||||||
|
cg.add_indentedln(&(field.get_rust() + ","));
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.addln("}\n");
|
||||||
|
}
|
||||||
|
Self::TraitDecl {
|
||||||
|
visibility,
|
||||||
|
name,
|
||||||
|
generics,
|
||||||
|
requirements,
|
||||||
|
items,
|
||||||
|
} => {
|
||||||
|
cg.addln(&format!(
|
||||||
|
"{}trait {}{}{} {{",
|
||||||
|
visibility.get_rust(),
|
||||||
|
name.get_rust(),
|
||||||
|
generics.get_rust(),
|
||||||
|
if requirements.len() != 0 {
|
||||||
|
String::from(": ")
|
||||||
|
+ &requirements
|
||||||
|
.into_iter()
|
||||||
|
.map(TypeExpr::get_rust)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("+")
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
},
|
||||||
|
));
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
for item in items {
|
||||||
|
item.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.addln("}\n");
|
||||||
|
}
|
||||||
|
Self::ClassDecl {
|
||||||
|
visibility,
|
||||||
|
name,
|
||||||
|
generics,
|
||||||
|
fields,
|
||||||
|
constructor,
|
||||||
|
items,
|
||||||
|
} => {
|
||||||
|
// Struct decl
|
||||||
|
cg.addln(&format!(
|
||||||
|
"{}struct {}{} {{",
|
||||||
|
visibility.get_rust(),
|
||||||
|
name.clone().get_rust(),
|
||||||
|
generics.clone().get_rust()
|
||||||
|
));
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
for field in fields.clone() {
|
||||||
|
cg.add_indentedln(&field.get_comment());
|
||||||
|
cg.add_indentedln(&field.item.decl.get_rust());
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.addln("}\n");
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
cg.addln(&format!(
|
||||||
|
"impl{} {}{} {{",
|
||||||
|
generics.clone().get_rust(),
|
||||||
|
name.clone().get_rust(),
|
||||||
|
format!(
|
||||||
|
"<{}>",
|
||||||
|
generics
|
||||||
|
.clone()
|
||||||
|
.0
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| Generic::from(v).get_rust())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
));
|
||||||
|
cg.indent += 1;
|
||||||
|
|
||||||
|
let constructor_comment = constructor.get_comment();
|
||||||
|
|
||||||
|
cg.add_indentedln("#[allow(invalid_value)]");
|
||||||
|
cg.add_indentedln(&constructor_comment);
|
||||||
|
|
||||||
|
(fields, constructor).gen_rust(ctx, cg);
|
||||||
|
|
||||||
|
for item in items.clone() {
|
||||||
|
match item {
|
||||||
|
ClassItem::ImplDecl(_) => {}
|
||||||
|
ClassItem::Method(method) => method.gen_rust(ctx, cg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.indent -= 1;
|
||||||
|
cg.addln("}\n");
|
||||||
|
|
||||||
|
for item in items {
|
||||||
|
match item {
|
||||||
|
ClassItem::ImplDecl(impl_) => {
|
||||||
|
let mut impl_ = impl_.clone();
|
||||||
|
|
||||||
|
impl_.item.trait_ = Some(impl_.item.target);
|
||||||
|
impl_.item.target =
|
||||||
|
TypeExpr(TypeExprKind::Path(Path(vec![name.clone()])), Vec::new());
|
||||||
|
|
||||||
|
impl_.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
ClassItem::Method(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,18 +13,12 @@ pub enum LogLevel {
|
|||||||
|
|
||||||
impl fmt::Display for LogLevel {
|
impl fmt::Display for LogLevel {
|
||||||
fmt::Result fmt(self*, Formatter<'_> mut* f) {
|
fmt::Result fmt(self*, Formatter<'_> mut* f) {
|
||||||
match (self) {
|
return match (self) {
|
||||||
LogLevel::Info => {
|
LogLevel::Info => write!(f, "[INFO]");
|
||||||
return write!(f, "[INFO]");
|
|
||||||
}
|
|
||||||
|
|
||||||
LogLevel::Warning => {
|
LogLevel::Warning => write!(f, "[WARN]");
|
||||||
return write!(f, "[WARN]");
|
|
||||||
}
|
|
||||||
|
|
||||||
LogLevel::Error => {
|
LogLevel::Error => write!(f, "[ERROR]");
|
||||||
return write!(f, "[ERROR]");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ pub struct Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub Task create_task(str* name) {
|
pub Task create_task(str* name) {
|
||||||
return Task {
|
Task {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
state: TaskState::Pending,
|
state: TaskState::Pending,
|
||||||
executions: 0,
|
executions: 0,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ pub enum Statement {
|
|||||||
iterator: Expression,
|
iterator: Expression,
|
||||||
body: Box<Statement>,
|
body: Box<Statement>,
|
||||||
},
|
},
|
||||||
Match(Expression, Vec<(Vec<Pattern>, Block)>),
|
Match(Expression, Vec<(Vec<Pattern>, Expression)>),
|
||||||
|
|
||||||
Return(Option<Expression>),
|
Return(Option<Expression>),
|
||||||
Break,
|
Break,
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ for_stmt = {
|
|||||||
pattern_list = { pattern ~ ("|" ~ pattern)* }
|
pattern_list = { pattern ~ ("|" ~ pattern)* }
|
||||||
|
|
||||||
match_item = {
|
match_item = {
|
||||||
pattern_list ~ "=>" ~ block
|
pattern_list ~ "=>" ~ statement
|
||||||
}
|
}
|
||||||
|
|
||||||
match_stmt = {
|
match_stmt = {
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
|
|||||||
let mut match_inner = match_itms.into_inner();
|
let mut match_inner = match_itms.into_inner();
|
||||||
Ok((
|
Ok((
|
||||||
collect_recovered(match_inner.next().unwrap().into_inner()).get()?,
|
collect_recovered(match_inner.next().unwrap().into_inner()).get()?,
|
||||||
Block::try_from(match_inner.next().unwrap()).get()?,
|
Expression::try_from(match_inner.next().unwrap()).get()?,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.collect::<AstResult<'a, Vec<_>>>(),
|
.collect::<AstResult<'a, Vec<_>>>(),
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod codegen;
|
|
||||||
pub mod transpiler;
|
pub mod transpiler;
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
-987
@@ -1,987 +0,0 @@
|
|||||||
use mist_parser::ast::{
|
|
||||||
Attribute, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression, FieldDecl,
|
|
||||||
FunctionDecl, Generic, GenericDecl, Generics, GenericsDecl, Identifier, ImplDecl, Literal,
|
|
||||||
Path, Pattern, Postfix, Prefix, Spanned, Statement, StatementBranch, TopLevel, TopLevelKind,
|
|
||||||
TypeExpr, TypeExprKind, TypePostfix, VarDecl, VarDeclStmt, Visibility,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Traits
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// Implemented by nodes that *write* into the codegen output buffer.
|
|
||||||
/// Requires `&mut RustCodegen` because it calls `add` / `addln` / indentation helpers.
|
|
||||||
pub trait ToRust {
|
|
||||||
fn to_rust(self, cg: &mut RustCodegen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implemented by nodes that *produce* a `String` without mutating the codegen.
|
|
||||||
/// Only needs `&RustCodegen` (e.g. for indent level or helper access).
|
|
||||||
pub trait GetRust {
|
|
||||||
fn get_rust(self) -> String;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Codegen struct
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
pub struct RustCodegen {
|
|
||||||
output: String,
|
|
||||||
indent: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RustCodegen {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
output: String::new(),
|
|
||||||
indent: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn indent_str(&self) -> String {
|
|
||||||
" ".repeat(self.indent)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add(&mut self, s: &str) {
|
|
||||||
self.output.push_str(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn addln(&mut self, s: &str) {
|
|
||||||
self.add(s);
|
|
||||||
self.add("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_indentedln(&mut self, s: &str) {
|
|
||||||
let line = format!("{}{}\n", self.indent_str(), s);
|
|
||||||
self.add(&line);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate(&mut self, toplevels: Vec<TopLevel>) -> String {
|
|
||||||
for tl in toplevels {
|
|
||||||
tl.to_rust(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.output.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ensure_brackets(&mut self, stmt: Box<Statement>) {
|
|
||||||
match *stmt {
|
|
||||||
Statement::Block(_) => stmt.to_rust(self),
|
|
||||||
_ => {
|
|
||||||
self.add_indentedln("{");
|
|
||||||
self.indent += 1;
|
|
||||||
stmt.to_rust(self);
|
|
||||||
self.indent -= 1;
|
|
||||||
self.add_indentedln("}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for RustCodegen {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// GetRust — pure string production (expressions, types)
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
impl<T: GetRust> GetRust for Spanned<T> {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
format!(
|
|
||||||
"/* {}:{} */ {}",
|
|
||||||
self.line,
|
|
||||||
self.column,
|
|
||||||
self.item.get_rust()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for TypeExpr {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
get_type_postfixes(self.1) + &self.0.get_rust()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for TypeExprKind {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
TypeExprKind::Path(path) => get_static_type_path(path),
|
|
||||||
TypeExprKind::Lifetime(name) => format!("'{}", name.get_rust()),
|
|
||||||
TypeExprKind::PathParams(path, params) => {
|
|
||||||
format!(
|
|
||||||
"{}<{}>",
|
|
||||||
get_static_type_path(path),
|
|
||||||
params
|
|
||||||
.into_iter()
|
|
||||||
.map(|t| t.get_rust())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
TypeExprKind::Tuple(types) => format!(
|
|
||||||
"({})",
|
|
||||||
types
|
|
||||||
.into_iter()
|
|
||||||
.map(|t| t.get_rust())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Literal {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Int(n) => n.to_string(),
|
|
||||||
Self::Float(n) => format!("{n:?}"),
|
|
||||||
Self::Bool(b) => b.to_string(),
|
|
||||||
Self::String(s) => format!("\"{s}\""),
|
|
||||||
Self::Tuple(t) => {
|
|
||||||
format!(
|
|
||||||
"({})",
|
|
||||||
t.into_iter()
|
|
||||||
.map(Expression::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Self::Array(values) => format!(
|
|
||||||
"[{}]",
|
|
||||||
values
|
|
||||||
.into_iter()
|
|
||||||
.map(Expression::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
),
|
|
||||||
Self::ArrayRepeat(value, repeat) => {
|
|
||||||
format!("[{}; {}]", value.get_rust(), repeat.get_rust())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Expression {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Expression::Path(path) => path.get_rust(),
|
|
||||||
Expression::Literal(literal) => literal.get_rust(),
|
|
||||||
Expression::Statement(stmt) => {
|
|
||||||
let mut cg = RustCodegen::new();
|
|
||||||
cg.indent += 1;
|
|
||||||
stmt.to_rust(&mut cg);
|
|
||||||
cg.output
|
|
||||||
}
|
|
||||||
Expression::Fix {
|
|
||||||
initial,
|
|
||||||
prefixes,
|
|
||||||
postfixes,
|
|
||||||
} => {
|
|
||||||
prefixes.clone().get_rust()
|
|
||||||
+ &initial.get_rust()
|
|
||||||
+ &Some(prefixes).get_rust()
|
|
||||||
+ &postfixes.get_rust()
|
|
||||||
}
|
|
||||||
// Safely integrated to handle the tree structure built by the Pratt Parser
|
|
||||||
Expression::Binary { lhs, op, rhs } => {
|
|
||||||
format!("{} {} {}", lhs.get_rust(), op, rhs.get_rust())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Prefix {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Deref => "*",
|
|
||||||
Self::Ref => "&",
|
|
||||||
Self::RefMut => "&mut ",
|
|
||||||
Self::Not => "!",
|
|
||||||
Self::New(_) => "",
|
|
||||||
Self::Neg => "-",
|
|
||||||
}
|
|
||||||
.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Vec<Prefix> {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
self.into_iter().map(Prefix::get_rust).collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for ExprPath {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
self.0
|
|
||||||
.into_iter()
|
|
||||||
.map(ExprPathSegment::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("::")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for ExprPathSegment {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
format!(
|
|
||||||
"{}{}",
|
|
||||||
self.ident.get_rust(),
|
|
||||||
self.generics
|
|
||||||
.map(|v| format!("::{}", v.get_rust()))
|
|
||||||
.unwrap_or_default()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Option<Vec<Prefix>> {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
self.map(|prefixes| {
|
|
||||||
prefixes
|
|
||||||
.into_iter()
|
|
||||||
.last()
|
|
||||||
.map(|p| match p {
|
|
||||||
Prefix::New(generics) => format!(
|
|
||||||
"::new{}",
|
|
||||||
generics
|
|
||||||
.map(|v| format!("::{}", v.get_rust()))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
),
|
|
||||||
_ => String::new(),
|
|
||||||
})
|
|
||||||
.unwrap_or_default()
|
|
||||||
.to_string()
|
|
||||||
})
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Postfix {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Postfix::FieldAccess(field, generics) => format!(
|
|
||||||
".{}{}",
|
|
||||||
field.get_rust(),
|
|
||||||
generics
|
|
||||||
.map(|v| format!("::{}", v.get_rust()))
|
|
||||||
.unwrap_or_default()
|
|
||||||
),
|
|
||||||
|
|
||||||
Postfix::Call(args) => {
|
|
||||||
let args = args
|
|
||||||
.into_iter()
|
|
||||||
.map(|a| a.get_rust())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ");
|
|
||||||
format!("({})", args)
|
|
||||||
}
|
|
||||||
|
|
||||||
Postfix::MacroCall(inner) => {
|
|
||||||
format!("!({})", inner)
|
|
||||||
}
|
|
||||||
|
|
||||||
Postfix::StructCall(fields) => {
|
|
||||||
let fields = fields
|
|
||||||
.into_iter()
|
|
||||||
.map(|(k, v)| format!("{}: {}", k.get_rust(), v.get_rust()))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ");
|
|
||||||
format!("{{ {} }}", fields)
|
|
||||||
}
|
|
||||||
|
|
||||||
Postfix::Index(idx) => {
|
|
||||||
format!("[{}]", idx.get_rust())
|
|
||||||
}
|
|
||||||
|
|
||||||
Postfix::As(ty) => format!(" as {}", ty.get_rust()),
|
|
||||||
|
|
||||||
Postfix::Try => String::from("?"),
|
|
||||||
|
|
||||||
Postfix::Assign(cmp, expr) => format!("{cmp} {}", expr.get_rust()),
|
|
||||||
Postfix::Increment => "+=1".to_string(),
|
|
||||||
Postfix::Decrement => "-=1".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Vec<Postfix> {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
self.into_iter().map(Postfix::get_rust).collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ToRust — output-writing (top-level, statements, blocks)
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
impl<T: ToRust> ToRust for Spanned<T> {
|
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
|
||||||
cg.add_indentedln(&format!("/* {}:{} */", self.line, self.column));
|
|
||||||
self.item.to_rust(cg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToRust for Block {
|
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
|
||||||
for stmt in self.0 {
|
|
||||||
cg.add_indentedln(&(stmt.get_rust() + ";"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(soft_return) = self.1 {
|
|
||||||
cg.add_indentedln(&soft_return.get_rust());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToRust for TopLevel {
|
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
|
||||||
if let TopLevelKind::ModAttribute = self.0.item {
|
|
||||||
for attr in self.1 {
|
|
||||||
cg.addln(&format!("#![{}]", attr.get_rust()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for attr in self.1 {
|
|
||||||
cg.addln(&format!("#[{}]", attr.get_rust()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.0.to_rust(cg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Attribute {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Path(path) => path.get_rust(),
|
|
||||||
Self::NameValue { path, value } => {
|
|
||||||
format!("{} = {}", path.get_rust(), value.get_rust())
|
|
||||||
}
|
|
||||||
Self::List { path, items } => {
|
|
||||||
format!(
|
|
||||||
"{}({})",
|
|
||||||
path.get_rust(),
|
|
||||||
items
|
|
||||||
.into_iter()
|
|
||||||
.map(Attribute::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToRust for TopLevelKind {
|
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
|
||||||
match self {
|
|
||||||
Self::ModAttribute => {}
|
|
||||||
Self::Import(vis, path) => {
|
|
||||||
cg.addln(&format!("{}use {};", vis.get_rust(), path.get_rust()))
|
|
||||||
}
|
|
||||||
Self::Mod(vis, id) => cg.addln(&format!("{}mod {};", vis.get_rust(), id.get_rust())),
|
|
||||||
Self::FunctionDecl(decl) => decl.to_rust(cg),
|
|
||||||
Self::ImplDecl(impl_) => impl_.to_rust(cg),
|
|
||||||
Self::StructDecl {
|
|
||||||
visibility,
|
|
||||||
name,
|
|
||||||
generics,
|
|
||||||
fields,
|
|
||||||
} => {
|
|
||||||
cg.addln(&format!(
|
|
||||||
"{}struct {}{} {{",
|
|
||||||
visibility.get_rust(),
|
|
||||||
name.get_rust(),
|
|
||||||
generics.get_rust()
|
|
||||||
));
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
for field in fields {
|
|
||||||
cg.add_indentedln(&field.get_rust());
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.addln("}\n");
|
|
||||||
}
|
|
||||||
Self::EnumDecl {
|
|
||||||
visibility,
|
|
||||||
name,
|
|
||||||
generics,
|
|
||||||
fields,
|
|
||||||
} => {
|
|
||||||
cg.addln(&format!(
|
|
||||||
"{}enum {}{} {{",
|
|
||||||
visibility.get_rust(),
|
|
||||||
name.get_rust(),
|
|
||||||
generics.get_rust()
|
|
||||||
));
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
for field in fields {
|
|
||||||
cg.add_indentedln(&(field.get_rust() + ","));
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.addln("}\n");
|
|
||||||
}
|
|
||||||
Self::TraitDecl {
|
|
||||||
visibility,
|
|
||||||
name,
|
|
||||||
generics,
|
|
||||||
requirements,
|
|
||||||
items,
|
|
||||||
} => {
|
|
||||||
cg.addln(&format!(
|
|
||||||
"{}trait {}{}{} {{",
|
|
||||||
visibility.get_rust(),
|
|
||||||
name.get_rust(),
|
|
||||||
generics.get_rust(),
|
|
||||||
if requirements.len() != 0 {
|
|
||||||
String::from(": ")
|
|
||||||
+ &requirements
|
|
||||||
.into_iter()
|
|
||||||
.map(TypeExpr::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("+")
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
},
|
|
||||||
));
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
for item in items {
|
|
||||||
item.to_rust(cg);
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.addln("}\n");
|
|
||||||
}
|
|
||||||
Self::ClassDecl {
|
|
||||||
visibility,
|
|
||||||
name,
|
|
||||||
generics,
|
|
||||||
fields,
|
|
||||||
constructor,
|
|
||||||
items,
|
|
||||||
} => {
|
|
||||||
// Struct decl
|
|
||||||
cg.addln(&format!(
|
|
||||||
"{}struct {}{} {{",
|
|
||||||
visibility.get_rust(),
|
|
||||||
name.clone().get_rust(),
|
|
||||||
generics.clone().get_rust()
|
|
||||||
));
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
for field in fields.clone() {
|
|
||||||
cg.add_indentedln(&field.get_comment());
|
|
||||||
cg.add_indentedln(&field.item.decl.get_rust());
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.addln("}\n");
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
cg.addln(&format!(
|
|
||||||
"impl{} {}{} {{",
|
|
||||||
generics.clone().get_rust(),
|
|
||||||
name.clone().get_rust(),
|
|
||||||
format!(
|
|
||||||
"<{}>",
|
|
||||||
generics
|
|
||||||
.clone()
|
|
||||||
.0
|
|
||||||
.into_iter()
|
|
||||||
.map(|v| Generic::from(v).get_rust())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
));
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
let constructor_comment = constructor.get_comment();
|
|
||||||
|
|
||||||
let constructor = constructor.item;
|
|
||||||
|
|
||||||
let params_str = constructor
|
|
||||||
.params
|
|
||||||
.0
|
|
||||||
.clone()
|
|
||||||
.into_iter()
|
|
||||||
.map(VarDecl::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ");
|
|
||||||
|
|
||||||
cg.add_indentedln("#[allow(invalid_value)]");
|
|
||||||
cg.add_indentedln(&constructor_comment);
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"{}fn new{}({}) -> Self {{",
|
|
||||||
constructor.visibility.clone().get_rust(),
|
|
||||||
constructor.generics.clone().get_rust(),
|
|
||||||
params_str
|
|
||||||
));
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::<Self>::zeroed().assume_init() };");
|
|
||||||
|
|
||||||
for field in fields {
|
|
||||||
let comment = field.get_comment();
|
|
||||||
|
|
||||||
if let Some(init) = field.item.init {
|
|
||||||
cg.add_indentedln(&comment);
|
|
||||||
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"this.{} = {};",
|
|
||||||
field.item.decl.name.get_rust(),
|
|
||||||
init.get_rust()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"this.construct_class({});",
|
|
||||||
constructor
|
|
||||||
.params
|
|
||||||
.0
|
|
||||||
.into_iter()
|
|
||||||
.map(|e| e.name.get_rust())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
));
|
|
||||||
|
|
||||||
cg.add_indentedln("this");
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}\n");
|
|
||||||
|
|
||||||
// Constructor function
|
|
||||||
cg.add_indentedln(&constructor_comment);
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"{}fn construct_class{}(&mut self, {}) {{",
|
|
||||||
constructor.visibility.get_rust(),
|
|
||||||
constructor.generics.get_rust(),
|
|
||||||
params_str
|
|
||||||
));
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
constructor.body.to_rust(cg);
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}\n");
|
|
||||||
|
|
||||||
for item in items.clone() {
|
|
||||||
match item {
|
|
||||||
ClassItem::ImplDecl(_) => {}
|
|
||||||
ClassItem::Method(method) => method.to_rust(cg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.addln("}\n");
|
|
||||||
|
|
||||||
for item in items {
|
|
||||||
match item {
|
|
||||||
ClassItem::ImplDecl(impl_) => {
|
|
||||||
let mut impl_ = impl_.clone();
|
|
||||||
|
|
||||||
impl_.item.trait_ = Some(impl_.item.target);
|
|
||||||
impl_.item.target =
|
|
||||||
TypeExpr(TypeExprKind::Path(Path(vec![name.clone()])), Vec::new());
|
|
||||||
|
|
||||||
impl_.to_rust(cg);
|
|
||||||
}
|
|
||||||
ClassItem::Method(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToRust for Statement {
|
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
|
||||||
match self {
|
|
||||||
Statement::Block(block) => {
|
|
||||||
cg.add_indentedln("{");
|
|
||||||
cg.indent += 1;
|
|
||||||
block.to_rust(cg);
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::VarDecl(VarDeclStmt { decl, init }) => {
|
|
||||||
let init = init
|
|
||||||
.map(|e| format!(" = {}", e.get_rust()))
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
cg.add_indentedln(&format!("let {}{}", decl.get_rust(), init));
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::Match(expr, match_items) => {
|
|
||||||
cg.add_indentedln(&format!("match {} {{", expr.get_rust()));
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
for itm in match_items {
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"{} =>",
|
|
||||||
itm.0
|
|
||||||
.into_iter()
|
|
||||||
.map(Pattern::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(" | ")
|
|
||||||
));
|
|
||||||
cg.add_indentedln("{");
|
|
||||||
cg.indent += 1;
|
|
||||||
itm.1.to_rust(cg);
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::If {
|
|
||||||
initial,
|
|
||||||
else_if,
|
|
||||||
else_branch,
|
|
||||||
} => {
|
|
||||||
cg.add_indentedln(&format!("if {}", initial.condition.get_rust()));
|
|
||||||
cg.ensure_brackets(initial.body);
|
|
||||||
|
|
||||||
for else_if_branch in else_if {
|
|
||||||
cg.add_indentedln(&format!("else if {}", else_if_branch.condition.get_rust()));
|
|
||||||
cg.ensure_brackets(else_if_branch.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(else_br) = else_branch {
|
|
||||||
cg.add_indentedln("else");
|
|
||||||
cg.ensure_brackets(else_br);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::While(StatementBranch { condition, body }) => {
|
|
||||||
cg.add_indentedln(&format!("while {}", condition.get_rust()));
|
|
||||||
cg.ensure_brackets(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::CStyleFor {
|
|
||||||
init,
|
|
||||||
condition,
|
|
||||||
update,
|
|
||||||
body,
|
|
||||||
} => {
|
|
||||||
cg.add_indentedln("{");
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
init.to_rust(cg);
|
|
||||||
|
|
||||||
cg.add_indentedln(&format!("while {}", condition.get_rust()));
|
|
||||||
|
|
||||||
cg.add_indentedln("{");
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
cg.ensure_brackets(body);
|
|
||||||
|
|
||||||
update.to_rust(cg);
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}");
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::For {
|
|
||||||
mutable,
|
|
||||||
pattern,
|
|
||||||
iterator,
|
|
||||||
body,
|
|
||||||
} => {
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"for {}{} in {}",
|
|
||||||
get_mutable(mutable),
|
|
||||||
pattern.get_rust(),
|
|
||||||
iterator.get_rust()
|
|
||||||
));
|
|
||||||
cg.ensure_brackets(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::Return(expr) => {
|
|
||||||
let val = expr.map(|e| e.get_rust()).unwrap_or_default();
|
|
||||||
cg.add_indentedln(&format!("return {}", val));
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::Break => cg.add_indentedln("break"),
|
|
||||||
Statement::Continue => cg.add_indentedln("continue"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToRust for FunctionDecl {
|
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
|
||||||
let params_str = self
|
|
||||||
.params
|
|
||||||
.0
|
|
||||||
.into_iter()
|
|
||||||
.map(VarDecl::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ");
|
|
||||||
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"{}fn {}{}({}) -> {}",
|
|
||||||
self.visibility.get_rust(),
|
|
||||||
self.name.get_rust(),
|
|
||||||
self.generics.get_rust(),
|
|
||||||
params_str,
|
|
||||||
self.return_type.get_rust()
|
|
||||||
));
|
|
||||||
if let Some(body) = self.body {
|
|
||||||
cg.add_indentedln("{\n");
|
|
||||||
cg.indent += 1;
|
|
||||||
body.to_rust(cg);
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}\n");
|
|
||||||
} else {
|
|
||||||
cg.add(";");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToRust for ImplDecl {
|
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
|
||||||
if let Some(trait_) = self.trait_ {
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"impl{} {} for {} {{",
|
|
||||||
self.generics.get_rust(),
|
|
||||||
trait_.get_rust(),
|
|
||||||
self.target.get_rust()
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"impl{} {} {{",
|
|
||||||
self.generics.get_rust(),
|
|
||||||
self.target.get_rust()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
for method in self.methods {
|
|
||||||
method.to_rust(cg);
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for VarDecl {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
let ty = self
|
|
||||||
.type_
|
|
||||||
.map(|t| format!(": {}", t.get_rust()))
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{}{}{}",
|
|
||||||
get_mutable(self.mutable),
|
|
||||||
self.name.get_rust(),
|
|
||||||
ty
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Path {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
self.0
|
|
||||||
.into_iter()
|
|
||||||
.map(Identifier::get_rust)
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join("::")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for TypePostfix {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
TypePostfix::Ref => format!("&"),
|
|
||||||
TypePostfix::RefMut => format!("&mut "),
|
|
||||||
TypePostfix::RefLifetime(lifetime) => format!("&'{} ", lifetime.get_rust()),
|
|
||||||
TypePostfix::RefMutLifetime(lifetime) => format!("&'{} mut ", lifetime.get_rust()),
|
|
||||||
TypePostfix::Dyn => format!("dyn "),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Visibility {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Visibility::Public => "pub ".to_string(),
|
|
||||||
Visibility::PublicTarget(path) => format!("pub({}) ", path.get_rust()),
|
|
||||||
Visibility::Private => "".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Identifier {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
self.0.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for EnumItem {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Named(id) => id.get_rust(),
|
|
||||||
Self::Struct(id, s) => format!(
|
|
||||||
"{} {{{}}}",
|
|
||||||
id.get_rust(),
|
|
||||||
s.into_iter()
|
|
||||||
.map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust()))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
),
|
|
||||||
Self::Tuple(id, t) => format!(
|
|
||||||
"{} ({})",
|
|
||||||
id.get_rust(),
|
|
||||||
t.into_iter()
|
|
||||||
.map(TypeExpr::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Pattern {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Id(id) => id.get_rust(),
|
|
||||||
Self::Path(path) => path.get_rust(),
|
|
||||||
Self::Literal(lit) => lit.get_rust(),
|
|
||||||
Self::Struct(path, ids) => format!(
|
|
||||||
"{} {{{}}}",
|
|
||||||
path.get_rust(),
|
|
||||||
ids.into_iter()
|
|
||||||
.map(Identifier::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
),
|
|
||||||
Self::Tuple(ids) => format!(
|
|
||||||
"({})",
|
|
||||||
ids.into_iter()
|
|
||||||
.map(Identifier::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
),
|
|
||||||
Self::NamedTuple(path, ids) => {
|
|
||||||
format!(
|
|
||||||
"{} ({})",
|
|
||||||
path.get_rust(),
|
|
||||||
ids.into_iter()
|
|
||||||
.map(Identifier::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for GenericsDecl {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
if self.0.len() == 0 {
|
|
||||||
String::new()
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"<{}>",
|
|
||||||
self.0
|
|
||||||
.into_iter()
|
|
||||||
.map(|v| v.get_rust())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for GenericDecl {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
GenericDecl::Lifetime(name) => format!("'{}", name.get_rust()),
|
|
||||||
GenericDecl::Type(name, requirements) => {
|
|
||||||
name.get_rust()
|
|
||||||
+ &(if requirements.len() != 0 {
|
|
||||||
format!(
|
|
||||||
": {}",
|
|
||||||
requirements
|
|
||||||
.into_iter()
|
|
||||||
.map(TypeExpr::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("+")
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Generics {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
if self.0.len() == 0 {
|
|
||||||
String::new()
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"<{}>",
|
|
||||||
self.0
|
|
||||||
.into_iter()
|
|
||||||
.map(Generic::get_rust)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(", ")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for Generic {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Lifetime(name) => format!("'{}", name.get_rust()),
|
|
||||||
Self::Type(ty) => ty.get_rust(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetRust for FieldDecl {
|
|
||||||
fn get_rust(self) -> String {
|
|
||||||
format!(
|
|
||||||
"{}{}: {},",
|
|
||||||
self.visibility.get_rust(),
|
|
||||||
self.name.get_rust(),
|
|
||||||
self.type_.get_rust()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_static_type_path(path: Path) -> String {
|
|
||||||
let rust_path = path.get_rust();
|
|
||||||
|
|
||||||
if rust_path == "void" {
|
|
||||||
format!("()")
|
|
||||||
} else {
|
|
||||||
rust_path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_type_postfixes(postfixes: Vec<TypePostfix>) -> String {
|
|
||||||
postfixes
|
|
||||||
.into_iter()
|
|
||||||
.map(TypePostfix::get_rust)
|
|
||||||
.rev()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mutable(mutable: bool) -> String {
|
|
||||||
if mutable { "mut " } else { "" }.to_string()
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ use <std::env>;
|
|||||||
use <std::fs>;
|
use <std::fs>;
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod codegen;
|
|
||||||
pub mod transpiler;
|
pub mod transpiler;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|||||||
+1
-1
@@ -141,7 +141,7 @@ fn build_dir(root: &Path, base_src: &Path, current_dir: &Path, out_dir: &Path) {
|
|||||||
|
|
||||||
// semantic::walk_ast(semantic::scope::Scope::from_top(root, &ast), &mut ast);
|
// semantic::walk_ast(semantic::scope::Scope::from_top(root, &ast), &mut ast);
|
||||||
|
|
||||||
let mut gc = crate::codegen::RustCodegen::new();
|
let mut gc = mist_codegen::RustCodegen::new();
|
||||||
let output = gc.generate(ast);
|
let output = gc.generate(ast);
|
||||||
|
|
||||||
if let Err(e) = fs::write(&output_path, output) {
|
if let Err(e) = fs::write(&output_path, output) {
|
||||||
|
|||||||
Reference in New Issue
Block a user