DEV Community

IrrelevantGaymer
IrrelevantGaymer

Posted on

$ugar Progress and Accessors

Progress

Since the last post, I had finished the elxer and started work on the parser. I've been building the project in Rust, and I've been loving it so far. I've done a couple projects in Rust but none of them made me dive into the borrow checker and lifetimes that much. This project however has forced me to wrestle with the compiler in a fun way. I still am personally struggling with the concept of interior mutability, but I think my struggling was due to using the wrong struct. I was trying to use a Cell to allow for passing a usize to multiple methods which can mutate the value, when I think in retrospect RefCell or some other structure might have been better. When Cell wasn't working for me, I decided to encapsulate the value into the state of the lexer, so any methods would mutate the lexer object instead of passing the value around everywhere.

While working on the project, I wanted to mess with nasm to help me better understand the layout of my abstract syntax tree and how some of my planned features will work in assembly. My devices have been on windows, and in my experience, I could not make a single executable at all. I then decided to try out Linux on the laptop I had recently purchased which was where I had moved the project to. I downloaded Linux Cinnamon, and I downloaded all my languages and applications: I've honestly been really enjoying it. My computer is much faster, downloading things with the terminal has been super nice, and I've been slightly learning neovim. For now, I will be sticking with Visual Studio Code for the mean time, until I learn to be fast with neovim. I also got assembly working, which was a breeze with Linux, and then it hit me. I forgot to save my progress.

I had been meaning to create a git repository for $ugar, and failing to do so has bitten me in the ass. At the moment, I have a half finished Lexer. The good news is that I have a really good idea of how I want to structure the Lexer now, I know what changes need to be made, and the second Lexer should be a little more organized than the first one.

For each blog post, I either want to share a feature or describe how a feature is implemented. I think this will also help lighten the mood of the post given the wake of my incompetence.

User Defined Accessors

Accessors is a concept that restricts or permits the accessibility of a variable to other objects/namespaces. Most accessors fall in one of 3 categories: everyone can access me (public), only I can access me (private), and only my family can access me (protected). There are other accessors that are based off the programs assembly, but for the most part, languages (in my experience) have public, private, and protected in some form or another. In $ugar, there are 3 default accessors: pub, prv, and pkg. Because $ugar doesn't have a concept of inheriting fields from other classes, protected in its traditional sense doesn't make any sense, so what pkg does is allow any class or namespace within the variables namespace to access the variable.

These 3 accessors are probably sufficient enough on their own, however I really believe in the concept of only giving access to things that need access. It'd be nice to say that only these classes/namespaces can access this variable, which indicates what portions of your code is accessing or modifying the data. This would be very useful for code readability, maintainability, and safety. This is the goal for user defined accessors or custom accessors.

You will be able to give a name and set whitelists and blacklists for what classes and namespaces.

accessor @user_pub {
    blacklist {

    }
}
Enter fullscreen mode Exit fullscreen mode

The general convention for naming accessors is snake_case prefaced by the @ symbol (a for accessor). This will be just a convention however, and does not need to be followed (although it is highly recommended that you do). The above accessor will allow any class or namespace to access any variable with the @user_pub accessor, so its just another pub accessor.

Custom accessors have a whitelist and a blacklist. The whitelist includes classes/namespaces which can access the attached variables/functions, while blacklists exclude instead. If a whitelist is not defined, every class and namespace is included in the whitelist which the blacklist can exclude classes and namespaces from. A whitelist and/or a blacklist must be included in the accessor definition: Including both may be useful if you want to include a namespace but exclude certain classes or namespaces within the whitelisted namespace.

accessor @health {
    whitelist {
        PlayerSystem, EnemySystem, HealthSystem
    }
    blacklist {
        InventorySystem
    }
}
Enter fullscreen mode Exit fullscreen mode

This custom accessor denotes that only these systems interact with health related data, shows which variables and functions, and restricts classes and namespaces which do not touch the Health System from accessing those variables and functions.

To apply the accessor to a variable or function, you simply would replace a default accessor with your custom accessor.

@health static f32 maxHealth = 20.0;
@health static f32 health = 10.0;

@health mut fn ReplenishHealth {
    health = maxHealth;
}
Enter fullscreen mode Exit fullscreen mode

The syntax for accessors allow to easily be modified in the future. It also doesn't have a scaling issue like colored functions or lifetimes in rust, where adding/changing something will not require you to propagate that change everywhere that utilizes the modified thing.

Top comments (0)