Replies: 8 comments
-
The base of the languageZilch is a functional at core programming language, focused on low-level and performance by integrating a few features from imperative programming. The surface languageThe surface language is basically a λ-calculus extended with rec fact(n : u64) : u64 ≔
if n = 0 then 1 else n × fact(n - 1) Alternatively, this could also be written rec fact(n : u64) : u64 ≔
match n with
0 ⇒ 1
_ ⇒ n × fact(n - 1) Notice the heavy use of Unicode in the source code. It is a good idea to install WinCompose if you are on Windows, or to configure XCompose on Linux (I do not know the alternative for Mac users…sorry). Builtin types
Currently planned builtin operations (may change)Some operations will be implemented as primops (meaning directly written in N⋆, but having a special meaning within the compiler itself).
All these operations are builtin because they convey specific information and must be used (and compiled) differently within the type-checker. |
Beta Was this translation helpful? Give feedback.
-
Dependent and quantitative typesThe type system for Zilch is based on a Dependent Type Theory augmented with multiplicities to get explicit erasure and resource linearity (also known as Quantitative Type Theory, where the resource fragment contains In Zilch, the syntax for multiplicities is:
In the absence of explicit multiplicities, the following multiplicities are assumed:
|
Beta Was this translation helpful? Give feedback.
-
Semi-automatic memory management with (infered) regionsRegions are a model of memory management which is mostly automatic. In general, it seems to exhibit faster speeds than garbage collectors, and speeds similar to manual memory management, all while having a small runtime footprint. In Zilch, regions can either be constructed explicitly using the let my-fun() : ⟨console⟩ 𝟏 ≔
region ρ
let r ≔ make-ref{ρ, u64}(0)
let () ≔ ref-update(r, 1)
() The newly created region let my-fun() : ⟨console⟩ ref(u64, _) ≔
region ρ
let r ≔ make-ref{ρ, u64}(0)
let () ≔ ref-update(r, 1)
r In this case, the hole |
Beta Was this translation helpful? Give feedback.
-
Algebraic effectsAlgebraic effects allow users to dynamically inject code in place of certain function calls, through the notion of “handlers”. A common example of algebraic effects are exceptions, which have been commonly found in high-level programming languages for quite a while. effect exn(@0 E : type) ≔
val throw(ex : E) : 𝟏 Various handlers could be defined. Here are the two most common handlers:
Writing handlers is as easy as that, as long as all the potential effects are handled (here, only This approach to handling side effects is more fine-grained than what can be found in e.g. Haskell (death to |
Beta Was this translation helpful? Give feedback.
-
Refinement typesRefinement types are specific kinds of types associating a base type with (a few) acceptation condition. let @0 nat64 ≔ [x : s64 | x ⩾ 0] The type let @0 vec64-7 ≔ [v : vec(u64) | size(v) = 5 ∧ vec-all(λ x. x ⩾ 7, v)] Although this last type is something that nobody actually wants, it shows that multiple conditions can be specified. Note that in fact, any boolean expression is allowed as the refinement predicate. Verification condition are automatically generated an discharged (when possible) using standard SMT techniques, so as not to burden the users with actually having to do proofs (which would not necessarily be possible anyway, since Zilch isn't focused on that at all). |
Beta Was this translation helpful? Give feedback.
-
Syntax notationsIn modern programming languages (and mostly in proof assistants), it is usually common to define some syntactic elements such as custom operators. There are several ways to define new notations for custom operations:
Note that declaring infix operators with |
Beta Was this translation helpful? Give feedback.
-
Datatypes, records and dictionary instancesData in Zilch is structured using two kinds of construct:
|
Beta Was this translation helpful? Give feedback.
-
Foreign interfaceExporting functionsBy default, polymorphic bindings are mangled following the Itanium C++ ABI naming conventions, but monomorphic bindings can be chosen not to be mangled, giving stable names for C interoperability (and all languages which can interoperate with C, such as C++ or Rust). Importing functionsAs for using foreign functions, note that only monomorphic functions can be called (or at least should be accepted by the compiler), so as not to expose the internal value representation. |
Beta Was this translation helpful? Give feedback.
-
Last year, I initiated a topic (see #4) to try and discuss all planned features for the first versions of Zilch.
Initially, it was supposed to record any design progress as well as any thoughts, but it kinda quickly became inactive, and I have been thinking a lot on my own without posting about it.
I feel that the language itself has evolved quite a lot, and needs to be broken down somewhere at some point.
This is the goal of this topic.
All features will be posted in separate comments below, one by one.
Beta Was this translation helpful? Give feedback.
All reactions