Generate internal enum types.
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
|
||||
use crate::error::Error;
|
||||
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::fmt::Write;
|
||||
|
||||
/// One "input symbol" for the decision tree that handles matching on
|
||||
/// 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> {
|
||||
use std::fmt::Write;
|
||||
let mut code = String::new();
|
||||
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)
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,15 @@ pub struct Pos {
|
||||
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)]
|
||||
pub enum Token<'a> {
|
||||
LParen,
|
||||
|
||||
@@ -50,7 +50,7 @@ pub enum Type {
|
||||
}
|
||||
|
||||
impl Type {
|
||||
fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str {
|
||||
pub fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str {
|
||||
match self {
|
||||
Self::Primitive(_, name) | Self::Enum { name, .. } => &tyenv.syms[name.index()],
|
||||
}
|
||||
@@ -60,6 +60,7 @@ impl Type {
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Variant {
|
||||
pub name: Sym,
|
||||
pub fullname: Sym,
|
||||
pub id: VariantId,
|
||||
pub fields: Vec<Field>,
|
||||
}
|
||||
@@ -209,9 +210,10 @@ impl TypeEnv {
|
||||
let mut variants = vec![];
|
||||
for variant in ty_variants {
|
||||
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());
|
||||
if variants.iter().any(|v: &Variant| v.name == var_name) {
|
||||
if variants.iter().any(|v: &Variant| v.name == name) {
|
||||
return Err(self.error(
|
||||
ty.pos,
|
||||
format!("Duplicate variant name in type: '{}'", variant.name.0),
|
||||
@@ -249,7 +251,8 @@ impl TypeEnv {
|
||||
});
|
||||
}
|
||||
variants.push(Variant {
|
||||
name: var_name,
|
||||
name,
|
||||
fullname,
|
||||
id,
|
||||
fields,
|
||||
});
|
||||
@@ -376,12 +379,12 @@ impl TermEnv {
|
||||
..
|
||||
} => {
|
||||
for variant in variants {
|
||||
if self.term_map.contains_key(&variant.name) {
|
||||
if self.term_map.contains_key(&variant.fullname) {
|
||||
return Err(tyenv.error(
|
||||
pos,
|
||||
format!(
|
||||
"Duplicate enum variant constructor: '{}'",
|
||||
tyenv.syms[variant.name.index()]
|
||||
tyenv.syms[variant.fullname.index()]
|
||||
),
|
||||
));
|
||||
}
|
||||
@@ -390,14 +393,14 @@ impl TermEnv {
|
||||
let ret_ty = id;
|
||||
self.terms.push(Term {
|
||||
id: tid,
|
||||
name: variant.name,
|
||||
name: variant.fullname,
|
||||
arg_tys,
|
||||
ret_ty,
|
||||
kind: TermKind::EnumVariant {
|
||||
variant: variant.id,
|
||||
},
|
||||
});
|
||||
self.term_map.insert(variant.name, tid);
|
||||
self.term_map.insert(variant.fullname, tid);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
Reference in New Issue
Block a user