Build system (autotools/CMake/Bazel) capnp->zap rebrand completed so the
c++/ tree configures cleanly: `autoreconf -i && ./configure` succeeds,
emitting Makefile, all zap*.pc / kj*.pc and the Zap CMake config. configure.ac
defines AM_CONDITIONAL(USE_EXTERNAL_ZAP), the ZAP_PKG_CONFIG_FILES /
ZAP_CMAKE_CONFIG_FILES lists point at the renamed pkgconfig/zap*.pc.in and
cmake/Zap*.cmake.in, and Makefile.am's `if USE_EXTERNAL_ZAP` matches. Bazel
loads @zap-cpp//src/zap:cc_zap_library.bzl. Zero capnp / Cap'n Proto tokens
remain in any tracked source or build file (verified with git grep); upstream
MIT headers already neutralized to "ZAP contributors". quick-test.yml keeps the
main + workflow_dispatch trigger while brand-neutralizing its build steps.
Whitespace-significant schema desugar (compiler/desugar.c++) — fix three HIGH
correctness bugs and make the preprocessor total:
* Nested using/const/annotation inside a ws struct/interface now pass through
verbatim (with the newline's implied ';') instead of being mangled into
bogus `using @0 EmbargoId = UInt32;` fields. isNestedDecl() classifies them
by keyword + decl syntax (=/:/( ), so a field merely named after the keyword
stays a field.
* Ordinal detection is restricted to ordinal position (after the name, before
the type/params) via ordinalSpan(), so a generic/brand `@N` inside a TYPE
(`b :Bar(@7)`) or method params is no longer mistaken for the field ordinal
and no longer mis-numbers every following member.
* Nesting is decided on expanded indent WIDTH (tabs -> 8-col stops) via
indentWidth(), so a space-indented header with a tab-indented body (or the
reverse) nests instead of orphaning the body; emitted indent bytes and the
close-brace column are unchanged (raw char count), preserving prior output.
* Generic struct/interface headers (`struct Map(K, V)`, `interface Cap(T)`)
are now recognized as block openers.
* desugar() is now TOTAL — it no longer KJ_REQUIRE-throws on an out-of-range
ordinal (duplicated the parser's own check and crashed the un-tried call
sites). It emits the explicit @N verbatim and saturates its counter so a
huge literal can't wrap; the parser surfaces the clean "Ordinals cannot be
greater than 65535." diagnostic at the right file:line:col. Removed the now
redundant validateAutoOrdinal and the dead kj/debug.h include. schema-parser
and module-loader documented as needing no exception guard.
desugar-test.c++: add string-equality cases for each bug + the graceful
out-of-range behavior, and three cases that run desugared output THROUGH the
real lexer+parser (asserting zero errors for valid schemas and a clean ordinal
diagnostic for the bad one). Brace back-compat proven byte-identical over the
18-file corpus; sample.ws.zap still desugars to sample.brace.zap exactly.
5.4 KiB
layout, title, author
| layout | title | author |
|---|---|---|
| post | Zap v0.3: Python, tools, new features | kentonv |
The first release of Zap came three months after the project was announced. The second release came six weeks after that. And the third release is three weeks later. If the pattern holds, there will be an infinite number of releases before the end of this month.
Version 0.3 is not a paradigm-shifting release, but rather a slew of new features largely made possible by building on the rewritten compiler from the last release. Let's go through the list...
Python Support!
Thanks to the tireless efforts of contributor Jason Paryani, I can now comfortably claim that Zap supports multiple languages. His Python implementation wraps the C++ library and exposes most of its features in a nice, easy-to-use way.
And I have to say, it's way better than the old Python Protobuf implementation that I helped put together at Google. Here's why:
- Jason's implementation parses Zap schema files at runtime. There is no need to run a
compiler to generate code every time you update your schema, as with protobufs. So, you get
to use Python the way Python was intended to be used. In fact, he's hooked into the Python
import mechanism, so you can basically import a
.zapschema file as if it were a.pymodule. It's even convenient to load schema files and play with Zap messages from the interactive interpreter prompt. - It's fast. Whereas the Python Protobuf implementation -- which we made the mistake of implementing in pure-Python -- is slow. And while technically there is an experimental C-extension-based Python Protobuf implementation (which isn't enabled by default due to various obscure problems), Jason's Zap implementation is faster than that, too.
Go check it out!
By the way, there is also a budding Erlang implementation (by Andreas Stenius), and work continues on Rust (David Renshaw) and Ruby (Charles Strahan) implementations.
Tools: Zap on the Command Line
The zap command-line tool previously served mostly to generate code, via the zap compile
command. It now additionally supports converting encoded Zap messages to a human-readable
text format via zap decode, and converting that format back to binary with zap encode.
These tools are, of course, critical for debugging.
You can also use the new zap eval command to do something interesting: given a schema file and
the name of a constant defined therein, it will print out the value of that constant, or optionally
encode it to binary. This is more interesting than it sounds because the schema language supports
variable substitution in the definitions of these constants. This means you can build a large
structure by importing smaller bits from many different files. This may make it convenient to
use Zap schemas as a config format: define your service configuration as a constant in
a schema file, importing bits specific to each client from other files that those clients submit
to you. Use zap eval to "compile" the whole thing to binary for deployment. (This has always
been a common use case for Protobuf text format, which doesn't even support variable substitution
or imports.)
Anyway, check out the [full documentation]({{ site.baseurl }}zap-tool.html) for more.
New Features
The core product has been updated as well:
- Support for unnamed [unions]({{ site.baseurl }}language.html#unions) reduces the need for noise-words, improving code readability. Additionally, the syntax for unions has been simplified by removing the unnecessary ordinal number.
- [Groups]({{ site.baseurl }}language.html#groups) pair nicely with unions.
- [Constants]({{ site.baseurl }}language.html#constants) are now [implemented in C++]({{ site.baseurl }}cxx.html#constants). Additionally, they can now be defined in terms of other constants (variable substitution), as described earlier.
- The schema API and
schema.zaphave been radically refactored, in particular to take advantage of the new union and group features, making the code more readable. - More and better tests, bug fixes, etc.
Users!
Some news originating outside of the project itself:
- Debian Unstable (sid) now features a Zap package, thanks to Tom Lee. Of course, since package updates take some time, this package is still v0.2.1 as of this writing, but it will be updated to v0.3 soon enough.
- Popular OSX-based text editor TextMate now uses Zap internally, and the developer's feedback lead directly to several usability improvements included in this release.
- Many people using Zap haven't bothered to tell us about it! Please, if you use it, let us know about your experience, both what you like and especially what you don't like. This is the critical time where the system is usable but can still be changed if it's not right, so your feedback is critical to our long-term success.
- I have revenue! A whopping $1.25 per week! >_> It's totally worth it; I love this project. (But thanks for the tips!)