chore: add FreshNameGenerator

This commit is contained in:
Shunsuke Shibayama 2023-06-10 15:31:26 +09:00
parent 46cf002a71
commit d6f30924f1
12 changed files with 84 additions and 62 deletions

View file

@ -1,15 +1,33 @@
use std::sync::atomic::AtomicUsize;
static VAR_ID: AtomicUsize = AtomicUsize::new(0);
use crate::Str;
pub fn fresh_varname() -> String {
VAR_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
let i = VAR_ID.load(std::sync::atomic::Ordering::SeqCst);
format!("%v{i}")
#[derive(Debug, Default)]
pub struct FreshNameGenerator {
id: AtomicUsize,
/// To avoid conflicts with variable names generated in another phase
prefix: &'static str,
}
pub fn fresh_param_name() -> String {
VAR_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
let i = VAR_ID.load(std::sync::atomic::Ordering::SeqCst);
format!("%p{i}")
impl FreshNameGenerator {
pub const fn new(prefix: &'static str) -> Self {
Self {
id: AtomicUsize::new(0),
prefix,
}
}
pub fn fresh_varname(&self) -> Str {
self.id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
let i = self.id.load(std::sync::atomic::Ordering::SeqCst);
Str::from(format!("%v_{}_{i}", self.prefix))
}
pub fn fresh_param_name(&self) -> Str {
self.id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
let i = self.id.load(std::sync::atomic::Ordering::SeqCst);
Str::from(format!("%p_{}_{i}", self.prefix))
}
}
pub static FRESH_GEN: FreshNameGenerator = FreshNameGenerator::new("global");

View file

@ -10,6 +10,7 @@ use erg_common::cache::CacheSet;
use erg_common::config::ErgConfig;
use erg_common::env::erg_std_path;
use erg_common::error::{ErrorDisplay, Location};
use erg_common::fresh::FreshNameGenerator;
use erg_common::io::Input;
use erg_common::opcode::{CommonOpcode, CompareOp};
use erg_common::opcode308::Opcode308;
@ -39,7 +40,6 @@ use crate::hir::{
use crate::ty::value::ValueObj;
use crate::ty::{HasType, Type, TypeCode, TypePair, VisibilityModifier};
use crate::varinfo::VarInfo;
use erg_common::fresh::fresh_varname;
use AccessKind::*;
use Type::*;
@ -172,6 +172,7 @@ pub struct PyCodeGenerator {
abc_loaded: bool,
unit_size: usize,
units: PyCodeGenStack,
fresh_gen: FreshNameGenerator,
}
impl PyCodeGenerator {
@ -190,6 +191,7 @@ impl PyCodeGenerator {
abc_loaded: false,
unit_size: 0,
units: PyCodeGenStack::empty(),
fresh_gen: FreshNameGenerator::new("codegen"),
}
}
@ -1997,7 +1999,7 @@ impl PyCodeGenerator {
self.stack_inc_n(2);
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
self.emit_with_block(lambda.body, params);
let stash = Identifier::private_with_line(Str::from(fresh_varname()), lambda_line);
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
self.emit_store_instr(stash.clone(), Name);
self.emit_load_const(ValueObj::None);
self.emit_load_const(ValueObj::None);
@ -2046,7 +2048,7 @@ impl PyCodeGenerator {
self.stack_inc_n(2);
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
self.emit_with_block(lambda.body, params);
let stash = Identifier::private_with_line(Str::from(fresh_varname()), lambda_line);
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
self.emit_store_instr(stash.clone(), Name);
self.write_instr(POP_BLOCK);
self.write_arg(0);
@ -2099,7 +2101,7 @@ impl PyCodeGenerator {
// self.stack_inc_n(2);
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
self.emit_with_block(lambda.body, params);
let stash = Identifier::private_with_line(Str::from(fresh_varname()), lambda_line);
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
self.emit_store_instr(stash.clone(), Name);
self.write_instr(POP_BLOCK);
self.write_arg(0);
@ -2849,9 +2851,9 @@ impl PyCodeGenerator {
let (param_name, params) = if let Some(new_first_param) = new_first_param {
let param_name = new_first_param
.name()
.map(|s| s.to_string())
.unwrap_or_else(fresh_varname);
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
.cloned()
.unwrap_or_else(|| self.fresh_gen.fresh_varname());
let param = VarName::from_str_and_line(param_name.clone(), line);
let raw =
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
let vi = VarInfo::nd_parameter(
@ -2932,9 +2934,9 @@ impl PyCodeGenerator {
if let Some(new_first_param) = ident.vi.t.non_default_params().unwrap().first() {
let param_name = new_first_param
.name()
.map(|s| s.to_string())
.unwrap_or_else(fresh_varname);
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
.cloned()
.unwrap_or_else(|| self.fresh_gen.fresh_varname());
let param = VarName::from_str_and_line(param_name.clone(), line);
let vi = VarInfo::nd_parameter(
new_first_param.typ().clone(),
ident.vi.def_loc.clone(),
@ -2947,8 +2949,7 @@ impl PyCodeGenerator {
let bounds = TypeBoundSpecs::empty();
let sig = SubrSignature::new(ident, bounds, params, sig.t_spec_with_op().cloned());
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
Str::from(param_name),
line,
param_name, line,
)));
let call = class_new.call_expr(Args::single(arg));
let block = Block::new(vec![call]);

View file

@ -1,7 +1,7 @@
use erg_common::consts::{ERG_MODE, PYTHON_MODE};
use erg_common::fresh::FRESH_GEN;
#[allow(unused_imports)]
use erg_common::log;
use erg_common::Str as StrStruct;
use crate::ty::constructors::*;
use crate::ty::typaram::TyParam;
@ -1233,7 +1233,7 @@ impl Context {
mut_type,
);
array_.register_trait(arr_t.clone(), array_mutizable);
let var = StrStruct::from(fresh_varname());
let var = FRESH_GEN.fresh_varname();
let input = refinement(
var.clone(),
Nat,

View file

@ -16,7 +16,6 @@ use erg_common::config::ErgConfig;
use erg_common::consts::{DEBUG_MODE, ERG_MODE, PYTHON_MODE};
use erg_common::dict;
use erg_common::error::Location;
use erg_common::fresh::fresh_varname;
#[allow(unused_imports)]
use erg_common::log;
use erg_common::Str;

View file

@ -2,7 +2,7 @@
use std::mem;
use std::option::Option;
use erg_common::fresh::fresh_varname;
use erg_common::fresh::FRESH_GEN;
use erg_common::traits::Locational;
use erg_common::Str;
#[allow(unused_imports)]
@ -576,7 +576,7 @@ impl Context {
match target {
TyParam::FreeVar(fv) => {
if let Ok(evaled) = self.eval_tp(value.clone()) {
let pred = Predicate::ge(fresh_varname().into(), evaled);
let pred = Predicate::ge(FRESH_GEN.fresh_varname(), evaled);
let new_type = self.type_from_pred(pred);
let new_constr = Constraint::new_type_of(Type::from(new_type));
fv.update_constraint(new_constr, false);

View file

@ -2,6 +2,7 @@ use std::mem;
use std::path::{Path, PathBuf};
use erg_common::config::ErgConfig;
use erg_common::fresh::FreshNameGenerator;
use erg_common::pathutil::squash;
use erg_common::traits::Locational;
use erg_common::Str;
@ -13,7 +14,6 @@ use erg_parser::token::{Token, TokenKind, DOT, EQUAL};
use crate::ty::typaram::TyParam;
use crate::ty::value::ValueObj;
use crate::ty::HasType;
use erg_common::fresh::fresh_varname;
use crate::hir::*;
use crate::module::SharedModuleCache;
@ -23,11 +23,16 @@ use crate::module::SharedModuleCache;
pub struct HIRLinker<'a> {
cfg: &'a ErgConfig,
mod_cache: &'a SharedModuleCache,
fresh_gen: FreshNameGenerator,
}
impl<'a> HIRLinker<'a> {
pub fn new(cfg: &'a ErgConfig, mod_cache: &'a SharedModuleCache) -> Self {
Self { cfg, mod_cache }
Self {
cfg,
mod_cache,
fresh_gen: FreshNameGenerator::new("hir_linker"),
}
}
pub fn link(&self, mut main: HIR) -> HIR {
@ -351,7 +356,7 @@ impl<'a> HIRLinker<'a> {
Expr::Accessor(Accessor::private_with_line(Str::ever("#ModuleType"), line));
let args = Args::single(PosArg::new(mod_name.clone()));
let block = Block::new(vec![module_type.call_expr(args)]);
let tmp = Identifier::private_with_line(Str::from(fresh_varname()), line);
let tmp = Identifier::private_with_line(self.fresh_gen.fresh_varname(), line);
let mod_def = Expr::Def(Def::new(
Signature::Var(VarSignature::new(tmp.clone(), None)),
DefBody::new(EQUAL, block, DefId(0)),

View file

@ -8,7 +8,7 @@ use erg_common::consts::{ERG_MODE, PYTHON_MODE};
use erg_common::dict;
use erg_common::dict::Dict;
use erg_common::error::{Location, MultiErrorDisplay};
use erg_common::fresh::fresh_varname;
use erg_common::fresh::FreshNameGenerator;
use erg_common::set;
use erg_common::set::Set;
use erg_common::traits::{ExitStatus, Locational, NoTypeDisplay, Runnable, Stream};
@ -75,6 +75,7 @@ pub struct ASTLowerer {
pub(crate) module: ModuleContext,
pub(crate) errs: LowerErrors,
pub(crate) warns: LowerWarnings,
fresh_gen: FreshNameGenerator,
}
impl Default for ASTLowerer {
@ -177,6 +178,7 @@ impl ASTLowerer {
cfg,
errs: LowerErrors::empty(),
warns: LowerWarnings::empty(),
fresh_gen: FreshNameGenerator::new("lower"),
}
}
@ -186,6 +188,7 @@ impl ASTLowerer {
module,
errs: LowerErrors::empty(),
warns: LowerWarnings::empty(),
fresh_gen: FreshNameGenerator::new("lower"),
}
}
@ -754,7 +757,7 @@ impl ASTLowerer {
TokenKind::Gre => {
let value = self.module.context.expr_to_value(rhs.clone())?;
let t = value.class();
let varname = Str::from(fresh_varname());
let varname = self.fresh_gen.fresh_varname();
let pred = Predicate::gt(varname.clone(), TyParam::value(value));
let refine = refinement(varname, t, pred);
Some(guard(var, refine))
@ -762,7 +765,7 @@ impl ASTLowerer {
TokenKind::GreEq => {
let value = self.module.context.expr_to_value(rhs.clone())?;
let t = value.class();
let varname = Str::from(fresh_varname());
let varname = self.fresh_gen.fresh_varname();
let pred = Predicate::ge(varname.clone(), TyParam::value(value));
let refine = refinement(varname, t, pred);
Some(guard(var, refine))
@ -770,7 +773,7 @@ impl ASTLowerer {
TokenKind::Less => {
let value = self.module.context.expr_to_value(rhs.clone())?;
let t = value.class();
let varname = Str::from(fresh_varname());
let varname = self.fresh_gen.fresh_varname();
let pred = Predicate::lt(varname.clone(), TyParam::value(value));
let refine = refinement(varname, t, pred);
Some(guard(var, refine))
@ -778,7 +781,7 @@ impl ASTLowerer {
TokenKind::LessEq => {
let value = self.module.context.expr_to_value(rhs.clone())?;
let t = value.class();
let varname = Str::from(fresh_varname());
let varname = self.fresh_gen.fresh_varname();
let pred = Predicate::le(varname.clone(), TyParam::value(value));
let refine = refinement(varname, t, pred);
Some(guard(var, refine))

View file

@ -1,5 +1,7 @@
use std::convert::TryInto;
use erg_common::fresh::FRESH_GEN;
use crate::ty::*;
#[inline]
@ -92,7 +94,7 @@ pub fn v_enum(s: Set<ValueObj>) -> Type {
if !is_homogeneous(&s) {
panic!("{s} is not homogeneous");
}
let name = Str::from(fresh_varname());
let name = FRESH_GEN.fresh_varname();
let t = inner_class(&s);
let preds = s
.into_iter()
@ -103,7 +105,7 @@ pub fn v_enum(s: Set<ValueObj>) -> Type {
}
pub fn tp_enum(ty: Type, s: Set<TyParam>) -> Type {
let name = Str::from(fresh_varname());
let name = FRESH_GEN.fresh_varname();
let preds = s
.into_iter()
.map(|tp| Predicate::eq(name.clone(), tp))
@ -113,7 +115,7 @@ pub fn tp_enum(ty: Type, s: Set<TyParam>) -> Type {
}
pub fn singleton(ty: Type, tp: TyParam) -> Type {
let name = Str::from(fresh_varname());
let name = FRESH_GEN.fresh_varname();
let preds = Predicate::eq(name.clone(), tp);
let refine = RefinementType::new(name, ty, preds);
Type::Refinement(refine)
@ -129,7 +131,7 @@ where
{
let l = l.try_into().unwrap_or_else(|l| todo!("{l:?}"));
let r = r.try_into().unwrap_or_else(|r| todo!("{r:?}"));
let name = Str::from(fresh_varname());
let name = FRESH_GEN.fresh_varname();
let pred = match op {
IntervalOp::LeftOpen if l == TyParam::value(NegInf) => Predicate::le(name.clone(), r),
// l<..r => {I: classof(l) | I >= l+ε and I <= r}

View file

@ -20,7 +20,7 @@ use std::path::PathBuf;
use erg_common::dict::Dict;
use erg_common::error::Location;
use erg_common::fresh::fresh_varname;
use erg_common::fresh::FRESH_GEN;
#[allow(unused_imports)]
use erg_common::log;
use erg_common::set::Set;
@ -2296,7 +2296,7 @@ impl Type {
match self {
Type::FreeVar(fv) if fv.is_linked() => fv.crack().clone().into_refinement(),
Type::Nat => {
let var = Str::from(fresh_varname());
let var = FRESH_GEN.fresh_varname();
RefinementType::new(
var.clone(),
Type::Int,
@ -2304,7 +2304,7 @@ impl Type {
)
}
Type::Bool => {
let var = Str::from(fresh_varname());
let var = FRESH_GEN.fresh_varname();
RefinementType::new(
var.clone(),
Type::Int,

View file

@ -9,7 +9,7 @@ use std::sync::Arc;
use erg_common::dict::Dict;
use erg_common::error::{ErrorCore, ErrorKind, Location};
use erg_common::fresh::fresh_varname;
use erg_common::fresh::FRESH_GEN;
use erg_common::io::Input;
use erg_common::python_util::PythonVersion;
use erg_common::serialize::*;
@ -714,7 +714,7 @@ impl HasType for ValueObj {
/// その要素だけの集合型を返す、クラスが欲しい場合は.classで
#[inline]
fn t(&self) -> Type {
let name = Str::from(fresh_varname());
let name = FRESH_GEN.fresh_varname();
let pred = Predicate::eq(name.clone(), TyParam::Value(self.clone()));
refinement(name, self.class(), pred)
}

View file

@ -3,8 +3,8 @@
//! Syntax sugarをdesugarする
//! e.g. Literal parameters, Multi assignment
//! 型チェックなどによる検証は行わない
use std::sync::atomic::AtomicUsize;
use erg_common::fresh::FreshNameGenerator;
use erg_common::traits::{Locational, Stream};
use erg_common::Str;
use erg_common::{enum_unwrap, get_hash, log, set};
@ -32,24 +32,17 @@ enum BufIndex<'i> {
#[derive(Debug)]
pub struct Desugarer {
// _desugared: Set<Str>,
var_id: AtomicUsize,
var_gen: FreshNameGenerator,
}
impl Desugarer {
pub fn new() -> Desugarer {
Self {
// _desugared: Set::default(),
var_id: AtomicUsize::new(0),
var_gen: FreshNameGenerator::new("desugar"),
}
}
fn fresh_varname(&self) -> String {
let i = self.var_id.load(std::sync::atomic::Ordering::SeqCst);
self.var_id
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
format!("%v{i}")
}
pub fn desugar(&mut self, module: Module) -> Module {
log!(info "the desugaring process has started.");
let module = self.desugar_multiple_pattern_def(module);
@ -517,10 +510,10 @@ impl Desugarer {
let sig = LambdaSignature::new(params, return_t_spec.clone(), sig.bounds);
let second_branch = Lambda::new(sig, op, def.body.block, def.body.id);
let first_arg = if params_len == 1 {
Expr::dummy_local(&self.fresh_varname())
Expr::dummy_local(&self.var_gen.fresh_varname())
} else {
let args =
(0..params_len).map(|_| PosArg::new(Expr::dummy_local(&self.fresh_varname())));
let args = (0..params_len)
.map(|_| PosArg::new(Expr::dummy_local(&self.var_gen.fresh_varname())));
Expr::Tuple(Tuple::Normal(NormalTuple::new(Args::pos_only(
args.collect(),
None,
@ -547,8 +540,8 @@ impl Desugarer {
&mut self,
line: u32,
t_spec: Option<TypeSpecWithOp>,
) -> (String, Signature) {
let buf_name = self.fresh_varname();
) -> (Str, Signature) {
let buf_name = self.var_gen.fresh_varname();
let buf_sig = Signature::Var(VarSignature::new(
VarPattern::Ident(Identifier::private_with_line(Str::rc(&buf_name), line)),
t_spec,
@ -556,8 +549,8 @@ impl Desugarer {
(buf_name, buf_sig)
}
fn gen_buf_nd_param(&mut self, line: u32) -> (String, ParamPattern) {
let buf_name = self.fresh_varname();
fn gen_buf_nd_param(&mut self, line: u32) -> (Str, ParamPattern) {
let buf_name = self.var_gen.fresh_varname();
let pat = ParamPattern::VarName(VarName::from_str_and_line(Str::rc(&buf_name), line));
(buf_name, pat)
}

View file

@ -1,5 +1,6 @@
//! Implements `Parser` for Erg. `Parser` parses the source code to generate `AST`,
//! and performs type checking and other optimizations if necessary.
//! Implements `Parser` for Erg. `Parser` parses the source code to generate `AST`.
//! The generated `AST`s are guaranteed to be identical if the source code is identical.
//! However, identical `AST`s may be generated even if the source code is (a bit) different.
#![allow(clippy::large_enum_variant)]
extern crate erg_common;