add dark mode

This commit is contained in:
waalge 2023-08-31 20:27:04 +00:00
parent 05969ce7cc
commit f3b88b8446
14 changed files with 254 additions and 66 deletions

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,177 @@ Aims:
- Describe the pipeline, and components getting from aiken to uplc. - Describe the pipeline, and components getting from aiken to uplc.
## Preface
Aiken is undergoing active development.
This post was started Aiken ~v1.14.
With Aiken v1.15, there were already reasonably significant changes to the compilation pipeline.
The word is that there aren't as big changes in the near future, but
this article will undoubtably begin to diverge from the current codebase even before publishing.
## Aiken build
Tracing `aiken build`, the pipeline is roughly something like:
```
. -> Project::read_source_files ->
Vec<Source> -> Project::parse_sources ->
ParsedModules -> Project::type_check ->
CheckedModules -> CodeGenerator::build ->
AirTree -> AirTree::to_vec ->
Vec<Air> -> CodeGenerator::uplc_code_gen ->
Program / Term<Name> -> serialize ->
.
```
We'll pick our way through these steps
At a high level we are trying to do something straightforward: reformulate aiken code as uplc.
Some aiken expressions are relatively easy to handle for example an aiken `Int` goes to an `Int` in uplc.
Some aiken expressions require more involved handling, for example an aiken `If... If Else... Else `
must have the branches "nested" in uplc.
### The Preamble
#### cli handling
The cli enters at `aiken/src/cmd/mod.rs` which parses the command.
With some establishing of context, the program enters `Project::build` (`crates/aiken-project/src/lib.rs`),
which in turn calls `Project::compile`.
#### File crawl
The program looks for aiken files in both `./lib` and `./validator` subdirs.
For each it walks over all contents (recursively) looking for `.ak` extensions.
It treats these two sets of files a little differently.
Only validator files can contain the special validator functions.
#### Parse and Type check
`Project::parse_sources` parses the module source code.
The heavy lifting is done by `aiken_lang::parser::module`, which is evaluated on each file.
It produces a `Module` containing a list of parsed definitions of the file: functions, types _etc_,
together with "metadata" like docstrings and the file path.
`Project::type_check` inspects the parsed modules and, as the name implies, checks the types.
It flags type level warnings and errors.
It constructs a hash map of `CheckedModule`s.
#### Code generator
The code generator `CodeGenerator` (`aiken-lang/src/gen_uplc.rs`) is given
the definitions found from the previous step,
together with the plutus builtins.
It has additional fields for things like debugging.
This is handed over to a `Blueprint` (`aiken-project/src/blueprint/mod.rs`).
A blueprint does little more than find the validators on which to run the code gen.
The heavy lifting is done by `CodeGenerator::generate`.
We are now ready to take the source code and create plutus.
### Up in the air
Things become a bit intimidating at this point in terms of sheer lines of code:
`gen_uplc.rs` and three modules in `gen_uplc/` totals > 8500 LoC.
Aiken has its own _intermediate representation_ called `air` (as in Aiken Intermediate Representation).
These are common in compiled languages.
`Air` is defined in `aiken-lang/src/gen_uplc/air.rs`.
Unsurprisingly, it looks little bit like a language between aiken and plutus.
In fact, Aiken has another intermediate representation: `AirTree`.
This is constructed between the `TypedExpr` and `Vec<Air>` ie between parsed aiken and air.
#### AirTree
Within `CodeGenerator::generate`, `CodeGenerator::build` is called on the function body.
This constructs and returns an `AirTree`.
More on what an airtree is and its construction below.
At the same time `self` is treated as `mut`, so we need to keep an eye on this too.
The method which is called and uses this mutability of self is `self.assignment`.
It does so by
```sample
self.assignment >> self.expect_type_assign >> self.code_gen_functions.insert
```
and thus is creating a hashmap of all the functions that appear in the definition.
(`self.handle_each_clause` is also called with `mut` which in turn calls `self.build` for which `mut` it is needed.
`self.clause_pattern` is called with `mut` but it isn't used.)
###### Codegen assignment
~200 LoC
###### Codegen expect type assign
~400 LoC
###### ... Back to build
Validators in aiken are boolean functions while in uplc they are unit-valued (aka void-valued) functions.
Thus the airtree is wrapped such that `false` results in an error (`wrap_validator_condition`).
(Ed: I don't know why there is a prevailing thought that boolean functions are preferable than functions
that simply error if anything is wrong.)
`check_validator_args` again extends the airtree from the previous step,
and again calls `self.assignment` mutating self.
Something interesting is happening here.
Script context is the final argument of a validator - for any script purpose.
`check_validator_args` treats the script context like it is an unused argument.
We'll circle back to how this works later on.
Next we encounter
```rust
AirTree::no_op().hoist_over(validator_args_tree);
```
Its not very apparent why we need to do this. Let's look ahead and consider this later.
The final airtree to step(s) are in `self.hoist_functions_to_validator`.
TODO: What happens here?!
Note that `AirTree` and its methods aren't fully typesafe.
For example `hoist_over` will throw an error if called on an `Expression`.
As `AirTree` is for internal use only, the scope for potential problems is reasonably contained.
The AirTree has the following definition
```rust
pub enum AirTree {
Statement {
statement: AirStatement,
hoisted_over: Option<Box<AirTree>>,
},
Expression(AirExpression),
UnhoistedSequence(Vec<AirTree>),
}
```
We can see it has a tree-like structure, as the name suggests.
`AirExpression` has multiple constructors. These include (non-exhaustive)
- air primitives (including all the ones that appear in plutus)
- constructors `Call` and `Fn` to handle functions
- binary and unary operators
- handling when and if
- error and tracing
`AirStatement` also has multiple constructors.
for handling functions, `plutus primitives, along with
An `AirStatement`
## Down to uplc
## Air ## Air
Aiken compiles aiken code to uplc via _air_: Aiken compiles aiken code to uplc via _air_:

View File

@ -58,6 +58,7 @@ main = hakyll $ do
getResourceBody getResourceBody
>>= applyAsTemplate indexCtx >>= applyAsTemplate indexCtx
>>= loadAndApplyTemplate "templates/index.html" indexCtx >>= loadAndApplyTemplate "templates/index.html" indexCtx
>>= loadAndApplyTemplate "templates/default.html" indexCtx
>>= relativizeUrls >>= relativizeUrls
match "templates/*" $ compile templateBodyCompiler match "templates/*" $ compile templateBodyCompiler

View File

@ -8,8 +8,12 @@ module.exports = {
extend: {}, extend: {},
fontFamily: { fontFamily: {
'sans' : ['jetbrains-mono',], 'sans' : ['jetbrains-mono',],
} },
typography: (theme) => ({}),
}, },
darkMode: 'class',
variants: {},
// plugins: [require('@tailwindcss/typography')],
plugins: [], plugins: [],
} }

View File

@ -2,7 +2,7 @@
<header class="text-3xl"> <header class="text-3xl">
# blog # blog
</header> </header>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
A nascent initiative sharing some of the things happening at Kompact.io. A nascent initiative sharing some of the things happening at Kompact.io.
</div> </div>
</section> </section>

View File

@ -2,7 +2,7 @@
<header class="text-3xl"> <header class="text-3xl">
# contact # contact
</header> </header>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Questions? We'll be happy to help answer any of your questions. Send us an email and we'll get back to you shortly. Questions? We'll be happy to help answer any of your questions. Send us an email and we'll get back to you shortly.
</div> </div>
<div> <div>

View File

@ -1,5 +1,5 @@
<!doctype html> <!doctype html>
<html> <html class="">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
@ -9,8 +9,25 @@
<title>$title$</title> <title>$title$</title>
</head> </head>
<body> <script>
<div class="container mx-auto"> // On page load or when changing themes, best to add inline in `head` to avoid FOUC
function updateTheme() {
if (
localStorage.theme === 'dark' ||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
}
updateTheme()
</script>
<body class="bg-white text-gray-900 min-h-screen
dark:bg-gradient-to-br dark:from-slate-950 dark:to-black dark:text-white">
<div class="container mx-auto ">
<hr /> <hr />
$partial("templates/nav.html")$ $partial("templates/nav.html")$
<hr /> <hr />

View File

@ -1,8 +1,9 @@
<section id="footer" class="py-12 px-2 flex flex-row gap-12 mx-2 sm:mx-4 items-start justify-between"> <section id="footer" class="py-12 px-2 flex flex-row gap-12 mx-2 sm:mx-4 items-start justify-between
<div class="text-sm text-gray-700"> text-gray-800 dark:text-gray-200 dark:fill-white">
<div class="text-sm">
&reg; 2023 kompact.io &trade; All Rights Reserved. &reg; 2023 kompact.io &trade; All Rights Reserved.
</div> </div>
<div class="text-gray-700 flex flex-row gap-4"> <div class="flex flex-row gap-4">
<a href="https://www.linkedin.com/in/dominic-algernon-wallis-123b42187/"> <a href="https://www.linkedin.com/in/dominic-algernon-wallis-123b42187/">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" height="20" preserveAspectRatio="xMidYMid meet"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" height="20" preserveAspectRatio="xMidYMid meet">
<!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --> <!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->

View File

@ -4,7 +4,7 @@
⟨K⟩ ⟨K⟩
</div> </div>
<div class="flex flex-col gap-2 truncate"> <div class="flex flex-col gap-2 truncate">
<div>withKompact &#36; <span class="text-red-500">do</span> </div> <div>withKompact &#36; <span class="text-red-500 dark:text-yellow-400">do</span> </div>
<div><span class="text-gray-400">· ·</span> dapp <- lean dev </div> <div><span class="text-gray-400">· ·</span> dapp <- lean dev </div>
<div><span class="text-gray-400">· ·</span> run dapp </div> <div><span class="text-gray-400">· ·</span> run dapp </div>
</div> </div>

View File

@ -1,30 +1,7 @@
<!doctype html> $partial("templates/hero.html")$
<html> <hr />
$partial("templates/services.html")$
<head> <hr />
<meta charset="UTF-8"> $partial("templates/pricing.html")$
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <hr />
<link rel="icon" type="image/x-icon" href="/favicon.png"> $partial("templates/contact.html")$
<title>$title$</title>
<link href="/css/mini.css" rel="stylesheet">
</head>
<body>
<div class="container mx-auto">
<hr />
$partial("templates/nav.html")$
<hr />
$partial("templates/hero.html")$
<hr />
$partial("templates/services.html")$
<hr />
$partial("templates/pricing.html")$
<hr />
$partial("templates/contact.html")$
<hr />
$partial("templates/footer.html")$
<hr />
</div>
</body>
</html>

View File

@ -1,12 +1,29 @@
<nav class="mx-2 sm:mx-4"> <nav class="mx-2 sm:mx-4">
<div class="relative flex h-16 items-center justify-between "> <div class="relative flex h-16 items-center justify-between">
<div> <div>
<a href="/"> <a href="/">
Kompact.io <span class="hidden sm:inline">Kompact.io</span>
<span class="inline sm:hidden">K.io</span>
</a> </a>
</div> </div>
<div> <div>
<ul class="flex flex-row gap-4 md:gap-8"> <ul class="flex flex-row gap-4 md:gap-8">
<li>
<button onClick="
(() => {
if (!('theme' in localStorage)) {
localStorage.theme = 'light'
}
console.log('*', localStorage.theme)
if (localStorage.theme === 'light') {
localStorage.theme = 'dark'
} else {
localStorage.theme = 'light'
}
updateTheme()
})()
">◧</button>
</li>
<li> <li>
<a href="/index.html#contact"> <a href="/index.html#contact">
contact contact

View File

@ -2,7 +2,7 @@
$for(posts)$ $for(posts)$
<li class="mt-4"> <li class="mt-4">
<a href="$url$"> <a href="$url$">
<span class="text-gray-700"> <span class="text-gray-800 dark:text-gray-200">
$date$ :: $date$ ::
</span> </span>
$title$ $title$

View File

@ -2,7 +2,7 @@
<header class="text-3xl"> <header class="text-3xl">
# pricing # pricing
</header> </header>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Plutus development has traditionally meant long development schedules, and expensive ( &#36; 25k+/mo FTE) engineers. Plutus development has traditionally meant long development schedules, and expensive ( &#36; 25k+/mo FTE) engineers.
We can work with you at competitive rates in either deliverable or retainer based engagements. We can work with you at competitive rates in either deliverable or retainer based engagements.
</div> </div>
@ -11,16 +11,16 @@
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">
## retainer ## retainer
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Time-based Time-based
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Still figuring out your project scope? Still figuring out your project scope?
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Need an extra pair of hands on an existing project? Need an extra pair of hands on an existing project?
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Then a retainer based engagement is for you. Then a retainer based engagement is for you.
</div> </div>
</div> </div>
@ -28,17 +28,17 @@
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">
## deliverable ## deliverable
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Output-based Output-based
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
You know what you want and need help implementing it? You know what you want and need help implementing it?
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
We'll first produce a spec on how the dapp will operate technically. We'll first produce a spec on how the dapp will operate technically.
This involves discussing different options and trade-offs on things from UX to validator complexity. This involves discussing different options and trade-offs on things from UX to validator complexity.
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Once settled we'll begin the implementation phase and finally integration phase. Once settled we'll begin the implementation phase and finally integration phase.
</div> </div>
</div> </div>

View File

@ -2,7 +2,7 @@
<header class="text-3xl"> <header class="text-3xl">
# services # services
</header> </header>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
We are cardano native dapp dev outfit focused on helping you going from 0 to launch ASAP. We are cardano native dapp dev outfit focused on helping you going from 0 to launch ASAP.
</div> </div>
@ -11,7 +11,7 @@
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">
## strategy ## strategy
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
We'll work with you to validate your concept, and translate it into an implementable Proof of Concept We'll work with you to validate your concept, and translate it into an implementable Proof of Concept
</div> </div>
</div> </div>
@ -19,7 +19,7 @@
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">
## implementation ## implementation
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
Cook up appropriate Plutus validators to meet your needs Cook up appropriate Plutus validators to meet your needs
</div> </div>
</div> </div>
@ -27,7 +27,7 @@
<div class="text-1xl font-bold"> <div class="text-1xl font-bold">
## deployment ## deployment
</div> </div>
<div class="text-gray-700 mt-4"> <div class="text-gray-800 dark:text-gray-200 mt-4">
We facilitate integrating the on-chain aspects with the rest of your stack We facilitate integrating the on-chain aspects with the rest of your stack
</div> </div>
</div> </div>