Generate internal enum types.

This commit is contained in:
Chris Fallin
2021-09-04 12:59:19 -07:00
parent 5aa72bc060
commit e9a57d854d
3 changed files with 63 additions and 10 deletions

View File

@@ -2,8 +2,9 @@
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, TypeEnv}; use crate::sema::{RuleId, TermEnv, TermId, Type, TypeEnv};
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Write;
/// One "input symbol" for the decision tree that handles matching on /// One "input symbol" for the decision tree that handles matching on
/// a term. Each symbol represents one step: we either run a match op, /// a term. Each symbol represents one step: we either run a match op,
@@ -509,9 +510,49 @@ impl<'a> Codegen<'a> {
} }
pub fn generate_rust(&self) -> Result<String, Error> { pub fn generate_rust(&self) -> Result<String, Error> {
use std::fmt::Write;
let mut code = String::new(); let mut code = String::new();
writeln!(&mut code, "// GENERATED BY ISLE. DO NOT EDIT!")?; writeln!(&mut code, "// GENERATED BY ISLE. DO NOT EDIT!")?;
writeln!(
&mut code,
"use super::*; // Pulls in all external types and ctors/etors"
)?;
self.generate_internal_types(&mut code)?;
Ok(code) Ok(code)
} }
fn generate_internal_types(&self, code: &mut dyn Write) -> Result<(), Error> {
for ty in &self.typeenv.types {
match ty {
&Type::Enum {
name,
is_extern,
ref variants,
pos,
..
} if !is_extern => {
let name = &self.typeenv.syms[name.index()];
writeln!(
code,
"\n// Internal type {}: defined at {}.",
name,
pos.pretty_print_line(&self.typeenv.filename)
)?;
writeln!(code, "enum {} {{", name)?;
for variant in variants {
let name = &self.typeenv.syms[variant.name.index()];
writeln!(code, " {} {{", name)?;
for field in &variant.fields {
let name = &self.typeenv.syms[field.name.index()];
let ty_name = self.typeenv.types[field.ty.index()].name(&self.typeenv);
writeln!(code, " {}: {},", name, ty_name)?;
}
writeln!(code, " }}")?;
}
writeln!(code, "}}")?;
}
_ => {}
}
}
Ok(())
}
} }

View File

@@ -14,6 +14,15 @@ pub struct Pos {
pub col: usize, pub col: usize,
} }
impl Pos {
pub fn pretty_print(&self, filename: &str) -> String {
format!("{}:{}:{}", filename, self.line, self.col)
}
pub fn pretty_print_line(&self, filename: &str) -> String {
format!("{} line {}", filename, self.line)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Token<'a> { pub enum Token<'a> {
LParen, LParen,

View File

@@ -50,7 +50,7 @@ pub enum Type {
} }
impl Type { impl Type {
fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str { pub fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str {
match self { match self {
Self::Primitive(_, name) | Self::Enum { name, .. } => &tyenv.syms[name.index()], Self::Primitive(_, name) | Self::Enum { name, .. } => &tyenv.syms[name.index()],
} }
@@ -60,6 +60,7 @@ impl Type {
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct Variant { pub struct Variant {
pub name: Sym, pub name: Sym,
pub fullname: Sym,
pub id: VariantId, pub id: VariantId,
pub fields: Vec<Field>, pub fields: Vec<Field>,
} }
@@ -209,9 +210,10 @@ impl TypeEnv {
let mut variants = vec![]; let mut variants = vec![];
for variant in ty_variants { for variant in ty_variants {
let combined_ident = ast::Ident(format!("{}.{}", ty.name.0, variant.name.0)); let combined_ident = ast::Ident(format!("{}.{}", ty.name.0, variant.name.0));
let var_name = self.intern_mut(&combined_ident); let fullname = self.intern_mut(&combined_ident);
let name = self.intern_mut(&variant.name);
let id = VariantId(variants.len()); let id = VariantId(variants.len());
if variants.iter().any(|v: &Variant| v.name == var_name) { if variants.iter().any(|v: &Variant| v.name == name) {
return Err(self.error( return Err(self.error(
ty.pos, ty.pos,
format!("Duplicate variant name in type: '{}'", variant.name.0), format!("Duplicate variant name in type: '{}'", variant.name.0),
@@ -249,7 +251,8 @@ impl TypeEnv {
}); });
} }
variants.push(Variant { variants.push(Variant {
name: var_name, name,
fullname,
id, id,
fields, fields,
}); });
@@ -376,12 +379,12 @@ impl TermEnv {
.. ..
} => { } => {
for variant in variants { for variant in variants {
if self.term_map.contains_key(&variant.name) { if self.term_map.contains_key(&variant.fullname) {
return Err(tyenv.error( return Err(tyenv.error(
pos, pos,
format!( format!(
"Duplicate enum variant constructor: '{}'", "Duplicate enum variant constructor: '{}'",
tyenv.syms[variant.name.index()] tyenv.syms[variant.fullname.index()]
), ),
)); ));
} }
@@ -390,14 +393,14 @@ impl TermEnv {
let ret_ty = id; let ret_ty = id;
self.terms.push(Term { self.terms.push(Term {
id: tid, id: tid,
name: variant.name, name: variant.fullname,
arg_tys, arg_tys,
ret_ty, ret_ty,
kind: TermKind::EnumVariant { kind: TermKind::EnumVariant {
variant: variant.id, variant: variant.id,
}, },
}); });
self.term_map.insert(variant.name, tid); self.term_map.insert(variant.fullname, tid);
} }
} }
_ => {} _ => {}