-
Notifications
You must be signed in to change notification settings - Fork 0
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
Implement rules for types. #5
Conversation
…r to Common and rename test function for Common.
Most of this is now done. Simple interfaces can be defined with a fluent syntax, for example: const IsVec3Simple =
Blank()
.And(IsInType(FindField("x")))
.And(IsInType(FindField("y")))
.And(IsInType(FindField("z"))); will define a ruleset that will validate any type that has three fields "x", "y", "z" in them. Then we can add the following ruleset: const IsVec3Alternative =
Blank()
.And(IsInType(FindField("buffer"))); (And probably expand on this rule-set with more rules. like checking the dimension to be "3"). We could use either, and we could try to check every combination, or we could define a rule-set based off of them, like this: const IsVec3Full =
Blank()
.Or(IsVec3Simple)
.Or(IsVec3Alternative); This will verify if it either has 3 components, or an internal buffer where they are stored. We may require this so that the type itself doesn't require more memory than we want it to. Sure, a vec3 could also be implemented with 60k linked lists that somehow intermingle and result in a vec3 behavior, but we may want a simple vec3 that is implemented like this and not that abstract. This is nice, but then we would like to check if it has accessor methods, because we don't know (nor care) for the actual internal structure, so we'd define this: const IsVec3Accessors =
Blank()
.And(IsFunction(FindDeclaration("get_X")))
.And(IsFunction(FindDeclaration("get_Y")))
.And(IsFunction(FindDeclaration("get_Z"))); Now we'd have some (rudimentary) accessor checking. Then we could combine them to get our full const IsVec3 =
Blank()
.And(IsVec3Full)
.And(IsVec3Accessors); And then we could check any type like so: pub fn ComplexVec3Op(arg: anytype) !void {
comptime try IsVec3.Check(arg);
// ... do something with arg ...
// ... knowing it's a vec3 ...
} All these work so far, so it's safe to merge this. They're all at compile-time, and are therefore zero-cost (well, zero runtime cost, of course this will increase the compilation time, by how much I cannot judge right now, we'll see as this develops). |
In order for easy and flexible type checking to take place, we need some nice types that would let this happen.
Type checking a type requires checking its internals for certain wanted behavior. Each internal check will be called a "rule", and the entire type check will be called a "rule set".
For instance, take this type:
Checking whether there is a member of name
a
insidesampleType
would be done by creating a rule that can check for a member of namea
inside any type, given a certain look-up mode (Either look up anything, or just fields or just declarations), and then using it onsampleType
.Analogous to checking whether a member of name
a
exists insidesampleType
, we could make a rule that could check whether any type has a field namedb
that is alsoconst
and then use it onsampleType
.All these queries are atomic, but it would be a nice idea to let users make their own custom rules, as long as their own rules are checked so that they are valid custom type rule definitions, with valid custom rule descriptors.
Each Rule is defined and obeys an interface (for now it is not checked, as type checking is not implemented; afterwards all rules will check themselves).
Any type that checks the rule interface must have a
Check
function with the specified function signature below:Any custom rule is defined by a custom rule descriptor type (Which obeys the Rule interface mentioned earlier), and another
Check
function. This wrapperCheck
function inside the custom rule (NOT the descriptor!) first checks that the custom rule descriptor itself is a valid rule, and then safely calls theCheck
function from inside of the custom rule descriptor.Things remaining to do: