spec: Typecheck padding#670
Conversation
Codex Code ReviewNo issues found in the PR diff. I reviewed the changed TOML padding values and the new recursive padding/template checker in
It completed with |
Review: spec/typecheck-paddingSummaryThis PR introduces type-checking for padding values in chip specs, fixing two concrete bugs:
It also reorders The overall approach is sound. Two issues worth addressing: IssuesMedium – Medium – Unhandled Minor notes
|
There was a problem hiding this comment.
I agree that the padding is invalid.
The proposed solution works.
A cleaner solution might be to have div_by_zero = 0.
There was a problem hiding this comment.
Encoding 0/1 = 0 then?
There was a problem hiding this comment.
Aha, the downside is that it makes the NEG workaround no longer work, because then we have NEG<1, signed>
| if file in sys.argv[1:3]: | ||
| continue | ||
| chips.append(Chip.from_file(config, file)) | ||
| chips.append(chip := Chip.from_file(config, file)) |
There was a problem hiding this comment.
Not a fan of the walrus here.
| chips.append(chip := Chip.from_file(config, file)) | |
| chip = Chip.from_file(config, file) | |
| chips.append(chip) |
| continue | ||
| chips.append(Chip.from_file(config, file)) | ||
| chips.append(chip := Chip.from_file(config, file)) | ||
| template_checkers[chip.name] = template_checker(template_checkers, chip) |
There was a problem hiding this comment.
this recursion is trippy: to set template_checkers[some chip]: Callable, it passes in all of template_checkers, which gets bound (?) into a function which is then returned?
This, I believe, requires proper documentation, either directly here, or by wrapping this in a well-named function and documenting that function. I cannot make heads or tails of what is happening here, nor what template_checkers even means / is supposed to do.
There was a problem hiding this comment.
template_checkers is a collection of functions, indexed by template name/tag, that checks whether a given assignment satisfies the template.
Passing in template_checkers could be delayed to the invocations of these checkers as well, we're just tying the knot a bit earlier here.
We need to pass template_checkers to an individual checker somewhere to be able to deal with templates inside of a template definition (such as IS_BIT inside of ADD).
The downside of delaying the access to all templates to later is that the typing of template_checkers itself needs to become recursive, since now the Callable needs an argument of the type dict[str, Callable[dict[...], Optional[Type], ...]. Which could in itself work out
| def check_padding_fits(var_name: str, config: "Config", type: Type, pad: Expr): | ||
| def fits(v, t): | ||
| if isinstance(v, Range): | ||
| return v.is_const() and constant_fits(v.get_const(), t) | ||
| else: | ||
| return isinstance(v, list) and isinstance(t, list) and len(v) == len(t) and all(map(fits, v, t)) | ||
|
|
||
| val = pad.typecheck(Environment(config, {}, {})) | ||
| reporter.asserts(fits(val, type), f"{var_name!r}: Invalid padding {pad!r} for type {type!r}") |
There was a problem hiding this comment.
Given that var_name is passed in to be solely passed on to reporter, consider passing it in through reporter.context to give this function a cleaner signature.
There was a problem hiding this comment.
Can we do something about the names typecheck, type_match and Type?
To me, typecheck suggests a function with boolean output (fail/pass), but instead it returns an object of type Type (another stumbling block), which is actually an evaluation of sorts.
I also never know what the difference between typecheck and type_match are supposed to be.
There was a problem hiding this comment.
This is using type checking as the act of assigning types to expressions. While technically the correct term for this may actually be typing, that feels more confusing to me.
Type being a type is kinda inherent to the reification of types that you need in a context like this.
type_match is more of a local thing for individual kinds of expression, that may have a different name possible. Where it is used, it's doing essentially some combination of type coercion to make operands compatible and computing the type for the combination of the result. The reason it's separate from the typecheck method in those places is because there's a variadic number of operands in those expressions, and we collapse them with a fold. Maybe typecheck_binary is a replacement name?
This manages to catch both the observed issue with the CPUs padding for
half_instruction_lengthand an previously unknown issue in the padding for DVRM.