serene-simple-version post has been added
This commit is contained in:
parent
f464de27be
commit
ee583894e2
|
@ -44,6 +44,10 @@
|
|||
Code of Honor
|
||||
</a>
|
||||
|
||||
<a href="https://dl.lxsameer.com/lxsameer.pub.gpg" class="navbar-item">
|
||||
GPG Key
|
||||
</a>
|
||||
|
||||
<a href="/about/" class="navbar-item {% if page.url == '/about/' %}is-active{% endif %}">
|
||||
About Me
|
||||
</a>
|
||||
|
@ -60,6 +64,17 @@
|
|||
</span>
|
||||
</a>
|
||||
|
||||
<a class="navbar-item" href="https://social.lxsameer.com/">
|
||||
<span class="icon is-large is-hidden-mobile">
|
||||
<i class="fab fa-mastodon fa-lg"></i>
|
||||
</span>
|
||||
|
||||
<span class="is-large is-hidden-desktop">
|
||||
<i class="pad fab fa-mastodon fa-lg"></i>
|
||||
ActivityPub
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a class="navbar-item" href="https://www.linkedin.com/in/lxsameer/">
|
||||
<span class="icon is-large is-hidden-mobile">
|
||||
<i class="fab fa-linkedin fa-lg"></i>
|
||||
|
@ -101,7 +116,7 @@
|
|||
</div>
|
||||
<footer class="footer">
|
||||
<div class="content has-text-centered">
|
||||
<p>© 2010-2019 Sameer Rahmani</p>
|
||||
<p>© 2010-2020 Sameer Rahmani</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="/assets/js/main.js?1"></script>
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
layout: default
|
||||
---
|
||||
|
||||
<div class="column is-half-desktop is-offset-one-quarter-desktop">
|
||||
|
||||
<div class="column is-half-desktop is-offset-one-quarter-desktop para">
|
||||
<section class="section is-size-4-desktop is-size-5-mobile">
|
||||
<p class="text-centered">
|
||||
<img
|
||||
|
@ -15,10 +16,17 @@ layout: default
|
|||
Hi! I'm <b>Sameer</b> and I usually write about
|
||||
technology and software development (hmmm more like nagging instead of writing). Since
|
||||
I'm lazy, my posts are short so I can write more often.
|
||||
|
||||
<p class="info text-justified">
|
||||
If you have any comment on the articles or anything in general either send me an
|
||||
email for connect to me via my <a class="home" href="https://activitypub.rocks/">activity pub</a>
|
||||
feed on <a class="home" href="https://social.lxsameer.com">lxsameer@social.lxsameer.com</a>.
|
||||
</p>
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="column is-half-desktop is-offset-one-quarter-desktop">
|
||||
<section class="section">
|
||||
<h3 class="header is-size-4">
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
---
|
||||
layout: post
|
||||
title: "Step 2: Serene (Simple) version"
|
||||
date: 2020-01-03
|
||||
categories: Programming
|
||||
tags: Serene language
|
||||
theme: dark
|
||||
---
|
||||
As you might already know I'm working on [my own programming language ](programming/my-new-programming-language/)
|
||||
for a while now. I'm still on early stages and I'm working on
|
||||
[choosing the right platform](/programming/choosing-the-target-platform/)
|
||||
for [#Serence](https://social.lxsameer.com/tags/Serene) and
|
||||
I'm trying spend time on enough research and make decision based
|
||||
on facts, scientific papers and collected data from experiments
|
||||
rather than rushing into things and end up with a mess.
|
||||
I believe those languages that take their time and move slowly
|
||||
but with great research, plan and design are more successful in
|
||||
the long term (Thanks to **Pouya** for pointing it out). Take **Clojure**
|
||||
as an example. They are taking their time experimenting and validating
|
||||
their hypothesis. As the result, Clojure is a well designed, stable
|
||||
and highly backward compatible language with amazing productivity
|
||||
pace. However, some other languages like Python are extremely
|
||||
popular and consequently has more contributors. Dealing with all
|
||||
those contributors caused Python to move faster than should. As a
|
||||
result they ended up with some bad choices and horrible designs that
|
||||
fixing them requires a humongous effort. Little by little, it becomes
|
||||
harder and harder to fix those and move away from them. GIL is a good example,
|
||||
instead of fixing the issue and removing GIL they are introducing
|
||||
[something else](https://lwn.net/Articles/754162/) that might become
|
||||
an other problem to fix the original one. In order to avoid these kind
|
||||
of problem as much as possible I'm trying to take my time and do as
|
||||
many as experiments that I need.
|
||||
|
||||
As I mentioned [earlier](/programming/choosing-the-target-platform/)
|
||||
I think **GraalVM** and **Truffle** is the right answer for
|
||||
Serene. But to verify my initial Idea I decided to run an experiment.
|
||||
The experiment is all about implementing a Lisp in two environments.
|
||||
A pure Java implementation vs a **Truffle** implementation.
|
||||
I'll update the experiment files accordingly at the
|
||||
[experiment reports](https://gitlab.com/serene-lang/experiment-reports/tree/master/001)
|
||||
repository.
|
||||
|
||||
I spend several days and implemented the pure java version. There repository
|
||||
of the simple version is available in [gitlab repo](https://gitlab.com/serene-lang/simple-version).
|
||||
I didn't paid too much attention to the details and created a very simple lisp
|
||||
that follows the specification below.
|
||||
|
||||
> Node: In this post where ever I use the name **Serene** for the implementation,
|
||||
> I'm referring to the simple version.
|
||||
|
||||
## Data structures
|
||||
Since I tried to avoid unnecessary work I didn't do much and implemented
|
||||
only one collection type which is the most important and essential data
|
||||
structure of Lisp, the mighty List. While my final goal is to have functional
|
||||
data structures, this List is not a functional one and is a simple linked
|
||||
list. You can find the implementation under `serene.simple.ListNode`.
|
||||
|
||||
For the number types I just added the support for `Long` and `Double` numbers
|
||||
via `serene.simple.SNumber` class which act as a dispatcher between two inner
|
||||
classes.
|
||||
|
||||
For Strings, boolean types and `nil`, I just used the equivalent Java data
|
||||
structures directly.
|
||||
|
||||
## Reader/Parser
|
||||
Instead of using a parser generator or a sophisticated parser, I just created
|
||||
a simple read ahead position based parser that reads two chars and call the
|
||||
appropriate method to create the corresponding `Node`. the `serene.simple.Node`
|
||||
is an abstract class which has just one important method, `eval`. The whole
|
||||
purpose of the reader is to parse code and create an AST like data structure
|
||||
which each node extends the `Node` class (I should've create the interface for
|
||||
it but too lazy to change it now). The `eval` method of `ListNode` is a bit
|
||||
special. It calls the `eval` method on all the elements on the list
|
||||
and the call the first element as a function and pass the rest of elements
|
||||
as the arguments to that function. First rule of lisp :))
|
||||
|
||||
The `eval` method of `ListNode` contains more details regarding to java
|
||||
interop as well which I leave it out of this blog post.
|
||||
|
||||
## Scope
|
||||
Scope are simply a mapping between symbol names and values. There are two
|
||||
different scopes, both implemented `serene.simple.IScope` and extends
|
||||
`serene.simple.AScope` abstract class that contains the logic for symbol
|
||||
lookup and insertion. These two classes are `serene.simple.Scope` which
|
||||
is the general scope and it has a parent/child type of relationship with
|
||||
other instances of the same class or `serene.simple.RootScope` which is
|
||||
the top level scope. Beside that `RootScope` is pre-populated with all
|
||||
the builtin functions and types.
|
||||
|
||||
## Special forms
|
||||
Serene's [special forms](https://courses.cs.northwestern.edu/325/readings/special-forms.php)
|
||||
are pretty limited. All of them all classes which extend `serene.simple.SpecialForm`
|
||||
abstract class and inherit from `Node` indirectly. The difference between
|
||||
special form evaluation and function evaluation is that in case of special forms
|
||||
Serene does not evaluate the arguments and leave the evaluation to the special form
|
||||
itself. Here is the list of Serene's special forms:
|
||||
|
||||
`def`: Creates a binding between a symbol name and the given value:
|
||||
```cl
|
||||
(def name "serene")
|
||||
```
|
||||
|
||||
`fn`: Creates an anonymous function:
|
||||
```clojure
|
||||
(def inc (fn (x) (+ 1 x)))
|
||||
```
|
||||
`quote`: Prevent the evaluation of the given argument and return it as it is:
|
||||
|
||||
```clojure
|
||||
(quote (1 2 3 4)) ;; => (1 2 3 4)
|
||||
```
|
||||
`if`: Evaluated the body based on the return value of the given predicate.
|
||||
|
||||
```clojure
|
||||
(if (= x 1)
|
||||
(...) ;; if x is 1
|
||||
(...)) ;; if x is not 1
|
||||
```
|
||||
|
||||
`let`: Setup a local scope and runs its body using that scope.
|
||||
|
||||
```cl
|
||||
(let ((x 1)
|
||||
(y 2))
|
||||
(println x y))
|
||||
```
|
||||
|
||||
`do`: Simple group several expressions together.
|
||||
|
||||
```clojure
|
||||
(do
|
||||
(println ...)
|
||||
(if ....))
|
||||
```
|
||||
|
||||
`cond`: Gets several predicates and only evaluates the body corresponding
|
||||
to the first truthy predicate.
|
||||
|
||||
```cl
|
||||
(cond
|
||||
((= x 1) (body1...)
|
||||
((= x 2) (body2...))
|
||||
(true (else...))))
|
||||
```
|
||||
|
||||
## Builtin Function
|
||||
All the build in function are created by extending the `serene.simple.builtin.AFn`
|
||||
abstract class and follow the same `Node` convention. Here is a list of the most
|
||||
important built in functions:
|
||||
|
||||
`(println ....)`: Prints all the arguments on the stdout.
|
||||
|
||||
`(quit)`: Quits the program.
|
||||
|
||||
`(conj coll x...)`: Returns a new list by adding the given arguments.
|
||||
|
||||
`(count coll)`: Returns the number of elements in the given COLL.
|
||||
|
||||
`(reverse coll)`: Return a new list which is the reverse of COLL.
|
||||
|
||||
`(list 1 2 3..)`: Creates a list from the given arguments.
|
||||
|
||||
`(first coll)`: Returns the first element of the given COLL.
|
||||
|
||||
`(rest coll)`: Return all the elements beside the first of the given COLL.
|
||||
|
||||
`(doc fn)`: Return the documentation for the given symbol if any.
|
||||
|
||||
`(reduce f coll initial)`: Reduce the COLL by applying F to its elements with the
|
||||
INITIAL as the default value. F takes two arguments 1) the accumulation 2) the element.
|
||||
|
||||
`(new Class arg1 arg2...)`: Create a new instance of the given CLASS by passing the given
|
||||
arguments to its constructor.
|
||||
|
||||
### Example program
|
||||
Here is an example program in Serene simple version (`benchmarks/fib.srns` in the repo):
|
||||
|
||||
```clojure
|
||||
;; We have a reduce function but just in case...
|
||||
(def reduce1
|
||||
(fn (f xs initial-value)
|
||||
(cond
|
||||
((first xs) (reduce f (rest xs) (f initial-value (first xs))))
|
||||
(true initial-value))))
|
||||
|
||||
;; A simple map function implementation in serene
|
||||
(def map
|
||||
(fn (f xs)
|
||||
(reduce (fn (acc x) (cons acc (f x))) xs (list))))
|
||||
|
||||
(def range-list
|
||||
(fn (x y init)
|
||||
(if (< y x)
|
||||
(do
|
||||
(conj (range-list x (+ y 1) init) y))
|
||||
init)))
|
||||
|
||||
(def range
|
||||
(fn (x)
|
||||
(range-list x 0 (list))))
|
||||
|
||||
(def fib
|
||||
(fn (n)
|
||||
(def fib-iter
|
||||
(fn (x y z)
|
||||
(if (= x 0)
|
||||
z
|
||||
(fib-iter (- x 1)
|
||||
z
|
||||
(+ y z)))))
|
||||
(fib-iter n 0 1)))
|
||||
|
||||
(def benchmark-fn
|
||||
(fn (x)
|
||||
(let ((start (now)))
|
||||
(println (fib x))
|
||||
(- (now) start))))
|
||||
|
||||
|
||||
(def run-benchmark
|
||||
(fn (times)
|
||||
(map (fn (x)
|
||||
(println "Benchmark: " x)
|
||||
(println "Took: " (benchmark-fn 500)))
|
||||
(range times))))
|
||||
|
||||
(run-benchmark 20)
|
||||
|
||||
```
|
||||
|
||||
|
||||
## What is missing ?
|
||||
Since Serene (simple) is an experimental language and I'll abandon it eventually,
|
||||
I didn't bother with details and tried to get to the point as soon as possible.
|
||||
So I sacrificed lots of details. Here is a list of the most important missing
|
||||
details:
|
||||
|
||||
* A namespace functionality. Because creating and compiling dynamic classes
|
||||
is a rabbit hole and tons of work which doesn't make sense for a toy
|
||||
project.
|
||||
* Unified function interface.
|
||||
* Requiring different namespaces
|
||||
* A sophisticated parser. My Reader implementation is really cheap that
|
||||
suits a toy project. It might worth investigating on different solutions
|
||||
including using a parser generator or a head of time read implementation.
|
||||
* Primitive functions in Serene. I implemented lots of primitive functions
|
||||
in java rather than Serene itself mostly because of two reasons. Lack of
|
||||
macros and namespaces.
|
||||
* Decent [functional] data structures. The only data structure I implemented
|
||||
is list.
|
||||
* Quality code. The general quality of this implementation is not great, I
|
||||
sacrificed quality for time.
|
||||
|
||||
## Conclusion
|
||||
I'm not going to improve the simple version anymore at this stage. I'm going to run
|
||||
some benchmarks to measure different aspect of the current implementation and then
|
||||
I'll move to the **Truffle** version to continue the
|
||||
[experiment(001)](https://gitlab.com/serene-lang/experiment-reports/tree/master/001).
|
||||
Please let me know if you have any comment or question on this topic. As always
|
||||
I'm available throw social media and email.
|
147
_sass/code.scss
147
_sass/code.scss
|
@ -1,65 +1,88 @@
|
|||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight .c { color: #0099FF; font-style: italic } /* Comment */
|
||||
.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */
|
||||
.highlight .k { color: #006699; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #555555 } /* Operator */
|
||||
.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #009999 } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
|
||||
.highlight .go { color: #AAAAAA } /* Generic.Output */
|
||||
.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #99CC66 } /* Generic.Traceback */
|
||||
.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #006699 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */
|
||||
.highlight .m { color: #FF6600 } /* Literal.Number */
|
||||
.highlight .s { color: #CC3300 } /* Literal.String */
|
||||
.highlight .na { color: #330099 } /* Name.Attribute */
|
||||
.highlight .nb { color: #336666 } /* Name.Builtin */
|
||||
.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #336600 } /* Name.Constant */
|
||||
.highlight .nd { color: #9999FF } /* Name.Decorator */
|
||||
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #CC00FF } /* Name.Function */
|
||||
.highlight .nl { color: #9999FF } /* Name.Label */
|
||||
.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #003333 } /* Name.Variable */
|
||||
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mf { color: #FF6600 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #CC3300 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #CC3300 } /* Literal.String.Double */
|
||||
.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #AA0000 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #CC3300 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #33AAAA } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #CC3300 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #003333 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #003333 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #003333 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */
|
||||
|
||||
pre.highlight {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
/* Punctuation */
|
||||
.highlight .cm {
|
||||
color: #aaaaaa !important; }
|
||||
|
||||
/* Comment.Multiline */
|
||||
.highlight .cp {
|
||||
color: #aaaaaa !important; }
|
||||
|
||||
/* Comment.Preproc */
|
||||
.highlight .c1 {
|
||||
color: #aaaaaa !important; }
|
||||
|
||||
/* Comment.Single */
|
||||
.highlight .cs {
|
||||
color: #aaaaaa !important; }
|
||||
|
||||
//.highlight pre { background-color: #272822; }
|
||||
.highlight pre { background-color: #373269; }
|
||||
.highlight .hll { background-color: #272822; }
|
||||
//.highlight .c { color: #75715e } /* Comment */
|
||||
.highlight .c { color: #aaaaaa } /* Comment */
|
||||
.highlight .cl { color: #aaaaaa } /* Comment */
|
||||
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
|
||||
.highlight .k { color: #66d9ef } /* Keyword */
|
||||
.highlight .l { color: #ae81ff } /* Literal */
|
||||
.highlight .n { color: #f8f8f2 } /* Name */
|
||||
.highlight .o { color: #f92672 } /* Operator */
|
||||
.highlight .p { color: #f8f8f2 } /* Punctuation */
|
||||
.highlight .cm { color: #75715e } /* Comment.Multiline */
|
||||
.highlight .cp { color: #75715e } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #75715e } /* Comment.Single */
|
||||
.highlight .cs { color: #75715e } /* Comment.Special */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
|
||||
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #66d9ef } /* Keyword.Type */
|
||||
.highlight .ld { color: #e6db74 } /* Literal.Date */
|
||||
.highlight .m { color: #ae81ff } /* Literal.Number */
|
||||
.highlight .s { color: #e6db74 } /* Literal.String */
|
||||
.highlight .na { color: #a6e22e } /* Name.Attribute */
|
||||
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
|
||||
.highlight .nc { color: #a6e22e } /* Name.Class */
|
||||
.highlight .no { color: #66d9ef } /* Name.Constant */
|
||||
.highlight .nd { color: #a6e22e } /* Name.Decorator */
|
||||
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
|
||||
.highlight .ne { color: #a6e22e } /* Name.Exception */
|
||||
.highlight .nf { color: #a6e22e } /* Name.Function */
|
||||
.highlight .nl { color: #f8f8f2 } /* Name.Label */
|
||||
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
|
||||
.highlight .nx { color: #a6e22e } /* Name.Other */
|
||||
.highlight .py { color: #f8f8f2 } /* Name.Property */
|
||||
.highlight .nt { color: #f92672 } /* Name.Tag */
|
||||
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
|
||||
.highlight .ow { color: #f92672 } /* Operator.Word */
|
||||
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
|
||||
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
|
||||
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
|
||||
|
||||
.highlight .gh { } /* Generic Heading & Diff Header */
|
||||
.highlight .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
|
||||
.highlight .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */
|
||||
.highlight .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */
|
||||
|
|
|
@ -56,7 +56,20 @@ body.light
|
|||
background: $purple
|
||||
color: $light
|
||||
|
||||
a.home
|
||||
color: $blue !important
|
||||
&:hover
|
||||
text-decoration: underline
|
||||
|
||||
|
||||
body.dark
|
||||
.para
|
||||
p, h1, h2, h3, h4, h5, strong
|
||||
padding-top: 1em
|
||||
padding-bottom: 0.5em
|
||||
line-height: 1.5
|
||||
color: darken($white, 10%)
|
||||
|
||||
color: $light
|
||||
background: $purple
|
||||
footer.footer
|
||||
|
@ -69,11 +82,10 @@ body.dark
|
|||
|
||||
&:hover
|
||||
color: darken($white, 30%)
|
||||
|
||||
|
||||
content.post
|
||||
text-align: justify
|
||||
|
||||
blockquote
|
||||
font-style: italic
|
||||
h1
|
||||
@extend .is-size-2
|
||||
h2
|
||||
|
@ -90,6 +102,7 @@ body.dark
|
|||
padding-bottom: 0.5em
|
||||
line-height: 1.5
|
||||
color: darken($white, 10%)
|
||||
|
||||
strong
|
||||
color: white
|
||||
p
|
||||
|
@ -105,7 +118,12 @@ body.dark
|
|||
text-decoration: underline
|
||||
|
||||
font-size: 1.3rem
|
||||
line-height: 2rem
|
||||
|
||||
pre
|
||||
code
|
||||
font-size: 0.8em
|
||||
line-height: 1em !important
|
||||
|
||||
code.highlighter-rouge
|
||||
background: darken($purple, 10%)
|
||||
color: $light
|
||||
|
|
Loading…
Reference in New Issue