468 lines
14 KiB
Rust
468 lines
14 KiB
Rust
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()
|
|
.map(|v| expr_pattern(&v.name))
|
|
.enumerate()
|
|
{
|
|
if i > 0 {
|
|
cg.add(", ");
|
|
}
|
|
|
|
ctx.expr_ensure_semicolon = false;
|
|
param.gen_rust(ctx, cg);
|
|
}
|
|
|
|
cg.addln(");");
|
|
|
|
cg.add_indentedln("this");
|
|
|
|
cg.indent -= 1;
|
|
cg.add_indentedln("}\n");
|
|
|
|
let mut constructor_params = vec![VarDecl {
|
|
name: Pattern::Path(false, Path(vec![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);
|
|
}
|
|
}
|
|
|
|
pub fn expr_pattern(pat: &Pattern) -> Expression {
|
|
match pat {
|
|
Pattern::Literal(v) => Expression::Literal(v.clone()),
|
|
Pattern::Path(_, v) => Expression::Path(v.clone().into()),
|
|
Pattern::Tuple(items) => Expression::Literal(Literal::Tuple(
|
|
items.iter().map(|v| expr_pattern(&v)).collect(),
|
|
)),
|
|
Pattern::NamedTuple(path, items) => Expression::Fix {
|
|
initial: Box::new(Expression::Path(path.clone().into())),
|
|
prefixes: Vec::new(),
|
|
postfixes: vec![Postfix::Call(
|
|
items.iter().map(|v| expr_pattern(&v)).collect(),
|
|
)],
|
|
},
|
|
Pattern::Struct(_, _) => unimplemented!(),
|
|
}
|
|
}
|
|
|
|
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,
|
|
inherits,
|
|
fields,
|
|
constructor,
|
|
items,
|
|
} => {
|
|
// Struct decl
|
|
cg.addln(&format!(
|
|
"{}struct {}{} {{",
|
|
visibility.get_rust(),
|
|
name.clone().get_rust(),
|
|
generics.clone().get_rust()
|
|
));
|
|
cg.indent += 1;
|
|
|
|
if let Some(inherits) = inherits {
|
|
cg.add_indented("pub _super: ");
|
|
cg.add(&inherits.get_rust());
|
|
cg.addln(",");
|
|
}
|
|
|
|
for field in fields.clone() {
|
|
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(_) => {}
|
|
}
|
|
}
|
|
|
|
if let Some(inherits) = inherits {
|
|
cg.add("impl std::ops::Deref for ");
|
|
cg.add(&name.get_rust());
|
|
|
|
cg.addln(" {");
|
|
cg.indent += 1;
|
|
|
|
cg.add_indented("type Target = ");
|
|
cg.add(&inherits.get_rust());
|
|
cg.addln(";");
|
|
|
|
cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}");
|
|
|
|
cg.indent -= 1;
|
|
cg.addln("}");
|
|
|
|
// Mut
|
|
|
|
cg.add("impl std::ops::DerefMut for ");
|
|
cg.add(&name.get_rust());
|
|
|
|
cg.addln(" {");
|
|
cg.indent += 1;
|
|
|
|
cg.add_indentedln(
|
|
"fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}",
|
|
);
|
|
|
|
cg.indent -= 1;
|
|
cg.addln("}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|