(I've also posted the following on SO, but I guess it's a more Nim-specific question)
Before saying anything, please let me make it clear that this question is part of my work on an interpreter - and has nothing to do with validating a Nim proc's arguments.
Let's say we have an enum of Value types. So a value can be:
SV, // stringValue
IV, // integerValue
AV, // arrayValue
etc, etc
then let's say we have a function F which takes one of the following combinations of arguments:
[
[SV],
[SV,IV],
[AV]
]
Now, the function is called, we calculate the values passed, and get their types. Let's say we get [XV,YV].
The question is:
What is the most efficient way to check if the passed values are allowed?
In more specific terms, let's say we have these constraints:
@[@[AV,FV],@[DV,FV],@[BV,FV],@[IV,FV]]
meaning: first argument can be AV, second FV - OR - first argument DV, second FV - OR - and so on...
and this is my validation function:
proc validate(xl: ExpressionList, name: string, req: FunctionConstraints): seq[Value] {.inline.} =
## Validate given ExpressionList against given array of constraints
result = xl.list.map((x) => x.evaluate()) # each x.evaluate returns a Value
if not req.contains(result.map((x) => x.kind)): # each Value has a kind: SV, IV, AV, etc...
Of course, even the .map, .contains and all that can be expensive when called many times...
So, I'm looking for alternatives. All ears! :)
If you have less than 65k values (2^16) just use Nim sets.
import strformat
type RuntimeTag = enum
SV # stringValue
IV # integerValue
AV # arrayValue
type AllowedInput = set[RuntimeTag]
proc validate(x: RuntimeTag, req: AllowedInput) =
if x notin req:
raise newException(ValueError, &"Invalid input {x}, expected one of \"{req}\"")
Is it an interpreter for a static language or dynamic language? For static language you can't have the type of the second argument change depending on the type of the first. Otherwise the fastest way is probably a state machine.