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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mist-codegen"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"mist-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mist-lang"
|
||||
version = "0.0.3-alpha4"
|
||||
dependencies = [
|
||||
"cargo_metadata",
|
||||
"mist-analyzer",
|
||||
"mist-codegen",
|
||||
"mist-parser",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -21,6 +21,7 @@ serde = { version = "1.0.228", features = ["serde_derive"] }
|
||||
serde_json = "1.0.149"
|
||||
mist-parser = { path = "./parser", version = "0.1.4"}
|
||||
mist-analyzer = { path = "./analyzer", version = "0.0.1"}
|
||||
mist-codegen = { path = "./codegen", version = "0.1.0"}
|
||||
cargo_metadata = "0.23.1"
|
||||
|
||||
[[bin]]
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ impl LanguageServer for Backend {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn completion(&self, params: CompletionParams) -> Result<Option<CompletionResponse>> {
|
||||
async fn completion(&self, _params: CompletionParams) -> Result<Option<CompletionResponse>> {
|
||||
self.client
|
||||
.log_message(MessageType::INFO, "getting completion")
|
||||
.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 {
|
||||
fmt::Result fmt(self*, Formatter<'_> mut* f) {
|
||||
match (self) {
|
||||
LogLevel::Info => {
|
||||
return write!(f, "[INFO]");
|
||||
}
|
||||
return match (self) {
|
||||
LogLevel::Info => write!(f, "[INFO]");
|
||||
|
||||
LogLevel::Warning => {
|
||||
return write!(f, "[WARN]");
|
||||
}
|
||||
LogLevel::Warning => write!(f, "[WARN]");
|
||||
|
||||
LogLevel::Error => {
|
||||
return write!(f, "[ERROR]");
|
||||
}
|
||||
LogLevel::Error => write!(f, "[ERROR]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ pub struct Task {
|
||||
}
|
||||
|
||||
pub Task create_task(str* name) {
|
||||
return Task {
|
||||
Task {
|
||||
name: name.to_string(),
|
||||
state: TaskState::Pending,
|
||||
executions: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ pub enum Statement {
|
||||
iterator: Expression,
|
||||
body: Box<Statement>,
|
||||
},
|
||||
Match(Expression, Vec<(Vec<Pattern>, Block)>),
|
||||
Match(Expression, Vec<(Vec<Pattern>, Expression)>),
|
||||
|
||||
Return(Option<Expression>),
|
||||
Break,
|
||||
|
||||
@@ -419,7 +419,7 @@ for_stmt = {
|
||||
pattern_list = { pattern ~ ("|" ~ pattern)* }
|
||||
|
||||
match_item = {
|
||||
pattern_list ~ "=>" ~ block
|
||||
pattern_list ~ "=>" ~ statement
|
||||
}
|
||||
|
||||
match_stmt = {
|
||||
|
||||
@@ -95,7 +95,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
|
||||
let mut match_inner = match_itms.into_inner();
|
||||
Ok((
|
||||
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<_>>>(),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
pub mod builder;
|
||||
pub mod codegen;
|
||||
pub mod transpiler;
|
||||
|
||||
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>;
|
||||
|
||||
pub mod builder;
|
||||
pub mod codegen;
|
||||
pub mod transpiler;
|
||||
|
||||
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);
|
||||
|
||||
let mut gc = crate::codegen::RustCodegen::new();
|
||||
let mut gc = mist_codegen::RustCodegen::new();
|
||||
let output = gc.generate(ast);
|
||||
|
||||
if let Err(e) = fs::write(&output_path, output) {
|
||||
|
||||
Reference in New Issue
Block a user