-
-
Notifications
You must be signed in to change notification settings - Fork 1
Conversation
src/schema.rs
Outdated
pub struct Schema { | ||
pub name: String, | ||
pub tables: Vec<Table>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should pub the attributes.
We can only pub(crate) at best, and provide getter methods as needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the right approach for this - e8415da?
I have used suffixed underscore on the field that is meant to be private and provided an immutable getter for it with the actual name. I did this because I did not like the idea of having get_xxx()
methods. Just xxx()
seems more rust-y.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the suffix _
is not as necessary in Rust as in other languages because Rust already requires you to use self.xxx
explicitly when using fields (but in, say, C++, you can simply type xxx
to use a data member so it may be confused with a local variable). Again, I really appreciate this sense of clarity provided by Rust :).
Regarding the getters, I like the use of xxx()
here instead of get_xxx()
, because xxx()
gives the sense that this method is simply a minimalistic getter without any noticeable work needed to be done. Usually, I prefer using get_xxx()
only when xxx
is a derived state that requires a significant amount of work to get.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shpun817 I assumed it would be a problem to have a field and a function with the same name, but looks like Rust handles that. Pretty cool.
Regarding the getters, I like the use of
xxx()
here instead ofget_xxx()
, becausexxx()
gives the sense that this method is simply a minimalistic getter without any noticeable work needed to be done. Usually, I prefer usingget_xxx()
only whenxxx
is a derived state that requires a significant amount of work to get.
I agree with this, makes a lot of sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed the visibility for other structs too.
src/vm.rs
Outdated
} | ||
|
||
pub enum Register { | ||
Table(Rc<Table>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might not wander into multi-thread context soon, but perhaps Arc
is better (or perhaps like sea-query, SeaRc
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean this - https://github.com/SeaQL/sea-query/blob/34532bc8d2a0511c8c617bebf59abd8e48d6d96d/src/types.rs#L6-L9?
That's an interesting way to go about this. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I implemented this in 6882d4f. What do you think of the name Mrc
?
src/vm.rs
Outdated
use crate::{table::Table, ic::IntermediateCode}; | ||
|
||
pub struct VirtualMachine { | ||
pub registers: HashMap<usize, Register>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we would like the hash key to be a new type instead of usize, may be something like pub struct RegisterIndex(usize)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get it. Wouldn't this mean we would have to derive or implement Hash
, Eq
, Clone
again for this new type? I meant for this to be used like a sparse array/vec. I don't see how a new type adds value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I second Chris in this.
Using a new type provides better clarity in the value when it's used (imagine creating a variable to hold the index and seeing its type is usize
vs RegisterIndex
).
It can also achieve encapsulation. If you design a nice API for it, the user does not need to know about what RegisterIndex
is made up of. That way you can also better control, say, how a new index is generated and so on.
Wouldn't this mean we would have to derive or implement Hash, Eq, Clone again for this new type
That's true, but I would also argue that, even though it may incur additional costs of deriving/implementing those traits, it, again, provides clarity of the set of properties that you need for this index type. You see, usize
is a built-in type with a lot of traits ready-implemented, but surely not all the traits are required for it to serve as your index type. If you create a new type and derive/implement only the necessary traits, you and anyone who takes just a glance of your code can be well-informed of exactly what functionalities are needed of this type in its place.
I believe this kind of stricter requirements in the typing system is one of the best of what Rust has to offer, since it ensures clarity and correctness in the long run.
Of course, those are general comments about abstracting types when built-in types "suffice". They may not always be or seem that relevant especially before things get too complicated in your systems, but I'd say investing that little extra work eventually pays off more often than not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it did not make sense to have an auto-incrementing register index in the VM. The intermediate code will be generated before execution, so it will have concrete indexes anyway. Fixed this in b46d3e8. Though, this makes the insert
and get
methods simply a wrapper of HashMap
's methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you Sanford for the great points!
Actually why I want to avoid usize is to avoid the accidental casting from other integer types, particularly isize.
And that when a function accepts two usizes say foo(idx: usize, len: usize)
this is error prone.
I have seen nasty bugs this way multiple times.
UInt8Null(Option<u8>), | ||
UInt8(u8), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks clumsy. I would prefer a Nullable<T>
may be. Havn't got a clear idea of the use yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nullable<T>
Do you mean an Option<T>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I mean you remove all XXNull variants, and create a Nullable to wrap it.
It's kind of like Option, but with our own definition.
The trick is, we only impl Nullable<Value>
so it is actually a sealed type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see. That seems like a much better approach. Alternatively, there could be a Null
variant of Value
.
Would merge this now. Nice work so far! |
Actually, the commit messages in this branch weren't good. I wanted to squash them before merging. I'll do that on main instead. |
PR Info
Adds
Fixes
Breaking Changes
Changes