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

Add pub attribute for struct fields #232

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
19 changes: 5 additions & 14 deletions src/type_checker/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,22 +123,13 @@ impl<B: Backend> TypeChecker<B> {
.find(|(field_name, _, _)| field_name == &rhs.value)
{
// check for the pub attribute
let is_public = attribute
.as_ref()
.map(|attr| matches!(attr.kind, AttributeKind::Pub))
.unwrap_or(false);
let is_public = matches!(attribute, &Some(Attribute { kind: AttributeKind::Pub, .. }));

// check if we're inside a method of the same struct
let in_method = if let Some(fn_kind) = typed_fn_env.current_fn_kind() {
match fn_kind {
FuncOrMethod::Method(method_struct) => {
method_struct.name == struct_name
}
FuncOrMethod::Function(_) => false,
}
} else {
false
};
let in_method = matches!(
typed_fn_env.current_fn_kind(),
FuncOrMethod::Method(method_struct) if method_struct.name == struct_name
);

if is_public || in_method {
// allow access
Expand Down
24 changes: 13 additions & 11 deletions src/type_checker/fn_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl TypeInfo {
}

/// The environment we use to type check functions.
#[derive(Default, Debug, Clone)]
#[derive(Debug, Clone)]
pub struct TypedFnEnv {
/// The current nesting level.
/// Starting at 0 (top level), and increasing as we go into a block.
Expand All @@ -57,13 +57,19 @@ pub struct TypedFnEnv {
forbid_forloop_scope: bool,

/// The kind of function we're currently type checking
current_fn_kind: Option<FuncOrMethod>,
current_fn_kind: FuncOrMethod,
}

impl TypedFnEnv {
/// Creates a new TypeEnv
pub fn new() -> Self {
Self::default()
/// Creates a new TypeEnv with the given function kind
pub fn new(fn_kind: &FuncOrMethod) -> Self {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sure there is a more elegant way of doing this. The reason I went with this is that since current_fn_kind is not an option, calling Self::default() calls the default constructor of FuncOrMethod as well, which calls unreachable!:

unreachable!()

How can we do it better?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch.
With FuncOrMethod, I think it should be always calling ::new to specify the fn_kind.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I didn't fully understand the last part. Do you mean the default() for FuncOrMethod should change (return a new object instead of unreachable) or is the current approach okay as is?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant default() should be removed, if it is not used anymore.

Self {
current_scope: 0,
vars: HashMap::new(),
forloop_scopes: Vec::new(),
forbid_forloop_scope: false,
current_fn_kind: fn_kind.clone(),
}
}

/// Enters a scoped block.
Expand Down Expand Up @@ -186,11 +192,7 @@ impl TypedFnEnv {
}
}

pub fn current_fn_kind(&self) -> Option<&FuncOrMethod> {
self.current_fn_kind.as_ref()
}

pub fn set_current_fn_kind(&mut self, kind: FuncOrMethod) {
self.current_fn_kind = Some(kind);
pub fn current_fn_kind(&self) -> &FuncOrMethod {
&self.current_fn_kind
}
}
4 changes: 1 addition & 3 deletions src/type_checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,7 @@ impl<B: Backend> TypeChecker<B> {
// `fn main() { ... }`
RootKind::FunctionDef(function) => {
// create a new typed fn environment to type check the function
let mut typed_fn_env = TypedFnEnv::default();

typed_fn_env.set_current_fn_kind(function.sig.kind.clone());
let mut typed_fn_env = TypedFnEnv::new(&function.sig.kind);

// if we're expecting a library, this should not be the main function
let is_main = function.is_main();
Expand Down
Loading