From: "Daniel P. Berrangé" <berrange@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: Victor Toso <victortoso@redhat.com>,
qemu-devel@nongnu.org, John Snow <jsnow@redhat.com>
Subject: Re: [PATCH v1 1/9] qapi: golang: Generate qapi's enum types in Go
Date: Thu, 28 Sep 2023 15:34:44 +0100 [thread overview]
Message-ID: <ZRWPBJKASLmmK/f/@redhat.com> (raw)
In-Reply-To: <87cyy2tm48.fsf@pond.sub.org>
On Thu, Sep 28, 2023 at 04:20:55PM +0200, Markus Armbruster wrote:
> Daniel P. Berrangé <berrange@redhat.com> writes:
>
> > On Wed, Sep 27, 2023 at 01:25:36PM +0200, Victor Toso wrote:
> >> This patch handles QAPI enum types and generates its equivalent in Go.
> >>
> >> Basically, Enums are being handled as strings in Golang.
> >>
> >> 1. For each QAPI enum, we will define a string type in Go to be the
> >> assigned type of this specific enum.
> >>
> >> 2. Naming: CamelCase will be used in any identifier that we want to
> >> export [0], which is everything.
> >>
> >> [0] https://go.dev/ref/spec#Exported_identifiers
> >>
> >> Example:
> >>
> >> qapi:
> >> | { 'enum': 'DisplayProtocol',
> >> | 'data': [ 'vnc', 'spice' ] }
> >>
> >> go:
> >> | type DisplayProtocol string
> >> |
> >> | const (
> >> | DisplayProtocolVnc DisplayProtocol = "vnc"
> >> | DisplayProtocolSpice DisplayProtocol = "spice"
> >> | )
> >>
> >> Signed-off-by: Victor Toso <victortoso@redhat.com>
> >> ---
> >> scripts/qapi/golang.py | 140 +++++++++++++++++++++++++++++++++++++++++
> >> scripts/qapi/main.py | 2 +
> >> 2 files changed, 142 insertions(+)
> >> create mode 100644 scripts/qapi/golang.py
> >>
> >> diff --git a/scripts/qapi/golang.py b/scripts/qapi/golang.py
> >> new file mode 100644
> >> index 0000000000..87081cdd05
> >> --- /dev/null
> >> +++ b/scripts/qapi/golang.py
> >> @@ -0,0 +1,140 @@
> >> +"""
> >> +Golang QAPI generator
> >> +"""
> >> +# Copyright (c) 2023 Red Hat Inc.
> >> +#
> >> +# Authors:
> >> +# Victor Toso <victortoso@redhat.com>
> >> +#
> >> +# This work is licensed under the terms of the GNU GPL, version 2.
> >> +# See the COPYING file in the top-level directory.
> >> +
> >> +# due QAPISchemaVisitor interface
> >> +# pylint: disable=too-many-arguments
> >> +
> >> +# Just for type hint on self
> >> +from __future__ import annotations
> >> +
> >> +import os
> >> +from typing import List, Optional
> >> +
> >> +from .schema import (
> >> + QAPISchema,
> >> + QAPISchemaType,
> >> + QAPISchemaVisitor,
> >> + QAPISchemaEnumMember,
> >> + QAPISchemaFeature,
> >> + QAPISchemaIfCond,
> >> + QAPISchemaObjectType,
> >> + QAPISchemaObjectTypeMember,
> >> + QAPISchemaVariants,
> >> +)
> >> +from .source import QAPISourceInfo
> >> +
> >> +TEMPLATE_ENUM = '''
> >> +type {name} string
> >> +const (
> >> +{fields}
> >> +)
> >> +'''
> >> +
> >> +
> >> +def gen_golang(schema: QAPISchema,
> >> + output_dir: str,
> >> + prefix: str) -> None:
> >> + vis = QAPISchemaGenGolangVisitor(prefix)
> >> + schema.visit(vis)
> >> + vis.write(output_dir)
> >> +
> >> +
> >> +def qapi_to_field_name_enum(name: str) -> str:
> >> + return name.title().replace("-", "")
> >> +
> >> +
> >> +class QAPISchemaGenGolangVisitor(QAPISchemaVisitor):
> >> +
> >> + def __init__(self, _: str):
> >> + super().__init__()
> >> + types = ["enum"]
> >> + self.target = {name: "" for name in types}
> >> + self.schema = None
> >> + self.golang_package_name = "qapi"
> >> +
> >> + def visit_begin(self, schema):
> >> + self.schema = schema
> >> +
> >> + # Every Go file needs to reference its package name
> >> + for target in self.target:
> >> + self.target[target] = f"package {self.golang_package_name}\n"
> >> +
> >> + def visit_end(self):
> >> + self.schema = None
> >> +
> >> + def visit_object_type(self: QAPISchemaGenGolangVisitor,
> >> + name: str,
> >> + info: Optional[QAPISourceInfo],
> >> + ifcond: QAPISchemaIfCond,
> >> + features: List[QAPISchemaFeature],
> >> + base: Optional[QAPISchemaObjectType],
> >> + members: List[QAPISchemaObjectTypeMember],
> >> + variants: Optional[QAPISchemaVariants]
> >> + ) -> None:
> >> + pass
> >> +
> >> + def visit_alternate_type(self: QAPISchemaGenGolangVisitor,
> >> + name: str,
> >> + info: Optional[QAPISourceInfo],
> >> + ifcond: QAPISchemaIfCond,
> >> + features: List[QAPISchemaFeature],
> >> + variants: QAPISchemaVariants
> >> + ) -> None:
> >> + pass
> >> +
> >> + def visit_enum_type(self: QAPISchemaGenGolangVisitor,
> >> + name: str,
> >> + info: Optional[QAPISourceInfo],
> >> + ifcond: QAPISchemaIfCond,
> >> + features: List[QAPISchemaFeature],
> >> + members: List[QAPISchemaEnumMember],
> >> + prefix: Optional[str]
> >> + ) -> None:
> >> +
> >> + value = qapi_to_field_name_enum(members[0].name)
> >> + fields = ""
> >> + for member in members:
> >> + value = qapi_to_field_name_enum(member.name)
> >> + fields += f'''\t{name}{value} {name} = "{member.name}"\n'''
> >> +
> >> + self.target["enum"] += TEMPLATE_ENUM.format(name=name, fields=fields[:-1])
> >
> > Here you are formatting the enums as you visit them, appending to
> > the output buffer. The resulting enums appear in whatever order we
> > visited them with, which is pretty arbitrary.
>
> We visit in source order, not in arbitrary order.
I meant arbitrary in the sense that us developers just add new
QAPI types pretty much anywhere we feel like it in the .qapi
files.
>
> > Browsing the generated Go code to understand it, I find myself
> > wishing that it was emitted in alphabetical order.
>
> If that's easier to read in generated Go, then I suspect it would also
> be easier to read in the QAPI schema and in generated C.
Yes, although C has some ordering constraints on things being
declared, so it would be a bit harder to do this in C.
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
next prev parent reply other threads:[~2023-09-28 14:35 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-27 11:25 [PATCH v1 0/9] qapi-go: add generator for Golang interface Victor Toso
2023-09-27 11:25 ` [PATCH v1 1/9] qapi: golang: Generate qapi's enum types in Go Victor Toso
2023-09-28 13:52 ` Daniel P. Berrangé
2023-09-28 14:20 ` Markus Armbruster
2023-09-28 14:34 ` Daniel P. Berrangé [this message]
2023-09-29 12:07 ` Victor Toso
2023-10-02 19:07 ` John Snow
2023-10-02 20:09 ` John Snow
2023-10-04 12:43 ` Victor Toso
2023-10-04 16:23 ` John Snow
2023-10-04 12:28 ` Victor Toso
2023-09-27 11:25 ` [PATCH v1 2/9] qapi: golang: Generate qapi's alternate " Victor Toso
2023-09-28 14:51 ` Daniel P. Berrangé
2023-09-29 12:23 ` Victor Toso
2023-09-29 12:37 ` Daniel P. Berrangé
2023-10-02 21:48 ` John Snow
2023-10-04 17:01 ` Victor Toso
2023-10-02 20:36 ` John Snow
2023-10-04 16:46 ` Victor Toso
2023-09-27 11:25 ` [PATCH v1 3/9] qapi: golang: Generate qapi's struct " Victor Toso
2023-09-28 14:06 ` Daniel P. Berrangé
2023-09-29 13:29 ` Victor Toso
2023-09-29 13:33 ` Daniel P. Berrangé
2023-09-27 11:25 ` [PATCH v1 4/9] qapi: golang: structs: Address 'null' members Victor Toso
2023-09-27 11:25 ` [PATCH v1 5/9] qapi: golang: Generate qapi's union types in Go Victor Toso
2023-09-28 14:21 ` Daniel P. Berrangé
2023-09-29 13:41 ` Victor Toso
2023-10-11 13:27 ` Victor Toso
2023-09-27 11:25 ` [PATCH v1 6/9] qapi: golang: Generate qapi's event " Victor Toso
2023-09-27 11:25 ` [PATCH v1 7/9] qapi: golang: Generate qapi's command " Victor Toso
2023-09-28 14:32 ` Daniel P. Berrangé
2023-09-29 13:53 ` Victor Toso
2023-10-14 14:26 ` Victor Toso
2023-09-27 11:25 ` [PATCH v1 8/9] qapi: golang: Add CommandResult type to Go Victor Toso
2023-09-28 15:03 ` Daniel P. Berrangé
2023-09-29 13:55 ` Victor Toso
2023-09-27 11:25 ` [PATCH v1 9/9] docs: add notes on Golang code generator Victor Toso
2023-09-28 13:22 ` Daniel P. Berrangé
2023-09-29 12:00 ` Victor Toso
2023-09-27 11:38 ` [PATCH v1 0/9] qapi-go: add generator for Golang interface Victor Toso
2023-09-28 13:40 ` Daniel P. Berrangé
2023-09-28 13:54 ` Daniel P. Berrangé
2023-09-29 14:08 ` Victor Toso
2023-09-29 14:17 ` Victor Toso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZRWPBJKASLmmK/f/@redhat.com \
--to=berrange@redhat.com \
--cc=armbru@redhat.com \
--cc=jsnow@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=victortoso@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).