erg_compiler/
transpile.rs

1use std::fs::File;
2use std::io::Write;
3
4use erg_common::error::{ErrorDisplay, ErrorKind, MultiErrorDisplay};
5use erg_common::log;
6use erg_common::set::Set as HashSet;
7use erg_common::traits::BlockKind;
8use erg_common::traits::{ExitStatus, Locational, New, Runnable, Stream};
9use erg_common::Str;
10use erg_common::{config::ErgConfig, dict};
11use erg_common::{config::TranspileTarget, dict::Dict as HashMap};
12
13use erg_parser::ast::{ParamPattern, TypeSpec, VarName, AST};
14use erg_parser::token::TokenKind;
15use erg_parser::ParserRunner;
16
17use crate::artifact::{
18    BuildRunnable, Buildable, CompleteArtifact, ErrorArtifact, IncompleteArtifact,
19};
20use crate::build_package::PackageBuilder;
21use crate::codegen::PyCodeGenerator;
22use crate::context::{Context, ContextProvider, ModuleContext};
23use crate::desugar_hir::HIRDesugarer;
24use crate::error::{CompileError, CompileErrors, CompileResult};
25use crate::hir::{
26    Accessor, Args, BinOp, Block, Call, ClassDef, Def, Dict, Expr, Identifier, Lambda, List,
27    Literal, Params, PatchDef, ReDef, Record, Set, Signature, Tuple, UnaryOp, HIR,
28};
29use crate::link_hir::HIRLinker;
30use crate::module::SharedCompilerResource;
31use crate::ty::typaram::OpKind;
32use crate::ty::value::ValueObj;
33use crate::ty::{Field, HasType, Type, VisibilityModifier};
34use crate::varinfo::{AbsLocation, VarInfo};
35
36/// patch method -> function
37/// patch attr -> variable
38fn debind(ident: &Identifier) -> Option<Str> {
39    match ident.vi.py_name.as_ref().map(|s| &s[..]) {
40        Some(name) if name.starts_with("Function::") => {
41            Some(Str::from(name.replace("Function::", "")))
42        }
43        Some(patch_method) if patch_method.contains("::") || patch_method.contains('.') => {
44            if ident.vis().is_private() {
45                Some(Str::from(format!("{patch_method}__")))
46            } else {
47                Some(Str::rc(patch_method))
48            }
49        }
50        _ => None,
51    }
52}
53
54fn demangle(name: &str) -> String {
55    name.trim_start_matches("::<module>")
56        .replace("::", "__")
57        .replace('.', "_")
58}
59
60// TODO:
61fn replace_non_symbolic(name: &str) -> String {
62    name.replace('\'', "__single_quote__")
63        .replace(' ', "__space__")
64        .replace('+', "__plus__")
65        .replace('-', "__minus__")
66        .replace('*', "__star__")
67        .replace('/', "__slash__")
68        .replace('%', "__percent__")
69        .replace('!', "__erg_proc__")
70        .replace('$', "erg_shared__")
71}
72
73pub enum Enclosure {
74    /// ()
75    Paren,
76    /// []
77    Bracket,
78    /// {}
79    Brace,
80    None,
81}
82
83impl Enclosure {
84    pub const fn open(&self) -> char {
85        match self {
86            Enclosure::Paren => '(',
87            Enclosure::Bracket => '[',
88            Enclosure::Brace => '{',
89            Enclosure::None => ' ',
90        }
91    }
92
93    pub const fn close(&self) -> char {
94        match self {
95            Enclosure::Paren => ')',
96            Enclosure::Bracket => ']',
97            Enclosure::Brace => '}',
98            Enclosure::None => ' ',
99        }
100    }
101}
102
103#[derive(Debug)]
104pub enum LastLineOperation {
105    Discard,
106    Return,
107    StoreTmp(Str),
108}
109
110use LastLineOperation::*;
111
112impl LastLineOperation {
113    pub const fn is_return(&self) -> bool {
114        matches!(self, LastLineOperation::Return)
115    }
116
117    pub const fn is_store_tmp(&self) -> bool {
118        matches!(self, LastLineOperation::StoreTmp(_))
119    }
120}
121
122#[derive(Debug)]
123pub enum TranspiledFile {
124    PyScript(PyScript),
125    Json(Json),
126}
127
128impl TranspiledFile {
129    pub fn code(&self) -> &str {
130        match self {
131            Self::PyScript(script) => &script.code,
132            Self::Json(json) => &json.code,
133        }
134    }
135
136    pub fn into_code(self) -> String {
137        match self {
138            Self::PyScript(script) => script.code,
139            Self::Json(json) => json.code,
140        }
141    }
142
143    pub fn filename(&self) -> &str {
144        match self {
145            Self::PyScript(script) => &script.filename,
146            Self::Json(json) => &json.filename,
147        }
148    }
149
150    pub fn extension(&self) -> &str {
151        match self {
152            Self::PyScript(_) => "py",
153            Self::Json(_) => "json",
154        }
155    }
156}
157
158#[derive(Debug, Clone)]
159pub struct PyScript {
160    pub filename: Str,
161    pub code: String,
162}
163
164#[derive(Debug, Clone)]
165pub struct Json {
166    pub filename: Str,
167    pub code: String,
168}
169
170/// Generates a `PyScript` from an String or other File inputs.
171#[derive(Debug)]
172pub struct Transpiler {
173    pub cfg: ErgConfig,
174    builder: PackageBuilder,
175    shared: SharedCompilerResource,
176    script_generator: PyScriptGenerator,
177}
178
179impl Default for Transpiler {
180    fn default() -> Self {
181        Self::new(ErgConfig::default())
182    }
183}
184
185impl New for Transpiler {
186    fn new(cfg: ErgConfig) -> Self {
187        let shared = SharedCompilerResource::new(cfg.copy());
188        Self {
189            shared: shared.clone(),
190            builder: PackageBuilder::new_with_cache(cfg.copy(), "<module>".into(), shared),
191            script_generator: PyScriptGenerator::new(),
192            cfg,
193        }
194    }
195}
196
197impl Runnable for Transpiler {
198    type Err = CompileError;
199    type Errs = CompileErrors;
200    const NAME: &'static str = "Erg transpiler";
201
202    #[inline]
203    fn cfg(&self) -> &ErgConfig {
204        &self.cfg
205    }
206    #[inline]
207    fn cfg_mut(&mut self) -> &mut ErgConfig {
208        &mut self.cfg
209    }
210
211    #[inline]
212    fn finish(&mut self) {}
213
214    fn initialize(&mut self) {
215        self.builder.initialize();
216        // mod_cache will be cleared by the builder
217        // self.mod_cache.initialize();
218    }
219
220    fn clear(&mut self) {
221        self.builder.clear();
222    }
223
224    fn exec(&mut self) -> Result<ExitStatus, Self::Errs> {
225        let mut path = self.cfg.dump_path();
226        let src = self.cfg.input.read();
227        let artifact = self.transpile(src, "exec").map_err(|eart| {
228            eart.warns.write_all_stderr();
229            eart.errors
230        })?;
231        artifact.warns.write_all_stderr();
232        path.set_extension(artifact.object.extension());
233        let mut f = File::create(path).unwrap();
234        f.write_all(artifact.object.code().as_bytes()).unwrap();
235        Ok(ExitStatus::compile_passed(artifact.warns.len()))
236    }
237
238    fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
239        let artifact = self.transpile(src, "eval").map_err(|eart| {
240            eart.warns.write_all_stderr();
241            eart.errors
242        })?;
243        artifact.warns.write_all_stderr();
244        Ok(artifact.object.into_code())
245    }
246
247    fn expect_block(&self, src: &str) -> BlockKind {
248        let mut parser = ParserRunner::new(self.cfg().clone());
249        match parser.eval(src.to_string()) {
250            Err(errs) => {
251                let kind = errs
252                    .iter()
253                    .filter(|e| e.core().kind == ErrorKind::ExpectNextLine)
254                    .map(|e| {
255                        let msg = e.core().sub_messages.last().unwrap();
256                        // ExpectNextLine error must have msg otherwise it's a bug
257                        msg.get_msg().first().unwrap().to_owned()
258                    })
259                    .next();
260                if let Some(kind) = kind {
261                    return BlockKind::from(kind.as_str());
262                }
263                if errs
264                    .iter()
265                    .any(|err| err.core.main_message.contains("\"\"\""))
266                {
267                    return BlockKind::MultiLineStr;
268                }
269                BlockKind::Error
270            }
271            Ok(_) => {
272                if src.contains("Class") {
273                    return BlockKind::ClassDef;
274                }
275                BlockKind::None
276            }
277        }
278    }
279}
280
281impl ContextProvider for Transpiler {
282    fn dir(&self) -> HashMap<&VarName, &VarInfo> {
283        self.builder.dir()
284    }
285
286    fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context> {
287        self.builder.get_receiver_ctx(receiver_name)
288    }
289
290    fn get_var_info(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
291        self.builder.get_var_info(name)
292    }
293}
294
295impl Buildable<TranspiledFile> for Transpiler {
296    fn inherit(cfg: ErgConfig, shared: SharedCompilerResource) -> Self {
297        let mod_name = Str::from(cfg.input.file_stem());
298        Self::new_with_cache(cfg, mod_name, shared)
299    }
300    fn inherit_with_name(cfg: ErgConfig, mod_name: Str, shared: SharedCompilerResource) -> Self {
301        Self::new_with_cache(cfg, mod_name, shared)
302    }
303    fn build(
304        &mut self,
305        src: String,
306        mode: &str,
307    ) -> Result<CompleteArtifact<TranspiledFile>, IncompleteArtifact<TranspiledFile>> {
308        self.transpile(src, mode)
309            .map_err(|err| IncompleteArtifact::new(None, err.errors, err.warns))
310    }
311    fn build_from_ast(
312        &mut self,
313        ast: AST,
314        mode: &str,
315    ) -> Result<CompleteArtifact<TranspiledFile>, IncompleteArtifact<TranspiledFile>> {
316        self.transpile_from_ast(ast, mode)
317            .map_err(|err| IncompleteArtifact::new(None, err.errors, err.warns))
318    }
319    fn pop_context(&mut self) -> Option<ModuleContext> {
320        self.builder.pop_context()
321    }
322    fn get_context(&self) -> Option<&ModuleContext> {
323        self.builder.get_context()
324    }
325}
326
327impl BuildRunnable<TranspiledFile> for Transpiler {}
328
329impl Transpiler {
330    pub fn new(cfg: ErgConfig) -> Self {
331        New::new(cfg)
332    }
333
334    pub fn new_with_cache(cfg: ErgConfig, mod_name: Str, shared: SharedCompilerResource) -> Self {
335        Self {
336            shared: shared.clone(),
337            builder: PackageBuilder::new_with_cache(cfg.copy(), mod_name, shared),
338            script_generator: PyScriptGenerator::new(),
339            cfg,
340        }
341    }
342
343    pub fn transpile(
344        &mut self,
345        src: String,
346        mode: &str,
347    ) -> Result<CompleteArtifact<TranspiledFile>, ErrorArtifact> {
348        log!(info "the transpiling process has started.");
349        let artifact = self.build_link_desugar(src, mode)?;
350        let file = self.lower(artifact.object)?;
351        log!(info "code:\n{}", file.code());
352        log!(info "the transpiling process has completed");
353        Ok(CompleteArtifact::new(file, artifact.warns))
354    }
355
356    pub fn transpile_from_ast(
357        &mut self,
358        ast: AST,
359        mode: &str,
360    ) -> Result<CompleteArtifact<TranspiledFile>, ErrorArtifact> {
361        log!(info "the transpiling process has started.");
362        let artifact = self.builder.build_from_ast(ast, mode)?;
363        let file = self.lower(artifact.object)?;
364        log!(info "code:\n{}", file.code());
365        log!(info "the transpiling process has completed");
366        Ok(CompleteArtifact::new(file, artifact.warns))
367    }
368
369    fn lower(&mut self, hir: HIR) -> CompileResult<TranspiledFile> {
370        match self.cfg.transpile_target {
371            Some(TranspileTarget::Json) => {
372                let mut gen = JsonGenerator::new(self.cfg.copy());
373                Ok(TranspiledFile::Json(gen.transpile(hir)?))
374            }
375            _ => Ok(TranspiledFile::PyScript(
376                self.script_generator.transpile(hir),
377            )),
378        }
379    }
380
381    pub fn transpile_module(&mut self) -> Result<CompleteArtifact<TranspiledFile>, ErrorArtifact> {
382        let src = self.cfg.input.read();
383        self.transpile(src, "exec")
384    }
385
386    fn build_link_desugar(
387        &mut self,
388        src: String,
389        mode: &str,
390    ) -> Result<CompleteArtifact, ErrorArtifact> {
391        let artifact = self.builder.build(src, mode)?;
392        self.link_desugar(artifact)
393    }
394
395    fn link_desugar(
396        &mut self,
397        artifact: CompleteArtifact,
398    ) -> Result<CompleteArtifact, ErrorArtifact> {
399        let linker = HIRLinker::new(&self.cfg, &self.shared.mod_cache);
400        let hir = linker.link(artifact.object);
401        let desugared = HIRDesugarer::desugar(hir);
402        Ok(CompleteArtifact::new(desugared, artifact.warns))
403    }
404
405    pub fn pop_mod_ctx(&mut self) -> Option<ModuleContext> {
406        self.builder.pop_context()
407    }
408
409    pub fn dir(&mut self) -> HashMap<&VarName, &VarInfo> {
410        ContextProvider::dir(self)
411    }
412
413    pub fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context> {
414        ContextProvider::get_receiver_ctx(self, receiver_name)
415    }
416
417    pub fn get_var_info(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
418        ContextProvider::get_var_info(self, name)
419    }
420}
421
422#[derive(Debug, Default)]
423pub struct PyScriptGenerator {
424    globals: HashSet<String>,
425    level: usize,
426    fresh_var_n: usize,
427    namedtuple_loaded: bool,
428    mutate_op_loaded: bool,
429    contains_op_loaded: bool,
430    range_ops_loaded: bool,
431    builtin_types_loaded: bool,
432    builtin_control_loaded: bool,
433    convertors_loaded: bool,
434    prelude: String,
435}
436
437impl PyScriptGenerator {
438    pub fn new() -> Self {
439        Self {
440            globals: HashSet::new(),
441            level: 0,
442            fresh_var_n: 0,
443            namedtuple_loaded: false,
444            mutate_op_loaded: false,
445            contains_op_loaded: false,
446            range_ops_loaded: false,
447            builtin_types_loaded: false,
448            builtin_control_loaded: false,
449            convertors_loaded: false,
450            prelude: String::new(),
451        }
452    }
453
454    pub fn transpile(&mut self, hir: HIR) -> PyScript {
455        let mut code = String::new();
456        for chunk in hir.module.into_iter() {
457            let expr = self.transpile_expr(chunk);
458            if !expr.is_empty() {
459                code += &expr;
460                code.push('\n');
461            }
462        }
463        code = std::mem::take(&mut self.prelude) + &code;
464        PyScript {
465            filename: hir.name,
466            code,
467        }
468    }
469
470    // TODO: more smart way
471    fn replace_import(src: &str) -> String {
472        src.replace("from _erg_nat import NatMut", "")
473            .replace("from _erg_nat import Nat", "")
474            .replace("from _erg_int import IntMut", "")
475            .replace("from _erg_int import Int", "")
476            .replace("from _erg_bool import BoolMut", "")
477            .replace("from _erg_bool import Bool", "")
478            .replace("from _erg_str import StrMut", "")
479            .replace("from _erg_str import Str", "")
480            .replace("from _erg_float import FloatMut", "")
481            .replace("from _erg_float import Float", "")
482            .replace("from _erg_list import List", "")
483            .replace("from _erg_range import Range", "")
484            .replace("from _erg_result import Error", "")
485            .replace("from _erg_result import is_ok", "")
486            .replace("from _erg_control import then__", "")
487            .replace("from _erg_contains_operator import contains_operator", "")
488            .replace("from _erg_type import is_type", "")
489            .replace("from _erg_type import _isinstance", "")
490            .replace("from _erg_type import UnionType", "")
491            .replace("from _erg_type import MutType", "")
492    }
493
494    fn load_namedtuple_if_not(&mut self) {
495        if !self.namedtuple_loaded {
496            self.prelude += "from collections import namedtuple as NamedTuple__\n";
497            self.namedtuple_loaded = true;
498        }
499    }
500
501    // TODO: name escaping
502    fn load_range_ops_if_not(&mut self) {
503        if !self.range_ops_loaded {
504            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_result.py"));
505            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_int.py"));
506            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_nat.py"));
507            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_str.py"));
508            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_range.py"));
509            self.range_ops_loaded = true;
510        }
511    }
512
513    fn load_contains_op_if_not(&mut self) {
514        if !self.contains_op_loaded {
515            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_result.py"));
516            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_range.py"));
517            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_type.py"));
518            self.prelude +=
519                &Self::replace_import(include_str!("lib/core/_erg_contains_operator.py"));
520            self.contains_op_loaded = true;
521        }
522    }
523
524    fn load_mutate_op_if_not(&mut self) {
525        if !self.mutate_op_loaded {
526            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_mutate_operator.py"));
527            self.mutate_op_loaded = true;
528        }
529    }
530
531    fn load_builtin_types_if_not(&mut self) {
532        if !self.builtin_types_loaded {
533            self.load_builtin_controls_if_not();
534            self.load_contains_op_if_not();
535            if self.range_ops_loaded {
536                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_float.py"));
537                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_list.py"));
538                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_dict.py"));
539                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_set.py"));
540                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_bytes.py"));
541            } else {
542                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_int.py"));
543                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_nat.py"));
544                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_bool.py"));
545                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_str.py"));
546                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_float.py"));
547                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_list.py"));
548                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_dict.py"));
549                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_set.py"));
550                self.prelude += &Self::replace_import(include_str!("lib/core/_erg_bytes.py"));
551            }
552            self.builtin_types_loaded = true;
553        }
554    }
555
556    fn load_builtin_controls_if_not(&mut self) {
557        if !self.builtin_control_loaded {
558            self.prelude += include_str!("lib/core/_erg_control.py");
559            self.builtin_control_loaded = true;
560        }
561    }
562
563    fn load_convertors_if_not(&mut self) {
564        if !self.convertors_loaded {
565            self.prelude += &Self::replace_import(include_str!("lib/core/_erg_convertors.py"));
566            self.convertors_loaded = true;
567        }
568    }
569
570    fn escape_str(s: &str) -> String {
571        s.replace('\n', "\\n")
572            .replace('\r', "\\r")
573            .replace('\t', "\\t")
574            // .replace('\'', "\\'")
575            .replace('\0', "\\0")
576    }
577
578    fn transpile_expr(&mut self, expr: Expr) -> String {
579        match expr {
580            Expr::Literal(lit) => self.transpile_lit(lit),
581            Expr::Call(call) => self.transpile_call(call),
582            Expr::BinOp(bin) => self.transpile_binop(bin),
583            Expr::UnaryOp(unary) => self.transpile_unaryop(unary),
584            Expr::List(list) => match list {
585                List::Normal(lis) => {
586                    self.load_builtin_types_if_not();
587                    let mut code = "List([".to_string();
588                    for elem in lis.elems.pos_args {
589                        code += &format!("{},", self.transpile_expr(elem.expr));
590                    }
591                    code += "])";
592                    code
593                }
594                other => todo!("transpiling {other}"),
595            },
596            Expr::Set(set) => match set {
597                Set::Normal(st) => {
598                    self.load_builtin_types_if_not();
599                    let mut code = "Set({".to_string();
600                    for elem in st.elems.pos_args {
601                        code += &format!("{},", self.transpile_expr(elem.expr));
602                    }
603                    code += "})";
604                    code
605                }
606                other => todo!("transpiling {other}"),
607            },
608            Expr::Record(rec) => self.transpile_record(rec),
609            Expr::Tuple(tuple) => match tuple {
610                Tuple::Normal(tup) => {
611                    let mut code = "(".to_string();
612                    for elem in tup.elems.pos_args {
613                        code += &format!("{},", self.transpile_expr(elem.expr));
614                    }
615                    code += ")";
616                    code
617                }
618            },
619            Expr::Dict(dict) => match dict {
620                Dict::Normal(dic) => {
621                    self.load_builtin_types_if_not();
622                    let mut code = "Dict({".to_string();
623                    for kv in dic.kvs {
624                        code += &format!(
625                            "({}): ({}),",
626                            self.transpile_expr(kv.key),
627                            self.transpile_expr(kv.value)
628                        );
629                    }
630                    code += "})";
631                    code
632                }
633                other => todo!("transpiling {other}"),
634            },
635            Expr::Accessor(acc) => self.transpile_acc(acc),
636            Expr::Def(def) => self.transpile_def(def),
637            Expr::Lambda(lambda) => self.transpile_lambda(lambda),
638            Expr::ClassDef(classdef) => self.transpile_classdef(classdef),
639            Expr::PatchDef(patchdef) => self.transpile_patchdef(patchdef),
640            Expr::ReDef(redef) => self.transpile_attrdef(redef),
641            // TODO:
642            Expr::Compound(comp) => {
643                let mut code = "".to_string();
644                for expr in comp.into_iter() {
645                    let expr = self.transpile_expr(expr);
646                    if !expr.is_empty() {
647                        code += &expr;
648                        code += &format!("\n{}", "    ".repeat(self.level));
649                    }
650                }
651                code
652            }
653            Expr::Import(acc) => {
654                let full_name = acc
655                    .qual_name()
656                    .map_or(acc.show(), |s| s.replace(".__init__", ""));
657                let root = PyCodeGenerator::get_root(&acc);
658                self.prelude += &format!(
659                    "{} = __import__(\"{full_name}\")\n",
660                    Self::transpile_ident(root)
661                );
662                String::new()
663            }
664            Expr::TypeAsc(tasc) => self.transpile_expr(*tasc.expr),
665            Expr::Code(_) => todo!("transpiling importing user-defined code"),
666            Expr::Dummy(_) => "".to_string(),
667        }
668    }
669
670    fn transpile_lit(&mut self, lit: Literal) -> String {
671        let escaped = Self::escape_str(&lit.token.content);
672        if matches!(
673            &lit.value,
674            ValueObj::Bool(_)
675                | ValueObj::Int(_)
676                | ValueObj::Nat(_)
677                | ValueObj::Str(_)
678                | ValueObj::Float(_)
679        ) {
680            self.load_builtin_types_if_not();
681            format!("{}({escaped})", lit.value.class())
682        } else {
683            escaped
684        }
685    }
686
687    fn transpile_record(&mut self, rec: Record) -> String {
688        self.load_namedtuple_if_not();
689        let mut attrs = "[".to_string();
690        let mut values = "(".to_string();
691        for mut attr in rec.attrs.into_iter() {
692            attrs += &format!("'{}',", Self::transpile_ident(attr.sig.into_ident()));
693            if attr.body.block.len() > 1 {
694                let name = format!("instant_block_{}__", self.fresh_var_n);
695                self.fresh_var_n += 1;
696                let mut instant = format!("def {name}():\n");
697                instant += &self.transpile_block(attr.body.block, Return);
698                self.prelude += &instant;
699                values += &format!("{name}(),");
700            } else {
701                let expr = attr.body.block.remove(0);
702                values += &format!("{},", self.transpile_expr(expr));
703            }
704        }
705        attrs += "]";
706        values += ")";
707        format!("NamedTuple__('Record', {attrs}){values}")
708    }
709
710    fn transpile_binop(&mut self, bin: BinOp) -> String {
711        match bin.op.kind {
712            TokenKind::Closed | TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Open => {
713                self.load_range_ops_if_not();
714                let mut code = match bin.op.kind {
715                    TokenKind::Closed => "ClosedRange(",
716                    TokenKind::LeftOpen => "LeftOpenRange(",
717                    TokenKind::RightOpen => "RightOpenRange(",
718                    TokenKind::Open => "OpenRange(",
719                    _ => unreachable!(),
720                }
721                .to_string();
722                code += &self.transpile_expr(*bin.lhs);
723                code.push(',');
724                code += &self.transpile_expr(*bin.rhs);
725                code.push(')');
726                code
727            }
728            TokenKind::ContainsOp => {
729                self.load_contains_op_if_not();
730                let mut code = "contains_operator(".to_string();
731                code += &self.transpile_expr(*bin.lhs);
732                code.push(',');
733                code += &self.transpile_expr(*bin.rhs);
734                code.push(')');
735                code
736            }
737            _ => {
738                let mut code = "(".to_string();
739                code += &self.transpile_expr(*bin.lhs);
740                code.push(' ');
741                code += &bin.op.content;
742                code.push(' ');
743                code += &self.transpile_expr(*bin.rhs);
744                code += ")";
745                code
746            }
747        }
748    }
749
750    fn transpile_unaryop(&mut self, unary: UnaryOp) -> String {
751        let mut code = "".to_string();
752        if unary.op.kind == TokenKind::Mutate {
753            self.load_mutate_op_if_not();
754            code += "mutate_operator(";
755        } else {
756            code += "(";
757            code += &unary.op.content;
758        }
759        code += &self.transpile_expr(*unary.expr);
760        code += ")";
761        code
762    }
763
764    fn transpile_acc(&mut self, acc: Accessor) -> String {
765        let mut prefix = "".to_string();
766        match acc.ref_t().derefine() {
767            v @ (Type::Bool | Type::Nat | Type::Int | Type::Float | Type::Str) => {
768                self.load_builtin_types_if_not();
769                prefix.push_str(&v.qual_name());
770                prefix.push('(');
771            }
772            other => {
773                if let t @ ("Bytes" | "List" | "Dict" | "Set") = &other.qual_name()[..] {
774                    self.load_builtin_types_if_not();
775                    prefix.push_str(t);
776                    prefix.push('(');
777                }
778            }
779        }
780        let postfix = if prefix.is_empty() { "" } else { ")" };
781        match acc {
782            Accessor::Ident(ident) => {
783                match &ident.inspect()[..] {
784                    "Str" | "Bytes" | "Bool" | "Nat" | "Int" | "Float" | "List" | "Dict"
785                    | "Set" | "Str!" | "Bytes!" | "Bool!" | "Nat!" | "Int!" | "Float!"
786                    | "List!" => {
787                        self.load_builtin_types_if_not();
788                    }
789                    "if" | "if!" | "for!" | "while" | "discard" => {
790                        self.load_builtin_controls_if_not();
791                    }
792                    "int" | "nat" | "float" | "str" => {
793                        self.load_convertors_if_not();
794                    }
795                    _ => {}
796                }
797                prefix + &Self::transpile_ident(ident) + postfix
798            }
799            Accessor::Attr(attr) => {
800                if let Some(name) = debind(&attr.ident) {
801                    demangle(&name)
802                } else {
803                    format!(
804                        "{prefix}({}).{}{postfix}",
805                        self.transpile_expr(*attr.obj),
806                        Self::transpile_ident(attr.ident),
807                    )
808                }
809            }
810        }
811    }
812
813    fn transpile_call(&mut self, mut call: Call) -> String {
814        match call.obj.local_name() {
815            Some("assert") => {
816                let mut code = format!("assert {}", self.transpile_expr(call.args.remove(0)));
817                if let Some(msg) = call.args.try_remove(0) {
818                    code += &format!(", {}", self.transpile_expr(msg));
819                }
820                code
821            }
822            Some("not") => format!("(not ({}))", self.transpile_expr(call.args.remove(0))),
823            Some("if" | "if!") => self.transpile_if(call),
824            Some("for" | "for!") => {
825                let mut code = "for ".to_string();
826                let iter = call.args.remove(0);
827                let Expr::Lambda(block) = call.args.remove(0) else {
828                    todo!()
829                };
830                let non_default = block.params.non_defaults.first().unwrap();
831                let param_token = match &non_default.raw.pat {
832                    ParamPattern::VarName(name) => name.token(),
833                    ParamPattern::Discard(token) => token,
834                    _ => unreachable!(),
835                };
836                code += &Self::transpile_name(
837                    &VisibilityModifier::Private,
838                    param_token.inspect(),
839                    &non_default.vi,
840                );
841                code += &format!(" in {}:\n", self.transpile_expr(iter));
842                code += &self.transpile_block(block.body, Discard);
843                code
844            }
845            Some("while" | "while!") => {
846                let mut code = "while ".to_string();
847                let Expr::Lambda(mut cond) = call.args.remove(0) else {
848                    todo!()
849                };
850                let Expr::Lambda(block) = call.args.remove(0) else {
851                    todo!()
852                };
853                code += &format!("{}:\n", self.transpile_expr(cond.body.remove(0)));
854                code += &self.transpile_block(block.body, Discard);
855                code
856            }
857            Some("match" | "match!") => self.transpile_match(call),
858            _ => self.transpile_simple_call(call),
859        }
860    }
861
862    fn transpile_if(&mut self, mut call: Call) -> String {
863        let cond = self.transpile_expr(call.args.remove(0));
864        let Expr::Lambda(mut then_block) = call.args.remove(0) else {
865            todo!()
866        };
867        let else_block = call.args.try_remove(0).map(|ex| {
868            if let Expr::Lambda(blk) = ex {
869                blk
870            } else {
871                todo!()
872            }
873        });
874        if then_block.body.len() == 1
875            && else_block
876                .as_ref()
877                .map(|blk| blk.body.len() == 1)
878                .unwrap_or(true)
879        {
880            let then = self.transpile_expr(then_block.body.remove(0));
881            if let Some(mut else_block) = else_block {
882                let els = self.transpile_expr(else_block.body.remove(0));
883                return format!("{then} if {cond} else {els}");
884            } else {
885                return format!("{then} if {cond} else None");
886            }
887        }
888        let tmp = Str::from(format!("if_tmp_{}__", self.fresh_var_n));
889        self.fresh_var_n += 1;
890        let tmp_func = Str::from(format!("if_tmp_func_{}__", self.fresh_var_n));
891        self.fresh_var_n += 1;
892        let mut code = format!("def {tmp_func}():\n");
893        code += &format!("    if {cond}:\n");
894        let level = self.level;
895        self.level = 1;
896        code += &self.transpile_block(then_block.body, StoreTmp(tmp.clone()));
897        self.level = level;
898        if let Some(else_block) = else_block {
899            code += "    else:\n";
900            let level = self.level;
901            self.level = 1;
902            code += &self.transpile_block(else_block.body, StoreTmp(tmp.clone()));
903            self.level = level;
904        } else {
905            code += "    else:\n";
906            code += &format!("        {tmp} = None\n");
907        }
908        code += &format!("    return {tmp}\n");
909        self.prelude += &code;
910        // ~~ NOTE: In Python, the variable environment of a function is determined at call time
911        // This is a very bad design, but can be used for this code ~~
912        // FIXME: this trick only works in the global namespace
913        format!("{tmp_func}()")
914    }
915
916    fn transpile_match(&mut self, mut call: Call) -> String {
917        let tmp = Str::from(format!("match_tmp_{}__", self.fresh_var_n));
918        self.fresh_var_n += 1;
919        let tmp_func = Str::from(format!("match_tmp_func_{}__", self.fresh_var_n));
920        self.fresh_var_n += 1;
921        let mut code = format!("def {tmp_func}():\n");
922        self.level += 1;
923        code += &"    ".repeat(self.level);
924        code += "match ";
925        let cond = call.args.remove(0);
926        code += &format!("{}:\n", self.transpile_expr(cond));
927        while let Some(Expr::Lambda(arm)) = call.args.try_remove(0) {
928            self.level += 1;
929            code += &"    ".repeat(self.level);
930            let target = arm.params.non_defaults.first().unwrap();
931            match &target.raw.pat {
932                ParamPattern::VarName(param) => {
933                    let param = Self::transpile_name(
934                        &VisibilityModifier::Private,
935                        param.inspect(),
936                        &target.vi,
937                    );
938                    match target.raw.t_spec.as_ref().map(|t| &t.t_spec) {
939                        Some(TypeSpec::Enum(enum_t)) => {
940                            let values = ValueObj::vec_from_const_args(enum_t.clone());
941                            let patterns = values
942                                .iter()
943                                .map(|v| v.to_string())
944                                .collect::<Vec<_>>()
945                                .join(" | ");
946                            code += &format!("case ({patterns}) as {param}:\n");
947                        }
948                        Some(other) => {
949                            if let Some(Expr::Set(Set::Normal(set))) = &target.t_spec_as_expr {
950                                let patterns = set
951                                    .elems
952                                    .pos_args
953                                    .iter()
954                                    .map(|elem| self.transpile_expr(elem.expr.clone()))
955                                    .collect::<Vec<_>>()
956                                    .join(" | ");
957                                code += &format!("case ({patterns}) as {param}:\n");
958                            } else {
959                                todo!("{other}")
960                            }
961                        }
962                        None => {
963                            code += &format!("case {param}:\n");
964                        }
965                    }
966                    code += &self.transpile_block(arm.body, StoreTmp(tmp.clone()));
967                    self.level -= 1;
968                }
969                ParamPattern::Discard(_) => {
970                    match target.raw.t_spec.as_ref().map(|t| &t.t_spec) {
971                        Some(TypeSpec::Enum(enum_t)) => {
972                            let values = ValueObj::vec_from_const_args(enum_t.clone());
973                            let patterns = values
974                                .iter()
975                                .map(|v| v.to_string())
976                                .collect::<Vec<_>>()
977                                .join(" | ");
978                            code += &format!("case {patterns}:\n");
979                        }
980                        Some(_) => todo!(),
981                        None => {
982                            code += "case _:\n";
983                        }
984                    }
985                    code += &self.transpile_block(arm.body, StoreTmp(tmp.clone()));
986                    self.level -= 1;
987                }
988                _ => todo!(),
989            }
990        }
991        code += &"    ".repeat(self.level);
992        code += &format!("return {tmp}\n");
993        self.prelude += &code;
994        self.level -= 1;
995        format!("{tmp_func}()")
996    }
997
998    fn transpile_simple_call(&mut self, call: Call) -> String {
999        let enc = if call.obj.ref_t().is_poly_meta_type() {
1000            Enclosure::Bracket
1001        } else {
1002            Enclosure::Paren
1003        };
1004        let is_py_api = if let Some(attr) = &call.attr_name {
1005            let is_py_api = attr.is_py_api();
1006            if let Some(name) = debind(attr) {
1007                let name = demangle(&name);
1008                return format!(
1009                    "{name}({}, {})",
1010                    self.transpile_expr(*call.obj),
1011                    self.transpile_args(call.args, is_py_api, enc)
1012                );
1013            }
1014            is_py_api
1015        } else {
1016            call.obj.is_py_api()
1017        };
1018        let mut code = format!("({})", self.transpile_expr(*call.obj));
1019        if let Some(attr) = call.attr_name {
1020            code += &format!(".{}", Self::transpile_ident(attr));
1021        }
1022        code += &self.transpile_args(call.args, is_py_api, enc);
1023        code
1024    }
1025
1026    fn transpile_args(&mut self, mut args: Args, is_py_api: bool, enc: Enclosure) -> String {
1027        let mut code = String::new();
1028        code.push(enc.open());
1029        while let Some(arg) = args.try_remove_pos(0) {
1030            code += &self.transpile_expr(arg.expr);
1031            code.push(',');
1032        }
1033        while let Some(arg) = args.try_remove_kw(0) {
1034            let escape = if is_py_api { "" } else { "__" };
1035            code += &format!(
1036                "{}{escape}={},",
1037                arg.keyword.content,
1038                self.transpile_expr(arg.expr)
1039            );
1040        }
1041        code.push(enc.close());
1042        code
1043    }
1044
1045    fn transpile_ident(ident: Identifier) -> String {
1046        Self::transpile_name(ident.vis(), ident.inspect(), &ident.vi)
1047    }
1048
1049    fn transpile_name(vis: &VisibilityModifier, name: &Str, vi: &VarInfo) -> String {
1050        if let Some(py_name) = &vi.py_name {
1051            return demangle(py_name);
1052        }
1053        let name = replace_non_symbolic(name);
1054        if vis.is_public() || &name == "_" {
1055            name.to_string()
1056        } else {
1057            let def_line = vi.def_loc.loc.ln_begin().unwrap_or(0);
1058            let def_col = vi.def_loc.loc.col_begin().unwrap_or(0);
1059            let line_mangling = match (def_line, def_col) {
1060                (0, 0) => "".to_string(),
1061                (0, _) => format!("_C{def_col}"),
1062                (_, 0) => format!("_L{def_line}"),
1063                (_, _) => format!("_L{def_line}_C{def_col}"),
1064            };
1065            format!("{name}{line_mangling}")
1066        }
1067    }
1068
1069    fn transpile_params(&mut self, params: Params) -> String {
1070        let mut code = String::new();
1071        for non_default in params.non_defaults {
1072            match non_default.raw.pat {
1073                ParamPattern::VarName(param) => {
1074                    code += &Self::transpile_name(
1075                        &VisibilityModifier::Private,
1076                        param.inspect(),
1077                        &non_default.vi,
1078                    );
1079                    code += ",";
1080                }
1081                ParamPattern::Discard(_) => {
1082                    code += &format!("_{},", self.fresh_var_n);
1083                    self.fresh_var_n += 1;
1084                }
1085                _ => unreachable!(),
1086            }
1087        }
1088        for default in params.defaults {
1089            match default.sig.raw.pat {
1090                ParamPattern::VarName(param) => {
1091                    code += &format!(
1092                        "{} = {},",
1093                        Self::transpile_name(
1094                            &VisibilityModifier::Private,
1095                            param.inspect(),
1096                            &default.sig.vi
1097                        ),
1098                        self.transpile_expr(default.default_val),
1099                    );
1100                }
1101                ParamPattern::Discard(_) => {
1102                    let n = self.fresh_var_n;
1103                    code += &format!("_{n} = {},", self.transpile_expr(default.default_val),);
1104                    self.fresh_var_n += 1;
1105                }
1106                _ => unreachable!(),
1107            }
1108        }
1109        code
1110    }
1111
1112    fn transpile_block(&mut self, block: Block, last_op: LastLineOperation) -> String {
1113        self.level += 1;
1114        let mut code = String::new();
1115        let last = block.len().saturating_sub(1);
1116        for (i, chunk) in block.into_iter().enumerate() {
1117            code += &"    ".repeat(self.level);
1118            if i == last {
1119                match last_op {
1120                    Return => {
1121                        code += "return ";
1122                    }
1123                    Discard => {}
1124                    StoreTmp(ref tmp) => {
1125                        code += &format!("{tmp} = ");
1126                    }
1127                }
1128            }
1129            let expr = self.transpile_expr(chunk);
1130            if !expr.is_empty() {
1131                code += &expr;
1132                code.push('\n');
1133            }
1134        }
1135        self.level -= 1;
1136        code
1137    }
1138
1139    fn transpile_lambda(&mut self, lambda: Lambda) -> String {
1140        if lambda.body.len() > 1 {
1141            let name = format!("lambda_{}__", self.fresh_var_n);
1142            self.fresh_var_n += 1;
1143            let mut code = format!("def {name}({}):\n", self.transpile_params(lambda.params));
1144            code += &self.transpile_block(lambda.body, Return);
1145            self.prelude += &code;
1146            name
1147        } else {
1148            let mut code = format!("(lambda {}:", self.transpile_params(lambda.params));
1149            code += &self.transpile_block(lambda.body, Discard);
1150            code.pop(); // \n
1151            code.push(')');
1152            code
1153        }
1154    }
1155
1156    // TODO: trait definition
1157    fn transpile_def(&mut self, mut def: Def) -> String {
1158        // HACK: allow reference to local variables in tmp functions
1159        let mut code = if self.level == 0 {
1160            "".to_string()
1161        } else {
1162            let name = Self::transpile_ident(def.sig.ident().clone());
1163            if self.globals.contains(&name) {
1164                "".to_string()
1165            } else {
1166                self.globals.insert(name.clone());
1167                format!("global {name}\n{}", "    ".repeat(self.level))
1168            }
1169        };
1170        match def.sig {
1171            Signature::Var(var) => {
1172                code += &format!("{} = ", Self::transpile_ident(var.ident));
1173                if def.body.block.len() > 1 {
1174                    let name = format!("instant_block_{}__", self.fresh_var_n);
1175                    self.fresh_var_n += 1;
1176                    let mut instant = format!("def {name}():\n");
1177                    instant += &self.transpile_block(def.body.block, Return);
1178                    self.prelude += &instant;
1179                    code + &format!("{name}()")
1180                } else {
1181                    let expr = def.body.block.remove(0);
1182                    code += &self.transpile_expr(expr);
1183                    code
1184                }
1185            }
1186            Signature::Subr(subr) => {
1187                code += &format!(
1188                    "def {}({}):\n",
1189                    Self::transpile_ident(subr.ident),
1190                    self.transpile_params(subr.params)
1191                );
1192                code += &self.transpile_block(def.body.block, Return);
1193                code
1194            }
1195            Signature::Glob(_) => todo!(),
1196        }
1197    }
1198
1199    fn transpile_classdef(&mut self, classdef: ClassDef) -> String {
1200        let class_name = Self::transpile_ident(classdef.sig.into_ident());
1201        let mut code = format!("class {class_name}():\n");
1202        let mut init_method = format!(
1203            "{}def __init__(self, param__):\n",
1204            "    ".repeat(self.level + 1)
1205        );
1206        match classdef.constructor.non_default_params().unwrap()[0].typ() {
1207            Type::Record(rec) => {
1208                for field in rec.keys() {
1209                    let vis = if field.vis.is_private() { "__" } else { "" };
1210                    init_method += &format!(
1211                        "{}self.{}{vis} = param__.{}{vis}\n",
1212                        "    ".repeat(self.level + 2),
1213                        field.symbol,
1214                        field.symbol,
1215                    );
1216                }
1217            }
1218            other => todo!("{other}"),
1219        }
1220        code += &init_method;
1221        if classdef.need_to_gen_new {
1222            code += &"    ".repeat(self.level + 1);
1223            code += &format!("def new(x): return {class_name}.__call__(x)\n");
1224        }
1225        let methods = ClassDef::take_all_methods(classdef.methods_list);
1226        code += &self.transpile_block(methods, Discard);
1227        code
1228    }
1229
1230    fn transpile_patchdef(&mut self, patch_def: PatchDef) -> String {
1231        let mut code = String::new();
1232        for chunk in patch_def.methods.into_iter() {
1233            let Expr::Def(mut def) = chunk else { todo!() };
1234            let name = format!(
1235                "{}{}",
1236                demangle(&patch_def.sig.ident().to_string_notype()),
1237                demangle(&def.sig.ident().to_string_notype()),
1238            );
1239            def.sig.ident_mut().raw.name = VarName::from_str(Str::from(name));
1240            code += &"    ".repeat(self.level);
1241            code += &self.transpile_def(def);
1242            code.push('\n');
1243        }
1244        code
1245    }
1246
1247    fn transpile_attrdef(&mut self, mut redef: ReDef) -> String {
1248        let mut code = format!("{} = ", self.transpile_expr(Expr::Accessor(redef.attr)));
1249        if redef.block.len() > 1 {
1250            let name = format!("instant_block_{}__", self.fresh_var_n);
1251            self.fresh_var_n += 1;
1252            let mut instant = format!("def {name}():\n");
1253            instant += &self.transpile_block(redef.block, Return);
1254            self.prelude += &instant;
1255            code + &format!("{name}()")
1256        } else {
1257            let expr = redef.block.remove(0);
1258            code += &self.transpile_expr(expr);
1259            code
1260        }
1261    }
1262}
1263
1264#[derive(Debug, Default)]
1265pub struct JsonGenerator {
1266    cfg: ErgConfig,
1267    binds: HashMap<AbsLocation, ValueObj>,
1268    errors: CompileErrors,
1269}
1270
1271impl JsonGenerator {
1272    pub fn new(cfg: ErgConfig) -> Self {
1273        Self {
1274            cfg,
1275            binds: HashMap::new(),
1276            errors: CompileErrors::empty(),
1277        }
1278    }
1279
1280    pub fn transpile(&mut self, hir: HIR) -> CompileResult<Json> {
1281        let mut code = "".to_string();
1282        let mut len = 0;
1283        for (i, chunk) in hir.module.into_iter().enumerate() {
1284            if i > 0 && len > 0 {
1285                code += ",\n";
1286            }
1287            let expr = self.transpile_expr(chunk);
1288            len = expr.len();
1289            code += &expr;
1290        }
1291        if self.errors.is_empty() {
1292            Ok(Json {
1293                filename: hir.name,
1294                code: format!("{{\n{code}\n}}"),
1295            })
1296        } else {
1297            Err(self.errors.take_all().into())
1298        }
1299    }
1300
1301    fn expr_into_value(&self, expr: Expr) -> Option<ValueObj> {
1302        match expr {
1303            Expr::List(List::Normal(lis)) => {
1304                let mut vals = vec![];
1305                for elem in lis.elems.pos_args {
1306                    if let Some(val) = self.expr_into_value(elem.expr) {
1307                        vals.push(val);
1308                    } else {
1309                        return None;
1310                    }
1311                }
1312                Some(ValueObj::List(vals.into()))
1313            }
1314            Expr::List(List::WithLength(lis)) => {
1315                let len = lis
1316                    .len
1317                    .and_then(|len| self.expr_into_value(*len))
1318                    .and_then(|v| usize::try_from(&v).ok())?;
1319                let vals = vec![self.expr_into_value(*lis.elem)?; len];
1320                Some(ValueObj::List(vals.into()))
1321            }
1322            Expr::Tuple(Tuple::Normal(tup)) => {
1323                let mut vals = vec![];
1324                for elem in tup.elems.pos_args {
1325                    if let Some(val) = self.expr_into_value(elem.expr) {
1326                        vals.push(val);
1327                    } else {
1328                        return None;
1329                    }
1330                }
1331                Some(ValueObj::Tuple(vals.into()))
1332            }
1333            Expr::Dict(Dict::Normal(dic)) => {
1334                let mut kvs = dict! {};
1335                for kv in dic.kvs {
1336                    let key = self.expr_into_value(kv.key)?;
1337                    let val = self.expr_into_value(kv.value)?;
1338                    kvs.insert(key, val);
1339                }
1340                Some(ValueObj::Dict(kvs))
1341            }
1342            Expr::Record(rec) => {
1343                let mut attrs = dict! {};
1344                for mut attr in rec.attrs {
1345                    let field = Field::from(attr.sig.ident());
1346                    let val = self.expr_into_value(attr.body.block.remove(0))?;
1347                    attrs.insert(field, val);
1348                }
1349                Some(ValueObj::Record(attrs))
1350            }
1351            Expr::Literal(lit) => Some(lit.value),
1352            Expr::Accessor(acc) => self.binds.get(&acc.var_info().def_loc).cloned(),
1353            Expr::BinOp(bin) => {
1354                let lhs = self.expr_into_value(*bin.lhs)?;
1355                let rhs = self.expr_into_value(*bin.rhs)?;
1356                lhs.try_binary(rhs, OpKind::try_from(bin.op.kind).ok()?)
1357            }
1358            _ => None,
1359        }
1360    }
1361
1362    fn transpile_def(&mut self, mut def: Def) -> String {
1363        self.register_def(&def);
1364        if def.sig.vis().is_public() {
1365            let expr = self.transpile_expr(def.body.block.remove(0));
1366            format!("\"{}\": {expr}", def.sig.inspect())
1367        } else {
1368            "".to_string()
1369        }
1370    }
1371
1372    fn register_def(&mut self, def: &Def) {
1373        if let Some(val) = def
1374            .body
1375            .block
1376            .first()
1377            .cloned()
1378            .and_then(|expr| self.expr_into_value(expr))
1379        {
1380            self.binds.insert(def.sig.ident().vi.def_loc.clone(), val);
1381        }
1382    }
1383
1384    fn transpile_expr(&mut self, expr: Expr) -> String {
1385        match expr {
1386            Expr::Literal(lit) => lit.token.content.to_string(),
1387            Expr::Accessor(acc) => {
1388                if let Some(val) = self.binds.get(&acc.var_info().def_loc) {
1389                    val.to_string()
1390                } else {
1391                    replace_non_symbolic(&acc.to_string())
1392                }
1393            }
1394            Expr::List(list) => match list {
1395                List::Normal(lis) => {
1396                    let mut code = "[".to_string();
1397                    for (i, elem) in lis.elems.pos_args.into_iter().enumerate() {
1398                        if i > 0 {
1399                            code += ", ";
1400                        }
1401                        code += &self.transpile_expr(elem.expr);
1402                    }
1403                    code += "]";
1404                    code
1405                }
1406                other => todo!("{other}"),
1407            },
1408            Expr::Tuple(tup) => match tup {
1409                Tuple::Normal(tup) => {
1410                    let mut code = "[".to_string();
1411                    for (i, elem) in tup.elems.pos_args.into_iter().enumerate() {
1412                        if i > 0 {
1413                            code += ", ";
1414                        }
1415                        code += &self.transpile_expr(elem.expr);
1416                    }
1417                    code += "]";
1418                    code
1419                }
1420            },
1421            Expr::Record(rec) => {
1422                let mut code = "".to_string();
1423                for (i, mut attr) in rec.attrs.into_iter().enumerate() {
1424                    if i > 0 {
1425                        code += ", ";
1426                    }
1427                    let expr = self.transpile_expr(attr.body.block.remove(0));
1428                    code += &format!("\"{}\": {expr}", attr.sig.inspect());
1429                }
1430                format!("{{{code}}}")
1431            }
1432            Expr::Dict(dic) => match dic {
1433                Dict::Normal(dic) => {
1434                    let mut code = "".to_string();
1435                    for (i, kv) in dic.kvs.into_iter().enumerate() {
1436                        if i > 0 {
1437                            code += ", ";
1438                        }
1439                        code += &format!(
1440                            "{}: {}",
1441                            self.transpile_expr(kv.key),
1442                            self.transpile_expr(kv.value)
1443                        );
1444                    }
1445                    format!("{{{code}}}")
1446                }
1447                Dict::Comprehension(other) => todo!("{other}"),
1448            },
1449            Expr::Def(def) => self.transpile_def(def),
1450            other => {
1451                let loc = other.loc();
1452                if let Some(val) = self.expr_into_value(other) {
1453                    val.to_string()
1454                } else {
1455                    self.errors.push(CompileError::not_const_expr(
1456                        self.cfg.input.clone(),
1457                        line!() as usize,
1458                        loc,
1459                        "".into(),
1460                    ));
1461                    "".to_string()
1462                }
1463            }
1464        }
1465    }
1466}