more codegen WIP: start to generate functions
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::ir::{lower_rule, ExprSequence, PatternInst, PatternSequence};
|
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::collections::HashMap;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
@@ -511,21 +511,31 @@ impl<'a> Codegen<'a> {
|
|||||||
|
|
||||||
pub fn generate_rust(&self) -> Result<String, Error> {
|
pub fn generate_rust(&self) -> Result<String, Error> {
|
||||||
let mut code = String::new();
|
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!(
|
writeln!(
|
||||||
&mut code,
|
code,
|
||||||
"// Generated automatically from the instruction-selection DSL code in:",
|
"// Generated automatically from the instruction-selection DSL code in:",
|
||||||
)?;
|
)?;
|
||||||
for file in &self.typeenv.filenames {
|
for file in &self.typeenv.filenames {
|
||||||
writeln!(&mut code, "// - {}", file)?;
|
writeln!(code, "// - {}", file)?;
|
||||||
}
|
}
|
||||||
writeln!(
|
writeln!(
|
||||||
&mut code,
|
code,
|
||||||
"\nuse super::*; // Pulls in all external types and ctors/etors"
|
"\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> {
|
fn generate_internal_types(&self, code: &mut dyn Write) -> Result<(), Error> {
|
||||||
@@ -564,4 +574,84 @@ impl<'a> Codegen<'a> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
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