Replies: 1 comment 1 reply
-
|
Just checking I understand your proposal, so to roughly sketch out the idea with function definitions you'd have something like the below? # PODs
@dataclass
class DefinitionRecord
id: ...
name: ...
...
@dataclass
class FunctionRecord
link_name: ...
...
# Protocols
class Parsed(Protocol)
def compile(self) -> Compiled:
...
# Wrapper classes
@dataclass
class ParsedFunctionDef()
definition_record: DefinitionRecord
function_record: FunctionRecord
metadata: FunctionMetadata
...
def compile(self) -> Compiled:
...I think using protocols is a good idea, though passing around the records and accessing fields on them might become a bit unwieldy? I also like the idea of the different stages being a bit more separated, however I am not sure I see how exactly this proposal achieves that (besides a big refactor like this being a good time to do it). |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Current State
The guppy codebase has quite a bit of inheritance (I'm just stating, not expressing an opinion for and against).
a. Some of this is for abstract methods to be implemented by a range of subclasses; for example,
def load_with_args. (I'm not clear whether there is any overriding of a superclass implementation.)b. In other cases it's so a dataclass can inherit a big bunch of fields - a typical example would be a class representing a checked thing (e.g. function def) inherits from the class for a parsed thing, then adds new information figured out by checking. This is attempting to inherit implementation (storage) but kind-of-accidentally also inheriting interface (potentially, unwanted methods).
As well as subclass/protocol polymorphism, many of the types of variables/function arguments/return values are union types - with lots of
isinstanceto handle all cases - specifically (these change in feat!: Monomorphise everything during type checking #1441):Not inherently opposed to having both virtual method dispatch for things with common interface and
isinstancefor things without, but I do wonder ifisinstancecombined with the inheritance of methods from earlier stages, might lead to accidents?Proposal
Firstly I wonder if the union types would be more readable if they were instead common protocols like
get_parsedorget_checked(whereParsedDeforCheckedDefwould justreturn self)More broadly we might want to think about defining:
Parsedprotocol might define a methodcheckthat returns something implementing aCheckedprotocol.Goals
Besides generally wanting to avoid "accidentally picking the wrong method", one goal would be to strengthen the separation between stages of parsing/checking/compiling. (I.e. by better separating the objects and interfaces.)
I think we will also want to separate phases in time: we'll need to finish checking (including comptime/tracing, an issue in itself...somewhere?) in order to build a callgraph and analyse that before can compile much to Hugr. So we might need to think about
get_checkedas well.Beta Was this translation helpful? Give feedback.
All reactions