more codegen WIP: start to generate functions
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::ir::{lower_rule, ExprSequence, PatternInst, PatternSequence};
|
||||
use crate::sema::{RuleId, TermEnv, TermId, Type, TypeEnv};
|
||||
use crate::sema::{RuleId, TermEnv, TermId, TermKind, Type, TypeEnv, TypeId};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Write;
|
||||
|
||||
@@ -511,21 +511,31 @@ impl<'a> Codegen<'a> {
|
||||
|
||||
pub fn generate_rust(&self) -> Result<String, Error> {
|
||||
let mut code = String::new();
|
||||
writeln!(&mut code, "// GENERATED BY ISLE. DO NOT EDIT!")?;
|
||||
writeln!(&mut code, "//")?;
|
||||
|
||||
self.generate_header(&mut code)?;
|
||||
self.generate_internal_types(&mut code)?;
|
||||
self.generate_internal_term_constructors(&mut code)?;
|
||||
self.generate_internal_term_extractors(&mut code)?;
|
||||
|
||||
Ok(code)
|
||||
}
|
||||
|
||||
fn generate_header(&self, code: &mut dyn Write) -> Result<(), Error> {
|
||||
writeln!(code, "// GENERATED BY ISLE. DO NOT EDIT!")?;
|
||||
writeln!(code, "//")?;
|
||||
writeln!(
|
||||
&mut code,
|
||||
code,
|
||||
"// Generated automatically from the instruction-selection DSL code in:",
|
||||
)?;
|
||||
for file in &self.typeenv.filenames {
|
||||
writeln!(&mut code, "// - {}", file)?;
|
||||
writeln!(code, "// - {}", file)?;
|
||||
}
|
||||
writeln!(
|
||||
&mut code,
|
||||
code,
|
||||
"\nuse super::*; // Pulls in all external types and ctors/etors"
|
||||
)?;
|
||||
self.generate_internal_types(&mut code)?;
|
||||
Ok(code)
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_internal_types(&self, code: &mut dyn Write) -> Result<(), Error> {
|
||||
@@ -564,4 +574,84 @@ impl<'a> Codegen<'a> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn constructor_name(&self, term: TermId) -> String {
|
||||
let termdata = &self.termenv.terms[term.index()];
|
||||
match &termdata.kind {
|
||||
&TermKind::EnumVariant { .. } => panic!("using enum variant as constructor"),
|
||||
&TermKind::Regular {
|
||||
constructor: Some(sym),
|
||||
..
|
||||
} => self.typeenv.syms[sym.index()].clone(),
|
||||
&TermKind::Regular {
|
||||
constructor: None, ..
|
||||
} => {
|
||||
format!("constructor_{}", self.typeenv.syms[termdata.name.index()])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn type_name(&self, typeid: TypeId, by_ref: bool) -> String {
|
||||
match &self.typeenv.types[typeid.index()] {
|
||||
&Type::Primitive(_, sym) => self.typeenv.syms[sym.index()].clone(),
|
||||
&Type::Enum { name, .. } => {
|
||||
let r = if by_ref { "&" } else { "" };
|
||||
format!("{}{}", r, self.typeenv.syms[name.index()])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_internal_term_constructors(&self, code: &mut dyn Write) -> Result<(), Error> {
|
||||
for (&termid, trie) in &self.functions_by_input {
|
||||
let termdata = &self.termenv.terms[termid.index()];
|
||||
// Skip terms that are enum variants or that have external constructors.
|
||||
match &termdata.kind {
|
||||
&TermKind::EnumVariant { .. } => continue,
|
||||
&TermKind::Regular { constructor, .. } if constructor.is_some() => continue,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Get the name of the term and build up the signature.
|
||||
let func_name = self.constructor_name(termid);
|
||||
let args = termdata
|
||||
.arg_tys
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &arg_ty)| {
|
||||
format!("arg{}: {}", i, self.type_name(arg_ty, /* by_ref = */ true))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
writeln!(
|
||||
code,
|
||||
"\n// Generated as internal constructor for term {}.",
|
||||
self.typeenv.syms[termdata.name.index()],
|
||||
)?;
|
||||
writeln!(
|
||||
code,
|
||||
"fn {}<C>(ctx: &mut C, {}) -> Option<{}> {{",
|
||||
func_name,
|
||||
args.join(", "),
|
||||
self.type_name(termdata.ret_ty, /* by_ref = */ false)
|
||||
)?;
|
||||
|
||||
self.generate_body(code, termid, trie)?;
|
||||
|
||||
writeln!(code, "}}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_internal_term_extractors(&self, _code: &mut dyn Write) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_body(
|
||||
&self,
|
||||
_code: &mut dyn Write,
|
||||
_termid: TermId,
|
||||
_trie: &TrieNode,
|
||||
) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user