Generate internal enum types.
This commit is contained in:
@@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|||||||
Reference in New Issue
Block a user