Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Name mangling #45

Open
brandonLi8 opened this issue Mar 8, 2023 · 1 comment
Open

Name mangling #45

brandonLi8 opened this issue Mar 8, 2023 · 1 comment

Comments

@brandonLi8
Copy link
Owner

Consider the following program:

let a = 1
if true {
  let a = 2;
  print(a) // 2
}
print(a) // 1

One approach to have this behavior is to remove the "redeclare" check in type checker. In the then_block, the a is added to identifier_types in the ir. However, im thinking that redceclaring might have problems in the register allocation, as a variable in a if block would share the conflicts of whatever it previously had prematurely. Additionally, without name mangling, both as would be assigned to the same location and this the result would not even be correct.

@brandonLi8
Copy link
Owner Author

brandonLi8 commented Mar 8, 2023

I started working on this and I think I realized that maybe redeclared variables shouldn't be allowed at all. The best way to do it for now could be to just do it the "java" model, where

let a = 1
if true {
  let a = 2; // ERROR: redeclare in the same scope (
}

In java, if statements are sort of a psuedo scope where anything it creates doesnt live past the if statement, but it is the same scope in the sense that It cant create a local a.

However, this will need to be revisited later on when functions are implemented (since they do have their own entire scope)

let a: int = 0
let b: int = 9

function f() {
   let a: int = 1; // entirely local a
   a + b // 10
}

In this case, the f() will by default inherit the global scope (so b=9, a=0), but allow it to have a local a. We will have to mangle the a within the f() to be different from the global a

Here is my progress for name_mangler:

``` // Copyright © 2022-2023 Brandon Li. All rights reserved.

//! Name mangling is the process of making every variable name unique. It is needed to ensure that variables in
//! different scopes are placed in different locations at run time. See https://github.com/brandonLi8/solis/issues/45.
//! It is performed in the same pass as the IR translation, and works in conjunction with the translator.
//!
//! The translator traverses down the AST tree, and flattens by post-operating on the sub results. Before operating on
//! the sub-results, the mangler operates on the expression.

use File;
use std::ops::Range;
use error_messages::compilation_error;
use std::collections::HashMap;

/// Name Mangler for each scope of the program.
pub struct Mangler<'a> {
/// Maps pre-mangled name to (the most recent) post-mangled name.
mangled_names: HashMap<String, String>,

/// The number of mangled names.
mangled_names_count: u32,

/// The original Solis input file, for error messaging purposes.
pub file: &'a File,

}

impl<'a> Mangler<'a> {
/// Mangler constructor.
/// * file: the original Solis file
pub fn new(file: &'a File) -> Self {
Mangler { file, mangled_names: HashMap::new(), mangled_names_count: 0 }
}

/// Constructs a Mangler from another Mangler, with the mangled_names cloned
pub fn inherited(mangler: &Mangler<'a>) -> Self {
    Mangler { file: mangler.file, mangled_names: mangler.mangled_names.clone(), mangled_names_count: 0 }
}

/// Converts a pre-mangled name to a post-mangled name for a variable.
pub fn mangle(&mut self, id: &String) -> String {
    let name = format!("{id}_mangle{}", self.mangled_names_count);
    self.mangled_names_count += 1;

    self.mangled_names.insert(id.to_string(), name.to_string());
    name
}

/// Gets the post-mangled name of a variable. If the variable has not been declared, a `compilation_error` is
/// created.
pub fn get_name(&self, id: &String, position: &Range<usize>) -> String {
    let name = self.mangled_names.get(id);
    if name.is_none() {
        compilation_error(self.file, position, &format!("Undeclared variable `{id}`"))
    }
    name.unwrap().clone()
}

}

</details>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant