more codegen WIP: start to generate functions

This commit is contained in:
Chris Fallin
2021-09-04 14:23:47 -07:00
parent 638c9edd01
commit 8c727b175a

View File

@@ -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(())
}
}